Import Cobalt 6.16000
diff --git a/src/base/base.gypi b/src/base/base.gypi
index 79b9dd4..c1a5fff 100644
--- a/src/base/base.gypi
+++ b/src/base/base.gypi
@@ -589,11 +589,6 @@
               ['include', 'sys_string_conversions_linux.cc'],
             ],
           }],
-          [ 'OS=="lb_shell" and target_arch!="linux" and target_arch!="android"', {
-            'sources!': [
-              'string16.cc',  # wchar_t is 2-bytes wide, string16 == wstring here.
-            ],
-          }],
           [ 'OS=="lb_shell" and target_arch=="android"', {
             'sources/' : [
               ['exclude', 'message_pump_shell.cc'],
@@ -660,14 +655,6 @@
               # We use thread_checker_impl_atomic.cc instead.
               'threading/thread_checker_impl.cc',
             ],
-            'conditions': [
-              ['target_os!="linux" and target_os!="android"', {
-                'sources!': [
-                  # Since wchar_t is 2-bytes wide, string16 == wstring here.
-                  'string16.cc',
-                ],
-              }],
-            ],
           }],  # OS == "starboard"
           [ 'OS=="lb_shell" or OS=="starboard"', {
             'sources!': [
diff --git a/src/base/string16.cc b/src/base/string16.cc
index 930e09f..9c5acb7 100644
--- a/src/base/string16.cc
+++ b/src/base/string16.cc
@@ -4,14 +4,9 @@
 
 #include "base/string16.h"
 
-#if defined(WCHAR_T_IS_UTF16)
 
-#error This file should not be used on 2-byte wchar_t systems
-// If this winds up being needed on 2-byte wchar_t systems, either the
-// definitions below can be used, or the host system's wide character
-// functions like wmemcmp can be wrapped.
-
-#elif defined(WCHAR_T_IS_UTF32)
+// See discussion in string16.h: This is only needed on 32-bit wchar_t systems.
+#if defined(WCHAR_T_IS_UTF32)
 
 #include <ostream>
 
diff --git a/src/cobalt/audio/audio_destination_node.cc b/src/cobalt/audio/audio_destination_node.cc
index 59d80df..e0eda2b 100644
--- a/src/cobalt/audio/audio_destination_node.cc
+++ b/src/cobalt/audio/audio_destination_node.cc
@@ -38,8 +38,6 @@
     : AudioNode(context), max_channel_count_(kMaxChannelCount) {
   AudioLock::AutoLock lock(audio_lock());
 
-  audio_device_.reset(
-      new AudioDevice(static_cast<int>(channel_count(NULL)), this));
   AddInput(new AudioNodeInput(this));
 }
 
@@ -54,6 +52,15 @@
   RemoveAllInputs();
 }
 
+void AudioDestinationNode::OnInputNodeConnected() {
+  audio_lock()->AssertLocked();
+
+  if (!audio_device_) {
+    audio_device_.reset(
+        new AudioDevice(static_cast<int>(channel_count(NULL)), this));
+  }
+}
+
 void AudioDestinationNode::FillAudioBus(ShellAudioBus* audio_bus,
                                         bool* silence) {
   // This is called by Audio thread.
diff --git a/src/cobalt/audio/audio_destination_node.h b/src/cobalt/audio/audio_destination_node.h
index 14fab99..50bfe7e 100644
--- a/src/cobalt/audio/audio_destination_node.h
+++ b/src/cobalt/audio/audio_destination_node.h
@@ -48,7 +48,8 @@
   uint32 max_channel_count() const { return max_channel_count_; }
 
   // From AudioNode.
-  scoped_ptr<ShellAudioBus> PassAudioBusFromSource(int32, /*number_of_frames*/
+  void OnInputNodeConnected() OVERRIDE;
+  scoped_ptr<ShellAudioBus> PassAudioBusFromSource(int32 /*number_of_frames*/,
                                                    SampleType) OVERRIDE {
     NOTREACHED();
     return scoped_ptr<ShellAudioBus>();
diff --git a/src/cobalt/audio/audio_node.h b/src/cobalt/audio/audio_node.h
index 9564898..01a578d 100644
--- a/src/cobalt/audio/audio_node.h
+++ b/src/cobalt/audio/audio_node.h
@@ -111,6 +111,9 @@
   // Disconnects an AudioNode's output.
   void Disconnect(uint32 output, script::ExceptionState* exception_state);
 
+  // Called when a new input node has been connected.
+  virtual void OnInputNodeConnected() {}
+
   // TODO: Support wrapping ShellAudioBus into another ShellAudioBus.
   virtual scoped_ptr<ShellAudioBus> PassAudioBusFromSource(
       int32 number_of_frames, SampleType sample_type) = 0;
diff --git a/src/cobalt/audio/audio_node_input.cc b/src/cobalt/audio/audio_node_input.cc
index b0c8597..b7ac086 100644
--- a/src/cobalt/audio/audio_node_input.cc
+++ b/src/cobalt/audio/audio_node_input.cc
@@ -197,6 +197,7 @@
 
   output->AddInput(this);
   outputs_.insert(output);
+  owner_node_->OnInputNodeConnected();
 }
 
 void AudioNodeInput::Disconnect(AudioNodeOutput* output) {
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousIndexedGetterInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousIndexedGetterInterface.cc
index ff82636..9a486e9 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousIndexedGetterInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousIndexedGetterInterface.cc
@@ -86,7 +86,6 @@
 
 bool IsSupportedIndexProperty(JSContext* context, JS::HandleObject object,
                               uint32_t index) {
-  TRACE_EVENT0("cobalt::bindings", "IsSupportedIndexProperty");
   WrapperPrivate* wrapper_private =
       WrapperPrivate::GetFromObject(context, object);
   AnonymousIndexedGetterInterface* impl =
@@ -109,7 +108,6 @@
 JSBool GetIndexedProperty(
     JSContext* context, JS::HandleObject object, JS::HandleId id,
     JS::MutableHandleValue vp) {
-  TRACE_EVENT0("cobalt::bindings", "GetIndexedProperty");
   JS::RootedValue id_value(context);
   if (!JS_IdToValue(context, id, id_value.address())) {
     NOTREACHED();
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedGetterInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedGetterInterface.cc
index a896d35..5431665 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedGetterInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedGetterInterface.cc
@@ -86,7 +86,6 @@
 
 bool IsSupportedNamedProperty(JSContext* context, JS::HandleObject object,
                               const std::string& property_name) {
-  TRACE_EVENT0("cobalt::bindings", "IsSupportedNamedProperty");
   WrapperPrivate* wrapper_private =
       WrapperPrivate::GetFromObject(context, object);
   AnonymousNamedGetterInterface* impl =
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedIndexedGetterInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedIndexedGetterInterface.cc
index 8f883ff..0d132c4 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedIndexedGetterInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedIndexedGetterInterface.cc
@@ -86,7 +86,6 @@
 
 bool IsSupportedNamedProperty(JSContext* context, JS::HandleObject object,
                               const std::string& property_name) {
-  TRACE_EVENT0("cobalt::bindings", "IsSupportedNamedProperty");
   WrapperPrivate* wrapper_private =
       WrapperPrivate::GetFromObject(context, object);
   AnonymousNamedIndexedGetterInterface* impl =
@@ -178,7 +177,6 @@
 
 bool IsSupportedIndexProperty(JSContext* context, JS::HandleObject object,
                               uint32_t index) {
-  TRACE_EVENT0("cobalt::bindings", "IsSupportedIndexProperty");
   WrapperPrivate* wrapper_private =
       WrapperPrivate::GetFromObject(context, object);
   AnonymousNamedIndexedGetterInterface* impl =
@@ -201,7 +199,6 @@
 JSBool GetIndexedProperty(
     JSContext* context, JS::HandleObject object, JS::HandleId id,
     JS::MutableHandleValue vp) {
-  TRACE_EVENT0("cobalt::bindings", "GetIndexedProperty");
   JS::RootedValue id_value(context);
   if (!JS_IdToValue(context, id, id_value.address())) {
     NOTREACHED();
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedGetterSetterInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedGetterSetterInterface.cc
index 1c88411..7c48cfc 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedGetterSetterInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedGetterSetterInterface.cc
@@ -86,7 +86,6 @@
 
 bool IsSupportedNamedProperty(JSContext* context, JS::HandleObject object,
                               const std::string& property_name) {
-  TRACE_EVENT0("cobalt::bindings", "IsSupportedNamedProperty");
   WrapperPrivate* wrapper_private =
       WrapperPrivate::GetFromObject(context, object);
   DerivedGetterSetterInterface* impl =
@@ -178,7 +177,6 @@
 
 bool IsSupportedIndexProperty(JSContext* context, JS::HandleObject object,
                               uint32_t index) {
-  TRACE_EVENT0("cobalt::bindings", "IsSupportedIndexProperty");
   WrapperPrivate* wrapper_private =
       WrapperPrivate::GetFromObject(context, object);
   DerivedGetterSetterInterface* impl =
@@ -201,7 +199,6 @@
 JSBool GetIndexedProperty(
     JSContext* context, JS::HandleObject object, JS::HandleId id,
     JS::MutableHandleValue vp) {
-  TRACE_EVENT0("cobalt::bindings", "GetIndexedProperty");
   JS::RootedValue id_value(context);
   if (!JS_IdToValue(context, id, id_value.address())) {
     NOTREACHED();
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsIndexedGetterInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsIndexedGetterInterface.cc
index b362b42..66f6497 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsIndexedGetterInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsIndexedGetterInterface.cc
@@ -86,7 +86,6 @@
 
 bool IsSupportedIndexProperty(JSContext* context, JS::HandleObject object,
                               uint32_t index) {
-  TRACE_EVENT0("cobalt::bindings", "IsSupportedIndexProperty");
   WrapperPrivate* wrapper_private =
       WrapperPrivate::GetFromObject(context, object);
   IndexedGetterInterface* impl =
@@ -109,7 +108,6 @@
 JSBool GetIndexedProperty(
     JSContext* context, JS::HandleObject object, JS::HandleId id,
     JS::MutableHandleValue vp) {
-  TRACE_EVENT0("cobalt::bindings", "GetIndexedProperty");
   JS::RootedValue id_value(context);
   if (!JS_IdToValue(context, id, id_value.address())) {
     NOTREACHED();
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedGetterInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedGetterInterface.cc
index 79fb735..51f1f54 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedGetterInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedGetterInterface.cc
@@ -86,7 +86,6 @@
 
 bool IsSupportedNamedProperty(JSContext* context, JS::HandleObject object,
                               const std::string& property_name) {
-  TRACE_EVENT0("cobalt::bindings", "IsSupportedNamedProperty");
   WrapperPrivate* wrapper_private =
       WrapperPrivate::GetFromObject(context, object);
   NamedGetterInterface* impl =
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedIndexedGetterInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedIndexedGetterInterface.cc
index e027bc0..2715fd9 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedIndexedGetterInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedIndexedGetterInterface.cc
@@ -86,7 +86,6 @@
 
 bool IsSupportedNamedProperty(JSContext* context, JS::HandleObject object,
                               const std::string& property_name) {
-  TRACE_EVENT0("cobalt::bindings", "IsSupportedNamedProperty");
   WrapperPrivate* wrapper_private =
       WrapperPrivate::GetFromObject(context, object);
   NamedIndexedGetterInterface* impl =
@@ -178,7 +177,6 @@
 
 bool IsSupportedIndexProperty(JSContext* context, JS::HandleObject object,
                               uint32_t index) {
-  TRACE_EVENT0("cobalt::bindings", "IsSupportedIndexProperty");
   WrapperPrivate* wrapper_private =
       WrapperPrivate::GetFromObject(context, object);
   NamedIndexedGetterInterface* impl =
@@ -201,7 +199,6 @@
 JSBool GetIndexedProperty(
     JSContext* context, JS::HandleObject object, JS::HandleId id,
     JS::MutableHandleValue vp) {
-  TRACE_EVENT0("cobalt::bindings", "GetIndexedProperty");
   JS::RootedValue id_value(context);
   if (!JS_IdToValue(context, id, id_value.address())) {
     NOTREACHED();
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsSingleOperationInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsSingleOperationInterface.cc
index 2bd13c6..36e73dd 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsSingleOperationInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsSingleOperationInterface.cc
@@ -27,6 +27,7 @@
 #include "cobalt/script/logging_exception_state.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
 #include "cobalt/script/mozjs/mozjs_callback_interface.h"
+#include "cobalt/script/mozjs/util/exception_helpers.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 #include "third_party/mozjs/js/src/jscntxt.h"
 
@@ -40,6 +41,7 @@
 using cobalt::script::mozjs::FromJSValue;
 using cobalt::script::mozjs::GetCallableForCallbackInterface;
 using cobalt::script::mozjs::ToJSValue;
+using cobalt::script::mozjs::util::GetExceptionString;
 }  // namespace
 
 namespace cobalt {
@@ -90,7 +92,8 @@
       DCHECK(function);
       success = JS::Call(context_, this_value, function, kNumArguments, args,
                          return_value.address());
-      DLOG_IF(WARNING, !success) << "Exception in callback.";
+      DLOG_IF(WARNING, !success) << "Exception in callback: "
+                                 << GetExceptionString(context_);
       if (success) {
         LoggingExceptionState exception_state;
         FromJSValue(context_, return_value, 0, &exception_state,
diff --git a/src/cobalt/bindings/mozjs/templates/callback-interface.cc.template b/src/cobalt/bindings/mozjs/templates/callback-interface.cc.template
index 115f228..895e453 100644
--- a/src/cobalt/bindings/mozjs/templates/callback-interface.cc.template
+++ b/src/cobalt/bindings/mozjs/templates/callback-interface.cc.template
@@ -20,6 +20,7 @@
 #include "cobalt/script/logging_exception_state.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
 #include "cobalt/script/mozjs/mozjs_callback_interface.h"
+#include "cobalt/script/mozjs/util/exception_helpers.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 #include "third_party/mozjs/js/src/jscntxt.h"
 {% endblock includes %}
@@ -30,6 +31,7 @@
 using cobalt::script::mozjs::FromJSValue;
 using cobalt::script::mozjs::GetCallableForCallbackInterface;
 using cobalt::script::mozjs::ToJSValue;
+using cobalt::script::mozjs::util::GetExceptionString;
 {% endblock using_directives %}
 
 {% block implementation %}
@@ -90,7 +92,8 @@
       DCHECK(function);
       success = JS::Call(context_, this_value, function, kNumArguments, args,
                          return_value.address());
-      DLOG_IF(WARNING, !success) << "Exception in callback.";
+      DLOG_IF(WARNING, !success) << "Exception in callback: "
+                                 << GetExceptionString(context_);
 {% if overload.type != 'void' %}
       if (success) {
         LoggingExceptionState exception_state;
diff --git a/src/cobalt/bindings/mozjs/templates/interface.cc.template b/src/cobalt/bindings/mozjs/templates/interface.cc.template
index 3307b67..b92a526 100644
--- a/src/cobalt/bindings/mozjs/templates/interface.cc.template
+++ b/src/cobalt/bindings/mozjs/templates/interface.cc.template
@@ -126,7 +126,6 @@
 {% if named_property_getter %}
 bool IsSupportedNamedProperty(JSContext* context, JS::HandleObject object,
                               const std::string& property_name) {
-  TRACE_EVENT0("cobalt::bindings", "IsSupportedNamedProperty");
 {{ get_impl_class_instance(impl_class) }}
   return impl->CanQueryNamedProperty(property_name);
 }
@@ -215,7 +214,6 @@
 {% if indexed_property_getter %}
 bool IsSupportedIndexProperty(JSContext* context, JS::HandleObject object,
                               uint32_t index) {
-  TRACE_EVENT0("cobalt::bindings", "IsSupportedIndexProperty");
 {{ get_impl_class_instance(impl_class) }}
   return index < impl->length();
 }
@@ -232,7 +230,6 @@
 JSBool GetIndexedProperty(
     JSContext* context, JS::HandleObject object, JS::HandleId id,
     JS::MutableHandleValue vp) {
-  TRACE_EVENT0("cobalt::bindings", "GetIndexedProperty");
   JS::RootedValue id_value(context);
   if (!JS_IdToValue(context, id, id_value.address())) {
     NOTREACHED();
diff --git a/src/cobalt/browser/application.cc b/src/cobalt/browser/application.cc
index ffded5e..470eda6 100644
--- a/src/cobalt/browser/application.cc
+++ b/src/cobalt/browser/application.cc
@@ -20,6 +20,7 @@
 #include <vector>
 
 #include "base/command_line.h"
+#include "base/debug/trace_event.h"
 #include "base/lazy_instance.h"
 #include "base/logging.h"
 #include "base/path_service.h"
@@ -62,7 +63,11 @@
 
 namespace {
 const int kStatUpdatePeriodMs = 1000;
+#if defined(COBALT_BUILD_TYPE_GOLD)
+const int kLiteStatUpdatePeriodMs = 1000;
+#else
 const int kLiteStatUpdatePeriodMs = 16;
+#endif
 
 const char kDefaultURL[] = "https://www.youtube.com/tv";
 
@@ -320,6 +325,8 @@
         FilePath(FILE_PATH_LITERAL("timed_trace.json")), trace_duration);
   }
 
+  TRACE_EVENT0("cobalt::browser", "Application::Application()");
+
   DCHECK(MessageLoop::current());
   DCHECK_EQ(MessageLoop::TYPE_UI, MessageLoop::current()->type());
 
@@ -586,6 +593,7 @@
 }
 
 void Application::OnAccountEvent(const base::Event* event) {
+  TRACE_EVENT0("cobalt::browser", "Application::OnAccountEvent()");
   const account::AccountEvent* account_event =
       base::polymorphic_downcast<const account::AccountEvent*>(event);
   if (account_event->type() == account::AccountEvent::kSignedIn) {
@@ -600,6 +608,7 @@
 }
 
 void Application::OnNetworkEvent(const base::Event* event) {
+  TRACE_EVENT0("cobalt::browser", "Application::OnNetworkEvent()");
   DCHECK(network_event_thread_checker_.CalledOnValidThread());
   const network::NetworkEvent* network_event =
       base::polymorphic_downcast<const network::NetworkEvent*>(event);
@@ -620,6 +629,7 @@
 }
 
 void Application::OnApplicationEvent(const base::Event* event) {
+  TRACE_EVENT0("cobalt::browser", "Application::OnApplicationEvent()");
   DCHECK(application_event_thread_checker_.CalledOnValidThread());
   const system_window::ApplicationEvent* app_event =
       base::polymorphic_downcast<const system_window::ApplicationEvent*>(event);
@@ -651,6 +661,7 @@
 }
 
 void Application::OnDeepLinkEvent(const base::Event* event) {
+  TRACE_EVENT0("cobalt::browser", "Application::OnDeepLinkEvent()");
   const base::DeepLinkEvent* deep_link_event =
       base::polymorphic_downcast<const base::DeepLinkEvent*>(event);
   // TODO: Remove this when terminal application states are properly handled.
@@ -660,6 +671,7 @@
 }
 
 void Application::WebModuleRecreated() {
+  TRACE_EVENT0("cobalt::browser", "Application::WebModuleRecreated()");
 #if defined(ENABLE_WEBDRIVER)
   if (web_driver_module_) {
     web_driver_module_->OnWindowRecreated();
@@ -741,6 +753,7 @@
 }
 
 void Application::UpdatePeriodicStats() {
+  TRACE_EVENT0("cobalt::browser", "Application::UpdatePeriodicStats()");
 #if defined(__LB_SHELL__)
   bool memory_stats_updated = false;
 #if !defined(__LB_SHELL__FOR_RELEASE__)
diff --git a/src/cobalt/browser/browser_module.cc b/src/cobalt/browser/browser_module.cc
index e725572..9a730cc 100644
--- a/src/cobalt/browser/browser_module.cc
+++ b/src/cobalt/browser/browser_module.cc
@@ -168,11 +168,21 @@
       has_resumed_(true, false),
       will_quit_(false),
       suspended_(false) {
+  TRACE_EVENT0("cobalt::browser", "BrowserModule::BrowserModule()");
   // All allocations for media will be tracked by "Media" memory scope.
   {
     TRACK_MEMORY_SCOPE("Media");
+    math::Size output_size = renderer_module_.render_target()->GetSize();
+    if (system_window->GetVideoPixelRatio() != 1.f) {
+      output_size.set_width(
+          static_cast<int>(static_cast<float>(output_size.width()) *
+                           system_window->GetVideoPixelRatio()));
+      output_size.set_height(
+          static_cast<int>(static_cast<float>(output_size.height()) *
+                           system_window->GetVideoPixelRatio()));
+    }
     media_module_ = (media::MediaModule::Create(
-        system_window, renderer_module_.render_target()->GetSize(),
+        system_window, output_size,
         renderer_module_.pipeline()->GetResourceProvider(),
         options.media_module_options));
   }
@@ -225,6 +235,7 @@
 }
 
 void BrowserModule::Navigate(const GURL& url) {
+  TRACE_EVENT0("cobalt::browser", "BrowserModule::Navigate()");
   web_module_loaded_.Reset();
 
   // Always post this as a task in case this is being called from the WebModule.
@@ -233,6 +244,7 @@
 }
 
 void BrowserModule::Reload() {
+  TRACE_EVENT0("cobalt::browser", "BrowserModule::Reload()");
   DCHECK_EQ(MessageLoop::current(), self_message_loop_);
   DCHECK(web_module_);
   web_module_->ExecuteJavascript(
@@ -241,6 +253,7 @@
 }
 
 void BrowserModule::NavigateInternal(const GURL& url) {
+  TRACE_EVENT0("cobalt::browser", "BrowserModule::NavigateInternal()");
   DCHECK_EQ(MessageLoop::current(), self_message_loop_);
 
   // First try the registered handlers (e.g. for h5vcc://). If one of these
@@ -264,7 +277,7 @@
                        renderer_module_.pipeline()->GetResourceProvider(),
                        kLayoutMaxRefreshFrequencyInHz));
 
-#if defined(STARBOARD)
+#if defined(OS_STARBOARD)
 #if SB_HAS(1_CORE)
   // Wait until the splash screen is ready before loading the main web module.
   // This prevents starvation of the splash screen module and decoding of the
@@ -312,6 +325,7 @@
 }
 
 void BrowserModule::OnLoad() {
+  TRACE_EVENT0("cobalt::browser", "BrowserModule::OnLoad()");
   // Repost to our own message loop if necessary. This also prevents
   // asynchonrous access to this object by |web_module_| during destruction.
   if (MessageLoop::current() != self_message_loop_) {
@@ -325,6 +339,7 @@
 }
 
 bool BrowserModule::WaitForLoad(const base::TimeDelta& timeout) {
+  TRACE_EVENT0("cobalt::browser", "BrowserModule::WaitForLoad()");
   return web_module_loaded_.TimedWait(timeout);
 }
 
@@ -502,6 +517,7 @@
 }
 
 void BrowserModule::OnError(const GURL& url, const std::string& error) {
+  TRACE_EVENT0("cobalt::browser", "BrowserModule::OnError()");
   LOG(ERROR) << error;
   std::string url_string = "h5vcc://network-failure";
 
@@ -512,6 +528,7 @@
 }
 
 bool BrowserModule::FilterKeyEvent(const dom::KeyboardEvent::Data& event) {
+  TRACE_EVENT0("cobalt::browser", "BrowserModule::FilterKeyEvent()");
   // Check for hotkeys first. If it is a hotkey, no more processing is needed.
   if (!FilterKeyEventForHotkeys(event)) {
     return false;
@@ -577,7 +594,10 @@
   return false;
 }
 
-void BrowserModule::DestroySplashScreen() { splash_screen_.reset(NULL); }
+void BrowserModule::DestroySplashScreen() {
+  TRACE_EVENT0("cobalt::browser", "BrowserModule::DestroySplashScreen()");
+  splash_screen_.reset(NULL);
+}
 
 #if defined(ENABLE_WEBDRIVER)
 scoped_ptr<webdriver::SessionDriver> BrowserModule::CreateSessionDriver(
@@ -649,6 +669,7 @@
 }
 
 void BrowserModule::Suspend() {
+  TRACE_EVENT0("cobalt::browser", "BrowserModule::Suspend()");
   DCHECK_EQ(MessageLoop::current(), self_message_loop_);
   DCHECK(!suspended_);
 
@@ -691,6 +712,7 @@
 }
 
 void BrowserModule::Resume() {
+  TRACE_EVENT0("cobalt::browser", "BrowserModule::Resume()");
   DCHECK_EQ(MessageLoop::current(), self_message_loop_);
   DCHECK(suspended_);
 
@@ -721,6 +743,8 @@
 
 #if defined(OS_STARBOARD)
 void BrowserModule::OnRendererSubmissionRasterized() {
+  TRACE_EVENT0("cobalt::browser",
+               "BrowserModule::OnRendererSubmissionRasterized()");
   if (!is_rendered_) {
     // Hide the system splash screen when the first render has completed.
     is_rendered_ = true;
diff --git a/src/cobalt/browser/stack_size_constants.h b/src/cobalt/browser/stack_size_constants.h
index d700f4b..c4e62ea 100644
--- a/src/cobalt/browser/stack_size_constants.h
+++ b/src/cobalt/browser/stack_size_constants.h
@@ -24,8 +24,11 @@
 #if defined(COBALT_BUILD_TYPE_DEBUG)
   // Non-optimized builds require a bigger stack size.
   const size_t kBaseStackSize = 2 * 1024 * 1024;
+#elif defined(COBALT_BUILD_TYPE_DEVEL)
+  // Devel builds require a slightly bigger stack size.
+  const size_t kBaseStackSize = 448 * 1024;
 #else
-  const size_t kBaseStackSize = 256 * 1024;
+  const size_t kBaseStackSize = 384 * 1024;
 #endif
   const size_t kWebModuleStackSize =
       kBaseStackSize + base::kAsanAdditionalStackSize;
diff --git a/src/cobalt/browser/web_module.cc b/src/cobalt/browser/web_module.cc
index af93505..defb344 100644
--- a/src/cobalt/browser/web_module.cc
+++ b/src/cobalt/browser/web_module.cc
@@ -46,11 +46,11 @@
 
 namespace {
 
-#if defined(COBALT_RELEASE)
+#if defined(COBALT_BUILD_TYPE_GOLD)
 const int kPollerPeriodMs = 2000;
-#else   // #if defined(COBALT_RELEASE)
+#else   // #if defined(COBALT_BUILD_TYPE_GOLD)
 const int kPollerPeriodMs = 20;
-#endif  // #if defined(COBALT_RELEASE)
+#endif  // #if defined(COBALT_BUILD_TYPE_GOLD)
 
 // The maximum number of element depth in the DOM tree. Elements at a level
 // deeper than this could be discarded, and will not be rendered.
@@ -147,7 +147,11 @@
   void CreateDebugServerIfNull();
 #endif  // ENABLE_DEBUG_CONSOLE
 
-  void Suspend();
+  // Suspension of the WebModule is a two-part process since a message loop
+  // gap is needed in order to give a chance to handle loader callbacks
+  // that were initiated from a loader thread.
+  void SuspendLoaders();
+  void FinishSuspend();
   void Resume(render_tree::ResourceProvider* resource_provider);
 
  private:
@@ -618,21 +622,20 @@
   }
 }
 
-void WebModule::Impl::Suspend() {
-  TRACE_EVENT0("cobalt::browser", "WebModule::Impl::Suspend()");
-  DCHECK(resource_provider_);
+void WebModule::Impl::SuspendLoaders() {
+  TRACE_EVENT0("cobalt::browser", "WebModule::Impl::SuspendLoaders()");
 
   // Stop the generation of render trees.
   layout_manager_->Suspend();
 
-#if defined(ENABLE_DEBUG_CONSOLE)
-  // The debug overlay may be holding onto a render tree, clear that out.
-  debug_overlay_->ClearInput();
-#endif
-
   // Clear out the loader factory's resource provider, possibly aborting any
   // in-progress loads.
   loader_factory_->Suspend();
+}
+
+void WebModule::Impl::FinishSuspend() {
+  TRACE_EVENT0("cobalt::browser", "WebModule::Impl::FinishSuspend()");
+  DCHECK(resource_provider_);
 
   // Ensure the document is not holding onto any more image cached resources so
   // that they are eligible to be purged.
@@ -645,6 +648,11 @@
   image_cache_->Purge();
   remote_typeface_cache_->Purge();
 
+#if defined(ENABLE_DEBUG_CONSOLE)
+  // The debug overlay may be holding onto a render tree, clear that out.
+  debug_overlay_->ClearInput();
+#endif
+
   // Finally mark that we have no resource provider.
   resource_provider_ = NULL;
 }
@@ -877,16 +885,43 @@
 #endif  // defined(ENABLE_DEBUG_CONSOLE)
 
 void WebModule::Suspend() {
-  message_loop()->PostTask(
-      FROM_HERE,
-      base::Bind(&WebModule::Impl::Suspend, base::Unretained(impl_.get())));
+  TRACE_EVENT0("cobalt::browser", "WebModule::Suspend()");
 
-  base::WaitableEvent resource_provider_released(true, false);
-  message_loop()->PostTask(
-      FROM_HERE, base::Bind(&base::WaitableEvent::Signal,
-                            base::Unretained(&resource_provider_released)));
+  // Suspend() must only be called by a thread external from the WebModule
+  // thread.
+  DCHECK_NE(MessageLoop::current(), message_loop());
 
-  resource_provider_released.Wait();
+  base::WaitableEvent task_finished(false /* automatic reset */,
+                                    false /* initially unsignaled */);
+
+  // Suspension of the WebModule is orchestrated here in two phases.
+  // 1) Send a signal to suspend WebModule loader activity and cancel any
+  //    in-progress loads.  Since loading may occur from any thread, this may
+  //    result in cancel/completion callbacks being posted to message_loop().
+  message_loop()->PostTask(FROM_HERE,
+                           base::Bind(&WebModule::Impl::SuspendLoaders,
+                                      base::Unretained(impl_.get())));
+
+  // Wait for the suspension task to complete before proceeding.
+  message_loop()->PostTask(FROM_HERE,
+                           base::Bind(&base::WaitableEvent::Signal,
+                                      base::Unretained(&task_finished)));
+  task_finished.Wait();
+
+  // 2) Now append to the task queue a task to complete the suspension process.
+  //    Between 1 and 2, tasks may have been registered to handle resource load
+  //    completion events, and so this FinishSuspend task will be executed after
+  //    the load completions are all resolved.
+  message_loop()->PostTask(FROM_HERE,
+                           base::Bind(&WebModule::Impl::FinishSuspend,
+                                      base::Unretained(impl_.get())));
+
+  // Wait for suspension to fully complete on the WebModule thread before
+  // continuing.
+  message_loop()->PostTask(FROM_HERE,
+                           base::Bind(&base::WaitableEvent::Signal,
+                                      base::Unretained(&task_finished)));
+  task_finished.Wait();
 }
 
 void WebModule::Resume(render_tree::ResourceProvider* resource_provider) {
diff --git a/src/cobalt/build/build.id b/src/cobalt/build/build.id
index 1cb6aab..e0a264e 100644
--- a/src/cobalt/build/build.id
+++ b/src/cobalt/build/build.id
@@ -1 +1 @@
-15306
\ No newline at end of file
+16000
\ No newline at end of file
diff --git a/src/cobalt/build/config/base.gypi b/src/cobalt/build/config/base.gypi
index 314650b..53cc9b4 100644
--- a/src/cobalt/build/config/base.gypi
+++ b/src/cobalt/build/config/base.gypi
@@ -67,6 +67,13 @@
     # platform.
     'default_renderer_options_dependency%': '<(DEPTH)/cobalt/renderer/default_options_starboard.gyp:default_options',
 
+    # Allow throttling of the frame rate. This is expressed in terms of
+    # milliseconds and can be a floating point number. Keep in mind that
+    # swapping frames may take some additional processing time, so it may be
+    # better to specify a lower delay. For example, '33' instead of '33.33'
+    # for 30 Hz refresh.
+    'cobalt_minimum_frame_time_in_milliseconds%': '0',
+
     # The variables allow changing the target type on platforms where the
     # native code may require an additional packaging step (ex. Android).
     'gtest_target_type%': 'executable',
diff --git a/src/cobalt/css_parser/css_parser.gyp b/src/cobalt/css_parser/css_parser.gyp
index 185ee0b..32f9c0d 100644
--- a/src/cobalt/css_parser/css_parser.gyp
+++ b/src/cobalt/css_parser/css_parser.gyp
@@ -111,6 +111,7 @@
       'dependencies': [
         '<(DEPTH)/cobalt/base/base.gyp:base',
         '<(DEPTH)/cobalt/cssom/cssom.gyp:cssom',
+        '<(DEPTH)/nb/nb.gyp:nb',
         '<(DEPTH)/third_party/icu/icu.gyp:icuuc',
         'css_grammar',
       ],
diff --git a/src/cobalt/css_parser/parser.cc b/src/cobalt/css_parser/parser.cc
index 25f4d35..cb4fb84 100644
--- a/src/cobalt/css_parser/parser.cc
+++ b/src/cobalt/css_parser/parser.cc
@@ -85,6 +85,7 @@
 #include "cobalt/cssom/unicode_range_value.h"
 #include "cobalt/cssom/universal_selector.h"
 #include "cobalt/cssom/url_value.h"
+#include "nb/memory_scope.h"
 
 namespace cobalt {
 namespace css_parser {
@@ -254,18 +255,21 @@
       into_declaration_data_(NULL) {}
 
 scoped_refptr<cssom::CSSStyleSheet> ParserImpl::ParseStyleSheet() {
+  TRACK_MEMORY_SCOPE("CSS");
   scanner_.PrependToken(kStyleSheetEntryPointToken);
   return Parse() ? style_sheet_
                  : make_scoped_refptr(new cssom::CSSStyleSheet(css_parser_));
 }
 
 scoped_refptr<cssom::CSSRule> ParserImpl::ParseRule() {
+  TRACK_MEMORY_SCOPE("CSS");
   scanner_.PrependToken(kRuleEntryPointToken);
   return Parse() ? rule_ : NULL;
 }
 
 scoped_refptr<cssom::CSSDeclaredStyleData>
 ParserImpl::ParseStyleDeclarationList() {
+  TRACK_MEMORY_SCOPE("CSS");
   scanner_.PrependToken(kStyleDeclarationListEntryPointToken);
   return Parse() ? style_declaration_data_
                  : make_scoped_refptr(new cssom::CSSDeclaredStyleData());
@@ -273,6 +277,7 @@
 
 scoped_refptr<cssom::CSSFontFaceDeclarationData>
 ParserImpl::ParseFontFaceDeclarationList() {
+  TRACK_MEMORY_SCOPE("CSS");
   scanner_.PrependToken(kFontFaceDeclarationListEntryPointToken);
   return Parse() ? font_face_declaration_data_
                  : make_scoped_refptr(new cssom::CSSFontFaceDeclarationData());
@@ -290,6 +295,7 @@
 
 scoped_refptr<cssom::PropertyValue> ParserImpl::ParsePropertyValue(
     const std::string& property_name) {
+  TRACK_MEMORY_SCOPE("CSS");
   Token property_name_token;
   bool is_property_name_known =
       scanner_.DetectPropertyNameToken(property_name, &property_name_token);
@@ -312,6 +318,7 @@
 void ParserImpl::ParsePropertyIntoDeclarationData(
     const std::string& property_name,
     cssom::CSSDeclarationData* declaration_data) {
+  TRACK_MEMORY_SCOPE("CSS");
   Token property_name_token;
   bool is_property_name_known =
       scanner_.DetectPropertyNameToken(property_name, &property_name_token);
@@ -340,11 +347,13 @@
 }
 
 scoped_refptr<cssom::MediaList> ParserImpl::ParseMediaList() {
+  TRACK_MEMORY_SCOPE("CSS");
   scanner_.PrependToken(kMediaListEntryPointToken);
   return Parse() ? media_list_ : make_scoped_refptr(new cssom::MediaList());
 }
 
 scoped_refptr<cssom::MediaQuery> ParserImpl::ParseMediaQuery() {
+  TRACK_MEMORY_SCOPE("CSS");
   scanner_.PrependToken(kMediaQueryEntryPointToken);
   return Parse() ? media_query_ : make_scoped_refptr(new cssom::MediaQuery());
 }
@@ -364,6 +373,7 @@
 }
 
 bool ParserImpl::Parse() {
+  TRACK_MEMORY_SCOPE("CSS");
   // For more information on error codes
   // see http://www.gnu.org/software/bison/manual/html_node/Parser-Function.html
   TRACE_EVENT0("cobalt::css_parser", "ParseImpl::Parse");
diff --git a/src/cobalt/dom/media_source.cc b/src/cobalt/dom/media_source.cc
index 83bc8c0..9807b48 100644
--- a/src/cobalt/dom/media_source.cc
+++ b/src/cobalt/dom/media_source.cc
@@ -21,6 +21,7 @@
 #include <vector>
 
 #include "base/compiler_specific.h"
+#include "base/debug/trace_event.h"
 #include "base/hash_tables.h"
 #include "base/lazy_instance.h"
 #include "base/logging.h"
@@ -303,6 +304,8 @@
     SetReadyState(kReadyStateOpen);
   }
 
+  TRACE_EVENT1("media_stack", "MediaSource::Append()", "size", size);
+
   // If size is greater than kMaxAppendSize, we will append the data in multiple
   // small chunks with size less than or equal to kMaxAppendSize.  This can
   // avoid memory allocation spike as ChunkDemuxer may try to allocator memory
diff --git a/src/cobalt/layout/box.cc b/src/cobalt/layout/box.cc
index 4426498..a04ced7 100644
--- a/src/cobalt/layout/box.cc
+++ b/src/cobalt/layout/box.cc
@@ -16,6 +16,7 @@
 
 #include "cobalt/layout/box.h"
 
+#include <algorithm>
 #include <limits>
 
 #include "base/logging.h"
@@ -907,7 +908,7 @@
                       style->opacity().get())->value();
 
   if (opacity < 1.0f) {
-    filter_node_builder->opacity_filter.emplace(opacity);
+    filter_node_builder->opacity_filter.emplace(std::max(0.0f, opacity));
   } else {
     // If opacity is 1, then no opacity filter should be applied, so the
     // source render tree should appear fully opaque.
@@ -1155,7 +1156,7 @@
     FilterNode::Builder filter_node_builder(border_node);
 
     if (opacity < 1.0f) {
-      filter_node_builder.opacity_filter = OpacityFilter(opacity);
+      filter_node_builder.opacity_filter.emplace(std::max(0.0f, opacity));
     }
 
     scoped_refptr<FilterNode> filter_node = new FilterNode(filter_node_builder);
diff --git a/src/cobalt/layout_tests/layout_tests.cc b/src/cobalt/layout_tests/layout_tests.cc
index 18dccb1..38adb86 100644
--- a/src/cobalt/layout_tests/layout_tests.cc
+++ b/src/cobalt/layout_tests/layout_tests.cc
@@ -189,6 +189,11 @@
     AnimationTimingAPILayoutTests, LayoutTest,
     ::testing::ValuesIn(EnumerateLayoutTests("animation-timing")));
 
+// Problematic test cases found through cluster-fuzz.
+INSTANTIATE_TEST_CASE_P(
+    ClusterFuzzLayoutTests, LayoutTest,
+    ::testing::ValuesIn(EnumerateLayoutTests("cluster-fuzz")));
+
 // Disable on Windows until network stack is implemented.
 #if !defined(COBALT_WIN)
 // Content Security Policy test cases.
diff --git a/src/cobalt/layout_tests/testdata/cluster-fuzz/fuzz-222-expected.png b/src/cobalt/layout_tests/testdata/cluster-fuzz/fuzz-222-expected.png
new file mode 100644
index 0000000..f1b767f
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/cluster-fuzz/fuzz-222-expected.png
Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/cluster-fuzz/fuzz-222.html b/src/cobalt/layout_tests/testdata/cluster-fuzz/fuzz-222.html
new file mode 100644
index 0000000..9f6ed1a
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/cluster-fuzz/fuzz-222.html
@@ -0,0 +1,17 @@
+cm/000000086.jpg" target="_blank"><img src="./picm/000000086.jpg" width="277" style="border: 0px solid ;"></a>
+<div class="blockImageCaption"><br>�s�d�k�F�i�O�W�V�j�W�V�W�|�Q�P�W�W�i���j<br>�e�`�w�F�i�O�W�V�j�W�V�W�|�Q�V�V�P</p>
+<!--  -->
+<!-- /blockText --></div>
+<!--  -->
+<!-- /blockText --></div>
+<!-- /block2column2 --></div>
+<br class="blockEdge">
+<!-- /CB0200_4 --></div>
+>
+<!--  -->
+
+<!--  --><div class="blockImage">
+<!--  -->
+ class="blockImageCaption"><small></small></div>
+>
+<!-- 
\ No newline at end of file
diff --git a/src/cobalt/layout_tests/testdata/cluster-fuzz/layout_tests.txt b/src/cobalt/layout_tests/testdata/cluster-fuzz/layout_tests.txt
new file mode 100644
index 0000000..12a4567
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/cluster-fuzz/layout_tests.txt
@@ -0,0 +1 @@
+fuzz-222
\ No newline at end of file
diff --git a/src/cobalt/loader/embedded_resources/splash_screen.css b/src/cobalt/loader/embedded_resources/splash_screen.css
index 7602576..3cba6e4 100644
--- a/src/cobalt/loader/embedded_resources/splash_screen.css
+++ b/src/cobalt/loader/embedded_resources/splash_screen.css
@@ -22,13 +22,12 @@
   width: 100%;
 }
 
-@keyframes loadwait {
-  0% {opacity: 0}
-  100% {opacity: 1}
-}
-
 #spinner {
-  animation: loadwait 2s steps(1, end);
+  /* The spinner starts with display set to none, and JavaScript will set this
+     to 'block' after some time has passed, if the splash screen is still
+     visible. */
+  display: none;
+
   height: 5.33em;
   margin: 0 auto;
   position: relative;
diff --git a/src/cobalt/loader/embedded_resources/splash_screen.html b/src/cobalt/loader/embedded_resources/splash_screen.html
index 2a572ed..0e57e3b 100644
--- a/src/cobalt/loader/embedded_resources/splash_screen.html
+++ b/src/cobalt/loader/embedded_resources/splash_screen.html
@@ -3,8 +3,9 @@
 
 <head>
 <meta http-equiv="Content-Security-Policy" content="default-src 'none';
+    script-src h5vcc-embedded://*/splash_screen.js;
     style-src h5vcc-embedded://*/splash_screen.css;
-    img-src h5vcc-embedded://*/you_tube_logo.png">
+    img-src h5vcc-embedded://*/you_tube_logo.png;">
 <link rel="stylesheet" type="text/css" href="h5vcc-embedded://splash_screen.css">
 </head>
 
@@ -24,6 +25,8 @@
       <div class="dot" id="dot8"></div>
     </div>
   </div>
+  <script type="text/javascript" src="h5vcc-embedded://splash_screen.js">
+  </script>
 </body>
 
 </html>
diff --git a/src/cobalt/loader/embedded_resources/splash_screen.js b/src/cobalt/loader/embedded_resources/splash_screen.js
new file mode 100644
index 0000000..0d30edc
--- /dev/null
+++ b/src/cobalt/loader/embedded_resources/splash_screen.js
@@ -0,0 +1,5 @@
+  // Enable the spinner after 3 seconds have passed.
+  window.setTimeout(function() {
+    var spinner = document.getElementById('spinner');
+    spinner.style.display = 'block';
+  }, 3000);
diff --git a/src/cobalt/loader/image/image_decoder.cc b/src/cobalt/loader/image/image_decoder.cc
index 6fcf6ec..5a55b9c 100644
--- a/src/cobalt/loader/image/image_decoder.cc
+++ b/src/cobalt/loader/image/image_decoder.cc
@@ -99,6 +99,7 @@
       failure_callback_(failure_callback),
       error_callback_(error_callback),
       state_(kWaitingForHeader) {
+  TRACE_EVENT0("cobalt::loader::image", "ImageDecoder::ImageDecoder()");
   signature_cache_.position = 0;
 
   if (!resource_provider_) {
@@ -109,6 +110,7 @@
 LoadResponseType ImageDecoder::OnResponseStarted(
     Fetcher* fetcher, const scoped_refptr<net::HttpResponseHeaders>& headers) {
   UNREFERENCED_PARAMETER(fetcher);
+  TRACE_EVENT0("cobalt::loader::image", "ImageDecoder::OnResponseStarted()");
 
   if (state_ == kSuspended) {
     DLOG(WARNING) << __FUNCTION__ << "[" << this << "] while suspended.";
@@ -202,6 +204,7 @@
 }
 
 bool ImageDecoder::Suspend() {
+  TRACE_EVENT0("cobalt::loader::image", "ImageDecoder::Suspend()");
   if (state_ == kDecoding) {
     DCHECK(decoder_);
     decoder_.reset();
@@ -213,6 +216,7 @@
 }
 
 void ImageDecoder::Resume(render_tree::ResourceProvider* resource_provider) {
+  TRACE_EVENT0("cobalt::loader::image", "ImageDecoder::Resume()");
   if (state_ != kSuspended) {
     DCHECK_EQ(resource_provider_, resource_provider);
     return;
@@ -227,6 +231,7 @@
 }
 
 void ImageDecoder::DecodeChunkInternal(const uint8* input_bytes, size_t size) {
+  TRACE_EVENT0("cobalt::loader::image", "ImageDecoder::DecodeChunkInternal()");
   switch (state_) {
     case kWaitingForHeader: {
       size_t consumed_size = 0;
@@ -263,6 +268,8 @@
 bool ImageDecoder::InitializeInternalDecoder(const uint8* input_bytes,
                                              size_t size,
                                              size_t* consumed_size) {
+  TRACE_EVENT0("cobalt::loader::image",
+               "ImageDecoder::InitializeInternalDecoder()");
   const size_t index = signature_cache_.position;
   size_t fill_size = std::min(kLengthOfLongestSignature - index, size);
   memcpy(signature_cache_.data + index, input_bytes, fill_size);
diff --git a/src/cobalt/loader/image/image_decoder_starboard.cc b/src/cobalt/loader/image/image_decoder_starboard.cc
index 5a90442..1fdb7bf 100644
--- a/src/cobalt/loader/image/image_decoder_starboard.cc
+++ b/src/cobalt/loader/image/image_decoder_starboard.cc
@@ -38,17 +38,25 @@
       mime_type_(mime_type),
       format_(format),
       provider_(resource_provider->GetSbDecodeTargetProvider()),
-      target_(kSbDecodeTargetInvalid) {}
+      target_(kSbDecodeTargetInvalid) {
+  TRACE_EVENT0("cobalt::loader::image",
+               "ImageDecoderStarboard::ImageDecoderStarboard()");
+}
 
 ImageDecoderStarboard::~ImageDecoderStarboard() {}
 
 size_t ImageDecoderStarboard::DecodeChunkInternal(const uint8* data,
                                                   size_t input_byte) {
+  TRACE_EVENT0("cobalt::loader::image",
+               "ImageDecoderStarboard::DecodeChunkInternal()");
+
   buffer_.insert(buffer_.end(), data, data + input_byte);
   return input_byte;
 }
 
 void ImageDecoderStarboard::FinishInternal() {
+  TRACE_EVENT0("cobalt::loader::image",
+               "ImageDecoderStarboard::FinishInternal()");
   DCHECK(!buffer_.empty());
   DCHECK(SbImageIsDecodeSupported(mime_type_, format_));
   target_ =
diff --git a/src/cobalt/loader/image/jpeg_image_decoder.cc b/src/cobalt/loader/image/jpeg_image_decoder.cc
index 6fe1d91..29b99dc 100644
--- a/src/cobalt/loader/image/jpeg_image_decoder.cc
+++ b/src/cobalt/loader/image/jpeg_image_decoder.cc
@@ -84,6 +84,7 @@
 JPEGImageDecoder::JPEGImageDecoder(
     render_tree::ResourceProvider* resource_provider)
     : ImageDataDecoder(resource_provider) {
+  TRACE_EVENT0("cobalt::loader::image", "JPEGImageDecoder::JPEGImageDecoder()");
   memset(&info_, 0, sizeof(info_));
   memset(&source_manager_, 0, sizeof(source_manager_));
 
@@ -111,6 +112,8 @@
 
 size_t JPEGImageDecoder::DecodeChunkInternal(const uint8* data,
                                              size_t input_byte) {
+  TRACE_EVENT0("cobalt::loader::image",
+               "JPEGImageDecoder::DecodeChunkInternal()");
   // |client_data| is available for use by application.
   jmp_buf jump_buffer;
   info_.client_data = &jump_buffer;
@@ -175,6 +178,7 @@
 }
 
 bool JPEGImageDecoder::ReadHeader() {
+  TRACE_EVENT0("cobalt::loader::image", "JPEGImageDecoder::ReadHeader()");
   if (jpeg_read_header(&info_, true) == JPEG_SUSPENDED) {
     // Since |jpeg_read_header| doesn't have enough data, go back to the state
     // before reading the header.
@@ -189,6 +193,7 @@
 }
 
 bool JPEGImageDecoder::StartDecompress() {
+  TRACE_EVENT0("cobalt::loader::image", "JPEGImageDecoder::StartDecompress()");
   // jpeg_has_multiple_scans() returns TRUE if the incoming image file has more
   // than one scan.
   info_.buffered_image = jpeg_has_multiple_scans(&info_);
@@ -215,6 +220,8 @@
 // TODO: support displaying the low resolution image while decoding
 // the progressive JPEG.
 bool JPEGImageDecoder::DecodeProgressiveJPEG() {
+  TRACE_EVENT0("cobalt::loader::image",
+               "JPEGImageDecoder::DecodeProgressiveJPEG()");
   int status;
   do {
     // |jpeg_consume_input| decodes the input data as it arrives.
@@ -291,6 +298,8 @@
 }
 
 bool JPEGImageDecoder::ReadLines() {
+  TRACE_EVENT0("cobalt::loader::image", "JPEGImageDecoder::ReadLines()");
+
   // Creation of 2-D sample arrays which is for one row.
   // See the comments in jmemmgr.c.
   JSAMPARRAY buffer = (*info_.mem->alloc_sarray)(
diff --git a/src/cobalt/loader/image/png_image_decoder.cc b/src/cobalt/loader/image/png_image_decoder.cc
index e87eeb9..b09e637 100644
--- a/src/cobalt/loader/image/png_image_decoder.cc
+++ b/src/cobalt/loader/image/png_image_decoder.cc
@@ -16,6 +16,7 @@
 
 #include "cobalt/loader/image/png_image_decoder.h"
 
+#include "base/debug/trace_event.h"
 #include "base/logging.h"
 
 namespace cobalt {
@@ -72,6 +73,8 @@
       info_(NULL),
       has_alpha_(false),
       interlace_buffer_(0) {
+  TRACE_EVENT0("cobalt::loader::image", "PNGImageDecoder::PNGImageDecoder()");
+
   png_ = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, DecodingFailed,
                                 DecodingWarning);
   info_ = png_create_info_struct(png_);
@@ -80,6 +83,8 @@
 }
 
 size_t PNGImageDecoder::DecodeChunkInternal(const uint8* data, size_t size) {
+  TRACE_EVENT0("cobalt::loader::image",
+               "PNGImageDecoder::DecodeChunkInternal()");
   // int setjmp(jmp_buf env) saves the current environment (ths program state),
   // at some point of program execution, into a platform-specific data
   // structure (jmp_buf) that can be used at some later point of program
@@ -107,6 +112,7 @@
 }
 
 PNGImageDecoder::~PNGImageDecoder() {
+  TRACE_EVENT0("cobalt::loader::image", "PNGImageDecoder::~PNGImageDecoder()");
   // Both are created at the same time. So they should be both zero
   // or both non-zero. Use && here to be safer.
   if (png_ && info_) {
@@ -127,6 +133,7 @@
 // static
 void PNGImageDecoder::HeaderAvailable(png_structp png, png_infop info) {
   UNREFERENCED_PARAMETER(info);
+  TRACE_EVENT0("cobalt::loader::image", "PNGImageDecoder::~PNGImageDecoder()");
   PNGImageDecoder* decoder =
       static_cast<PNGImageDecoder*>(png_get_progressive_ptr(png));
   decoder->HeaderAvailableCallback();
@@ -146,12 +153,16 @@
 // static
 void PNGImageDecoder::DecodeDone(png_structp png, png_infop info) {
   UNREFERENCED_PARAMETER(info);
+  TRACE_EVENT0("cobalt::loader::image", "PNGImageDecoder::DecodeDone()");
+
   PNGImageDecoder* decoder =
       static_cast<PNGImageDecoder*>(png_get_progressive_ptr(png));
   decoder->DecodeDoneCallback();
 }
 
 void PNGImageDecoder::HeaderAvailableCallback() {
+  TRACE_EVENT0("cobalt::loader::image",
+               "PNGImageDecoder::HeaderAvailableCallback()");
   DCHECK_EQ(state(), kWaitingForHeader);
 
   png_uint_32 width = png_get_image_width(png_, info_);
diff --git a/src/cobalt/loader/image/webp_image_decoder.cc b/src/cobalt/loader/image/webp_image_decoder.cc
index 53f24eb..cff8594 100644
--- a/src/cobalt/loader/image/webp_image_decoder.cc
+++ b/src/cobalt/loader/image/webp_image_decoder.cc
@@ -16,6 +16,7 @@
 
 #include "cobalt/loader/image/webp_image_decoder.h"
 
+#include "base/debug/trace_event.h"
 #include "base/logging.h"
 
 namespace cobalt {
@@ -25,6 +26,7 @@
 WEBPImageDecoder::WEBPImageDecoder(
     render_tree::ResourceProvider* resource_provider)
     : ImageDataDecoder(resource_provider), internal_decoder_(NULL) {
+  TRACE_EVENT0("cobalt::loader::image", "WEBPImageDecoder::WEBPImageDecoder()");
   // Initialize the configuration as empty.
   WebPInitDecoderConfig(&config_);
   // Skip the in-loop filtering.
@@ -37,10 +39,16 @@
   config_.options.no_enhancement = 1;
 }
 
-WEBPImageDecoder::~WEBPImageDecoder() { DeleteInternalDecoder(); }
+WEBPImageDecoder::~WEBPImageDecoder() {
+  TRACE_EVENT0("cobalt::loader::image",
+               "WEBPImageDecoder::~WEBPImageDecoder()");
+  DeleteInternalDecoder();
+}
 
 size_t WEBPImageDecoder::DecodeChunkInternal(const uint8* data,
                                              size_t input_byte) {
+  TRACE_EVENT0("cobalt::loader::image",
+               "WEBPImageDecoder::DecodeChunkInternal()");
   const uint8* next_input_byte = data;
   size_t bytes_in_buffer = input_byte;
 
@@ -81,6 +89,7 @@
 
 bool WEBPImageDecoder::ReadHeader(const uint8* data, size_t size,
                                   bool* has_alpha) {
+  TRACE_EVENT0("cobalt::loader::image", "WEBPImageDecoder::ReadHeader()");
   // Retrieve features from the bitstream. The *features structure is filled
   // with information gathered from the bitstream.
   // Returns VP8_STATUS_OK when the features are successfully retrieved. Returns
@@ -105,6 +114,8 @@
 }
 
 bool WEBPImageDecoder::CreateInternalDecoder(bool has_alpha) {
+  TRACE_EVENT0("cobalt::loader::image",
+               "WEBPImageDecoder::CreateInternalDecoder()");
   config_.output.colorspace = has_alpha ? MODE_rgbA : MODE_RGBA;
   config_.output.u.RGBA.stride = image_data()->GetDescriptor().pitch_in_bytes;
   config_.output.u.RGBA.size =
@@ -127,6 +138,8 @@
 }
 
 void WEBPImageDecoder::DeleteInternalDecoder() {
+  TRACE_EVENT0("cobalt::loader::image",
+               "WEBPImageDecoder::DeleteInternalDecoder()");
   if (internal_decoder_) {
     // Deletes the WebPIDecoder object and associated memory. Must always be
     // called if WebPIDecode succeeded.
diff --git a/src/cobalt/loader/sync_loader.cc b/src/cobalt/loader/sync_loader.cc
index 1d0d116..7ceff82 100644
--- a/src/cobalt/loader/sync_loader.cc
+++ b/src/cobalt/loader/sync_loader.cc
@@ -18,6 +18,7 @@
 
 #include "base/bind.h"
 #include "base/compiler_specific.h"
+#include "base/debug/trace_event.h"
 #include "base/synchronization/waitable_event.h"
 
 namespace cobalt {
@@ -117,6 +118,7 @@
     base::Callback<scoped_ptr<Fetcher>(Fetcher::Handler*)> fetcher_creator,
     base::Callback<scoped_ptr<Decoder>()> decoder_creator,
     base::Callback<void(const std::string&)> error_callback) {
+  TRACE_EVENT0("cobalt::loader", "LoadSynchronously()");
   DCHECK(message_loop);
   DCHECK(!error_callback.is_null());
 
diff --git a/src/cobalt/math/cubic_bezier.cc b/src/cobalt/math/cubic_bezier.cc
index 17c8368..51b5df0 100644
--- a/src/cobalt/math/cubic_bezier.cc
+++ b/src/cobalt/math/cubic_bezier.cc
@@ -66,8 +66,10 @@
   }
 
   // We should have terminated the above loop because we got close to x, not
-  // because we exceeded MAX_STEPS. Do a DCHECK here to confirm.
-  DCHECK_GT(kBezierEpsilon, std::abs(eval_bezier(x1, x2, t) - x));
+  // because we exceeded MAX_STEPS. Warn if this is not the case.
+  if (std::abs(eval_bezier(x1, x2, t) - x) > kBezierEpsilon) {
+    DLOG(WARNING) << "Notable error detected in bezier evaluation.";
+  }
 
   return t;
 }
diff --git a/src/cobalt/media/media.gyp b/src/cobalt/media/media.gyp
index 70c6929..ed7dc27 100644
--- a/src/cobalt/media/media.gyp
+++ b/src/cobalt/media/media.gyp
@@ -35,6 +35,7 @@
       'dependencies': [
         '<(DEPTH)/cobalt/network/network.gyp:network',
         '<(DEPTH)/media/media.gyp:media',
+        '<(DEPTH)/nb/nb.gyp:nb',
       ],
       'export_dependent_settings': [
         '<(DEPTH)/media/media.gyp:media',
@@ -46,9 +47,6 @@
             'shell_media_platform_<(sb_media_platform).cc',
             'shell_media_platform_<(sb_media_platform).h',
           ],
-          'dependencies': [
-            '<(DEPTH)/nb/nb.gyp:nb',
-          ],
         }],
         ['OS=="starboard" and sb_media_platform == "ps4"', {
           'sources': [
@@ -72,9 +70,6 @@
             'shell_media_platform_ps3.cc',
             'shell_media_platform_ps3.h',
           ],
-          'dependencies': [
-            '<(DEPTH)/nb/nb.gyp:nb',
-          ],
         }],
       ],
     },
diff --git a/src/cobalt/renderer/backend/egl/display.cc b/src/cobalt/renderer/backend/egl/display.cc
index dc325c7..c294168 100644
--- a/src/cobalt/renderer/backend/egl/display.cc
+++ b/src/cobalt/renderer/backend/egl/display.cc
@@ -54,6 +54,16 @@
   surface_ = eglCreateWindowSurface(display_, config_, native_window_, NULL);
   CHECK_EQ(EGL_SUCCESS, eglGetError());
 
+  // Configure the surface to preserve contents on swap.
+  EGLBoolean surface_attrib_set =
+      eglSurfaceAttrib(display_, surface_,
+                       EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED);
+  // NOTE: Must check eglGetError() to clear any error flags and also check
+  // the return value of eglSurfaceAttrib since some implementations may not
+  // set the error condition.
+  content_preserved_on_swap_ =
+      eglGetError() == EGL_SUCCESS && surface_attrib_set == EGL_TRUE;
+
   // Query and cache information about the surface now that we have created it.
   EGLint egl_surface_width;
   EGLint egl_surface_height;
diff --git a/src/cobalt/renderer/backend/egl/graphics_system.cc b/src/cobalt/renderer/backend/egl/graphics_system.cc
index 16b5104..d8895bd 100644
--- a/src/cobalt/renderer/backend/egl/graphics_system.cc
+++ b/src/cobalt/renderer/backend/egl/graphics_system.cc
@@ -64,23 +64,35 @@
 
   // Setup our configuration to support RGBA and compatibility with PBuffer
   // objects (for offscreen rendering).
-  EGLint const attribute_list[] = {EGL_RED_SIZE,
-                                   8,
-                                   EGL_GREEN_SIZE,
-                                   8,
-                                   EGL_BLUE_SIZE,
-                                   8,
-                                   EGL_ALPHA_SIZE,
-                                   8,
-                                   EGL_SURFACE_TYPE,
-                                   EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
-                                   EGL_BIND_TO_TEXTURE_RGBA,
-                                   EGL_TRUE,
-                                   EGL_NONE};
+  EGLint attribute_list[] = {EGL_SURFACE_TYPE,    // this must be first
+                             EGL_WINDOW_BIT | EGL_PBUFFER_BIT |
+                                EGL_SWAP_BEHAVIOR_PRESERVED_BIT,
+                             EGL_RED_SIZE,
+                             8,
+                             EGL_GREEN_SIZE,
+                             8,
+                             EGL_BLUE_SIZE,
+                             8,
+                             EGL_ALPHA_SIZE,
+                             8,
+                             EGL_BIND_TO_TEXTURE_RGBA,
+                             EGL_TRUE,
+                             EGL_NONE};
+
+  // Try to allow preservation of the frame contents between swap calls --
+  // this will allow rendering of only parts of the frame that have changed.
+  DCHECK_EQ(EGL_SURFACE_TYPE, attribute_list[0]);
+  EGLint& surface_type_value = attribute_list[1];
 
   EGLint num_configs;
-  EGL_CALL(
-      eglChooseConfig(display_, attribute_list, &config_, 1, &num_configs));
+  eglChooseConfig(display_, attribute_list, &config_, 1, &num_configs);
+  if (eglGetError() != EGL_SUCCESS || num_configs == 0) {
+    // Swap buffer preservation may not be supported. Try to find a config
+    // without the feature.
+    surface_type_value &= ~EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
+    EGL_CALL(
+        eglChooseConfig(display_, attribute_list, &config_, 1, &num_configs));
+  }
   DCHECK_EQ(1, num_configs);
 
 #if defined(GLES3_SUPPORTED)
diff --git a/src/cobalt/renderer/backend/egl/render_target.h b/src/cobalt/renderer/backend/egl/render_target.h
index d88c385..9256372 100644
--- a/src/cobalt/renderer/backend/egl/render_target.h
+++ b/src/cobalt/renderer/backend/egl/render_target.h
@@ -27,7 +27,11 @@
 
 class RenderTargetEGL : public RenderTarget {
  public:
-  RenderTargetEGL() : swap_count_(0), has_been_made_current_(false) {}
+  RenderTargetEGL()
+      : swap_count_(0)
+      , has_been_made_current_(false)
+      , content_preserved_on_swap_(false)
+  {}
 
   // An EGLSurface is needed for the EGL function eglMakeCurrent() which
   // associates a render target with a rendering context.
@@ -40,6 +44,10 @@
 
   virtual bool IsWindowRenderTarget() const { return false; }
 
+  // Returns whether the render target contents are preserved after the
+  // target has been displayed via eglSwapBuffers().
+  bool IsContentPreservedOnSwap() const { return content_preserved_on_swap_; }
+
   int64 swap_count() { return swap_count_; }
   void increment_swap_count() { ++swap_count_; }
 
@@ -51,6 +59,7 @@
 
   int64 swap_count_;
   bool has_been_made_current_;
+  bool content_preserved_on_swap_;
 };
 
 }  // namespace backend
diff --git a/src/cobalt/renderer/frame_rate_throttler.cc b/src/cobalt/renderer/frame_rate_throttler.cc
new file mode 100644
index 0000000..20d662e
--- /dev/null
+++ b/src/cobalt/renderer/frame_rate_throttler.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.
+ */
+
+#include "cobalt/renderer/frame_rate_throttler.h"
+
+#include "base/threading/platform_thread.h"
+
+namespace cobalt {
+namespace renderer {
+
+void FrameRateThrottler::BeginInterval() {
+  if (COBALT_MINIMUM_FRAME_TIME_IN_MILLISECONDS > 0) {
+    begin_time_ = base::TimeTicks::HighResNow();
+  }
+}
+
+void FrameRateThrottler::EndInterval() {
+  // Throttle presentation of new frames if a minimum frame time is specified.
+  if (COBALT_MINIMUM_FRAME_TIME_IN_MILLISECONDS > 0) {
+    if (!begin_time_.is_null()) {
+      base::TimeDelta elapsed = base::TimeTicks::HighResNow() - begin_time_;
+      base::TimeDelta wait_time =
+          base::TimeDelta::FromMillisecondsD(
+              COBALT_MINIMUM_FRAME_TIME_IN_MILLISECONDS) -
+          elapsed;
+      if (wait_time > base::TimeDelta::FromMicroseconds(0)) {
+        base::PlatformThread::Sleep(wait_time);
+      }
+    }
+  }
+}
+
+}  // namespace renderer
+}  // namespace cobalt
diff --git a/src/cobalt/renderer/frame_rate_throttler.h b/src/cobalt/renderer/frame_rate_throttler.h
new file mode 100644
index 0000000..6af2be7
--- /dev/null
+++ b/src/cobalt/renderer/frame_rate_throttler.h
@@ -0,0 +1,44 @@
+/*
+ * 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_RENDERER_FRAME_RATE_THROTTLER_H_
+#define COBALT_RENDERER_FRAME_RATE_THROTTLER_H_
+
+#include "base/time.h"
+
+namespace cobalt {
+namespace renderer {
+
+// The FrameRateThrottler is used to enforce a minimum frame time. The
+// rasterizer should call the provided hooks just before and after submitting
+// a new frame. This can be used to throttle the frame rate (to 30 Hz for
+// example) when the presentation interval cannot be specified.
+class FrameRateThrottler {
+ public:
+  // To be called just after submitting a new frame.
+  void BeginInterval();
+
+  // To be called just before submitting a new frame.
+  void EndInterval();
+
+ private:
+  base::TimeTicks begin_time_;
+};
+
+}  // namespace renderer
+}  // namespace cobalt
+
+#endif  // COBALT_RENDERER_FRAME_RATE_THROTTLER_H_
diff --git a/src/cobalt/renderer/pipeline.cc b/src/cobalt/renderer/pipeline.cc
index 0056361..58d850b 100644
--- a/src/cobalt/renderer/pipeline.cc
+++ b/src/cobalt/renderer/pipeline.cc
@@ -74,9 +74,6 @@
       submission_disposal_thread_("Rasterizer Submission Disposal"),
       submit_even_if_render_tree_is_unchanged_(
           submit_even_if_render_tree_is_unchanged),
-      rasterize_current_tree_interval_timer_(
-          "Renderer.Rasterize.Interval",
-          kRasterizeCurrentTreeTimerTimeIntervalInMs),
       rasterize_current_tree_timer_("Renderer.Rasterize.Duration",
                                     kRasterizeCurrentTreeTimerTimeIntervalInMs)
 #if defined(ENABLE_DEBUG_CONSOLE)
@@ -239,7 +236,6 @@
     return;
   }
 
-  rasterize_current_tree_interval_timer_.Start(now);
   rasterize_current_tree_timer_.Start(now);
 
   // Rasterize the last submitted render tree.
diff --git a/src/cobalt/renderer/pipeline.h b/src/cobalt/renderer/pipeline.h
index 3b96cc3..d3a2e96 100644
--- a/src/cobalt/renderer/pipeline.h
+++ b/src/cobalt/renderer/pipeline.h
@@ -185,10 +185,8 @@
   // The submission time used during the last render tree render.
   base::optional<base::TimeDelta> last_render_time_;
 
-  // Timers for tracking how frequently |RasterizeCurrentTree| is called and
-  // the amount of time spent in |RasterizeCurrentTree| each call.
-  base::CValTimeIntervalTimer<base::CValPublic>
-      rasterize_current_tree_interval_timer_;
+  // Timer tracking the amount of time spent in |RasterizeCurrentTree| each
+  // call.
   base::CValTimeIntervalTimer<base::CValPublic> rasterize_current_tree_timer_;
 
 #if defined(ENABLE_DEBUG_CONSOLE)
diff --git a/src/cobalt/renderer/rasterizer/blitter/cached_software_rasterizer.cc b/src/cobalt/renderer/rasterizer/blitter/cached_software_rasterizer.cc
index bcb25db..5e65c9c 100644
--- a/src/cobalt/renderer/rasterizer/blitter/cached_software_rasterizer.cc
+++ b/src/cobalt/renderer/rasterizer/blitter/cached_software_rasterizer.cc
@@ -117,7 +117,7 @@
       surface_map_.erase(found);
       surface_map_.insert(to_insert);
 
-      cache_frame_usage_ += found->second.GetEstimatedMemoryUsage();
+      cache_frame_usage_ += to_insert.second.GetEstimatedMemoryUsage();
 
       return to_insert.second;
     }
diff --git a/src/cobalt/renderer/rasterizer/blitter/hardware_rasterizer.cc b/src/cobalt/renderer/rasterizer/blitter/hardware_rasterizer.cc
index 7c9304e..cfca7ab 100644
--- a/src/cobalt/renderer/rasterizer/blitter/hardware_rasterizer.cc
+++ b/src/cobalt/renderer/rasterizer/blitter/hardware_rasterizer.cc
@@ -26,6 +26,7 @@
 #include "cobalt/render_tree/resource_provider_stub.h"
 #include "cobalt/renderer/backend/blitter/graphics_context.h"
 #include "cobalt/renderer/backend/blitter/render_target.h"
+#include "cobalt/renderer/frame_rate_throttler.h"
 #include "cobalt/renderer/rasterizer/blitter/cached_software_rasterizer.h"
 #include "cobalt/renderer/rasterizer/blitter/render_state.h"
 #include "cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.h"
@@ -80,6 +81,8 @@
 
   CachedSoftwareRasterizer software_surface_cache_;
 
+  FrameRateThrottler frame_rate_throttler_;
+
 #if defined(ENABLE_DEBUG_CONSOLE)
   // Debug command to toggle cache highlights to help visualize which nodes
   // are being cached.
@@ -219,7 +222,9 @@
                                 SbBlitterMakeRect(0, 0, width, height),
                                 SbBlitterMakeRect(0, 0, width, height)));
   CHECK(SbBlitterFlushContext(context));
+  frame_rate_throttler_.EndInterval();
   render_target_blitter->Flip();
+  frame_rate_throttler_.BeginInterval();
 
   ++submit_count_;
 }
diff --git a/src/cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.cc b/src/cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.cc
index 8fc3821..47dcf43 100644
--- a/src/cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.cc
+++ b/src/cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.cc
@@ -17,6 +17,7 @@
 #include "cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.h"
 
 #include "base/bind.h"
+#include "base/debug/trace_event.h"
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/math/matrix3_f.h"
 #include "cobalt/math/rect.h"
@@ -33,6 +34,17 @@
 
 #if SB_HAS(BLITTER)
 
+// This define exists so that developers can quickly toggle it temporarily and
+// obtain trace results for the render tree visit process here.  In general
+// though it slows down tracing too much to leave it enabled.
+#define ENABLE_RENDER_TREE_VISITOR_TRACING 0
+
+#if ENABLE_RENDER_TREE_VISITOR_TRACING
+#define TRACE_EVENT0_IF_ENABLED(x) TRACE_EVENT0("cobalt::renderer", x)
+#else
+#define TRACE_EVENT0_IF_ENABLED(x)
+#endif
+
 namespace cobalt {
 namespace renderer {
 namespace rasterizer {
@@ -78,6 +90,8 @@
 
 void RenderTreeNodeVisitor::Visit(
     render_tree::CompositionNode* composition_node) {
+  TRACE_EVENT0_IF_ENABLED("Visit(CompositionNode)");
+
   const render_tree::CompositionNode::Children& children =
       composition_node->data().children();
 
@@ -119,6 +133,8 @@
 }  // namespace
 
 void RenderTreeNodeVisitor::Visit(render_tree::FilterNode* filter_node) {
+  TRACE_EVENT0_IF_ENABLED("Visit(FilterNode)");
+
   if (filter_node->data().blur_filter) {
     // The Starboard Blitter API does not support blur filters, so we fallback
     // to software for this.
@@ -193,6 +209,8 @@
 }
 
 void RenderTreeNodeVisitor::Visit(render_tree::ImageNode* image_node) {
+  TRACE_EVENT0_IF_ENABLED("Visit(ImageNode)");
+
   // All Blitter API images derive from skia::Image (so that they can be
   // compatible with the Skia software renderer), so we start here by casting
   // to skia::Image.
@@ -252,6 +270,8 @@
 
 void RenderTreeNodeVisitor::Visit(
     render_tree::MatrixTransformNode* matrix_transform_node) {
+  TRACE_EVENT0_IF_ENABLED("Visit(MatrixTransformNode)");
+
   const Matrix3F& transform = matrix_transform_node->data().transform;
 
   if (transform.Get(1, 0) != 0 || transform.Get(0, 1) != 0 ||
@@ -276,20 +296,16 @@
 
 void RenderTreeNodeVisitor::Visit(
     render_tree::PunchThroughVideoNode* punch_through_video_node) {
+  TRACE_EVENT0_IF_ENABLED("Visit(PunchThroughVideoNode)");
+
   SbBlitterRect blitter_rect =
       RectFToBlitterRect(render_state_.transform.TransformRect(
           punch_through_video_node->data().rect));
 
-  if (punch_through_video_node->data().set_bounds_cb.is_null()) {
-    return;
-  }
-  bool render_punch_through =
-      punch_through_video_node->data().set_bounds_cb.Run(
-          math::Rect(blitter_rect.x, blitter_rect.y, blitter_rect.width,
-                     blitter_rect.height));
-  if (!render_punch_through) {
-    return;
-  }
+  punch_through_video_node->data().set_bounds_cb.Run(
+      math::Rect(blitter_rect.x, blitter_rect.y, blitter_rect.width,
+                 blitter_rect.height));
+
   SbBlitterSetColor(context_, SbBlitterColorFromRGBA(0, 0, 0, 0));
   SbBlitterSetBlending(context_, false);
   SbBlitterFillRect(context_, blitter_rect);
@@ -355,6 +371,8 @@
 }  // namespace
 
 void RenderTreeNodeVisitor::Visit(render_tree::RectNode* rect_node) {
+  TRACE_EVENT0_IF_ENABLED("Visit(RectNode)");
+
   if (rect_node->data().rounded_corners) {
     // We can't render rounded corners through the Blitter API.
     RenderWithSoftwareRenderer(rect_node);
@@ -436,15 +454,20 @@
 
 void RenderTreeNodeVisitor::Visit(
     render_tree::RectShadowNode* rect_shadow_node) {
+  TRACE_EVENT0_IF_ENABLED("Visit(RectShadowNode)");
+
   RenderWithSoftwareRenderer(rect_shadow_node);
 }
 
 void RenderTreeNodeVisitor::Visit(render_tree::TextNode* text_node) {
+  TRACE_EVENT0_IF_ENABLED("Visit(TextNode)");
+
   RenderWithSoftwareRenderer(text_node);
 }
 
 void RenderTreeNodeVisitor::RenderWithSoftwareRenderer(
     render_tree::Node* node) {
+  TRACE_EVENT0("cobalt::renderer", "RenderWithSoftwareRenderer()");
   CachedSoftwareRasterizer::SurfaceReference software_surface_reference(
       software_surface_cache_, node, render_state_.transform);
   CachedSoftwareRasterizer::Surface software_surface =
@@ -483,6 +506,7 @@
   } else  // NOLINT(readability/braces)
 #endif    // defined(ENABLE_DEBUG_CONSOLE)
   {
+    TRACE_EVENT0("cobalt::renderer", "SbBlitterBlitRectToRect()");
     SbBlitterBlitRectToRect(
         context_, software_surface.surface,
         SbBlitterMakeRect(
@@ -494,6 +518,8 @@
 
 scoped_ptr<RenderTreeNodeVisitor::OffscreenRender>
 RenderTreeNodeVisitor::RenderToOffscreenSurface(render_tree::Node* node) {
+  TRACE_EVENT0_IF_ENABLED("RenderToOffscreenSurface()");
+
   common::OffscreenRenderCoordinateMapping coord_mapping =
       common::GetOffscreenRenderCoordinateMapping(
           node->GetBounds(), render_state_.transform.ToMatrix(),
diff --git a/src/cobalt/renderer/rasterizer/blitter/software_rasterizer.cc b/src/cobalt/renderer/rasterizer/blitter/software_rasterizer.cc
index 6622fbc..f96d931 100644
--- a/src/cobalt/renderer/rasterizer/blitter/software_rasterizer.cc
+++ b/src/cobalt/renderer/rasterizer/blitter/software_rasterizer.cc
@@ -95,7 +95,9 @@
 
   SbBlitterDestroySurface(surface);
 
+  frame_rate_throttler_.EndInterval();
   render_target_blitter->Flip();
+  frame_rate_throttler_.BeginInterval();
 }
 
 render_tree::ResourceProvider* SoftwareRasterizer::GetResourceProvider() {
diff --git a/src/cobalt/renderer/rasterizer/blitter/software_rasterizer.h b/src/cobalt/renderer/rasterizer/blitter/software_rasterizer.h
index 646f3c4..04aa2ac 100644
--- a/src/cobalt/renderer/rasterizer/blitter/software_rasterizer.h
+++ b/src/cobalt/renderer/rasterizer/blitter/software_rasterizer.h
@@ -26,6 +26,7 @@
 #include "cobalt/renderer/backend/blitter/graphics_context.h"
 #include "cobalt/renderer/backend/graphics_context.h"
 #include "cobalt/renderer/backend/render_target.h"
+#include "cobalt/renderer/frame_rate_throttler.h"
 #include "cobalt/renderer/rasterizer/rasterizer.h"
 #include "cobalt/renderer/rasterizer/skia/software_rasterizer.h"
 
@@ -51,6 +52,7 @@
  private:
   backend::GraphicsContextBlitter* context_;
   skia::SoftwareRasterizer skia_rasterizer_;
+  FrameRateThrottler frame_rate_throttler_;
 };
 
 }  // namespace blitter
diff --git a/src/cobalt/renderer/rasterizer/egl/software_rasterizer.cc b/src/cobalt/renderer/rasterizer/egl/software_rasterizer.cc
index 97fcc63..8798b04 100644
--- a/src/cobalt/renderer/rasterizer/egl/software_rasterizer.cc
+++ b/src/cobalt/renderer/rasterizer/egl/software_rasterizer.cc
@@ -92,7 +92,9 @@
       context_, render_target_egl);
 
   context_->Blit(output_texture->gl_handle(), 0, 0, width, height);
+  frame_rate_throttler_.EndInterval();
   context_->SwapBuffers(render_target_egl);
+  frame_rate_throttler_.BeginInterval();
 }
 
 render_tree::ResourceProvider* SoftwareRasterizer::GetResourceProvider() {
diff --git a/src/cobalt/renderer/rasterizer/egl/software_rasterizer.h b/src/cobalt/renderer/rasterizer/egl/software_rasterizer.h
index 8ae5e84..479ce7e 100644
--- a/src/cobalt/renderer/rasterizer/egl/software_rasterizer.h
+++ b/src/cobalt/renderer/rasterizer/egl/software_rasterizer.h
@@ -21,6 +21,7 @@
 #include "cobalt/render_tree/resource_provider.h"
 #include "cobalt/renderer/backend/graphics_context.h"
 #include "cobalt/renderer/backend/render_target.h"
+#include "cobalt/renderer/frame_rate_throttler.h"
 #include "cobalt/renderer/rasterizer/rasterizer.h"
 #include "cobalt/renderer/rasterizer/skia/software_rasterizer.h"
 
@@ -51,6 +52,7 @@
  private:
   backend::GraphicsContextEGL* context_;
   skia::SoftwareRasterizer skia_rasterizer_;
+  FrameRateThrottler frame_rate_throttler_;
 };
 
 }  // namespace egl
diff --git a/src/cobalt/renderer/rasterizer/pixel_test.cc b/src/cobalt/renderer/rasterizer/pixel_test.cc
index 2fd11a4..68e4c7a 100644
--- a/src/cobalt/renderer/rasterizer/pixel_test.cc
+++ b/src/cobalt/renderer/rasterizer/pixel_test.cc
@@ -2802,8 +2802,8 @@
       RoundedCorners(50, 50)));
 }
 
-// If SetBoundsCB() returns false, the PunchThroughVideoNode should have no
-// effect.
+// PunchThroughVideoNode should trigger the painting of a solid rectangle with
+// RGBA(0, 0, 0, 0) regardless of whether SetBoundsCB returns true or false.
 TEST_F(PixelTest, PunchThroughVideoNodePunchesThroughSetBoundsCBReturnsFalse) {
   CompositionNode::Builder builder;
   builder.AddChild(new RectNode(RectF(25, 25, 150, 150),
@@ -2816,8 +2816,6 @@
   TestTree(new CompositionNode(builder.Pass()));
 }
 
-// If SetBoundsCB() returns true, the PunchThroughVideoNode should trigger the
-// painting of a solid rectangle with RGBA(0, 0, 0, 0).
 TEST_F(PixelTest, PunchThroughVideoNodePunchesThroughSetBoundsCBReturnsTrue) {
   CompositionNode::Builder builder;
   builder.AddChild(new RectNode(RectF(25, 25, 150, 150),
diff --git a/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.cc b/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.cc
index c3e2a0d..2ea8e6e 100644
--- a/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.cc
+++ b/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.cc
@@ -20,6 +20,8 @@
 
 #include "base/debug/trace_event.h"
 #include "cobalt/renderer/backend/egl/graphics_context.h"
+#include "cobalt/renderer/backend/egl/graphics_system.h"
+#include "cobalt/renderer/frame_rate_throttler.h"
 #include "cobalt/renderer/rasterizer/common/surface_cache.h"
 #include "cobalt/renderer/rasterizer/skia/cobalt_skia_type_conversions.h"
 #include "cobalt/renderer/rasterizer/skia/hardware_resource_provider.h"
@@ -85,6 +87,8 @@
 
   base::optional<SurfaceCacheDelegate> surface_cache_delegate_;
   base::optional<common::SurfaceCache> surface_cache_;
+
+  FrameRateThrottler frame_rate_throttler_;
 };
 
 namespace {
@@ -231,6 +235,13 @@
 
   if (options.flags & Rasterizer::kSubmitFlags_Clear) {
     canvas->clear(SkColorSetARGB(0, 0, 0, 0));
+  } else if (options.dirty) {
+    // Only a portion of the display is dirty. Reuse the previous frame
+    // if possible.
+    if (render_target_egl->IsContentPreservedOnSwap() &&
+        render_target_egl->swap_count() >= 3) {
+      canvas->clipRect(CobaltRectFToSkiaRect(*options.dirty));
+    }
   }
 
   {
@@ -254,7 +265,9 @@
     canvas->flush();
   }
 
+  frame_rate_throttler_.EndInterval();
   graphics_context_->SwapBuffers(render_target_egl);
+  frame_rate_throttler_.BeginInterval();
   canvas->restore();
 }
 
diff --git a/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.cc b/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.cc
index a17b893..195b6fb 100644
--- a/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.cc
+++ b/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.cc
@@ -177,14 +177,13 @@
   SkFontMgr_Cobalt* font_manager =
       base::polymorphic_downcast<SkFontMgr_Cobalt*>(font_manager_.get());
 
-  SkTypeface* typeface = font_manager->matchFaceNameOnlyIfFound(font_face_name);
-  SkiaTypeface* skia_type_face = NULL;
+  SkTypeface* typeface = font_manager->matchFaceName(font_face_name);
   if (typeface != NULL) {
     SkAutoTUnref<SkTypeface> typeface_unref_helper(typeface);
-    skia_type_face = new SkiaTypeface(typeface);
+    return scoped_refptr<render_tree::Typeface>(new SkiaTypeface(typeface));
   }
 
-  return scoped_refptr<render_tree::Typeface>(skia_type_face);
+  return NULL;
 }
 
 scoped_refptr<render_tree::Typeface>
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 9e2116d..fd5dfd9 100644
--- a/src/cobalt/renderer/rasterizer/skia/render_tree_node_visitor.cc
+++ b/src/cobalt/renderer/rasterizer/skia/render_tree_node_visitor.cc
@@ -737,18 +737,11 @@
   SkRect sk_rect_transformed;
   total_matrix.mapRect(&sk_rect_transformed, sk_rect);
 
-  if (punch_through_video_node->data().set_bounds_cb.is_null()) {
-    return;
-  }
-  bool render_punch_through =
-      punch_through_video_node->data().set_bounds_cb.Run(
-          math::Rect(static_cast<int>(sk_rect_transformed.x()),
-                     static_cast<int>(sk_rect_transformed.y()),
-                     static_cast<int>(sk_rect_transformed.width()),
-                     static_cast<int>(sk_rect_transformed.height())));
-  if (!render_punch_through) {
-    return;
-  }
+  punch_through_video_node->data().set_bounds_cb.Run(
+      math::Rect(static_cast<int>(sk_rect_transformed.x()),
+                 static_cast<int>(sk_rect_transformed.y()),
+                 static_cast<int>(sk_rect_transformed.width()),
+                 static_cast<int>(sk_rect_transformed.height())));
 
   SkPaint paint;
   paint.setXfermodeMode(SkXfermode::kSrc_Mode);
diff --git a/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontConfigParser_cobalt.cc b/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontConfigParser_cobalt.cc
index 63f1e67..4111f1b 100644
--- a/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontConfigParser_cobalt.cc
+++ b/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontConfigParser_cobalt.cc
@@ -300,7 +300,7 @@
         break;
       case 15:
         if (strncmp("postscript_name", name, 15) == 0) {
-          file->postcript_name = value;
+          file->postscript_name = value;
           seen_attributes_flag |= kSeenFontPostscriptName;
           continue;
         }
@@ -341,7 +341,7 @@
   DCHECK_EQ(seen_attributes_flag, kSeenFontFullName | kSeenFontPostscriptName |
                                       kSeenWeight | kSeenStyle);
   DCHECK(!file->full_font_name.isEmpty());
-  DCHECK(!file->postcript_name.isEmpty());
+  DCHECK(!file->postscript_name.isEmpty());
 }
 
 FontFamily* FindFamily(FamilyData* family_data, const char* family_name) {
diff --git a/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontMgr_cobalt.cc b/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontMgr_cobalt.cc
index 5ab5536..6c9aa9d 100644
--- a/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontMgr_cobalt.cc
+++ b/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontMgr_cobalt.cc
@@ -25,6 +25,7 @@
 
 #include "base/at_exit.h"
 #include "base/bind.h"
+#include "base/debug/trace_event.h"
 #include "base/lazy_instance.h"
 #include "base/memory/singleton.h"
 #include "cobalt/base/c_val.h"
@@ -48,6 +49,8 @@
 
 // NOTE: It is the responsibility of the caller to call Unref() on the SkData.
 SkData* NewDataFromFile(const SkString& file_path) {
+  TRACE_EVENT1("cobalt::renderer", "SkFontMgr_cobalt::NewDataFromFile()",
+               "file_path", TRACE_STR_COPY(file_path.c_str()));
   LOG(INFO) << "Loading font file: " << file_path.c_str();
 
   SkAutoTUnref<SkStream> file_stream(SkStream::NewFromFile(file_path.c_str()));
@@ -159,6 +162,7 @@
   }
 
   virtual SkStream* onOpenStream(int* ttc_index) const SK_OVERRIDE {
+    TRACE_EVENT0("cobalt::renderer", "SkTypeface_CobaltSystem::onOpenStream()");
     *ttc_index = index_;
 
     // Scope the initial mutex lock.
@@ -175,6 +179,7 @@
       }
     }
 
+    TRACE_EVENT0("cobalt::renderer", "Load data from file");
     // This is where the bulk of the time will be spent, so load the font data
     // outside of a mutex lock.
     SkAutoTUnref<SkData> data(NewDataFromFile(path_name_));
@@ -237,6 +242,8 @@
       language_(family.language),
       page_ranges_(family.page_ranges),
       is_character_map_generated_(false) {
+  TRACE_EVENT0("cobalt::renderer",
+               "SkFontStyleSet_Cobalt::SkFontStyleSet_Cobalt()");
   DCHECK(manager_owned_mutex_);
 
   if (family.names.count() == 0) {
@@ -269,12 +276,12 @@
 
     std::string full_font_name(font_file.full_font_name.c_str(),
                                font_file.full_font_name.size());
-    std::string postcript_name(font_file.postcript_name.c_str(),
-                               font_file.postcript_name.size());
+    std::string postscript_name(font_file.postscript_name.c_str(),
+                                font_file.postscript_name.size());
 
     styles_.push_back().reset(SkNEW_ARGS(
         SkFontStyleSetEntry_Cobalt,
-        (path_name, font_file.index, style, full_font_name, postcript_name)));
+        (path_name, font_file.index, style, full_font_name, postscript_name)));
   }
 }
 
@@ -306,34 +313,57 @@
 
 SkTypeface* SkFontStyleSet_Cobalt::MatchStyleWithoutLocking(
     const SkFontStyle& pattern) {
-  while (styles_.count() > 0) {
-    int style_index = GetClosestStyleIndex(pattern);
-    SkFontStyleSetEntry_Cobalt* style = styles_[style_index];
-    if (style->typeface == NULL) {
-      CreateSystemTypeface(style);
-
-      // Check to see if the typeface is still NULL. If this is the case, then
-      // the style can't be created. Remove it from the array.
-      if (style->typeface == NULL) {
-        styles_[style_index].swap(&styles_.back());
-        styles_.pop_back();
-        continue;
-      }
-    }
-
-    return SkRef(style->typeface.get());
+  SkTypeface* typeface = NULL;
+  while (typeface == NULL && styles_.count() > 0) {
+    typeface = TryRetrieveTypefaceAndRemoveStyleOnFailure(
+        GetClosestStyleIndex(pattern));
   }
+  return typeface;
+}
 
+SkTypeface* SkFontStyleSet_Cobalt::MatchFullFontName(const std::string& name) {
+  for (int i = 0; i < styles_.count(); ++i) {
+    if (styles_[i]->full_font_name == name) {
+      return TryRetrieveTypefaceAndRemoveStyleOnFailure(i);
+    }
+  }
   return NULL;
 }
 
+SkTypeface* SkFontStyleSet_Cobalt::MatchFontPostScriptName(
+    const std::string& name) {
+  for (int i = 0; i < styles_.count(); ++i) {
+    if (styles_[i]->font_postscript_name == name) {
+      return TryRetrieveTypefaceAndRemoveStyleOnFailure(i);
+    }
+  }
+  return NULL;
+}
+
+SkTypeface* SkFontStyleSet_Cobalt::TryRetrieveTypefaceAndRemoveStyleOnFailure(
+    int style_index) {
+  DCHECK(style_index >= 0 && style_index < styles_.count());
+  SkFontStyleSetEntry_Cobalt* style = styles_[style_index];
+  // If the typeface doesn't already exist, then attempt to create it.
+  if (style->typeface == NULL) {
+    CreateSystemTypeface(style);
+    // If the creation attempt failed and the typeface is still NULL, then
+    // remove the entry from the set's styles.
+    if (style->typeface == NULL) {
+      styles_[style_index].swap(&styles_.back());
+      styles_.pop_back();
+      return NULL;
+    }
+  }
+  return SkRef(style->typeface.get());
+}
+
 bool SkFontStyleSet_Cobalt::ContainsTypeface(const SkTypeface* typeface) {
   for (int i = 0; i < styles_.count(); ++i) {
     if (styles_[i]->typeface == typeface) {
       return true;
     }
   }
-
   return false;
 }
 
@@ -371,6 +401,9 @@
   // The character map is lazily generated. Generate it now if it isn't already
   // generated.
   if (!is_character_map_generated_) {
+    TRACE_EVENT0("cobalt::renderer",
+                 "SkFontStyleSet_Cobalt::ContainsCharacter() and "
+                 "!is_character_map_generated_");
     // Attempt to load the closest font style from the set. If it fails to load,
     // it will be removed from the set and, as long as font styles remain in the
     // set, the logic will be attempted again.
@@ -422,6 +455,7 @@
   if (is_character_map_generated_) {
     return;
   }
+  TRACE_EVENT0("cobalt::renderer", "GenerateCharacterMapFromData()");
 
   FT_Library freetype_lib;
   if (FT_Init_FreeType(&freetype_lib) != 0) {
@@ -476,6 +510,8 @@
 
 void SkFontStyleSet_Cobalt::CreateSystemTypeface(
     SkFontStyleSetEntry_Cobalt* style_entry) {
+  TRACE_EVENT0("cobalt::renderer",
+               "SkFontStyleSet_Cobalt::CreateSystemTypeface()");
   SkAutoTUnref<SkData> font_data(NewDataFromFile(style_entry->font_file_path));
   if (font_data != NULL) {
     CreateSystemTypefaceFromData(style_entry, font_data);
@@ -484,6 +520,8 @@
 
 void SkFontStyleSet_Cobalt::CreateSystemTypefaceFromData(
     SkFontStyleSetEntry_Cobalt* style_entry, SkData* data) {
+  TRACE_EVENT0("cobalt::renderer",
+               "SkFontStyleSet_Cobalt::CreateSystemTypefaceFromData()");
   DCHECK(!style_entry->typeface);
 
   // Since the font data is available, generate the character map if this is a
@@ -582,13 +620,17 @@
     const char* directory, const SkTArray<SkString, true>& default_fonts)
     : default_family_(NULL),
       last_font_cache_purge_time_(base::TimeTicks::Now()) {
+  TRACE_EVENT0("cobalt::renderer", "SkFontMgr_Cobalt::SkFontMgr_Cobalt()");
   // Ensure that both the CValManager and SkFontMgrCVals are initialized. The
   // CValManager is created first as it must outlast the SkFontMgrCVals.
   base::CValManager::GetInstance();
   SkFontMgrCVals::GetInstance();
 
   SkTDArray<FontFamily*> font_families;
-  SkFontConfigParser::GetFontFamilies(directory, &font_families);
+  {
+    TRACE_EVENT0("cobalt::renderer", "SkFontConfigParser::GetFontFamilies()");
+    SkFontConfigParser::GetFontFamilies(directory, &font_families);
+  }
   BuildNameToFamilyMap(directory, &font_families);
   font_families.deleteAll();
 
@@ -610,6 +652,41 @@
   }
 }
 
+SkTypeface* SkFontMgr_Cobalt::matchFaceName(const std::string& font_face_name) {
+  if (font_face_name.empty()) {
+    return NULL;
+  }
+
+  // Lock the style sets mutex prior to accessing them.
+  SkAutoMutexAcquire scoped_mutex(style_sets_mutex_);
+
+  // Prioritize looking up the postscript name first since some of our client
+  // applications prefer this method to specify face names.
+  for (int i = 0; i <= 1; ++i) {
+    NameToStyleSetMap& name_to_style_set_map =
+        i == 0 ? font_postscript_name_to_style_set_map_
+               : full_font_name_to_style_set_map_;
+
+    NameToStyleSetMap::iterator style_set_iterator =
+        name_to_style_set_map.find(font_face_name);
+    if (style_set_iterator != name_to_style_set_map.end()) {
+      SkFontStyleSet_Cobalt* style_set = style_set_iterator->second;
+      SkTypeface* typeface =
+          i == 0 ? style_set->MatchFontPostScriptName(font_face_name)
+                 : style_set->MatchFullFontName(font_face_name);
+      if (typeface != NULL) {
+        return typeface;
+      } else {
+        // If no typeface was successfully created then remove the entry from
+        // the map. It won't provide a successful result in subsequent calls
+        // either.
+        name_to_style_set_map.erase(style_set_iterator);
+      }
+    }
+  }
+  return NULL;
+}
+
 int SkFontMgr_Cobalt::onCountFamilies() const { return family_names_.count(); }
 
 void SkFontMgr_Cobalt::onGetFamilyName(int index, SkString* family_name) const {
@@ -626,7 +703,7 @@
     return NULL;
   }
 
-  NameToFamilyMap::const_iterator family_iterator =
+  NameToStyleSetMap::const_iterator family_iterator =
       name_to_family_map_.find(family_names_[index].c_str());
   if (family_iterator != name_to_family_map_.end()) {
     return SkRef(family_iterator->second);
@@ -643,7 +720,7 @@
 
   SkAutoAsciiToLC tolc(family_name);
 
-  NameToFamilyMap::const_iterator family_iterator =
+  NameToStyleSetMap::const_iterator family_iterator =
       name_to_family_map_.find(tolc.lc());
   if (family_iterator != name_to_family_map_.end()) {
     return SkRef(family_iterator->second);
@@ -652,79 +729,6 @@
   return NULL;
 }
 
-SkTypeface* SkFontMgr_Cobalt::matchFullFontFaceNameHelper(
-    SkFontStyleSet_Cobalt* style_set,
-    SkFontStyleSet_Cobalt::SkFontStyleSetEntry_Cobalt* style) const {
-  DCHECK(style_set != NULL);
-  if (!style) {
-    NOTREACHED() << "style should not be NULL.";
-    return NULL;
-  }
-
-  if (style->typeface == NULL) {
-    if (!style_set) {
-      return NULL;
-    }
-    style_set->CreateSystemTypeface(style);
-  }
-
-  if (style->typeface != NULL) {
-    return SkRef(style->typeface.get());
-  }
-
-  return NULL;
-}
-
-SkTypeface* SkFontMgr_Cobalt::matchFaceNameOnlyIfFound(
-    const std::string& font_face_name) const {
-  // Prioritize looking it up postscript name first since some of our client
-  // applications prefer this method to specify face names.
-  SkTypeface* typeface = matchPostScriptName(font_face_name);
-  if (typeface != NULL) return typeface;
-
-  typeface = matchFullFontFaceName(font_face_name);
-  if (typeface != NULL) return typeface;
-
-  return NULL;
-}
-
-SkTypeface* SkFontMgr_Cobalt::matchFullFontFaceName(
-    const std::string& font_face_name) const {
-  SkAutoMutexAcquire scoped_mutex(style_sets_mutex_);
-
-  if (font_face_name.empty()) {
-    return NULL;
-  }
-
-  FullFontNameToFontFaceInfoMap::const_iterator font_face_iterator =
-      fullfontname_to_fontface_info_map_.find(font_face_name);
-
-  if (font_face_iterator != fullfontname_to_fontface_info_map_.end()) {
-    return matchFullFontFaceNameHelper(
-        font_face_iterator->second.style_set_entry_parent,
-        font_face_iterator->second.style_set_entry);
-  }
-
-  return NULL;
-}
-
-SkTypeface* SkFontMgr_Cobalt::matchPostScriptName(
-    const std::string& font_face_name) const {
-  if (font_face_name.empty()) {
-    return NULL;
-  }
-
-  PostScriptToFontFaceInfoMap::const_iterator font_face_iterator =
-      postscriptname_to_fontface_info_map_.find(font_face_name);
-  if (font_face_iterator != postscriptname_to_fontface_info_map_.end()) {
-    return matchFullFontFaceNameHelper(
-        font_face_iterator->second.style_set_entry_parent,
-        font_face_iterator->second.style_set_entry);
-  }
-
-  return NULL;
-}
-
 SkTypeface* SkFontMgr_Cobalt::onMatchFamilyStyle(
     const char family_name[], const SkFontStyle& style) const {
   SkTypeface* tf = NULL;
@@ -807,6 +811,7 @@
 
 SkTypeface* SkFontMgr_Cobalt::onCreateFromStream(SkStream* stream,
                                                  int ttc_index) const {
+  TRACE_EVENT0("cobalt::renderer", "SkFontMgr_Cobalt::onCreateFromStream()");
   bool is_fixed_pitch;
   SkTypeface::Style style;
   SkString name;
@@ -820,6 +825,7 @@
 
 SkTypeface* SkFontMgr_Cobalt::onCreateFromFile(const char path[],
                                                int ttc_index) const {
+  TRACE_EVENT0("cobalt::renderer", "SkFontMgr_Cobalt::onCreateFromFile()");
   SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
   return stream.get() ? createFromStream(stream, ttc_index) : NULL;
 }
@@ -838,6 +844,7 @@
 
 void SkFontMgr_Cobalt::BuildNameToFamilyMap(const char* base_path,
                                             SkTDArray<FontFamily*>* families) {
+  TRACE_EVENT0("cobalt::renderer", "SkFontMgr_Cobalt::BuildNameToFamilyMap()");
   for (int i = 0; i < families->count(); i++) {
     FontFamily& family = *(*families)[i];
     bool named_font = family.names.count() > 0;
@@ -861,47 +868,32 @@
              font_style_set_entry = new_set->styles_.begin();
          font_style_set_entry != new_set->styles_.end();
          ++font_style_set_entry) {
-      if (!font_style_set_entry) {
-        NOTREACHED() << " Font Style entry is invalid";
-        continue;
-      } else if ((*font_style_set_entry).get() == NULL) {
-        NOTREACHED() << " Font Style entry is NULL";
-        continue;
-      }
+      // On the first pass through, process the full font name.
+      // On the second pass through, process the font postscript name.
+      for (int i = 0; i <= 1; ++i) {
+        const std::string font_face_name_type_description =
+            i == 0 ? "Full Font" : "Postscript";
+        const std::string& font_face_name =
+            i == 0 ? (*font_style_set_entry)->full_font_name
+                   : (*font_style_set_entry)->font_postscript_name;
+        NameToStyleSetMap& font_face_name_style_set_map =
+            i == 0 ? full_font_name_to_style_set_map_
+                   : font_postscript_name_to_style_set_map_;
 
-      const std::string& full_font_name =
-          (*font_style_set_entry)->full_font_name;
-      DCHECK(!full_font_name.empty());
-      if (fullfontname_to_fontface_info_map_.find(full_font_name) ==
-          fullfontname_to_fontface_info_map_.end()) {
-        DLOG(INFO) << "Adding Full font name [" << full_font_name << "].";
-        fullfontname_to_fontface_info_map_[full_font_name] =
-            FullFontNameToFontFaceInfoMap::mapped_type(
-                font_style_set_entry->get(), new_set.get());
-      } else {
-        // Purposely, not overwriting the entry gives priority to the
-        // earlier entry.  This is consistent with how fonts.xml gives
-        // priority to fonts that are specified earlier in the file.
-        NOTREACHED() << "Full font name [" << full_font_name
-                     << "] already registered in BuildNameToFamilyMap.";
-      }
-
-      const std::string& postscript_font_name =
-          (*font_style_set_entry)->font_postscript_name;
-      DCHECK(!postscript_font_name.empty());
-      if (postscriptname_to_fontface_info_map_.find(postscript_font_name) ==
-          postscriptname_to_fontface_info_map_.end()) {
-        DLOG(INFO) << "Adding Postscript name [" << postscript_font_name
-                   << "].";
-        postscriptname_to_fontface_info_map_[postscript_font_name] =
-            PostScriptToFontFaceInfoMap::mapped_type(
-                font_style_set_entry->get(), new_set.get());
-      } else {
-        // Purposely, not overwriting the entry gives priority to the
-        // earlier entry.  This is consistent with how fonts.xml gives
-        // priority to fonts that are specified earlier in the file.
-        NOTREACHED() << "Adding Postscript name [" << postscript_font_name
-                     << "] already registered in BuildNameToFamilyMap.";
+        DCHECK(!font_face_name.empty());
+        if (font_face_name_style_set_map.find(font_face_name) ==
+            font_face_name_style_set_map.end()) {
+          DLOG(INFO) << "Adding " << font_face_name_type_description
+                     << " name [" << font_face_name << "].";
+          font_face_name_style_set_map[font_face_name] = new_set.get();
+        } else {
+          // Purposely, not overwriting the entry gives priority to the
+          // earlier entry.  This is consistent with how fonts.xml gives
+          // priority to fonts that are specified earlier in the file.
+          NOTREACHED() << font_face_name_type_description << " name ["
+                       << font_face_name
+                       << "] already registered in BuildNameToFamilyMap.";
+        }
       }
     }
 
@@ -988,6 +980,29 @@
   return NULL;
 }
 
+void SkFontMgr_Cobalt::HandlePeriodicProcessing() {
+  base::TimeTicks current_time = base::TimeTicks::Now();
+
+  ProcessSystemTypefacesWithOpenStreams(current_time);
+
+  // If the required delay has elapsed since the last font cache purge, then
+  // it's time to force another. This is accomplished by setting the limit to
+  // 1 byte smaller than it's current size, which initiates a partial purge (it
+  // always purges at least 25% of its contents). After this is done, the cache
+  // is set back to its previous size.
+  if ((current_time - last_font_cache_purge_time_).InMilliseconds() >=
+      kPeriodicFontCachePurgeDelayMs) {
+    last_font_cache_purge_time_ = current_time;
+
+    size_t font_cache_used = SkGraphics::GetFontCacheUsed();
+    if (font_cache_used > 0) {
+      size_t font_cache_limit = SkGraphics::GetFontCacheLimit();
+      SkGraphics::SetFontCacheLimit(font_cache_used - 1);
+      SkGraphics::SetFontCacheLimit(font_cache_limit);
+    }
+  }
+}
+
 // NOTE: It is the responsibility of the caller to lock
 // |system_typeface_stream_mutex_|
 void SkFontMgr_Cobalt::AddSystemTypefaceWithActiveOpenStream(
@@ -1024,26 +1039,6 @@
   }
 }
 
-void SkFontMgr_Cobalt::HandlePeriodicProcessing() {
-  base::TimeTicks current_time = base::TimeTicks::Now();
-
-  ProcessSystemTypefacesWithOpenStreams(current_time);
-
-  // If the required delay has elapsed since the last font cache purge, then
-  // it's time to force another. This is accomplished by setting the limit to
-  // 1 byte smaller than it's current size, which initiates a partial purge (it
-  // always purges at least 25% of its contents). After this is done, the cache
-  // is set back to its previous size.
-  if ((current_time - last_font_cache_purge_time_).InMilliseconds() >=
-      kPeriodicFontCachePurgeDelayMs) {
-    last_font_cache_purge_time_ = current_time;
-
-    size_t font_cache_limit = SkGraphics::GetFontCacheLimit();
-    SkGraphics::SetFontCacheLimit(SkGraphics::GetFontCacheUsed() - 1);
-    SkGraphics::SetFontCacheLimit(font_cache_limit);
-  }
-}
-
 void SkFontMgr_Cobalt::ProcessSystemTypefacesWithOpenStreams(
     const base::TimeTicks& current_time) const {
   SkAutoMutexAcquire scoped_mutex(system_typeface_stream_mutex_);
diff --git a/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontMgr_cobalt.h b/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontMgr_cobalt.h
index cebba88..cc74881 100644
--- a/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontMgr_cobalt.h
+++ b/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontMgr_cobalt.h
@@ -46,6 +46,11 @@
 class SkFontStyleSet_Cobalt : public SkFontStyleSet {
  public:
   struct SkFontStyleSetEntry_Cobalt : public SkRefCnt {
+    // NOTE: |SkFontStyleSetEntry_Cobalt| objects are not guaranteed to last for
+    // the lifetime of |SkFontMgr_Cobalt| and can be removed by their owning
+    // |SkFontStyleSet_Cobalt| if their typeface fails to load properly. As a
+    // result, it is not safe to store their pointers outside of
+    // |SkFontStyleSet_Cobalt|.
     SkFontStyleSetEntry_Cobalt(const SkString& file_path, const int index,
                                const SkFontStyle& style,
                                const std::string& full_name,
@@ -92,6 +97,9 @@
   // calling any of the non-const private functions.
 
   SkTypeface* MatchStyleWithoutLocking(const SkFontStyle& pattern);
+  SkTypeface* MatchFullFontName(const std::string& name);
+  SkTypeface* MatchFontPostScriptName(const std::string& name);
+  SkTypeface* TryRetrieveTypefaceAndRemoveStyleOnFailure(int style_index);
   bool ContainsTypeface(const SkTypeface* typeface);
 
   bool ContainsCharacter(const SkFontStyle& style, SkUnichar character);
@@ -138,33 +146,30 @@
   SkFontMgr_Cobalt(const char* directory,
                    const SkTArray<SkString, true>& default_fonts);
 
-  // Note: Unlike the other similar onMatch* functions, this function can return
-  // NULL.  This is so that we can try other things in case the match is not
-  // found.
-  SkTypeface* matchFaceNameOnlyIfFound(const std::string& font_face_name) const;
+  // NOTE: This returns NULL if a match is not found.
+  SkTypeface* matchFaceName(const std::string& font_face_name);
 
  protected:
-  // Note: These match*Name helper functions can return NULL.
-  SkTypeface* matchFullFontFaceName(const std::string& font_face_name) const;
-  SkTypeface* matchPostScriptName(const std::string& font_face_name) const;
-  SkTypeface* matchFullFontFaceNameHelper(
-      SkFontStyleSet_Cobalt* style_set,
-      SkFontStyleSet_Cobalt::SkFontStyleSetEntry_Cobalt* style) const;
-
   // From SkFontMgr
   virtual int onCountFamilies() const SK_OVERRIDE;
 
   virtual void onGetFamilyName(int index,
                                SkString* family_name) const SK_OVERRIDE;
 
+  // NOTE: This returns NULL if there is no accessible style set at the index.
   virtual SkFontStyleSet_Cobalt* onCreateStyleSet(int index) const SK_OVERRIDE;
 
+  // NOTE: This returns NULL if there is no family match.
   virtual SkFontStyleSet_Cobalt* onMatchFamily(const char family_name[]) const
       SK_OVERRIDE;
 
+  // NOTE: This always returns a non-NULL value. If the family name cannot be
+  // found, then the best match among the default family is returned.
   virtual SkTypeface* onMatchFamilyStyle(
       const char family_name[], const SkFontStyle& style) const SK_OVERRIDE;
 
+// NOTE: This always returns a non-NULL value. If no match can be found, then
+// the best match among the default family is returned.
 #ifdef SK_FM_NEW_MATCH_FAMILY_STYLE_CHARACTER
   virtual SkTypeface* onMatchFamilyStyleCharacter(
       const char family_name[], const SkFontStyle& style, const char* bcp47[],
@@ -175,19 +180,25 @@
       SkUnichar character) const SK_OVERRIDE;
 #endif
 
+  // NOTE: This returns NULL if a match is not found.
   virtual SkTypeface* onMatchFaceStyle(const SkTypeface* family_member,
                                        const SkFontStyle& font_style) const
       SK_OVERRIDE;
 
+  // NOTE: This returns NULL if the typeface cannot be created.
   virtual SkTypeface* onCreateFromData(SkData* data,
                                        int ttc_index) const SK_OVERRIDE;
 
+  // NOTE: This returns NULL if the typeface cannot be created.
   virtual SkTypeface* onCreateFromStream(SkStream* stream,
                                          int ttc_index) const SK_OVERRIDE;
 
+  // NOTE: This returns NULL if the typeface cannot be created.
   virtual SkTypeface* onCreateFromFile(const char path[],
                                        int ttc_index) const SK_OVERRIDE;
 
+  // NOTE: This always returns a non-NULL value. If no match can be found, then
+  // the best match among the default family is returned.
   virtual SkTypeface* onLegacyCreateTypeface(
       const char family_name[], unsigned style_bits) const SK_OVERRIDE;
 
@@ -201,23 +212,7 @@
     base::TimeTicks time;
   };
 
-  //  Map names to the back end so that all names for a given family refer to
-  //  the same (non-replicated) set of typefaces.
-  typedef base::hash_map<std::string, SkFontStyleSet_Cobalt*> NameToFamilyMap;
-
-  struct FontFaceInfo {
-    FontFaceInfo() : style_set_entry(NULL), style_set_entry_parent(NULL) {}
-    FontFaceInfo(SkFontStyleSet_Cobalt::SkFontStyleSetEntry_Cobalt* entry,
-                 SkFontStyleSet_Cobalt* parent)
-        : style_set_entry(entry), style_set_entry_parent(parent) {}
-
-    SkFontStyleSet_Cobalt::SkFontStyleSetEntry_Cobalt* style_set_entry;
-    SkFontStyleSet_Cobalt* style_set_entry_parent;
-  };
-
-  typedef base::hash_map<std::string, FontFaceInfo>
-      FullFontNameToFontFaceInfoMap;
-  typedef base::hash_map<std::string, FontFaceInfo> PostScriptToFontFaceInfoMap;
+  typedef base::hash_map<std::string, SkFontStyleSet_Cobalt*> NameToStyleSetMap;
 
   void BuildNameToFamilyMap(const char* base_path,
                             SkTDArray<FontFamily*>* families);
@@ -257,9 +252,11 @@
   SkTArray<SkAutoTUnref<SkFontStyleSet_Cobalt>, true> font_style_sets_;
 
   SkTArray<SkString> family_names_;
-  NameToFamilyMap name_to_family_map_;
-  FullFontNameToFontFaceInfoMap fullfontname_to_fontface_info_map_;
-  PostScriptToFontFaceInfoMap postscriptname_to_fontface_info_map_;
+  //  Map names to the back end so that all names for a given family refer to
+  //  the same (non-replicated) set of typefaces.
+  NameToStyleSetMap name_to_family_map_;
+  NameToStyleSetMap full_font_name_to_style_set_map_;
+  NameToStyleSetMap font_postscript_name_to_style_set_map_;
 
   SkTArray<SkFontStyleSet_Cobalt*> fallback_families_;
 
diff --git a/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontUtil_cobalt.h b/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontUtil_cobalt.h
index 020517c..80287a4 100644
--- a/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontUtil_cobalt.h
+++ b/src/cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontUtil_cobalt.h
@@ -111,7 +111,7 @@
   FontStyle style;
 
   SkString full_font_name;
-  SkString postcript_name;
+  SkString postscript_name;
 };
 
 // A font family provides one or more names for a collection of fonts, each of
diff --git a/src/cobalt/renderer/rasterizer/skia/software_resource_provider.cc b/src/cobalt/renderer/rasterizer/skia/software_resource_provider.cc
index d3af607..5a9afb7 100644
--- a/src/cobalt/renderer/rasterizer/skia/software_resource_provider.cc
+++ b/src/cobalt/renderer/rasterizer/skia/software_resource_provider.cc
@@ -127,7 +127,7 @@
   SkFontMgr_Cobalt* font_manager =
       base::polymorphic_downcast<SkFontMgr_Cobalt*>(font_manager_.get());
 
-  SkTypeface* typeface = font_manager->matchFaceNameOnlyIfFound(font_face_name);
+  SkTypeface* typeface = font_manager->matchFaceName(font_face_name);
   if (typeface != NULL) {
     SkAutoTUnref<SkTypeface> typeface_unref_helper(typeface);
     return scoped_refptr<render_tree::Typeface>(new SkiaTypeface(typeface));
diff --git a/src/cobalt/renderer/rasterizer/testdata/PunchThroughVideoNodePunchesThroughSetBoundsCBReturnsFalse-expected.png b/src/cobalt/renderer/rasterizer/testdata/PunchThroughVideoNodePunchesThroughSetBoundsCBReturnsFalse-expected.png
index d26f087..0f82d7a 100644
--- a/src/cobalt/renderer/rasterizer/testdata/PunchThroughVideoNodePunchesThroughSetBoundsCBReturnsFalse-expected.png
+++ b/src/cobalt/renderer/rasterizer/testdata/PunchThroughVideoNodePunchesThroughSetBoundsCBReturnsFalse-expected.png
Binary files differ
diff --git a/src/cobalt/renderer/renderer.gyp b/src/cobalt/renderer/renderer.gyp
index 5a1253e..d7619d5 100644
--- a/src/cobalt/renderer/renderer.gyp
+++ b/src/cobalt/renderer/renderer.gyp
@@ -22,6 +22,8 @@
       'target_name': 'renderer',
       'type': 'static_library',
       'sources': [
+        'frame_rate_throttler.cc',
+        'frame_rate_throttler.h',
         'pipeline.cc',
         'pipeline.h',
         'renderer_module.cc',
@@ -33,6 +35,9 @@
         'submission_queue.h',
       ],
 
+      'defines': [
+        'COBALT_MINIMUM_FRAME_TIME_IN_MILLISECONDS=<(cobalt_minimum_frame_time_in_milliseconds)',
+      ],
       'includes': [
         'copy_font_data.gypi',
       ],
diff --git a/src/cobalt/renderer/renderer_module_default_options_starboard.cc b/src/cobalt/renderer/renderer_module_default_options_starboard.cc
index 7ee0e3e..c19cc0b 100644
--- a/src/cobalt/renderer/renderer_module_default_options_starboard.cc
+++ b/src/cobalt/renderer/renderer_module_default_options_starboard.cc
@@ -16,6 +16,7 @@
 
 #include "cobalt/renderer/renderer_module.h"
 
+#include "base/debug/trace_event.h"
 #include "cobalt/renderer/rasterizer/blitter/hardware_rasterizer.h"
 #include "cobalt/renderer/rasterizer/blitter/software_rasterizer.h"
 #include "cobalt/renderer/rasterizer/egl/software_rasterizer.h"
@@ -30,6 +31,7 @@
 scoped_ptr<rasterizer::Rasterizer> CreateRasterizer(
     backend::GraphicsContext* graphics_context,
     const RendererModule::Options& options) {
+  TRACE_EVENT0("cobalt::renderer", "CreateRasterizer");
 #if COBALT_FORCE_STUB_RASTERIZER
   return scoped_ptr<rasterizer::Rasterizer>(new rasterizer::stub::Rasterizer());
 #else
diff --git a/src/cobalt/script/mozjs/mozjs_callback_function.h b/src/cobalt/script/mozjs/mozjs_callback_function.h
index 71d8914..ef6932a 100644
--- a/src/cobalt/script/mozjs/mozjs_callback_function.h
+++ b/src/cobalt/script/mozjs/mozjs_callback_function.h
@@ -27,7 +27,9 @@
 #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/util/exception_helpers.h"
 #include "cobalt/script/mozjs/weak_heap_object.h"
+#include "nb/memory_scope.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 #include "third_party/mozjs/js/src/jscntxt.h"
 
@@ -57,6 +59,7 @@
 
   CallbackResult<R> Run()
       const OVERRIDE {
+    TRACK_MEMORY_SCOPE("Javascript");
     TRACE_EVENT0("cobalt::script::mozjs", "MozjsCallbackFunction::Run");
     CallbackResult<R> callback_result;
     JSAutoRequest auto_request(context_);
@@ -79,7 +82,8 @@
       JSBool call_result = JS::Call(context_, this_value, function, 0, NULL,
           return_value.address());
       if (!call_result) {
-        DLOG(WARNING) << "Exception in callback.";
+        DLOG(WARNING) << "Exception in callback: "
+                      << util::GetExceptionString(context_);
         callback_result.exception = true;
       } else {
         callback_result = ConvertCallbackReturnValue<R>(context_, return_value);
@@ -111,6 +115,7 @@
   CallbackResult<R> Run(
       typename base::internal::CallbackParamTraits<A1>::ForwardType a1)
       const OVERRIDE {
+    TRACK_MEMORY_SCOPE("Javascript");
     TRACE_EVENT0("cobalt::script::mozjs", "MozjsCallbackFunction::Run");
     CallbackResult<R> callback_result;
     JSAutoRequest auto_request(context_);
@@ -138,7 +143,8 @@
       JSBool call_result = JS::Call(context_, this_value, function,
           kNumArguments, args, return_value.address());
       if (!call_result) {
-        DLOG(WARNING) << "Exception in callback.";
+        DLOG(WARNING) << "Exception in callback: "
+                      << util::GetExceptionString(context_);
         callback_result.exception = true;
       } else {
         callback_result = ConvertCallbackReturnValue<R>(context_, return_value);
@@ -171,6 +177,7 @@
       typename base::internal::CallbackParamTraits<A1>::ForwardType a1,
       typename base::internal::CallbackParamTraits<A2>::ForwardType a2)
       const OVERRIDE {
+    TRACK_MEMORY_SCOPE("Javascript");
     TRACE_EVENT0("cobalt::script::mozjs", "MozjsCallbackFunction::Run");
     CallbackResult<R> callback_result;
     JSAutoRequest auto_request(context_);
@@ -199,7 +206,8 @@
       JSBool call_result = JS::Call(context_, this_value, function,
           kNumArguments, args, return_value.address());
       if (!call_result) {
-        DLOG(WARNING) << "Exception in callback.";
+        DLOG(WARNING) << "Exception in callback: "
+                      << util::GetExceptionString(context_);
         callback_result.exception = true;
       } else {
         callback_result = ConvertCallbackReturnValue<R>(context_, return_value);
@@ -233,6 +241,7 @@
       typename base::internal::CallbackParamTraits<A2>::ForwardType a2,
       typename base::internal::CallbackParamTraits<A3>::ForwardType a3)
       const OVERRIDE {
+    TRACK_MEMORY_SCOPE("Javascript");
     TRACE_EVENT0("cobalt::script::mozjs", "MozjsCallbackFunction::Run");
     CallbackResult<R> callback_result;
     JSAutoRequest auto_request(context_);
@@ -262,7 +271,8 @@
       JSBool call_result = JS::Call(context_, this_value, function,
           kNumArguments, args, return_value.address());
       if (!call_result) {
-        DLOG(WARNING) << "Exception in callback.";
+        DLOG(WARNING) << "Exception in callback: "
+                      << util::GetExceptionString(context_);
         callback_result.exception = true;
       } else {
         callback_result = ConvertCallbackReturnValue<R>(context_, return_value);
@@ -297,6 +307,7 @@
       typename base::internal::CallbackParamTraits<A3>::ForwardType a3,
       typename base::internal::CallbackParamTraits<A4>::ForwardType a4)
       const OVERRIDE {
+    TRACK_MEMORY_SCOPE("Javascript");
     TRACE_EVENT0("cobalt::script::mozjs", "MozjsCallbackFunction::Run");
     CallbackResult<R> callback_result;
     JSAutoRequest auto_request(context_);
@@ -327,7 +338,8 @@
       JSBool call_result = JS::Call(context_, this_value, function,
           kNumArguments, args, return_value.address());
       if (!call_result) {
-        DLOG(WARNING) << "Exception in callback.";
+        DLOG(WARNING) << "Exception in callback: "
+                      << util::GetExceptionString(context_);
         callback_result.exception = true;
       } else {
         callback_result = ConvertCallbackReturnValue<R>(context_, return_value);
@@ -364,6 +376,7 @@
       typename base::internal::CallbackParamTraits<A4>::ForwardType a4,
       typename base::internal::CallbackParamTraits<A5>::ForwardType a5)
       const OVERRIDE {
+    TRACK_MEMORY_SCOPE("Javascript");
     TRACE_EVENT0("cobalt::script::mozjs", "MozjsCallbackFunction::Run");
     CallbackResult<R> callback_result;
     JSAutoRequest auto_request(context_);
@@ -395,7 +408,8 @@
       JSBool call_result = JS::Call(context_, this_value, function,
           kNumArguments, args, return_value.address());
       if (!call_result) {
-        DLOG(WARNING) << "Exception in callback.";
+        DLOG(WARNING) << "Exception in callback: "
+                      << util::GetExceptionString(context_);
         callback_result.exception = true;
       } else {
         callback_result = ConvertCallbackReturnValue<R>(context_, return_value);
@@ -433,6 +447,7 @@
       typename base::internal::CallbackParamTraits<A5>::ForwardType a5,
       typename base::internal::CallbackParamTraits<A6>::ForwardType a6)
       const OVERRIDE {
+    TRACK_MEMORY_SCOPE("Javascript");
     TRACE_EVENT0("cobalt::script::mozjs", "MozjsCallbackFunction::Run");
     CallbackResult<R> callback_result;
     JSAutoRequest auto_request(context_);
@@ -465,7 +480,8 @@
       JSBool call_result = JS::Call(context_, this_value, function,
           kNumArguments, args, return_value.address());
       if (!call_result) {
-        DLOG(WARNING) << "Exception in callback.";
+        DLOG(WARNING) << "Exception in callback: "
+                      << util::GetExceptionString(context_);
         callback_result.exception = true;
       } else {
         callback_result = ConvertCallbackReturnValue<R>(context_, return_value);
@@ -504,6 +520,7 @@
       typename base::internal::CallbackParamTraits<A6>::ForwardType a6,
       typename base::internal::CallbackParamTraits<A7>::ForwardType a7)
       const OVERRIDE {
+    TRACK_MEMORY_SCOPE("Javascript");
     TRACE_EVENT0("cobalt::script::mozjs", "MozjsCallbackFunction::Run");
     CallbackResult<R> callback_result;
     JSAutoRequest auto_request(context_);
@@ -537,7 +554,8 @@
       JSBool call_result = JS::Call(context_, this_value, function,
           kNumArguments, args, return_value.address());
       if (!call_result) {
-        DLOG(WARNING) << "Exception in callback.";
+        DLOG(WARNING) << "Exception in callback: "
+                      << util::GetExceptionString(context_);
         callback_result.exception = true;
       } else {
         callback_result = ConvertCallbackReturnValue<R>(context_, return_value);
diff --git a/src/cobalt/script/mozjs/mozjs_callback_function.h.pump b/src/cobalt/script/mozjs/mozjs_callback_function.h.pump
index 861dcd3..9bfb5f2 100644
--- a/src/cobalt/script/mozjs/mozjs_callback_function.h.pump
+++ b/src/cobalt/script/mozjs/mozjs_callback_function.h.pump
@@ -32,7 +32,9 @@
 #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/util/exception_helpers.h"
 #include "cobalt/script/mozjs/weak_heap_object.h"
+#include "nb/memory_scope.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 #include "third_party/mozjs/js/src/jscntxt.h"
 
@@ -76,6 +78,7 @@
 
       typename base::internal::CallbackParamTraits<A$(ARG)>::ForwardType a$(ARG)]])
       const OVERRIDE {
+    TRACK_MEMORY_SCOPE("Javascript");
     TRACE_EVENT0("cobalt::script::mozjs", "MozjsCallbackFunction::Run");
     CallbackResult<R> callback_result;
     JSAutoRequest auto_request(context_);
@@ -110,7 +113,8 @@
 ]]
 
       if (!call_result) {
-        DLOG(WARNING) << "Exception in callback.";
+        DLOG(WARNING) << "Exception in callback: "
+                      << util::GetExceptionString(context_);
         callback_result.exception = true;
       } else {
         callback_result = ConvertCallbackReturnValue<R>(context_, return_value);
diff --git a/src/cobalt/script/mozjs/mozjs_engine.cc b/src/cobalt/script/mozjs/mozjs_engine.cc
index 623a7e5..7b62f3f 100644
--- a/src/cobalt/script/mozjs/mozjs_engine.cc
+++ b/src/cobalt/script/mozjs/mozjs_engine.cc
@@ -18,6 +18,7 @@
 
 #include <algorithm>
 
+#include "base/debug/trace_event.h"
 #include "base/logging.h"
 #include "cobalt/base/c_val.h"
 #include "cobalt/browser/stack_size_constants.h"
@@ -101,6 +102,7 @@
 }  // namespace
 
 MozjsEngine::MozjsEngine() : accumulated_extra_memory_cost_(0) {
+  TRACE_EVENT0("cobalt::script", "MozjsEngine::MozjsEngine()");
   // TODO: Investigate the benefit of helper threads and things like
   // parallel compilation.
   runtime_ =
@@ -147,11 +149,13 @@
 }
 
 scoped_refptr<GlobalEnvironment> MozjsEngine::CreateGlobalEnvironment() {
+  TRACE_EVENT0("cobalt::script", "MozjsEngine::CreateGlobalEnvironment()");
   DCHECK(thread_checker_.CalledOnValidThread());
   return new MozjsGlobalEnvironment(runtime_);
 }
 
 void MozjsEngine::CollectGarbage() {
+  TRACE_EVENT0("cobalt::script", "MozjsEngine::CollectGarbage()");
   DCHECK(thread_checker_.CalledOnValidThread());
   JS_GC(runtime_);
 }
@@ -196,15 +200,18 @@
     MozjsGlobalEnvironment* global_environment =
         MozjsGlobalEnvironment::GetFromContext(engine->contexts_[i]);
     if (status == JSGC_BEGIN) {
+      TRACE_EVENT_BEGIN0("cobalt::script", "SpiderMonkey Garbage Collection");
       global_environment->BeginGarbageCollection();
     } else if (status == JSGC_END) {
       global_environment->EndGarbageCollection();
+      TRACE_EVENT_END0("cobalt::script", "SpiderMonkey Garbage Collection");
     }
   }
 }
 
 void MozjsEngine::FinalizeCallback(JSFreeOp* free_op, JSFinalizeStatus status,
                                    JSBool is_compartment) {
+  TRACE_EVENT0("cobalt::script", "MozjsEngine::FinalizeCallback()");
   MozjsEngine* engine =
       static_cast<MozjsEngine*>(JS_GetRuntimePrivate(free_op->runtime()));
   DCHECK(engine->thread_checker_.CalledOnValidThread());
@@ -220,6 +227,7 @@
 }  // namespace mozjs
 
 scoped_ptr<JavaScriptEngine> JavaScriptEngine::CreateEngine() {
+  TRACE_EVENT0("cobalt::script", "JavaScriptEngine::CreateEngine()");
   return make_scoped_ptr<JavaScriptEngine>(new mozjs::MozjsEngine());
 }
 
diff --git a/src/cobalt/script/mozjs/mozjs_global_environment.cc b/src/cobalt/script/mozjs/mozjs_global_environment.cc
index 89ddeb2..b9c05a9 100644
--- a/src/cobalt/script/mozjs/mozjs_global_environment.cc
+++ b/src/cobalt/script/mozjs/mozjs_global_environment.cc
@@ -28,6 +28,7 @@
 #include "cobalt/script/mozjs/proxy_handler.h"
 #include "cobalt/script/mozjs/referenced_object_map.h"
 #include "cobalt/script/mozjs/util/exception_helpers.h"
+#include "nb/memory_scope.h"
 #include "third_party/mozjs/js/src/jsfriendapi.h"
 #include "third_party/mozjs/js/src/jsfun.h"
 #include "third_party/mozjs/js/src/jsobj.h"
@@ -128,6 +129,7 @@
       environment_settings_(NULL),
       last_error_message_(NULL),
       eval_enabled_(false) {
+  TRACK_MEMORY_SCOPE("Javascript");
   context_ = JS_NewContext(runtime, kStackChunkSize);
   DCHECK(context_);
   // Set a pointer to this class inside the JSContext.
@@ -166,6 +168,7 @@
 }
 
 void MozjsGlobalEnvironment::CreateGlobalObject() {
+  TRACK_MEMORY_SCOPE("Javascript");
   DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK(!global_object_proxy_);
 
@@ -194,6 +197,7 @@
 bool MozjsGlobalEnvironment::EvaluateScript(
     const scoped_refptr<SourceCode>& source_code,
     std::string* out_result_utf8) {
+  TRACK_MEMORY_SCOPE("Javascript");
   DCHECK(thread_checker_.CalledOnValidThread());
 
   JSAutoRequest auto_request(context_);
@@ -225,6 +229,7 @@
     const scoped_refptr<SourceCode>& source_code,
     const scoped_refptr<Wrappable>& owning_object,
     base::optional<OpaqueHandleHolder::Reference>* out_opaque_handle) {
+  TRACK_MEMORY_SCOPE("Javascript");
   DCHECK(thread_checker_.CalledOnValidThread());
   JSAutoRequest auto_request(context_);
   JSAutoCompartment auto_compartment(context_, global_object_proxy_);
@@ -245,6 +250,7 @@
 bool MozjsGlobalEnvironment::EvaluateScriptInternal(
     const scoped_refptr<SourceCode>& source_code,
     JS::MutableHandleValue out_result) {
+  TRACK_MEMORY_SCOPE("Javascript");
   DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK(global_object_proxy_);
   MozjsSourceCode* mozjs_source_code =
@@ -291,6 +297,7 @@
 
 void MozjsGlobalEnvironment::AllowGarbageCollection(
     const scoped_refptr<Wrappable>& wrappable) {
+  TRACK_MEMORY_SCOPE("Javascript");
   DCHECK(thread_checker_.CalledOnValidThread());
   CachedWrapperMultiMap::iterator it =
       kept_alive_objects_.find(wrappable.get());
@@ -320,6 +327,7 @@
 
 void MozjsGlobalEnvironment::Bind(const std::string& identifier,
                                   const scoped_refptr<Wrappable>& impl) {
+  TRACK_MEMORY_SCOPE("Javascript");
   JSAutoRequest auto_request(context_);
   JSAutoCompartment auto_compartment(context_, global_object_proxy_);
 
@@ -342,12 +350,14 @@
 }
 
 void MozjsGlobalEnvironment::DoSweep() {
+  TRACK_MEMORY_SCOPE("Javascript");
   weak_object_manager_.SweepUnmarkedObjects();
   // Remove NULL references after sweeping weak references.
   referenced_objects_->RemoveNullReferences();
 }
 
 void MozjsGlobalEnvironment::BeginGarbageCollection() {
+  TRACK_MEMORY_SCOPE("Javascript");
   // It's possible that a GC could be triggered from within the
   // BeginGarbageCollection callback. Only create the OpaqueRootState the first
   // time we enter.
@@ -461,6 +471,7 @@
 }
 
 JSBool MozjsGlobalEnvironment::CheckEval(JSContext* context) {
+  TRACK_MEMORY_SCOPE("Javascript");
   MozjsGlobalEnvironment* global_object_proxy = GetFromContext(context);
   DCHECK(global_object_proxy);
   if (!global_object_proxy->report_eval_.is_null()) {
diff --git a/src/cobalt/script/mozjs/util/exception_helpers.cc b/src/cobalt/script/mozjs/util/exception_helpers.cc
index ce0ca06..3a4b80c 100644
--- a/src/cobalt/script/mozjs/util/exception_helpers.cc
+++ b/src/cobalt/script/mozjs/util/exception_helpers.cc
@@ -28,6 +28,25 @@
 namespace script {
 namespace mozjs {
 namespace util {
+std::string GetExceptionString(JSContext* context) {
+  if (!JS_IsExceptionPending(context)) {
+    return std::string("No exception pending.");
+  }
+  JS::RootedValue exception(context);
+  JS_GetPendingException(context, exception.address());
+  JS_ReportPendingException(context);
+  return GetExceptionString(context, exception);
+}
+
+std::string GetExceptionString(JSContext* context,
+                               JS::HandleValue exception) {
+  std::string exception_string;
+  MozjsExceptionState exception_state(context);
+  FromJSValue(context, exception, kNoConversionFlags, &exception_state,
+              &exception_string);
+  return exception_string;
+}
+
 std::vector<StackFrame> GetStackTrace(JSContext* context, int max_frames) {
   JSAutoRequest auto_request(context);
   JS::StackDescription* stack_description =
diff --git a/src/cobalt/script/mozjs/util/exception_helpers.h b/src/cobalt/script/mozjs/util/exception_helpers.h
index 75dff27..7e5e563 100644
--- a/src/cobalt/script/mozjs/util/exception_helpers.h
+++ b/src/cobalt/script/mozjs/util/exception_helpers.h
@@ -16,6 +16,7 @@
 #ifndef COBALT_SCRIPT_MOZJS_UTIL_EXCEPTION_HELPERS_H_
 #define COBALT_SCRIPT_MOZJS_UTIL_EXCEPTION_HELPERS_H_
 
+#include <string>
 #include <vector>
 
 #include "cobalt/script/stack_frame.h"
@@ -25,6 +26,10 @@
 namespace script {
 namespace mozjs {
 namespace util {
+std::string GetExceptionString(JSContext* context);
+
+std::string GetExceptionString(JSContext* context, JS::HandleValue exception);
+
 std::vector<StackFrame> GetStackTrace(JSContext* context, int max_frames);
 }  // namespace util
 }  // namespace mozjs
diff --git a/src/cobalt/script/script.gyp b/src/cobalt/script/script.gyp
index c827de2..46cc245 100644
--- a/src/cobalt/script/script.gyp
+++ b/src/cobalt/script/script.gyp
@@ -38,6 +38,7 @@
       ],
       'dependencies': [
         '<(DEPTH)/cobalt/base/base.gyp:base',
+        '<(DEPTH)/nb/nb.gyp:nb',
       ]
     },
     {
diff --git a/src/cobalt/speech/microphone_manager.cc b/src/cobalt/speech/microphone_manager.cc
index ea3ba7d..4414a77 100644
--- a/src/cobalt/speech/microphone_manager.cc
+++ b/src/cobalt/speech/microphone_manager.cc
@@ -16,12 +16,6 @@
 
 #include "cobalt/speech/microphone_manager.h"
 
-#if defined(ENABLE_FAKE_MICROPHONE)
-#include "cobalt/speech/microphone_fake.h"
-#endif  // defined(ENABLE_FAKE_MICROPHONE)
-#if defined(SB_USE_SB_MICROPHONE)
-#include "cobalt/speech/microphone_starboard.h"
-#endif  // defined(SB_USE_SB_MICROPHONE)
 #include "cobalt/speech/speech_recognition_error.h"
 
 namespace cobalt {
@@ -34,26 +28,16 @@
 const float kMicReadRateInHertz = 60.0f;
 }  // namespace
 
-MicrophoneManager::MicrophoneManager(int sample_rate,
-                                     const DataReceivedCallback& data_received,
-                                     const CompletionCallback& completion,
-                                     const ErrorCallback& error,
-                                     const Microphone::Options& options)
-    : sample_rate_(sample_rate),
-      data_received_callback_(data_received),
+MicrophoneManager::MicrophoneManager(
+    const DataReceivedCallback& data_received,
+    const CompletionCallback& completion, const ErrorCallback& error,
+    const MicrophoneCreator& microphone_creator)
+    : data_received_callback_(data_received),
       completion_callback_(completion),
       error_callback_(error),
-#if defined(ENABLE_FAKE_MICROPHONE)
-      microphone_options_(options),
-#endif  // defined(ENABLE_FAKE_MICROPHONE)
+      microphone_creator_(microphone_creator),
       state_(kStopped),
       thread_("microphone_thread") {
-  UNREFERENCED_PARAMETER(sample_rate_);
-#if defined(ENABLE_FAKE_MICROPHONE)
-  UNREFERENCED_PARAMETER(microphone_options_);
-#else
-  UNREFERENCED_PARAMETER(options);
-#endif  // defined(ENABLE_FAKE_MICROPHONE)
   thread_.StartWithOptions(base::Thread::Options(MessageLoop::TYPE_IO, 0));
 }
 
@@ -82,19 +66,7 @@
     return true;
   }
 
-#if defined(SB_USE_SB_MICROPHONE)
-#if defined(ENABLE_FAKE_MICROPHONE)
-  if (microphone_options_.enable_fake_microphone) {
-    microphone_.reset(new MicrophoneFake(microphone_options_));
-  } else {
-    microphone_.reset(
-        new MicrophoneStarboard(sample_rate_, kBufferSizeInBytes));
-  }
-#else
-  microphone_.reset(new MicrophoneStarboard(sample_rate_, kBufferSizeInBytes));
-#endif  // defined(ENABLE_FAKE_MICROPHONE)
-#endif  // defined(SB_USE_SB_MICROPHONE)
-
+  microphone_ = microphone_creator_.Run(kBufferSizeInBytes);
   if (microphone_ && microphone_->IsValid()) {
     state_ = kStopped;
     return true;
@@ -163,7 +135,7 @@
   DCHECK(microphone_);
   DCHECK(microphone_->MinMicrophoneReadInBytes() <= kBufferSizeInBytes);
 
-  static int16_t samples[kBufferSizeInBytes / sizeof(int16_t)];
+  int16_t samples[kBufferSizeInBytes / sizeof(int16_t)];
   int read_bytes =
       microphone_->Read(reinterpret_cast<char*>(samples), kBufferSizeInBytes);
   // If |read_bytes| is zero, nothing should happen.
diff --git a/src/cobalt/speech/microphone_manager.h b/src/cobalt/speech/microphone_manager.h
index c07c21a..08eaf6e 100644
--- a/src/cobalt/speech/microphone_manager.h
+++ b/src/cobalt/speech/microphone_manager.h
@@ -38,11 +38,12 @@
   typedef base::Callback<void(scoped_ptr<ShellAudioBus>)> DataReceivedCallback;
   typedef base::Callback<void(void)> CompletionCallback;
   typedef base::Callback<void(const scoped_refptr<dom::Event>&)> ErrorCallback;
+  typedef base::Callback<scoped_ptr<Microphone>(int)> MicrophoneCreator;
 
-  MicrophoneManager(int sample_rate, const DataReceivedCallback& data_received,
+  MicrophoneManager(const DataReceivedCallback& data_received,
                     const CompletionCallback& completion,
                     const ErrorCallback& error,
-                    const Microphone::Options& options);
+                    const MicrophoneCreator& microphone_creator);
 
   ~MicrophoneManager();
 
@@ -65,15 +66,12 @@
   // Timer callback for fetching audio data.
   void Read();
 
-  int sample_rate_;
   const DataReceivedCallback data_received_callback_;
   const CompletionCallback completion_callback_;
   const ErrorCallback error_callback_;
+  const MicrophoneCreator microphone_creator_;
 
   scoped_ptr<Microphone> microphone_;
-#if defined(ENABLE_FAKE_MICROPHONE)
-  Microphone::Options microphone_options_;
-#endif  // defined(ENABLE_FAKE_MICROPHONE)
 
   // Microphone state.
   State state_;
diff --git a/src/cobalt/speech/speech.gyp b/src/cobalt/speech/speech.gyp
index 4d431dd..c016372 100644
--- a/src/cobalt/speech/speech.gyp
+++ b/src/cobalt/speech/speech.gyp
@@ -77,6 +77,8 @@
           'sources': [
             'microphone_fake.cc',
             'microphone_fake.h',
+            'url_fetcher_fake.cc',
+            'url_fetcher_fake.h',
           ],
           'defines': [
             'ENABLE_FAKE_MICROPHONE',
diff --git a/src/cobalt/speech/speech_recognition_manager.cc b/src/cobalt/speech/speech_recognition_manager.cc
index 0b4ffdf..4eab7de 100644
--- a/src/cobalt/speech/speech_recognition_manager.cc
+++ b/src/cobalt/speech/speech_recognition_manager.cc
@@ -19,7 +19,15 @@
 #include "base/bind.h"
 #include "cobalt/base/tokens.h"
 #include "cobalt/dom/dom_exception.h"
+#if defined(ENABLE_FAKE_MICROPHONE)
+#include "cobalt/speech/microphone_fake.h"
+#include "cobalt/speech/url_fetcher_fake.h"
+#endif  // defined(ENABLE_FAKE_MICROPHONE)
 #include "cobalt/speech/microphone_manager.h"
+#if defined(SB_USE_SB_MICROPHONE)
+#include "cobalt/speech/microphone_starboard.h"
+#endif  // defined(SB_USE_SB_MICROPHONE)
+#include "net/url_request/url_fetcher.h"
 
 namespace cobalt {
 namespace speech {
@@ -27,6 +35,40 @@
 namespace {
 const int kSampleRate = 16000;
 const float kAudioPacketDurationInSeconds = 0.1f;
+
+scoped_ptr<net::URLFetcher> CreateURLFetcher(
+    const GURL& url, net::URLFetcher::RequestType request_type,
+    net::URLFetcherDelegate* delegate) {
+  return make_scoped_ptr<net::URLFetcher>(
+      net::URLFetcher::Create(url, request_type, delegate));
+}
+
+scoped_ptr<Microphone> CreateMicrophone(int buffer_size_bytes) {
+#if defined(SB_USE_SB_MICROPHONE)
+  return make_scoped_ptr<Microphone>(
+      new MicrophoneStarboard(kSampleRate, buffer_size_bytes));
+#else
+  UNREFERENCED_PARAMETER(buffer_size_bytes);
+  return scoped_ptr<Microphone>();
+#endif  // defined(SB_USE_SB_MICROPHONE)
+}
+
+#if defined(SB_USE_SB_MICROPHONE)
+#if defined(ENABLE_FAKE_MICROPHONE)
+scoped_ptr<net::URLFetcher> CreateFakeURLFetcher(
+    const GURL& url, net::URLFetcher::RequestType request_type,
+    net::URLFetcherDelegate* delegate) {
+  return make_scoped_ptr<net::URLFetcher>(
+      new URLFetcherFake(url, request_type, delegate));
+}
+
+scoped_ptr<Microphone> CreateFakeMicrophone(const Microphone::Options& options,
+                                            int /*buffer_size_bytes*/) {
+  return make_scoped_ptr<Microphone>(new MicrophoneFake(options));
+}
+#endif  // defined(ENABLE_FAKE_MICROPHONE)
+#endif  // defined(SB_USE_SB_MICROPHONE)
+
 }  // namespace
 
 SpeechRecognitionManager::SpeechRecognitionManager(
@@ -36,20 +78,38 @@
       weak_this_(weak_ptr_factory_.GetWeakPtr()),
       main_message_loop_(base::MessageLoopProxy::current()),
       event_callback_(event_callback),
-      ALLOW_THIS_IN_INITIALIZER_LIST(
-          recognizer_(network_module,
-                      base::Bind(&SpeechRecognitionManager::OnRecognizerEvent,
-                                 base::Unretained(this)))),
-      ALLOW_THIS_IN_INITIALIZER_LIST(microphone_manager_(new MicrophoneManager(
-          kSampleRate, base::Bind(&SpeechRecognitionManager::OnDataReceived,
-                                  base::Unretained(this)),
-          base::Bind(&SpeechRecognitionManager::OnDataCompletion,
-                     base::Unretained(this)),
-          base::Bind(&SpeechRecognitionManager::OnMicError,
-                     base::Unretained(this)),
-          microphone_options))),
       endpointer_delegate_(kSampleRate),
-      state_(kStopped) {}
+      state_(kStopped) {
+  UNREFERENCED_PARAMETER(microphone_options);
+
+  SpeechRecognizer::URLFetcherCreator url_fetcher_creator =
+      base::Bind(&CreateURLFetcher);
+  MicrophoneManager::MicrophoneCreator microphone_creator =
+      base::Bind(&CreateMicrophone);
+
+#if defined(SB_USE_SB_MICROPHONE)
+#if defined(ENABLE_FAKE_MICROPHONE)
+  if (microphone_options.enable_fake_microphone) {
+    // If fake microphone is enabled, fake URL fetchers should be enabled as
+    // well.
+    url_fetcher_creator = base::Bind(&CreateFakeURLFetcher);
+    microphone_creator = base::Bind(&CreateFakeMicrophone, microphone_options);
+  }
+#endif  // defined(ENABLE_FAKE_MICROPHONE)
+#endif  // defined(SB_USE_SB_MICROPHONE)
+
+  recognizer_.reset(new SpeechRecognizer(
+      network_module, base::Bind(&SpeechRecognitionManager::OnRecognizerEvent,
+                                 base::Unretained(this)),
+      url_fetcher_creator));
+  microphone_manager_.reset(new MicrophoneManager(
+      base::Bind(&SpeechRecognitionManager::OnDataReceived,
+                 base::Unretained(this)),
+      base::Bind(&SpeechRecognitionManager::OnDataCompletion,
+                 base::Unretained(this)),
+      base::Bind(&SpeechRecognitionManager::OnMicError, base::Unretained(this)),
+      microphone_creator));
+}
 
 SpeechRecognitionManager::~SpeechRecognitionManager() { Stop(); }
 
@@ -65,7 +125,7 @@
     return;
   }
 
-  recognizer_.Start(config, kSampleRate);
+  recognizer_->Start(config, kSampleRate);
   microphone_manager_->Open();
   endpointer_delegate_.Start();
   state_ = kStarted;
@@ -82,7 +142,7 @@
 
   endpointer_delegate_.Stop();
   microphone_manager_->Close();
-  recognizer_.Stop();
+  recognizer_->Stop();
   state_ = kStopped;
   event_callback_.Run(new dom::Event(base::Tokens::soundend()));
 }
@@ -98,7 +158,7 @@
 
   endpointer_delegate_.Stop();
   microphone_manager_->Close();
-  recognizer_.Stop();
+  recognizer_->Stop();
   state_ = kAborted;
   event_callback_.Run(new dom::Event(base::Tokens::soundend()));
 }
@@ -118,7 +178,7 @@
     if (endpointer_delegate_.IsFirstTimeSoundStarted(*audio_bus)) {
       event_callback_.Run(new dom::Event(base::Tokens::soundstart()));
     }
-    recognizer_.RecognizeAudio(audio_bus.Pass(), false);
+    recognizer_->RecognizeAudio(audio_bus.Pass(), false);
   }
 }
 
@@ -140,7 +200,7 @@
     scoped_ptr<ShellAudioBus> dummy_audio_bus(new ShellAudioBus(
         1, dummy_frames, ShellAudioBus::kInt16, ShellAudioBus::kInterleaved));
     dummy_audio_bus->ZeroAllFrames();
-    recognizer_.RecognizeAudio(dummy_audio_bus.Pass(), true);
+    recognizer_->RecognizeAudio(dummy_audio_bus.Pass(), true);
   }
 }
 
@@ -174,7 +234,7 @@
 
   // An error is occured in Mic, so stop the energy endpointer and recognizer.
   endpointer_delegate_.Stop();
-  recognizer_.Stop();
+  recognizer_->Stop();
   state_ = kAborted;
   event_callback_.Run(new dom::Event(base::Tokens::soundend()));
 }
diff --git a/src/cobalt/speech/speech_recognition_manager.h b/src/cobalt/speech/speech_recognition_manager.h
index 6f0faa7..2d622dd 100644
--- a/src/cobalt/speech/speech_recognition_manager.h
+++ b/src/cobalt/speech/speech_recognition_manager.h
@@ -80,7 +80,7 @@
 
   // Callback for sending dom events if available.
   EventCallback event_callback_;
-  SpeechRecognizer recognizer_;
+  scoped_ptr<SpeechRecognizer> recognizer_;
 
   scoped_ptr<MicrophoneManager> microphone_manager_;
 
diff --git a/src/cobalt/speech/speech_recognizer.cc b/src/cobalt/speech/speech_recognizer.cc
index 902fd48..17806b8 100644
--- a/src/cobalt/speech/speech_recognizer.cc
+++ b/src/cobalt/speech/speech_recognizer.cc
@@ -164,10 +164,12 @@
 }  // namespace
 
 SpeechRecognizer::SpeechRecognizer(network::NetworkModule* network_module,
-                                   const EventCallback& event_callback)
+                                   const EventCallback& event_callback,
+                                   const URLFetcherCreator& fetcher_creator)
     : network_module_(network_module),
       started_(false),
       event_callback_(event_callback),
+      fetcher_creator_(fetcher_creator),
       thread_("speech_recognizer") {
   thread_.StartWithOptions(base::Thread::Options(MessageLoop::TYPE_IO, 0));
 }
@@ -264,8 +266,8 @@
   // Use protobuffer as the output format.
   down_url = AppendQueryParameter(down_url, "output", "pb");
 
-  downstream_fetcher_.reset(
-      net::URLFetcher::Create(down_url, net::URLFetcher::GET, this));
+  downstream_fetcher_ =
+      fetcher_creator_.Run(down_url, net::URLFetcher::GET, this);
   downstream_fetcher_->SetRequestContext(
       network_module_->url_request_context_getter());
   downstream_fetcher_->Start();
@@ -312,8 +314,7 @@
     up_url = AppendQueryParameter(up_url, "interim", "");
   }
 
-  upstream_fetcher_.reset(
-      net::URLFetcher::Create(up_url, net::URLFetcher::POST, this));
+  upstream_fetcher_ = fetcher_creator_.Run(up_url, net::URLFetcher::POST, this);
   upstream_fetcher_->SetRequestContext(
       network_module_->url_request_context_getter());
   upstream_fetcher_->SetChunkedUpload(encoder_->GetMimeType());
diff --git a/src/cobalt/speech/speech_recognizer.h b/src/cobalt/speech/speech_recognizer.h
index 55cd68f..5dac2c6 100644
--- a/src/cobalt/speech/speech_recognizer.h
+++ b/src/cobalt/speech/speech_recognizer.h
@@ -46,9 +46,13 @@
   typedef base::Callback<void(const scoped_refptr<dom::Event>&)> EventCallback;
   typedef SpeechRecognitionResultList::SpeechRecognitionResults
       SpeechRecognitionResults;
+  typedef base::Callback<scoped_ptr<net::URLFetcher>(
+      const GURL&, net::URLFetcher::RequestType, net::URLFetcherDelegate*)>
+      URLFetcherCreator;
 
   SpeechRecognizer(network::NetworkModule* network_module,
-                   const EventCallback& event_callback);
+                   const EventCallback& event_callback,
+                   const URLFetcherCreator& fetcher_creator);
   ~SpeechRecognizer() OVERRIDE;
 
   // Multiple calls to Start/Stop are allowed, the implementation should take
@@ -86,7 +90,10 @@
   scoped_ptr<net::URLFetcher> upstream_fetcher_;
   // Fetcher for receiving the streaming results.
   scoped_ptr<net::URLFetcher> downstream_fetcher_;
-  EventCallback event_callback_;
+  // Used to send speech recognition event.
+  const EventCallback event_callback_;
+  // Used to create url fetcher.
+  const URLFetcherCreator fetcher_creator_;
   // Used for processing proto buffer data.
   content::ChunkedByteBuffer chunked_byte_buffer_;
   // Used for accumulating final results.
diff --git a/src/cobalt/speech/url_fetcher_fake.cc b/src/cobalt/speech/url_fetcher_fake.cc
new file mode 100644
index 0000000..2d621cb
--- /dev/null
+++ b/src/cobalt/speech/url_fetcher_fake.cc
@@ -0,0 +1,176 @@
+/*
+ * 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/speech/url_fetcher_fake.h"
+
+#if defined(ENABLE_FAKE_MICROPHONE)
+
+#include "base/basictypes.h"
+#include "base/sys_byteorder.h"
+#include "cobalt/speech/google_streaming_api.pb.h"
+#include "net/url_request/url_fetcher_delegate.h"
+
+namespace cobalt {
+namespace speech {
+namespace {
+const int kDownloadTimerInterval = 100;
+
+struct RecognitionAlternative {
+  const char* transcript;
+  float confidence;
+};
+
+const RecognitionAlternative kAlternatives_1[] = {
+    {"tube", 0.0f},
+};
+
+const RecognitionAlternative kAlternatives_2[] = {
+    {"to be", 0.0f},
+};
+
+const RecognitionAlternative kAlternatives_3[] = {
+    {" or not", 0.0f},
+};
+
+const RecognitionAlternative kAlternatives_4[] = {
+    {" or not to be", 0.0f}, {"to be", 0.0f},
+};
+
+const RecognitionAlternative kAlternatives_5[] = {
+    {"to be or not to be", 0.728f}, {"2 B or not to be", 0.0f},
+};
+
+const RecognitionAlternative kAlternatives_6[] = {
+    {"that", 0.0f}, {"is the", 0.0f},
+};
+
+const RecognitionAlternative kAlternatives_7[] = {
+    {"that", 0.0f}, {"is the question", 0.0f},
+};
+
+const RecognitionAlternative kAlternatives_8[] = {
+    {"that is", 0.0f}, {"the question", 0.0f},
+};
+
+const RecognitionAlternative kAlternatives_9[] = {
+    {"that is the question", 0.8577f}, {"that is a question", 0.0f},
+};
+
+struct RecognitionResult {
+  const RecognitionAlternative* alternatives;
+  bool final;
+  size_t number_of_alternatives;
+};
+
+const RecognitionResult kRecognitionResults[] = {
+    {kAlternatives_1, false, SB_ARRAY_SIZE_INT(kAlternatives_1)},
+    {kAlternatives_2, false, SB_ARRAY_SIZE_INT(kAlternatives_2)},
+    {kAlternatives_3, false, SB_ARRAY_SIZE_INT(kAlternatives_3)},
+    {kAlternatives_4, false, SB_ARRAY_SIZE_INT(kAlternatives_4)},
+    {kAlternatives_5, true, SB_ARRAY_SIZE_INT(kAlternatives_5)},
+    {kAlternatives_6, false, SB_ARRAY_SIZE_INT(kAlternatives_6)},
+    {kAlternatives_7, false, SB_ARRAY_SIZE_INT(kAlternatives_7)},
+    {kAlternatives_8, false, SB_ARRAY_SIZE_INT(kAlternatives_8)},
+    {kAlternatives_9, true, SB_ARRAY_SIZE_INT(kAlternatives_9)},
+};
+
+std::string GetMockProtoResult(int index) {
+  proto::SpeechRecognitionEvent proto_event;
+  proto_event.set_status(proto::SpeechRecognitionEvent::STATUS_SUCCESS);
+  proto::SpeechRecognitionResult* proto_result = proto_event.add_result();
+  proto_result->set_final(kRecognitionResults[index].final);
+  const RecognitionAlternative* recognition_alternatives =
+      kRecognitionResults[index].alternatives;
+
+  for (size_t i = 0; i < kRecognitionResults[index].number_of_alternatives;
+       ++i) {
+    proto::SpeechRecognitionAlternative* proto_alternative =
+        proto_result->add_alternative();
+    proto_alternative->set_confidence(recognition_alternatives[i].confidence);
+    proto_alternative->set_transcript(recognition_alternatives[i].transcript);
+  }
+
+  std::string response_string;
+  proto_event.SerializeToString(&response_string);
+
+  // Prepend 4 byte prefix length indication to the protobuf message as
+  // envisaged by the google streaming recognition webservice protocol.
+  uint32_t prefix =
+      base::HostToNet32(static_cast<uint32_t>(response_string.size()));
+  response_string.insert(0, reinterpret_cast<char*>(&prefix), sizeof(prefix));
+  return response_string;
+}
+
+}  // namespace
+
+URLFetcherFake::URLFetcherFake(const GURL& url,
+                               net::URLFetcher::RequestType /*request_type*/,
+                               net::URLFetcherDelegate* delegate)
+    : original_url_(url),
+      delegate_(delegate),
+      is_chunked_upload_(false),
+      download_index_(0) {}
+
+URLFetcherFake::~URLFetcherFake() {}
+
+void URLFetcherFake::SetChunkedUpload(
+    const std::string& /*upload_content_type*/) {
+  is_chunked_upload_ = true;
+}
+
+void URLFetcherFake::AppendChunkToUpload(const std::string& /*data*/,
+                                         bool /*is_last_chunk*/) {
+  SB_DCHECK(is_chunked_upload_);
+  // no-op.
+}
+
+void URLFetcherFake::SetRequestContext(
+    net::URLRequestContextGetter* /*request_context_getter*/) {
+  // no-op.
+}
+
+void URLFetcherFake::Start() {
+  if (!is_chunked_upload_) {
+    download_timer_.emplace();
+    download_timer_->Start(
+        FROM_HERE, base::TimeDelta::FromMilliseconds(kDownloadTimerInterval),
+        this, &URLFetcherFake::OnURLFetchDownloadData);
+  }
+}
+
+const net::URLRequestStatus& URLFetcherFake::GetStatus() const {
+  return fake_status_;
+}
+
+int URLFetcherFake::GetResponseCode() const { return 200; }
+
+void URLFetcherFake::OnURLFetchDownloadData() {
+  SB_DCHECK(!is_chunked_upload_);
+  std::string result = GetMockProtoResult(download_index_);
+  delegate_->OnURLFetchDownloadData(
+      this, make_scoped_ptr<std::string>(new std::string(result)));
+  download_index_++;
+  if (download_index_ ==
+      static_cast<int>(SB_ARRAY_SIZE_INT(kRecognitionResults))) {
+    download_index_ = 0;
+    download_timer_->Stop();
+  }
+}
+
+}  // namespace speech
+}  // namespace cobalt
+
+#endif  // defined(ENABLE_FAKE_MICROPHONE)
diff --git a/src/cobalt/speech/url_fetcher_fake.h b/src/cobalt/speech/url_fetcher_fake.h
new file mode 100644
index 0000000..cf3c150
--- /dev/null
+++ b/src/cobalt/speech/url_fetcher_fake.h
@@ -0,0 +1,156 @@
+/*
+ * 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_SPEECH_URL_FETCHER_FAKE_H_
+#define COBALT_SPEECH_URL_FETCHER_FAKE_H_
+
+#include "cobalt/speech/speech_configuration.h"
+
+#if defined(ENABLE_FAKE_MICROPHONE)
+
+#include <string>
+
+#include "base/optional.h"
+#include "base/timer.h"
+#include "googleurl/src/gurl.h"
+#include "net/base/host_port_pair.h"
+#include "net/url_request/url_fetcher.h"
+#include "net/url_request/url_request_status.h"
+
+namespace cobalt {
+namespace speech {
+
+class URLFetcherFake : public net::URLFetcher {
+ public:
+  URLFetcherFake(const GURL& url, net::URLFetcher::RequestType request_type,
+                 net::URLFetcherDelegate* delegate);
+  virtual ~URLFetcherFake();
+
+  // URLFetcher implementation:
+  void SetUploadData(const std::string& /*upload_content_type*/,
+                     const std::string& /*upload_content*/) OVERRIDE {
+    NOTREACHED();
+  }
+  void SetChunkedUpload(const std::string& /*upload_content_type*/) OVERRIDE;
+  void AppendChunkToUpload(const std::string& data,
+                           bool is_last_chunk) OVERRIDE;
+  void SetLoadFlags(int /*load_flags*/) OVERRIDE { NOTREACHED(); }
+  int GetLoadFlags() const OVERRIDE {
+    NOTREACHED();
+    return 0;
+  }
+  void SetReferrer(const std::string& /*referrer*/) OVERRIDE { NOTREACHED(); }
+  void SetExtraRequestHeaders(
+      const std::string& /*extra_request_headers*/) OVERRIDE {
+    NOTREACHED();
+  }
+  void AddExtraRequestHeader(const std::string& /*header_line*/) OVERRIDE {
+    NOTREACHED();
+  }
+  void GetExtraRequestHeaders(
+      net::HttpRequestHeaders* /*headers*/) const OVERRIDE {
+    NOTREACHED();
+  }
+  void SetRequestContext(
+      net::URLRequestContextGetter* request_context_getter) OVERRIDE;
+  void SetFirstPartyForCookies(
+      const GURL& /*first_party_for_cookies*/) OVERRIDE {
+    NOTREACHED();
+  }
+  void SetURLRequestUserData(
+      const void* /*key*/,
+      const CreateDataCallback& /*create_data_callback*/) OVERRIDE {
+    NOTREACHED();
+  }
+  void SetStopOnRedirect(bool /*stop_on_redirect*/) OVERRIDE { NOTREACHED(); }
+  void SetAutomaticallyRetryOn5xx(bool /*retry*/) OVERRIDE { NOTREACHED(); }
+  void SetMaxRetriesOn5xx(int /*max_retries*/) OVERRIDE { NOTREACHED(); }
+  int GetMaxRetriesOn5xx() const OVERRIDE {
+    NOTREACHED();
+    return 0;
+  }
+  base::TimeDelta GetBackoffDelay() const OVERRIDE {
+    NOTREACHED();
+    return base::TimeDelta();
+  }
+  void SetAutomaticallyRetryOnNetworkChanges(int /*max_retries*/) OVERRIDE {
+    NOTREACHED();
+  }
+  void SaveResponseToFileAtPath(
+      const FilePath& /*file_path*/,
+      scoped_refptr<base::TaskRunner> /*file_task_runner*/) OVERRIDE {
+    NOTREACHED();
+  }
+  void SaveResponseToTemporaryFile(
+      scoped_refptr<base::TaskRunner> /*file_task_runner*/) OVERRIDE {
+    NOTREACHED();
+  }
+  void DiscardResponse() OVERRIDE { NOTREACHED(); }
+  net::HttpResponseHeaders* GetResponseHeaders() const OVERRIDE {
+    NOTREACHED();
+    return NULL;
+  }
+  net::HostPortPair GetSocketAddress() const OVERRIDE {
+    NOTREACHED();
+    return net::HostPortPair();
+  }
+  bool WasFetchedViaProxy() const OVERRIDE {
+    NOTREACHED();
+    return false;
+  }
+  void Start() OVERRIDE;
+  const GURL& GetOriginalURL() const OVERRIDE { return original_url_; }
+  const GURL& GetURL() const OVERRIDE { return original_url_; }
+  const net::URLRequestStatus& GetStatus() const OVERRIDE;
+  int GetResponseCode() const OVERRIDE;
+  const net::ResponseCookies& GetCookies() const OVERRIDE {
+    NOTREACHED();
+    return fake_cookies_;
+  }
+  bool FileErrorOccurred(
+      base::PlatformFileError* /*out_error_code*/) const OVERRIDE {
+    NOTREACHED();
+    return false;
+  }
+  void ReceivedContentWasMalformed() OVERRIDE { NOTREACHED(); }
+  bool GetResponseAsString(
+      std::string* /*out_response_string*/) const OVERRIDE {
+    NOTREACHED();
+    return false;
+  }
+  bool GetResponseAsFilePath(bool /*take_ownership*/,
+                             FilePath* /*out_response_path*/) const OVERRIDE {
+    NOTREACHED();
+    return false;
+  }
+
+ private:
+  void OnURLFetchDownloadData();
+
+  GURL original_url_;
+  net::URLFetcherDelegate* delegate_;
+  bool is_chunked_upload_;
+  int download_index_;
+  net::ResponseCookies fake_cookies_;
+  net::URLRequestStatus fake_status_;
+  base::optional<base::RepeatingTimer<URLFetcherFake> > download_timer_;
+};
+
+}  // namespace speech
+}  // namespace cobalt
+
+#endif  // defined(ENABLE_FAKE_MICROPHONE)
+#endif  // COBALT_SPEECH_URL_FETCHER_FAKE_H_
diff --git a/src/cobalt/storage/virtual_file.cc b/src/cobalt/storage/virtual_file.cc
index 64904c2..dcb93ed 100644
--- a/src/cobalt/storage/virtual_file.cc
+++ b/src/cobalt/storage/virtual_file.cc
@@ -87,7 +87,10 @@
     buffer_.resize(offset + bytes);
   }
 
-  memcpy(&buffer_[offset], source, bytes);
+  if (!buffer_.empty()) {
+    // std::vector does not define access to underlying array when empty
+    memcpy(&buffer_[offset], source, bytes);
+  }
   return bytes_in;
 }
 
diff --git a/src/cobalt/system_window/starboard/system_window.cc b/src/cobalt/system_window/starboard/system_window.cc
index 331e028..2f1b24a 100644
--- a/src/cobalt/system_window/starboard/system_window.cc
+++ b/src/cobalt/system_window/starboard/system_window.cc
@@ -103,6 +103,15 @@
   return math::Size(window_size.width, window_size.height);
 }
 
+float SystemWindowStarboard::GetVideoPixelRatio() const {
+  SbWindowSize window_size;
+  if (!SbWindowGetSize(window_, &window_size)) {
+    DLOG(WARNING) << "SbWindowGetSize() failed.";
+    return 1.0;
+  }
+  return window_size.video_pixel_ratio;
+}
+
 SbWindow SystemWindowStarboard::GetSbWindow() { return window_; }
 
 void* SystemWindowStarboard::GetWindowHandle() {
diff --git a/src/cobalt/system_window/starboard/system_window.h b/src/cobalt/system_window/starboard/system_window.h
index 7d6a76e..b733bb9 100644
--- a/src/cobalt/system_window/starboard/system_window.h
+++ b/src/cobalt/system_window/starboard/system_window.h
@@ -36,6 +36,7 @@
   ~SystemWindowStarboard() OVERRIDE;
 
   math::Size GetWindowSize() const OVERRIDE;
+  float GetVideoPixelRatio() const OVERRIDE;
 
   // Returns a handle to the Starboard window object.
   SbWindow GetSbWindow();
diff --git a/src/cobalt/system_window/system_window.h b/src/cobalt/system_window/system_window.h
index 4695652..82683e0 100644
--- a/src/cobalt/system_window/system_window.h
+++ b/src/cobalt/system_window/system_window.h
@@ -74,6 +74,11 @@
   // Returns the dimensions of the window.
   virtual math::Size GetWindowSize() const = 0;
 
+  // video pixel ratio = resolution of video output / resolution of window.  Its
+  // value is usually 1.0.  Set it to a value greater than 1.0 allows the video
+  // to be played in higher resolution than the window.
+  virtual float GetVideoPixelRatio() const { return 1.f; }
+
   base::EventDispatcher* event_dispatcher() const { return event_dispatcher_; }
 
  private:
diff --git a/src/cobalt/webdriver/element_driver.cc b/src/cobalt/webdriver/element_driver.cc
index 950581a..d295974 100644
--- a/src/cobalt/webdriver/element_driver.cc
+++ b/src/cobalt/webdriver/element_driver.cc
@@ -105,7 +105,7 @@
   Keyboard::TranslateToKeyEvents(keys.utf8_keys(), Keyboard::kReleaseModifiers,
                                  events.get());
   // Dispatch the keyboard events.
-  return util::CallOnMessageLoopWithRetry(
+  return util::CallOnMessageLoop(
       element_message_loop_,
       base::Bind(&ElementDriver::SendKeysInternal, base::Unretained(this),
                  base::Passed(&events)),
@@ -114,7 +114,7 @@
 
 util::CommandResult<protocol::ElementId> ElementDriver::FindElement(
     const protocol::SearchStrategy& strategy) {
-  return util::CallOnMessageLoopWithRetry(
+  return util::CallOnMessageLoop(
       element_message_loop_,
       base::Bind(&ElementDriver::FindElementsInternal<protocol::ElementId>,
                  base::Unretained(this), strategy),
@@ -123,7 +123,7 @@
 
 util::CommandResult<std::vector<protocol::ElementId> >
 ElementDriver::FindElements(const protocol::SearchStrategy& strategy) {
-  return util::CallOnMessageLoopWithRetry(
+  return util::CallOnMessageLoop(
       element_message_loop_,
       base::Bind(&ElementDriver::FindElementsInternal<ElementIdVector>,
                  base::Unretained(this), strategy),
@@ -132,7 +132,7 @@
 
 util::CommandResult<bool> ElementDriver::Equals(
     const ElementDriver* other_element_driver) {
-  return util::CallOnMessageLoopWithRetry(
+  return util::CallOnMessageLoop(
       element_message_loop_,
       base::Bind(&ElementDriver::EqualsInternal, base::Unretained(this),
                  other_element_driver),
diff --git a/src/cobalt/webdriver/session_driver.cc b/src/cobalt/webdriver/session_driver.cc
index 91f3358..5a59853 100644
--- a/src/cobalt/webdriver/session_driver.cc
+++ b/src/cobalt/webdriver/session_driver.cc
@@ -28,6 +28,9 @@
 // Default page-load timeout.
 const int kPageLoadTimeoutInSeconds = 30;
 
+// Max retries for the "can_retry" CommandResult case.
+const int kMaxRetries = 5;
+
 protocol::LogEntry::LogLevel SeverityToLogLevel(int severity) {
   switch (severity) {
     case logging::LOG_INFO:
@@ -82,7 +85,11 @@
 }
 
 util::CommandResult<void> SessionDriver::Navigate(const GURL& url) {
-  util::CommandResult<void> result = window_driver_->Navigate(url);
+  int retries = 0;
+  util::CommandResult<void> result;
+  do {
+    result = window_driver_->Navigate(url);
+  } while (result.can_retry() && (retries++ < kMaxRetries));
   if (result.is_success()) {
     // TODO: Use timeout as specified by the webdriver client.
     wait_for_navigation_.Run(
diff --git a/src/cobalt/webdriver/util/call_on_message_loop.h b/src/cobalt/webdriver/util/call_on_message_loop.h
index f3af96f..c2a19d2 100644
--- a/src/cobalt/webdriver/util/call_on_message_loop.h
+++ b/src/cobalt/webdriver/util/call_on_message_loop.h
@@ -123,24 +123,20 @@
 }
 
 // Tries to call |callback| on messageloop |message_loop_proxy|,
-// retrying a few times if the WebModule thread appears to have gone
-// away (perhaps because of navigation). If failure persists,
-// returns a CommandResult of |window_disappeared_code|.
+// but returns a CommandResult of |window_disappeared_code| if the
+// message loop has shut down. This can happen if a WebModule shuts
+// down due to a page navigation.
 template <typename ReturnValue>
-util::CommandResult<ReturnValue> CallOnMessageLoopWithRetry(
+util::CommandResult<ReturnValue> CallOnMessageLoop(
     const scoped_refptr<base::MessageLoopProxy>& message_loop_proxy,
     const base::Callback<util::CommandResult<ReturnValue>(void)>& callback,
     protocol::Response::StatusCode window_disappeared_code) {
   util::CommandResult<ReturnValue> result;
-
-  const int kRetryAttempts = 5;
-  bool success = false;
-  for (int i = 0; !success && i < kRetryAttempts; i++) {
-    success = TryCallOnMessageLoop(message_loop_proxy, callback, &result);
-  }
+  bool success = TryCallOnMessageLoop(message_loop_proxy, callback, &result);
 
   if (!success) {
-    result = util::CommandResult<ReturnValue>(window_disappeared_code);
+    result =
+        util::CommandResult<ReturnValue>(window_disappeared_code, "", true);
   }
   return result;
 }
diff --git a/src/cobalt/webdriver/util/command_result.h b/src/cobalt/webdriver/util/command_result.h
index d1254c7..8944d4d 100644
--- a/src/cobalt/webdriver/util/command_result.h
+++ b/src/cobalt/webdriver/util/command_result.h
@@ -32,12 +32,17 @@
  public:
   CommandResult() : status_code_(protocol::Response::kUnknownError) {}
   explicit CommandResult(protocol::Response::StatusCode status)
-      : status_code_(status) {}
+      : status_code_(status), can_retry_(false) {}
   CommandResult(protocol::Response::StatusCode status,
                 const std::string& message)
-      : status_code_(status), error_message_(message) {}
+      : status_code_(status), error_message_(message), can_retry_(false) {}
+  CommandResult(protocol::Response::StatusCode status,
+                const std::string& message, bool can_retry)
+      : status_code_(status), error_message_(message), can_retry_(can_retry) {}
   explicit CommandResult(const T& result)
-      : status_code_(protocol::Response::kSuccess), result_(result) {}
+      : status_code_(protocol::Response::kSuccess),
+        result_(result),
+        can_retry_(false) {}
 
   bool is_success() const {
     return status_code_ == protocol::Response::kSuccess;
@@ -45,11 +50,16 @@
   protocol::Response::StatusCode status_code() const { return status_code_; }
   const T& result() const { return result_.value(); }
   std::string error_message() const { return error_message_.value_or(""); }
+  // Returns true if this result occurred due to a transient issue,
+  // such as the WebModule going away. Retrying w/ a new WebModule
+  // may succeed.
+  bool can_retry() const { return can_retry_; }
 
  private:
   protocol::Response::StatusCode status_code_;
   base::optional<T> result_;
   base::optional<std::string> error_message_;
+  bool can_retry_;
 };
 
 template <>
@@ -57,20 +67,28 @@
  public:
   CommandResult() : status_code_(protocol::Response::kUnknownError) {}
   explicit CommandResult(protocol::Response::StatusCode status)
-      : status_code_(status) {}
+      : status_code_(status), can_retry_(false) {}
   CommandResult(protocol::Response::StatusCode status,
                 const std::string& message)
-      : status_code_(status), error_message_(message) {}
+      : status_code_(status), error_message_(message), can_retry_(false) {}
+  CommandResult(protocol::Response::StatusCode status,
+                const std::string& message, bool can_retry)
+      : status_code_(status), error_message_(message), can_retry_(can_retry) {}
 
   bool is_success() const {
     return status_code_ == protocol::Response::kSuccess;
   }
   protocol::Response::StatusCode status_code() const { return status_code_; }
   std::string error_message() const { return error_message_.value_or(""); }
+  // Returns true if this result occurred due to a transient issue,
+  // such as the WebModule going away. Retrying w/ a new WebModule
+  // may succeed.
+  bool can_retry() const { return can_retry_; }
 
  private:
   protocol::Response::StatusCode status_code_;
   base::optional<std::string> error_message_;
+  bool can_retry_;
 };
 
 }  // namespace util
diff --git a/src/cobalt/webdriver/util/dispatch_command_factory.h b/src/cobalt/webdriver/util/dispatch_command_factory.h
index 1e45e4b..cfed299 100644
--- a/src/cobalt/webdriver/util/dispatch_command_factory.h
+++ b/src/cobalt/webdriver/util/dispatch_command_factory.h
@@ -122,6 +122,9 @@
 template <class DriverClassT>
 class DispatchCommandFactory
     : public base::RefCounted<DispatchCommandFactory<DriverClassT> > {
+  // Max retries for the "can_retry" CommandResult case.
+  static const int kMaxRetries = 5;
+
  public:
   // Typedef'd for less verbose code.
   typedef WebDriverDispatcher::CommandResultHandler CommandResultHandler;
@@ -220,7 +223,11 @@
         DriverClassT* driver, const base::Value* parameters,
         CommandResultHandler* result_handler) {
       // Ignore parameters.
-      util::CommandResult<R> command_result = driver_command.Run(driver);
+      int retries = 0;
+      util::CommandResult<R> command_result;
+      do {
+        command_result = driver_command.Run(driver);
+      } while (command_result.can_retry() && (retries++ < kMaxRetries));
       internal::ReturnResponse(session_id, command_result, result_handler);
     }
 
@@ -245,8 +252,11 @@
         result_handler->SendInvalidRequestResponse(
             WebDriverDispatcher::CommandResultHandler::kInvalidParameters, "");
       } else {
-        util::CommandResult<R> command_result =
-            driver_command.Run(driver, param.value());
+        int retries = 0;
+        util::CommandResult<R> command_result;
+        do {
+          command_result = driver_command.Run(driver, param.value());
+        } while (command_result.can_retry() && (retries++ < kMaxRetries));
         internal::ReturnResponse(session_id, command_result, result_handler);
       }
     }
diff --git a/src/cobalt/webdriver/window_driver.cc b/src/cobalt/webdriver/window_driver.cc
index 30c1415..b23abc2 100644
--- a/src/cobalt/webdriver/window_driver.cc
+++ b/src/cobalt/webdriver/window_driver.cc
@@ -162,7 +162,7 @@
 
 util::CommandResult<void> WindowDriver::Navigate(const GURL& url) {
   DCHECK(thread_checker_.CalledOnValidThread());
-  return util::CallOnMessageLoopWithRetry(
+  return util::CallOnMessageLoop(
       window_message_loop_,
       base::Bind(&WindowDriver::NavigateInternal, base::Unretained(this), url),
       protocol::Response::kNoSuchWindow);
@@ -190,7 +190,7 @@
     const protocol::SearchStrategy& strategy) {
   DCHECK(thread_checker_.CalledOnValidThread());
 
-  return util::CallOnMessageLoopWithRetry(
+  return util::CallOnMessageLoop(
       window_message_loop_,
       base::Bind(&WindowDriver::FindElementsInternal<protocol::ElementId>,
                  base::Unretained(this), strategy),
@@ -200,7 +200,7 @@
 util::CommandResult<std::vector<protocol::ElementId> >
 WindowDriver::FindElements(const protocol::SearchStrategy& strategy) {
   DCHECK(thread_checker_.CalledOnValidThread());
-  return util::CallOnMessageLoopWithRetry(
+  return util::CallOnMessageLoop(
       window_message_loop_,
       base::Bind(&WindowDriver::FindElementsInternal<ElementIdVector>,
                  base::Unretained(this), strategy),
@@ -226,7 +226,7 @@
 
   SyncExecuteResultHandler result_handler;
 
-  CommandResult result = util::CallOnMessageLoopWithRetry(
+  CommandResult result = util::CallOnMessageLoop(
       window_message_loop_,
       base::Bind(&WindowDriver::ExecuteScriptInternal, base::Unretained(this),
                  script, base::nullopt, &result_handler),
@@ -249,7 +249,7 @@
   const base::TimeDelta kDefaultAsyncTimeout =
       base::TimeDelta::FromMilliseconds(0);
   AsyncExecuteResultHandler result_handler;
-  CommandResult result = util::CallOnMessageLoopWithRetry(
+  CommandResult result = util::CallOnMessageLoop(
       window_message_loop_,
       base::Bind(&WindowDriver::ExecuteScriptInternal, base::Unretained(this),
                  script, kDefaultAsyncTimeout, &result_handler),
@@ -274,7 +274,7 @@
   Keyboard::TranslateToKeyEvents(keys.utf8_keys(), Keyboard::kKeepModifiers,
                                  events.get());
   // Dispatch the keyboard events.
-  return util::CallOnMessageLoopWithRetry(
+  return util::CallOnMessageLoop(
       window_message_loop_,
       base::Bind(&WindowDriver::SendKeysInternal, base::Unretained(this),
                  base::Passed(&events)),
@@ -282,7 +282,7 @@
 }
 
 util::CommandResult<protocol::ElementId> WindowDriver::GetActiveElement() {
-  return util::CallOnMessageLoopWithRetry(
+  return util::CallOnMessageLoop(
       window_message_loop_, base::Bind(&WindowDriver::GetActiveElementInternal,
                                        base::Unretained(this)),
       protocol::Response::kNoSuchWindow);
@@ -330,10 +330,10 @@
 util::CommandResult<void> WindowDriver::AddCookie(
     const protocol::Cookie& cookie) {
   DCHECK(thread_checker_.CalledOnValidThread());
-  return util::CallOnMessageLoopWithRetry(
-      window_message_loop_, base::Bind(&WindowDriver::AddCookieInternal,
-                                       base::Unretained(this), cookie),
-      protocol::Response::kNoSuchWindow);
+  return util::CallOnMessageLoop(window_message_loop_,
+                                 base::Bind(&WindowDriver::AddCookieInternal,
+                                            base::Unretained(this), cookie),
+                                 protocol::Response::kNoSuchWindow);
 }
 
 protocol::ElementId WindowDriver::ElementToId(
diff --git a/src/cobalt/webdriver_benchmarks/tv_testcase.py b/src/cobalt/webdriver_benchmarks/tv_testcase.py
index 57a7b77..c9a16ca 100644
--- a/src/cobalt/webdriver_benchmarks/tv_testcase.py
+++ b/src/cobalt/webdriver_benchmarks/tv_testcase.py
@@ -41,6 +41,11 @@
 BASE_PARAMS = {"env_forcedOffAllExperiments": True}
 PAGE_LOAD_WAIT_SECONDS = 30
 LAYOUT_TIMEOUT_SECONDS = 5
+# Today, Cobalt's WebDriver has a race that
+# can leave the former page's DOM visible after a navigate.
+# As a workaround, sleep for a bit
+# b/33275371
+COBALT_POST_NAVIGATE_SLEEP_SECONDS = 5
 
 
 def _percentile(results, percentile):
@@ -176,6 +181,7 @@
     parsed_url[4] = urlencode(query_dict, doseq=True)
     final_url = urlparse.urlunparse(parsed_url)
     self.get_webdriver().get(final_url)
+    time.sleep(COBALT_POST_NAVIGATE_SLEEP_SECONDS)
 
   def load_tv(self, label=None, additional_query_params=None):
     """Loads the main TV page and waits for it to display.
diff --git a/src/nb/analytics/memory_tracker.cc b/src/nb/analytics/memory_tracker.cc
index 8cb7664..56471dd 100644
--- a/src/nb/analytics/memory_tracker.cc
+++ b/src/nb/analytics/memory_tracker.cc
@@ -31,11 +31,37 @@
   return t;
 }
 
+
+MemoryStats GetProcessMemoryStats() {
+  MemoryStats memory_stats;
+
+  memory_stats.total_cpu_memory = SbSystemGetTotalCPUMemory();
+  memory_stats.used_cpu_memory = SbSystemGetUsedCPUMemory();
+
+  if (SbSystemHasCapability(kSbSystemCapabilityCanQueryGPUMemoryStats)) {
+    int64_t used_gpu_memory = SbSystemGetUsedGPUMemory();
+    memory_stats.total_gpu_memory = SbSystemGetTotalGPUMemory();
+    memory_stats.used_gpu_memory = SbSystemGetUsedGPUMemory();
+  }
+  return memory_stats;
+}
+
 nb::scoped_ptr<MemoryTrackerPrintThread>
 CreateDebugPrintThread(MemoryTracker* memory_tracker) {
   return nb::scoped_ptr<MemoryTrackerPrintThread>(
      new MemoryTrackerPrintThread(memory_tracker));
 }
 
+nb::scoped_ptr<MemoryTrackerPrintCSVThread>
+CreateDebugPrintCSVThread(MemoryTracker* memory_tracker,
+                          int sample_interval_ms,
+                          int total_sampling_time_ms) {
+  return nb::scoped_ptr<MemoryTrackerPrintCSVThread>(
+      new MemoryTrackerPrintCSVThread(
+          memory_tracker,
+          sample_interval_ms,
+          total_sampling_time_ms));
+}
+
 }  // namespace analytics
 }  // namespace nb
diff --git a/src/nb/analytics/memory_tracker.h b/src/nb/analytics/memory_tracker.h
index 4884c89..7d1c332 100644
--- a/src/nb/analytics/memory_tracker.h
+++ b/src/nb/analytics/memory_tracker.h
@@ -28,10 +28,22 @@
 
 class MemoryTracker;
 class MemoryTrackerPrintThread;
+class MemoryTrackerPrintCSVThread;
 class AllocationVisitor;
 class AllocationGroup;
 class AllocationRecord;
 
+struct MemoryStats {
+  MemoryStats() : total_cpu_memory(0), used_cpu_memory(0),
+                  total_gpu_memory(0), used_gpu_memory(0) {}
+  int64_t total_cpu_memory;
+  int64_t used_cpu_memory;
+  int64_t total_gpu_memory;
+  int64_t used_gpu_memory;
+};
+
+MemoryStats GetProcessMemoryStats();
+
 // Creates a MemoryTracker instance that implements the
 //  MemoryTracker. Once the instance is created it can begin tracking
 //  system allocations by calling InstallGlobalTrackingHooks().
@@ -142,6 +154,15 @@
 scoped_ptr<MemoryTrackerPrintThread>
     CreateDebugPrintThread(MemoryTracker* memory_tracker);
 
+// Creates a SimpleThread that will output the state of the memory
+// periodically. Start()/Cancel()/Join() are called AUTOMATICALLY with
+// this object. Start() is on the returned thread before it is returned.
+// Join() is automatically called on destruction.
+scoped_ptr<MemoryTrackerPrintCSVThread>
+    CreateDebugPrintCSVThread(MemoryTracker* memory_tracker,
+                              int sample_interval_ms,
+                              int total_sampling_time_ms);
+
 }  // namespace analytics
 }  // namespace nb
 
diff --git a/src/nb/analytics/memory_tracker_impl.cc b/src/nb/analytics/memory_tracker_impl.cc
index 3a9bdf4..a4a8c89 100644
--- a/src/nb/analytics/memory_tracker_impl.cc
+++ b/src/nb/analytics/memory_tracker_impl.cc
@@ -16,15 +16,66 @@
 
 #include "nb/analytics/memory_tracker_impl.h"
 
+#include <cstring>
 #include <iomanip>
+#include <iterator>
 #include <sstream>
 
 #include "nb/atomic.h"
-#include "starboard/log.h"
 #include "starboard/atomic.h"
+#include "starboard/log.h"
+#include "starboard/time.h"
 
 namespace nb {
 namespace analytics {
+namespace {
+// NoMemoryTracking will disable memory tracking while in the current scope of
+// execution. When the object is destroyed it will reset the previous state
+// of allocation tracking.
+// Example:
+//   void Foo() {
+//     NoMemoryTracking no_memory_tracking_in_scope;
+//     int* ptr = new int();  // ptr is not tracked.
+//     delete ptr;
+//     return;    // Previous memory tracking state is restored.
+//   }
+class NoMemoryTracking {
+ public:
+  NoMemoryTracking(MemoryTracker* owner) : owner_(owner) {
+    prev_val_ = owner_->IsMemoryTrackingEnabled();
+    owner_->SetMemoryTrackingEnabled(false);
+  }
+  ~NoMemoryTracking() { owner_->SetMemoryTrackingEnabled(prev_val_); }
+
+ private:
+  bool prev_val_;
+  MemoryTracker* owner_;
+};
+
+// This is a simple algorithm to remove the "needle" from the haystack. Note
+// that this function is simple and not well optimized.
+std::string RemoveString(const std::string& haystack, const char* needle) {

+  const size_t NOT_FOUND = std::string::npos;

+

+  // Base case. No modification needed.

+  size_t pos = haystack.find(needle);

+  if (pos == NOT_FOUND) {

+    return haystack;

+  }

+  const size_t n = strlen(needle);

+  std::string output;

+  output.reserve(haystack.size());

+

+  // Copy string, omitting the portion containing the "needle".

+  std::copy(haystack.begin(), haystack.begin() + pos,

+            std::back_inserter(output));

+  std::copy(haystack.begin() + pos + n, haystack.end(),

+            std::back_inserter(output));

+

+  // Recursively remove same needle in haystack.

+  return RemoveString(output, needle);

+}
+}  // namespace
 
 SbMemoryReporter* MemoryTrackerImpl::GetMemoryReporter() {
   return &sb_memory_tracker_;
@@ -197,7 +248,7 @@
   // We might do something more interesting with UnMapMemory calls later.
   OnDealloc(context, memory);
 }
-

+
 void MemoryTrackerImpl::OnPushAllocationGroup(
     void* context,
     NbMemoryScopeInfo* memory_scope_info) {
@@ -346,15 +397,15 @@
       prev_group_name = "none";
     }
 
-    if (!added) {

-      std::stringstream ss;

-      ss << "\nUnexpected condition, previous allocation was not removed:\n"

-         << "\tprevious alloc group: " << prev_group_name << "\n"

-         << "\tnew alloc group: " << group->name() << "\n"

-         << "\tprevious size: " << unexpected_alloc.size << "\n"

-         << "\tnew size: " << size << "\n";

-

-      SbLogRaw(ss.str().c_str());

+    if (!added) {
+      std::stringstream ss;
+      ss << "\nUnexpected condition, previous allocation was not removed:\n"
+         << "\tprevious alloc group: " << prev_group_name << "\n"
+         << "\tnew alloc group: " << group->name() << "\n"
+         << "\tprevious size: " << unexpected_alloc.size << "\n"
+         << "\tnew size: " << size << "\n";
+
+      SbLogRaw(ss.str().c_str());
     }
   }
   return added;
@@ -448,19 +499,8 @@
 }
 
 void MemoryTrackerPrintThread::Run() {
-  struct NoMemTracking {
-    NoMemTracking(MemoryTracker* owner) : owner_(owner) {
-      prev_val_ = owner_->IsMemoryTrackingEnabled();
-      owner_->SetMemoryTrackingEnabled(false);
-    }
-    ~NoMemTracking() { owner_->SetMemoryTrackingEnabled(prev_val_); }
-
-    bool prev_val_;
-    MemoryTracker* owner_;
-  };
-
   while (!finished_.load()) {
-    NoMemTracking no_mem_tracking_in_this_scope(memory_tracker_);
+    NoMemoryTracking no_mem_tracking_in_this_scope(memory_tracker_);
 
     // std::map<std::string, const AllocationGroup*> output;
     // typedef std::map<std::string, const AllocationGroup*>::const_iterator
@@ -539,5 +579,258 @@
   }
 }
 
+MemoryTrackerPrintCSVThread::MemoryTrackerPrintCSVThread(
+    MemoryTracker* memory_tracker,
+    int sampling_interval_ms,
+    int sampling_time_ms)
+    : SimpleThread("MemoryTrackerPrintCSVThread"),
+      memory_tracker_(memory_tracker),
+      sample_interval_ms_(sampling_interval_ms),
+      sampling_time_ms_(sampling_time_ms),
+      start_time_(SbTimeGetNow()) {
+  Start();
+}
+
+
+MemoryTrackerPrintCSVThread::~MemoryTrackerPrintCSVThread() {
+  Cancel();
+  Join();
+}
+
+void MemoryTrackerPrintCSVThread::Cancel() {
+  canceled_.store(true);
+}
+
+std::string MemoryTrackerPrintCSVThread::ToCsvString(
+    const MapAllocationSamples& samples_in) {
+  typedef MapAllocationSamples Map;
+  typedef Map::const_iterator MapIt;
+
+  const char QUOTE[] = "\"";
+  const char DELIM[] = ",";
+  const char NEW_LINE[] = "\n";
+
+  size_t largest_sample_size = 0;
+  size_t smallest_sample_size = INT_MAX;
+
+  // Sanitize samples_in and store as samples.
+  MapAllocationSamples samples;
+  for (MapIt it = samples_in.begin(); it != samples_in.end(); ++it) {
+    std::string name = it->first;
+    const AllocationSamples& value = it->second;
+
+    if (value.allocated_bytes_.size() != value.number_allocations_.size()) {
+      SB_NOTREACHED() << "Error at " << __FILE__ << ":" << __LINE__;
+      return "ERROR";
+    }
+
+    const size_t n = value.allocated_bytes_.size();
+    if (n > largest_sample_size) {
+      largest_sample_size = n;
+    }
+    if (n < smallest_sample_size) {
+      smallest_sample_size = n;
+    }
+
+    // Strip out any characters that could make parsing the csv difficult.
+    name = RemoveString(name, QUOTE);
+    name = RemoveString(name, DELIM);
+    name = RemoveString(name, NEW_LINE);
+
+    const bool duplicate_found = (samples.end() != samples.find(name));
+    if (duplicate_found) {
+      SB_NOTREACHED() << "Error, duplicate found for entry: "
+                      << name << NEW_LINE;
+    }
+    // Store value as a sanitized sample.
+    samples[name] = value;
+  }
+
+  SB_DCHECK(largest_sample_size == smallest_sample_size);
+
+  std::stringstream ss;
+
+  // Begin output to CSV.
+  // Sometimes we need to skip the CPU memory entry.
+  const MapIt total_cpu_memory_it = samples.find(UntrackedMemoryKey());
+
+  // Preamble
+  ss << NEW_LINE << "//////////////////////////////////////////////";
+  ss << NEW_LINE << "// CSV of bytes / allocation" << NEW_LINE;
+  // HEADER.
+  ss << "Name" << DELIM << QUOTE << "Bytes/Alloc" << QUOTE << NEW_LINE;
+  // DATA.
+  for (MapIt it = samples.begin(); it != samples.end(); ++it) {
+    if (total_cpu_memory_it == it) {
+      continue;
+    }
+
+    const AllocationSamples& samples = it->second;
+    if (samples.allocated_bytes_.empty() ||
+        samples.number_allocations_.empty()) {
+      SB_NOTREACHED() << "Should not be here";
+      return "ERROR";
+    }
+    const int32_t n_allocs = samples.number_allocations_.back();
+    const int64_t n_bytes = samples.allocated_bytes_.back();
+    int bytes_per_alloc = 0;
+    if (n_allocs > 0) {
+      bytes_per_alloc = n_bytes / n_allocs;
+    }
+    const std::string& name = it->first;
+    ss << QUOTE << name << QUOTE << DELIM << bytes_per_alloc << NEW_LINE;
+  }
+  ss << NEW_LINE;
+
+  // Preamble
+  ss << NEW_LINE << "//////////////////////////////////////////////"
+     << NEW_LINE << "// CSV of bytes allocated per region (MB's)."
+     << NEW_LINE << "// Units are in Megabytes. This is designed"
+     << NEW_LINE << "// to be used in a stacked graph." << NEW_LINE;
+
+  // HEADER.
+  for (MapIt it = samples.begin(); it != samples.end(); ++it) {
+    if (total_cpu_memory_it == it) {
+      continue;
+    }
+    const std::string& name = it->first;
+    ss << QUOTE << name << QUOTE << DELIM;
+  }
+  // Save the total for last.
+  if (total_cpu_memory_it != samples.end()) {
+    const std::string& name = total_cpu_memory_it->first;
+    ss << QUOTE << name << QUOTE << DELIM;
+  }
+  ss << NEW_LINE;
+
+  // Print out the values of each of the samples.
+  for (int i = 0; i < smallest_sample_size; ++i) {
+    for (MapIt it = samples.begin(); it != samples.end(); ++it) {
+      if (total_cpu_memory_it == it) {
+        continue;
+      }
+      const int64_t alloc_bytes = it->second.allocated_bytes_[i];
+      // Convert to float megabytes with decimals of precision.
+      double n = alloc_bytes / (1000 * 10);
+      n = n / (100.);
+      ss << n << DELIM;
+    }
+    if (total_cpu_memory_it != samples.end()) {
+      const int64_t alloc_bytes =
+         total_cpu_memory_it->second.allocated_bytes_[i];
+      // Convert to float megabytes with decimals of precision.
+      double n = alloc_bytes / (1000 * 10);
+      n = n / (100.);
+      ss << n << DELIM;
+    }
+    ss << NEW_LINE;
+  }
+
+  ss << NEW_LINE;
+  // Preamble
+  ss << NEW_LINE << "//////////////////////////////////////////////";
+  ss << NEW_LINE << "// CSV of number of allocations per region." << NEW_LINE;
+
+  // HEADER
+  for (MapIt it = samples.begin(); it != samples.end(); ++it) {
+    if (total_cpu_memory_it == it) {
+      continue;
+    }
+    const std::string& name = it->first;
+    ss << QUOTE << name << QUOTE << DELIM;
+  }
+  ss << NEW_LINE;
+  for (int i = 0; i < smallest_sample_size; ++i) {
+    for (MapIt it = samples.begin(); it != samples.end(); ++it) {
+      if (total_cpu_memory_it == it) {
+        continue;
+      }
+      const int64_t n_allocs = it->second.number_allocations_[i];
+      ss << n_allocs << DELIM;
+    }
+    ss << NEW_LINE;
+  }
+  std::string output = ss.str();
+  return output;
+}
+
+const char* MemoryTrackerPrintCSVThread::UntrackedMemoryKey() {
+  return "Untracked Memory";
+}
+
+void MemoryTrackerPrintCSVThread::Run() {
+  NoMemoryTracking no_mem_tracking_in_this_scope(memory_tracker_);
+
+  SbLogRaw("\nMemoryTrackerPrintCSVThread is sampling...\n");
+  int sample_count = 0;
+  MapAllocationSamples map_samples;
+
+  while (!TimeExpiredYet() && !canceled_.load()) {
+    // Sample total memory used by the system.
+    MemoryStats mem_stats = GetProcessMemoryStats();
+    int64_t untracked_used_memory = mem_stats.used_cpu_memory +
+                                    mem_stats.used_gpu_memory;
+
+    std::vector<const AllocationGroup*> vector_output;
+    memory_tracker_->GetAllocationGroups(&vector_output);
+
+    // Sample all known memory scopes.
+    for (int i = 0; i < vector_output.size(); ++i) {
+      const AllocationGroup* group = vector_output[i];
+      const std::string& name = group->name();
+
+      const bool first_creation = map_samples.find(group->name()) ==
+                                  map_samples.end();
+
+      AllocationSamples* new_entry  = &(map_samples[name]);
+
+      // Didn't see it before so create new entry.
+      if (first_creation) {
+        // Make up for lost samples...
+        new_entry->allocated_bytes_.resize(sample_count, 0);
+        new_entry->number_allocations_.resize(sample_count, 0);
+      }
+
+      int32_t num_allocs = - 1;
+      int64_t allocation_bytes = -1;
+      group->GetAggregateStats(&num_allocs, &allocation_bytes);
+
+      new_entry->allocated_bytes_.push_back(allocation_bytes);
+      new_entry->number_allocations_.push_back(num_allocs);
+
+      untracked_used_memory -= allocation_bytes;
+    }
+
+    // Now push in remaining total.
+    AllocationSamples* process_sample = &(map_samples[UntrackedMemoryKey()]);
+    if (untracked_used_memory < 0) {
+      // On some platforms, total GPU memory may not be correctly reported.
+      // However the allocations from the GPU memory may be reported. In this
+      // case untracked_used_memory will go negative. To protect the memory
+      // reporting the untracked_used_memory is set to 0 so that it doesn't
+      // cause an error in reporting.
+      untracked_used_memory = 0;
+    }
+    process_sample->allocated_bytes_.push_back(untracked_used_memory);
+    process_sample->number_allocations_.push_back(-1);
+
+    ++sample_count;
+    SbThreadSleep(kSbTimeMillisecond * sample_interval_ms_);
+  }
+
+  std::string output = ToCsvString(map_samples);
+  SbLogRaw(output.c_str());
+  SbLogFlush();
+  // Prevents the "thread exited code 0" from being interleaved into the
+  // output. This happens if SbLogFlush() is not implemented for the platform.
+  SbThreadSleep(1000 * kSbTimeMillisecond);
+}
+
+bool MemoryTrackerPrintCSVThread::TimeExpiredYet() {
+  const SbTime diff_us = SbTimeGetNow() - start_time_;
+  const bool expired_time = diff_us > (sampling_time_ms_ * kSbTimeMillisecond);
+  return expired_time;
+}
+
 }  // namespace analytics
 }  // namespace nb
diff --git a/src/nb/analytics/memory_tracker_impl.h b/src/nb/analytics/memory_tracker_impl.h
index 1575e7b..1af04aa 100644
--- a/src/nb/analytics/memory_tracker_impl.h
+++ b/src/nb/analytics/memory_tracker_impl.h
@@ -26,6 +26,7 @@
 #include "starboard/memory_reporter.h"
 #include "starboard/memory.h"
 #include "starboard/mutex.h"
+#include "starboard/time.h"
 
 namespace nb {
 namespace analytics {
@@ -177,7 +178,7 @@
 
 // Start() is called when this object is created, and Cancel() & Join() are
 // called during destruction.
-class MemoryTrackerPrintThread : private SimpleThread {
+class MemoryTrackerPrintThread : public SimpleThread {
  public:
   MemoryTrackerPrintThread(MemoryTracker* memory_tracker);
   virtual ~MemoryTrackerPrintThread() SB_OVERRIDE;
@@ -191,6 +192,41 @@
   MemoryTracker* memory_tracker_;
 };
 
+// Generates CSV values of the engine.
+// There are three sections of data including:
+//   1. average bytes / alloc
+//   2. # Bytes allocated per memory scope.
+//   3. # Allocations per memory scope.
+// This data can be pasted directly into a Google spreadsheet and visualized.
+// Note that this thread will implicitly call Start() is called during
+// construction and Cancel() & Join() during destruction.
+class MemoryTrackerPrintCSVThread : public SimpleThread {
+ public:
+  MemoryTrackerPrintCSVThread(MemoryTracker* memory_tracker,
+                              int sampling_interval_ms,
+                              int sampling_time_ms);
+  virtual ~MemoryTrackerPrintCSVThread() SB_OVERRIDE;
+
+  // Overridden so that the thread can exit gracefully.
+  virtual void Cancel() SB_OVERRIDE;
+  virtual void Run() SB_OVERRIDE;
+ private:
+  struct AllocationSamples {
+    std::vector<int32_t> number_allocations_;
+    std::vector<int64_t> allocated_bytes_;
+  };
+  typedef std::map<std::string, AllocationSamples> MapAllocationSamples;
+  static std::string ToCsvString(const MapAllocationSamples& samples);
+  static const char* UntrackedMemoryKey();
+  bool TimeExpiredYet();
+
+  MemoryTracker* memory_tracker_;
+  const int sample_interval_ms_;
+  const int sampling_time_ms_;
+  SbTime start_time_;
+  atomic_bool canceled_;
+};
+
 }  // namespace analytics
 }  // namespace nb
 
diff --git a/src/nb/memory_scope.h b/src/nb/memory_scope.h
index d7d37bf..72e1ddc 100644
--- a/src/nb/memory_scope.h
+++ b/src/nb/memory_scope.h
@@ -124,7 +124,7 @@
   // When true, if cached_handle_ is 0 then an object may be created that
   // represents the fields of this object. The handle that represents this
   // cached object is then placed in cached_hanlde_.
-  const bool allows_caching_;
+  bool allows_caching_;
 };
 
 // NbPopMemoryScopeOnScopeEnd is only allowed for C++ builds.
diff --git a/src/net/base/data_url.cc b/src/net/base/data_url.cc
index b7309cb..53a5ea8 100644
--- a/src/net/base/data_url.cc
+++ b/src/net/base/data_url.cc
@@ -13,6 +13,7 @@
 #include "base/string_split.h"
 #include "base/string_util.h"
 #include "googleurl/src/gurl.h"
+#include "nb/memory_scope.h"
 #include "net/base/escape.h"
 
 namespace net {
@@ -20,6 +21,7 @@
 // static
 bool DataURL::Parse(const GURL& url, std::string* mime_type,
                     std::string* charset, std::string* data) {
+  TRACK_MEMORY_SCOPE("Network");
   DCHECK(mime_type->empty());
   DCHECK(charset->empty());
   std::string::const_iterator begin = url.spec().begin();
diff --git a/src/net/base/host_resolver_impl.cc b/src/net/base/host_resolver_impl.cc
index 11ccd9f..9c1ac57 100644
--- a/src/net/base/host_resolver_impl.cc
+++ b/src/net/base/host_resolver_impl.cc
@@ -44,6 +44,7 @@
 #include "net/dns/dns_protocol.h"
 #include "net/dns/dns_response.h"
 #include "net/dns/dns_transaction.h"
+#include "nb/memory_scope.h"
 
 #if defined(OS_WIN)
 #include "net/base/winsock_init.h"
@@ -580,6 +581,7 @@
   ~ProcTask() {}
 
   void StartLookupAttempt() {
+    TRACK_MEMORY_SCOPE("Network");
     DCHECK(origin_loop_->BelongsToCurrentThread());
     base::TimeTicks start_time = base::TimeTicks::Now();
     ++attempt_number_;
diff --git a/src/net/base/host_resolver_proc.cc b/src/net/base/host_resolver_proc.cc
index 8950f5b..a4512e9 100644
--- a/src/net/base/host_resolver_proc.cc
+++ b/src/net/base/host_resolver_proc.cc
@@ -12,6 +12,7 @@
 #include "net/base/dns_reloader.h"
 #include "net/base/net_errors.h"
 #include "net/base/sys_addrinfo.h"
+#include "nb/memory_scope.h"
 
 #if defined(OS_STARBOARD)
 #include "starboard/socket.h"
@@ -133,6 +134,7 @@
                            HostResolverFlags host_resolver_flags,
                            AddressList* addrlist,
                            int* os_error) {
+  TRACK_MEMORY_SCOPE("Network");
   if (os_error)
     *os_error = 0;
 
diff --git a/src/net/base/net_errors.h b/src/net/base/net_errors.h
index 95a81e9..43cffab 100644
--- a/src/net/base/net_errors.h
+++ b/src/net/base/net_errors.h
@@ -49,7 +49,7 @@
 NET_EXPORT Error MapSocketError(SbSocketError error);
 
 // Gets the last socket error as a net error.
-SB_C_INLINE Error MapLastSocketError(SbSocket socket) {
+static SB_C_INLINE Error MapLastSocketError(SbSocket socket) {
   return MapSocketError(SbSocketGetLastError(socket));
 }
 
@@ -57,7 +57,7 @@
 NET_EXPORT Error MapSystemError(SbSystemError error);
 
 // Gets the last system error as a net error.
-SB_C_INLINE Error MapLastSystemError() {
+static SB_C_INLINE Error MapLastSystemError() {
   return MapSystemError(SbSystemGetLastError());
 }
 
diff --git a/src/net/http/http_stream_factory_impl_job.cc b/src/net/http/http_stream_factory_impl_job.cc
index 77422ce..9554ce6 100644
--- a/src/net/http/http_stream_factory_impl_job.cc
+++ b/src/net/http/http_stream_factory_impl_job.cc
@@ -12,6 +12,7 @@
 #include "base/stringprintf.h"
 #include "base/values.h"
 #include "build/build_config.h"
+#include "nb/memory_scope.h"
 #include "net/base/connection_type_histograms.h"
 #include "net/base/net_log.h"
 #include "net/base/net_util.h"
@@ -267,6 +268,7 @@
 }
 
 void HttpStreamFactoryImpl::Job::OnStreamReadyCallback() {
+  TRACK_MEMORY_SCOPE("Network");
   DCHECK(stream_.get());
   DCHECK(!IsPreconnecting());
   if (IsOrphaned()) {
diff --git a/src/net/net.gyp b/src/net/net.gyp
index 3d7b9d4..d13a159 100644
--- a/src/net/net.gyp
+++ b/src/net/net.gyp
@@ -57,6 +57,7 @@
         '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
         '../googleurl/googleurl.gyp:googleurl',
         '../crypto/crypto.gyp:crypto',
+        '../nb/nb.gyp:nb',
         '../third_party/icu/icu.gyp:icui18n',
         '../third_party/icu/icu.gyp:icuuc',
         '../third_party/zlib/zlib.gyp:zlib',
diff --git a/src/net/socket/client_socket_handle.cc b/src/net/socket/client_socket_handle.cc
index 20ab672..cffb902 100644
--- a/src/net/socket/client_socket_handle.cc
+++ b/src/net/socket/client_socket_handle.cc
@@ -9,6 +9,7 @@
 #include "base/compiler_specific.h"
 #include "base/metrics/histogram.h"
 #include "base/logging.h"
+#include "nb/memory_scope.h"
 #include "net/base/net_errors.h"
 #include "net/socket/client_socket_pool.h"
 #include "net/socket/client_socket_pool_histograms.h"
@@ -104,6 +105,7 @@
 }
 
 void ClientSocketHandle::OnIOComplete(int result) {
+  TRACK_MEMORY_SCOPE("Network");
   CompletionCallback callback = user_callback_;
   user_callback_.Reset();
   HandleInitCompletion(result);
@@ -111,6 +113,7 @@
 }
 
 void ClientSocketHandle::HandleInitCompletion(int result) {
+  TRACK_MEMORY_SCOPE("Network");
   CHECK_NE(ERR_IO_PENDING, result);
   if (result != OK) {
     if (!socket_.get())
diff --git a/src/net/socket/tcp_client_socket_starboard.cc b/src/net/socket/tcp_client_socket_starboard.cc
index 48d76b5..c970ac7 100644
--- a/src/net/socket/tcp_client_socket_starboard.cc
+++ b/src/net/socket/tcp_client_socket_starboard.cc
@@ -23,6 +23,7 @@
 #include "base/posix/eintr_wrapper.h"
 #include "base/string_util.h"
 #include "base/stringprintf.h"
+#include "nb/memory_scope.h"
 #include "net/base/address_family.h"
 #include "net/base/connection_type_histograms.h"
 #include "net/base/io_buffer.h"
@@ -154,6 +155,7 @@
 }
 
 int TCPClientSocketStarboard::Connect(const CompletionCallback& callback) {
+  TRACK_MEMORY_SCOPE("Network");
   DCHECK(CalledOnValidThread());
 
   // If this socket is already valid, then just return OK.
@@ -186,6 +188,7 @@
 // pretty much cribbed directly from TCPClientSocketLibevent and/or
 // TCPClientSocketWin, take your pick, they're identical
 int TCPClientSocketStarboard::DoConnectLoop(int result) {
+  TRACK_MEMORY_SCOPE("Network");
   DCHECK_NE(next_connect_state_, CONNECT_STATE_NONE);
 
   int rv = result;
@@ -211,6 +214,7 @@
 }
 
 int TCPClientSocketStarboard::DoConnect() {
+  TRACK_MEMORY_SCOPE("Network");
   DCHECK_GE(current_address_index_, 0);
   DCHECK_LT(current_address_index_, static_cast<int>(addresses_.size()));
 
@@ -257,6 +261,7 @@
 }
 
 int TCPClientSocketStarboard::DoConnectComplete(int result) {
+  TRACK_MEMORY_SCOPE("Network");
   // Log the end of this attempt (and any OS error it threw).
   int error = connect_error_;
   connect_error_ = OK;
@@ -287,6 +292,7 @@
 }
 
 void TCPClientSocketStarboard::DidCompleteConnect() {
+  TRACK_MEMORY_SCOPE("Network");
   DCHECK_EQ(next_connect_state_, CONNECT_STATE_CONNECT_COMPLETE);
 
   connect_error_ = SbSocketIsConnected(socket_) ? OK : ERR_FAILED;
@@ -298,6 +304,7 @@
 }
 
 void TCPClientSocketStarboard::LogConnectCompletion(int net_error) {
+  TRACK_MEMORY_SCOPE("Network");
   if (net_error == OK)
     UpdateConnectionTypeHistograms(CONNECTION_ANY);
 
@@ -422,6 +429,7 @@
 int TCPClientSocketStarboard::Read(IOBuffer* buf,
                                    int buf_len,
                                    const CompletionCallback& callback) {
+  TRACK_MEMORY_SCOPE("Network");
   DCHECK(SbSocketIsValid(socket_));
   DCHECK(!waiting_connect());
   DCHECK(!waiting_read_);
@@ -459,6 +467,7 @@
 }
 
 void TCPClientSocketStarboard::DidCompleteRead() {
+  TRACK_MEMORY_SCOPE("Network");
   DCHECK(waiting_read_);
   int bytes_read =
       SbSocketReceiveFrom(socket_, read_buf_->data(), read_buf_len_, NULL);
@@ -485,6 +494,7 @@
 }
 
 void TCPClientSocketStarboard::DoReadCallback(int rv) {
+  TRACK_MEMORY_SCOPE("Network");
   DCHECK_NE(rv, ERR_IO_PENDING);
 
   // since Run may result in Read being called, clear read_callback_ up front.
@@ -496,6 +506,7 @@
 int TCPClientSocketStarboard::Write(IOBuffer* buf,
                                     int buf_len,
                                     const CompletionCallback& callback) {
+  TRACK_MEMORY_SCOPE("Network");
   DCHECK(SbSocketIsValid(socket_));
   DCHECK(!waiting_connect());
   DCHECK(!waiting_write_);
@@ -535,6 +546,7 @@
 }
 
 void TCPClientSocketStarboard::DidCompleteWrite() {
+  TRACK_MEMORY_SCOPE("Network");
   DCHECK(waiting_write_);
   int nwrite =
       SbSocketSendTo(socket_, write_buf_->data(), write_buf_len_, NULL);
@@ -560,6 +572,7 @@
 }
 
 void TCPClientSocketStarboard::DoWriteCallback(int rv) {
+  TRACK_MEMORY_SCOPE("Network");
   DCHECK_NE(rv, ERR_IO_PENDING);
 
   // since Run may result in Write being called, clear write_callback_ up front.
@@ -569,22 +582,27 @@
 }
 
 bool TCPClientSocketStarboard::SetReceiveBufferSize(int32 size) {
+  TRACK_MEMORY_SCOPE("Network");
   return SbSocketSetReceiveBufferSize(socket_, size);
 }
 
 bool TCPClientSocketStarboard::SetSendBufferSize(int32 size) {
+  TRACK_MEMORY_SCOPE("Network");
   return SbSocketSetSendBufferSize(socket_, size);
 }
 
 bool TCPClientSocketStarboard::SetKeepAlive(bool enable, int delay) {
+  TRACK_MEMORY_SCOPE("Network");
   return SbSocketSetTcpKeepAlive(socket_, enable, delay);
 }
 
 bool TCPClientSocketStarboard::SetNoDelay(bool no_delay) {
+  TRACK_MEMORY_SCOPE("Network");
   return SbSocketSetTcpNoDelay(socket_, no_delay);
 }
 
 bool TCPClientSocketStarboard::SetWindowScaling(bool enable) {
+  TRACK_MEMORY_SCOPE("Network");
   return SbSocketSetTcpWindowScaling(socket_, enable);
 }
 
diff --git a/src/net/udp/udp_listen_socket.cc b/src/net/udp/udp_listen_socket.cc
index 848290b..82fdfd9 100644
--- a/src/net/udp/udp_listen_socket.cc
+++ b/src/net/udp/udp_listen_socket.cc
@@ -33,6 +33,7 @@
 #include "base/sys_byteorder.h"
 #include "base/threading/platform_thread.h"
 #include "build/build_config.h"
+#include "nb/memory_scope.h"
 #include "net/base/net_util.h"
 #if defined(OS_STARBOARD)
 #include "starboard/socket.h"
@@ -87,12 +88,14 @@
 
 void UDPListenSocket::SendTo(const IPEndPoint& address,
                              const std::string& str) {
+  TRACK_MEMORY_SCOPE("Network");
   SendTo(address, str.data(), static_cast<int>(str.length()));
 }
 
 void UDPListenSocket::SendTo(const IPEndPoint& address,
                              const char* bytes,
                              int len) {
+  TRACK_MEMORY_SCOPE("Network");
 #if defined(OS_STARBOARD)
   SbSocketAddress dst_addr;
   if (!address.ToSbSocketAddress(&dst_addr)) {
@@ -130,6 +133,7 @@
 }
 
 void UDPListenSocket::Read() {
+  TRACK_MEMORY_SCOPE("Network");
   if (buffer_ == NULL) {
     // +1 for null termination
     buffer_.reset(new char[kUdpMaxPacketSize + 1]);
@@ -192,6 +196,7 @@
 }
 
 void UDPListenSocket::WatchSocket() {
+  TRACK_MEMORY_SCOPE("Network");
 #if defined(OS_STARBOARD)
   MessageLoopForIO::current()->Watch(
       socket_, true, MessageLoopForIO::WATCH_READ, &watcher_, this);
diff --git a/src/net/url_request/url_fetcher_core.cc b/src/net/url_request/url_fetcher_core.cc
index ea36c74..82976da 100644
--- a/src/net/url_request/url_fetcher_core.cc
+++ b/src/net/url_request/url_fetcher_core.cc
@@ -13,6 +13,7 @@
 #include "base/stl_util.h"
 #include "base/thread_task_runner_handle.h"
 #include "base/tracked_objects.h"
+#include "nb/memory_scope.h"
 #include "net/base/io_buffer.h"
 #include "net/base/load_flags.h"
 #include "net/base/net_errors.h"
@@ -42,6 +43,7 @@
 URLFetcherCore::Registry::~Registry() {}
 
 void URLFetcherCore::Registry::AddURLFetcherCore(URLFetcherCore* core) {
+  TRACK_MEMORY_SCOPE("Network");
   DCHECK(!ContainsKey(fetchers_, core));
   fetchers_.insert(core);
 }
@@ -75,6 +77,7 @@
 
 void URLFetcherCore::FileWriter::CreateFileAtPath(
     const FilePath& file_path) {
+  TRACK_MEMORY_SCOPE("Network");
   DCHECK(core_->network_task_runner_->BelongsToCurrentThread());
   DCHECK(file_task_runner_.get());
   base::FileUtilProxy::CreateOrOpen(
@@ -87,6 +90,7 @@
 }
 
 void URLFetcherCore::FileWriter::CreateTempFile() {
+  TRACK_MEMORY_SCOPE("Network");
   DCHECK(core_->network_task_runner_->BelongsToCurrentThread());
   DCHECK(file_task_runner_.get());
   base::FileUtilProxy::CreateTemporary(
@@ -97,6 +101,7 @@
 }
 
 void URLFetcherCore::FileWriter::WriteBuffer(int num_bytes) {
+  TRACK_MEMORY_SCOPE("Network");
   DCHECK(core_->network_task_runner_->BelongsToCurrentThread());
 
   // Start writing to the file by setting the initial state
@@ -110,6 +115,7 @@
 void URLFetcherCore::FileWriter::ContinueWrite(
     base::PlatformFileError error_code,
     int bytes_written) {
+  TRACK_MEMORY_SCOPE("Network");
   DCHECK(core_->network_task_runner_->BelongsToCurrentThread());
 
   if (file_handle_ == base::kInvalidPlatformFileValue) {
@@ -154,6 +160,7 @@
 }
 
 void URLFetcherCore::FileWriter::DisownFile() {
+  TRACK_MEMORY_SCOPE("Network");
   DCHECK(core_->network_task_runner_->BelongsToCurrentThread());
 
   // Disowning is done by the delegate's OnURLFetchComplete method.
@@ -165,6 +172,7 @@
 }
 
 void URLFetcherCore::FileWriter::CloseFileAndCompleteRequest() {
+  TRACK_MEMORY_SCOPE("Network");
   DCHECK(core_->network_task_runner_->BelongsToCurrentThread());
 
   if (file_handle_ != base::kInvalidPlatformFileValue) {
@@ -177,6 +185,7 @@
 }
 
 void URLFetcherCore::FileWriter::CloseAndDeleteFile() {
+  TRACK_MEMORY_SCOPE("Network");
   DCHECK(core_->network_task_runner_->BelongsToCurrentThread());
 
   if (file_handle_ == base::kInvalidPlatformFileValue) {
@@ -193,6 +202,7 @@
 
 void URLFetcherCore::FileWriter::DeleteFile(
     base::PlatformFileError error_code) {
+  TRACK_MEMORY_SCOPE("Network");
   DCHECK(core_->network_task_runner_->BelongsToCurrentThread());
   if (file_path_.empty())
     return;
@@ -209,6 +219,7 @@
     base::PlatformFileError error_code,
     base::PassPlatformFile file_handle,
     bool created) {
+  TRACK_MEMORY_SCOPE("Network");
   DidCreateFileInternal(file_path, error_code, file_handle);
 }
 
@@ -216,6 +227,7 @@
     base::PlatformFileError error_code,
     base::PassPlatformFile file_handle,
     const FilePath& file_path) {
+  TRACK_MEMORY_SCOPE("Network");
   DidCreateFileInternal(file_path, error_code, file_handle);
 }
 
@@ -223,6 +235,7 @@
     const FilePath& file_path,
     base::PlatformFileError error_code,
     base::PassPlatformFile file_handle) {
+  TRACK_MEMORY_SCOPE("Network");
   DCHECK(core_->network_task_runner_->BelongsToCurrentThread());
 
   if (base::PLATFORM_FILE_OK != error_code) {
@@ -245,6 +258,7 @@
 
 void URLFetcherCore::FileWriter::DidCloseFile(
     base::PlatformFileError error_code) {
+  TRACK_MEMORY_SCOPE("Network");
   DCHECK(core_->network_task_runner_->BelongsToCurrentThread());
 
   if (base::PLATFORM_FILE_OK != error_code) {
@@ -300,6 +314,7 @@
 }
 
 void URLFetcherCore::Start() {
+  TRACK_MEMORY_SCOPE("Network");
   DCHECK(delegate_task_runner_);
   DCHECK(request_context_getter_) << "We need an URLRequestContext!";
   if (network_task_runner_) {
@@ -315,6 +330,7 @@
 }
 
 void URLFetcherCore::Stop() {
+  TRACK_MEMORY_SCOPE("Network");
   if (delegate_task_runner_)  // May be NULL in tests.
     DCHECK(delegate_task_runner_->BelongsToCurrentThread());
 
@@ -523,6 +539,7 @@
 
 bool URLFetcherCore::GetResponseAsFilePath(bool take_ownership,
                                            FilePath* out_response_path) {
+  TRACK_MEMORY_SCOPE("Network");
   DCHECK(delegate_task_runner_->BelongsToCurrentThread());
   const bool destination_is_file =
       response_destination_ == URLFetcherCore::TEMP_FILE ||
@@ -543,6 +560,7 @@
 void URLFetcherCore::OnReceivedRedirect(URLRequest* request,
                                         const GURL& new_url,
                                         bool* defer_redirect) {
+  TRACK_MEMORY_SCOPE("Network");
   DCHECK_EQ(request, request_.get());
   DCHECK(network_task_runner_->BelongsToCurrentThread());
   if (stop_on_redirect_) {
@@ -556,6 +574,7 @@
 }
 
 void URLFetcherCore::OnResponseStarted(URLRequest* request) {
+  TRACK_MEMORY_SCOPE("Network");
   DCHECK_EQ(request, request_.get());
   DCHECK(network_task_runner_->BelongsToCurrentThread());
   if (request_->status().is_success()) {
@@ -593,6 +612,7 @@
 
 void URLFetcherCore::OnReadCompleted(URLRequest* request,
                                      int bytes_read) {
+  TRACK_MEMORY_SCOPE("Network");
   DCHECK(request == request_);
   DCHECK(network_task_runner_->BelongsToCurrentThread());
 #if !defined(COBALT)
@@ -714,6 +734,7 @@
 }
 
 void URLFetcherCore::StartURLRequest() {
+  TRACK_MEMORY_SCOPE("Network");
   DCHECK(network_task_runner_->BelongsToCurrentThread());
   TRACE_EVENT_ASYNC_STEP0("net::url_request", "URLFetcher", this,
                           "Waiting For Data");
@@ -808,6 +829,7 @@
 }
 
 void URLFetcherCore::StartURLRequestWhenAppropriate() {
+  TRACK_MEMORY_SCOPE("Network");
   TRACE_EVENT_ASYNC_BEGIN1("net::url_request", "URLFetcher", this, "url",
                            original_url_.path());
   DCHECK(network_task_runner_->BelongsToCurrentThread());
@@ -841,6 +863,7 @@
 }
 
 void URLFetcherCore::CancelURLRequest() {
+  TRACK_MEMORY_SCOPE("Network");
   DCHECK(network_task_runner_->BelongsToCurrentThread());
 
   if (request_.get()) {
@@ -862,6 +885,7 @@
 
 void URLFetcherCore::OnCompletedURLRequest(
     base::TimeDelta backoff_delay) {
+  TRACK_MEMORY_SCOPE("Network");
   TRACE_EVENT_ASYNC_END1("net::url_request", "URLFetcher", this, "url",
                          original_url_.path());
   DCHECK(delegate_task_runner_->BelongsToCurrentThread());
@@ -874,12 +898,14 @@
 }
 
 void URLFetcherCore::InformDelegateFetchIsComplete() {
+  TRACK_MEMORY_SCOPE("Network");
   DCHECK(delegate_task_runner_->BelongsToCurrentThread());
   if (delegate_)
     delegate_->OnURLFetchComplete(fetcher_);
 }
 
 void URLFetcherCore::NotifyMalformedContent() {
+  TRACK_MEMORY_SCOPE("Network");
   DCHECK(network_task_runner_->BelongsToCurrentThread());
   if (url_throttler_entry_ != NULL) {
     int status_code = response_code_;
@@ -896,6 +922,7 @@
 }
 
 void URLFetcherCore::RetryOrCompleteUrlFetch() {
+  TRACK_MEMORY_SCOPE("Network");
   DCHECK(network_task_runner_->BelongsToCurrentThread());
   base::TimeDelta backoff_delay;
 
@@ -965,6 +992,7 @@
 }
 
 base::TimeTicks URLFetcherCore::GetBackoffReleaseTime() {
+  TRACK_MEMORY_SCOPE("Network");
   DCHECK(network_task_runner_->BelongsToCurrentThread());
 
   if (original_url_throttler_entry_) {
@@ -986,6 +1014,7 @@
 
 void URLFetcherCore::CompleteAddingUploadDataChunk(
     const std::string& content, bool is_last_chunk) {
+  TRACK_MEMORY_SCOPE("Network");
   if (was_cancelled_) {
     // Since CompleteAddingUploadDataChunk() is posted as a *delayed* task, it
     // may run after the URLFetcher was already stopped.
@@ -1003,6 +1032,7 @@
 // Return false if the write is pending, and the next read will
 // be done later.
 bool URLFetcherCore::WriteBuffer(int num_bytes) {
+  TRACK_MEMORY_SCOPE("Network");
   bool write_complete = false;
   switch (response_destination_) {
     case STRING:
@@ -1031,6 +1061,7 @@
 }
 
 void URLFetcherCore::ReadResponse() {
+  TRACK_MEMORY_SCOPE("Network");
   // Some servers may treat HEAD requests as GET requests.  To free up the
   // network connection as soon as possible, signal that the request has
   // completed immediately, without trying to read any data back (all we care
@@ -1069,6 +1100,7 @@
 #endif  // defined(COBALT)
 
 void URLFetcherCore::InformDelegateUploadProgress() {
+  TRACK_MEMORY_SCOPE("Network");
   DCHECK(network_task_runner_->BelongsToCurrentThread());
   if (request_.get()) {
     int64 current = request_->GetUploadProgress().position();
@@ -1088,12 +1120,14 @@
 
 void URLFetcherCore::InformDelegateUploadProgressInDelegateThread(
     int64 current, int64 total) {
+  TRACK_MEMORY_SCOPE("Network");
   DCHECK(delegate_task_runner_->BelongsToCurrentThread());
   if (delegate_)
     delegate_->OnURLFetchUploadProgress(fetcher_, current, total);
 }
 
 void URLFetcherCore::InformDelegateDownloadDataIfNecessary(int bytes_read) {
+  TRACK_MEMORY_SCOPE("Network");
   DCHECK(network_task_runner_->BelongsToCurrentThread());
   if (delegate_ && delegate_->ShouldSendDownloadData() && bytes_read != 0) {
     if (!download_data_cache_) {
@@ -1114,6 +1148,7 @@
 }
 
 void URLFetcherCore::InformDelegateDownloadData() {
+  TRACK_MEMORY_SCOPE("Network");
   DCHECK(network_task_runner_->BelongsToCurrentThread());
   if (delegate_ && delegate_->ShouldSendDownloadData() &&
       download_data_cache_) {
@@ -1126,6 +1161,7 @@
 
 void URLFetcherCore::InformDelegateDownloadDataInDelegateThread(
     scoped_ptr<std::string> download_data) {
+  TRACK_MEMORY_SCOPE("Network");
   DCHECK(delegate_task_runner_->BelongsToCurrentThread());
   if (delegate_) {
     delegate_->OnURLFetchDownloadData(fetcher_, download_data.Pass());
diff --git a/src/net/url_request/url_request_data_job.cc b/src/net/url_request/url_request_data_job.cc
index 5dffe32..e0c0cba 100644
--- a/src/net/url_request/url_request_data_job.cc
+++ b/src/net/url_request/url_request_data_job.cc
@@ -6,6 +6,7 @@
 
 #include "net/url_request/url_request_data_job.h"
 
+#include "nb/memory_scope.h"
 #include "net/base/data_url.h"
 #include "net/base/net_errors.h"
 
@@ -27,6 +28,7 @@
                                std::string* charset,
                                std::string* data,
                                const CompletionCallback& callback) const {
+  TRACK_MEMORY_SCOPE("Network");
   // Check if data URL is valid. If not, don't bother to try to extract data.
   // Otherwise, parse the data from the data URL.
   const GURL& url = request_->url();
diff --git a/src/starboard/build/convert_i18n_data.py b/src/starboard/build/convert_i18n_data.py
index a34916a..0f56a59 100644
--- a/src/starboard/build/convert_i18n_data.py
+++ b/src/starboard/build/convert_i18n_data.py
@@ -51,7 +51,7 @@
   messages = root[0]
 
   # Write each message to the output file on its own line.
-  with open(output_filename, 'w') as output_file:
+  with open(output_filename, 'wb') as output_file:
     for msg in messages:
       # Use ; as the separator. Which means it better not be in the name.
       assert not (';' in msg.attrib['name'])
diff --git a/src/starboard/client_porting/poem/getenv_stub_poem.h b/src/starboard/client_porting/poem/getenv_stub_poem.h
new file mode 100644
index 0000000..8e4ab81
--- /dev/null
+++ b/src/starboard/client_porting/poem/getenv_stub_poem.h
@@ -0,0 +1,28 @@
+// 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) stub implementation for getenv.
+
+#ifndef STARBOARD_CLIENT_PORTING_POEM_GETENV_STUB_POEM_H_
+#define STARBOARD_CLIENT_PORTING_POEM_GETENV_STUB_POEM_H_
+
+#include <stdlib.h>
+
+#include "starboard/configuration.h"
+
+static SB_C_INLINE const char* getenv(const char* unused) {
+  return NULL;
+}
+
+#endif  // STARBOARD_CLIENT_PORTING_POEM_GETENV_STUB_POEM_H_
diff --git a/src/starboard/client_porting/poem/inet_poem.h b/src/starboard/client_porting/poem/inet_poem.h
new file mode 100644
index 0000000..55cf47a
--- /dev/null
+++ b/src/starboard/client_porting/poem/inet_poem.h
@@ -0,0 +1,27 @@
+// 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 usually declared in <arpa/inet.h>
+
+#ifndef STARBOARD_CLIENT_PORTING_POEM_INET_POEM_H_
+#define STARBOARD_CLIENT_PORTING_POEM_INET_POEM_H_
+
+#include "starboard/byte_swap.h"
+
+#define htonl(x) SB_HOST_TO_NET_U32(x)
+#define htons(x) SB_HOST_TO_NET_U16(x)
+#define ntohl(x) SB_NET_TO_HOST_U32(x)
+#define ntohs(x) SB_NET_TO_HOST_U16(x)
+
+#endif  // STARBOARD_CLIENT_PORTING_POEM_INET_POEM_H_
diff --git a/src/starboard/client_porting/poem/poem.gyp b/src/starboard/client_porting/poem/poem.gyp
index def3f4e..947cc36 100644
--- a/src/starboard/client_porting/poem/poem.gyp
+++ b/src/starboard/client_porting/poem/poem.gyp
@@ -19,10 +19,13 @@
       'type': 'static_library',
       'sources': [
         'eztime_poem.h',
+        'getenv_stub_poem.h',
+        'inet_poem.h',
         'stdio_poem.h',
         'stdlib_poem.h',
         'string_poem.h',
         'strings_poem.h',
+        'strnlen_poem.h',
         'wchar_poem.h',
       ],
       'dependencies': [
@@ -44,5 +47,16 @@
         '<(DEPTH)/starboard/starboard.gyp:starboard',
       ],
     },
+    {
+      'target_name': 'poem_unittests_deploy',
+      'type': 'none',
+      'dependencies': [
+        'poem_unittests',
+      ],
+      'variables': {
+        'executable_name': 'poem_unittests',
+      },
+      'includes': [ '../../build/deploy.gypi' ],
+    },
   ],
 }
diff --git a/src/starboard/client_porting/poem/string_poem_test.cc b/src/starboard/client_porting/poem/string_poem_test.cc
index 2243b48..1a3e899 100644
--- a/src/starboard/client_porting/poem/string_poem_test.cc
+++ b/src/starboard/client_porting/poem/string_poem_test.cc
@@ -17,6 +17,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 
 #include "starboard/client_porting/poem/string_poem.h"
+#include "starboard/client_porting/poem/strnlen_poem.h"
 
 namespace starboard {
 namespace nplb {
@@ -76,6 +77,20 @@
   EXPECT_STREQ(a, "Wu");
 }
 
+TEST(StringPoemTest, PoemStringGetLengthFixed) {
+  char a[] = "abcdef";
+  char b[] = "abc\0def";
+
+  EXPECT_EQ(strnlen(a, 0), 0);
+  EXPECT_EQ(strnlen(a, 3), 3);
+  EXPECT_EQ(strnlen(a, sizeof(a)), 6);
+  EXPECT_EQ(strnlen(a, 256), 6);
+  EXPECT_EQ(strnlen(b, 2), 2);
+  EXPECT_EQ(strnlen(b, 3), 3);
+  EXPECT_EQ(strnlen(b, sizeof(b)), 3);
+  EXPECT_EQ(strnlen(b, 256), 3);
+}
+
 }  // namespace
 }  // namespace nplb
 }  // namespace starboard
diff --git a/src/starboard/client_porting/poem/strnlen_poem.h b/src/starboard/client_porting/poem/strnlen_poem.h
new file mode 100644
index 0000000..fb2d674
--- /dev/null
+++ b/src/starboard/client_porting/poem/strnlen_poem.h
@@ -0,0 +1,33 @@
+// 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) implementation for strnlen. Usually declared in
+// <string.h>, but may be missing on some platforms (e.g. PS3).
+
+#ifndef STARBOARD_CLIENT_PORTING_POEM_STRNLEN_POEM_H_
+#define STARBOARD_CLIENT_PORTING_POEM_STRNLEN_POEM_H_
+
+#include "starboard/configuration.h"
+
+static SB_C_INLINE size_t StringGetLengthFixed(const char* s, size_t maxlen) {
+  size_t i = 0;
+  while (i < maxlen && s[i]) {
+    ++i;
+  }
+  return i;
+}
+
+#define strnlen(s, maxlen) StringGetLengthFixed(s, maxlen)
+
+#endif  // STARBOARD_CLIENT_PORTING_POEM_STRNLEN_POEM_H_
diff --git a/src/starboard/client_porting/pr_starboard/pr_starboard.cc b/src/starboard/client_porting/pr_starboard/pr_starboard.cc
new file mode 100644
index 0000000..732ea14
--- /dev/null
+++ b/src/starboard/client_porting/pr_starboard/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 "starboard/client_porting/pr_starboard/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/starboard/client_porting/pr_starboard/pr_starboard.gyp b/src/starboard/client_porting/pr_starboard/pr_starboard.gyp
new file mode 100644
index 0000000..0874b65
--- /dev/null
+++ b/src/starboard/client_porting/pr_starboard/pr_starboard.gyp
@@ -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.
+
+{
+  'targets': [
+    {
+      'target_name': 'pr_starboard',
+      'type': 'static_library',
+      'sources': [
+        'pr_starboard.cc',
+        'pr_starboard.h',
+      ],
+      'dependencies': [
+        '<(DEPTH)/starboard/starboard.gyp:starboard',
+      ],
+    },
+  ],
+}
diff --git a/src/starboard/client_porting/pr_starboard/pr_starboard.h b/src/starboard/client_porting/pr_starboard/pr_starboard.h
new file mode 100644
index 0000000..63e5c4d
--- /dev/null
+++ b/src/starboard/client_porting/pr_starboard/pr_starboard.h
@@ -0,0 +1,189 @@
+// 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 a starboard based implementation of
+// the subset of nspr that SpiderMonkey depends on.  It directly matches the
+// NSPR API, with the exception that accessing thread local data should use
+// PRTLSIndex, rather than PRUintn.
+
+#ifndef STARBOARD_CLIENT_PORTING_PR_STARBOARD_PR_STARBOARD_H_
+#define STARBOARD_CLIENT_PORTING_PR_STARBOARD_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 {
+  explicit 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);
+
+static inline PRIntervalTime PR_MicrosecondsToInterval(PRUint32 micro) {
+  return (micro + 999) / 1000;
+}
+
+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  // STARBOARD_CLIENT_PORTING_PR_STARBOARD_PR_STARBOARD_H_
diff --git a/src/starboard/client_porting/wrap_main/wrap_main.h b/src/starboard/client_porting/wrap_main/wrap_main.h
index e4879d3..4734772 100644
--- a/src/starboard/client_porting/wrap_main/wrap_main.h
+++ b/src/starboard/client_porting/wrap_main/wrap_main.h
@@ -50,6 +50,11 @@
 }  // namespace client_porting
 }  // namespace starboard
 
+#if defined(_WIN32)
+// Today there is no Starboard win32. Make sure those who create it know
+// the _CrtSet* functions below should be moved to starboard win32 main.
+#error For starboard win32, please move _CrtSet* to main
+#endif
 #define STARBOARD_WRAP_SIMPLE_MAIN(main_function)                \
   void SbEventHandle(const SbEvent* event) {                     \
     ::starboard::client_porting::wrap_main::SimpleEventHandler<  \
@@ -57,10 +62,26 @@
   }
 
 #else
+#if defined(_WIN32)
+#include <windows.h>
+
+// TODO this case should be removed when win32 is starboardized
+#define STARBOARD_WRAP_SIMPLE_MAIN(main_function)                             \
+  int main(int argc, char** argv) {                                           \
+    if (!IsDebuggerPresent()) {                                               \
+      _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); \
+      _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);  \
+      _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);   \
+      _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);                    \
+    }                                                                         \
+    return main_function(argc, argv);                                         \
+  }
+#else  // defined(_WIN32)
 #define STARBOARD_WRAP_SIMPLE_MAIN(main_function) \
   int main(int argc, char** argv) {               \
     return main_function(argc, argv);             \
   }
+#endif
 
 #endif  // STARBOARD
 #endif  // STARBOARD_CLIENT_PORTING_WRAP_MAIN_WRAP_MAIN_H_
diff --git a/src/starboard/condition_variable.h b/src/starboard/condition_variable.h
index 673b7d9..4c519ba 100644
--- a/src/starboard/condition_variable.h
+++ b/src/starboard/condition_variable.h
@@ -56,10 +56,6 @@
 // placing the newly created condition variable in |out_condition|.
 //
 // The return value indicates whether the condition variable could be created.
-//
-// TODO: It looks like WTF does not have the mutex available when creating
-// the condition variable, and pthreads doesn't appear to require the mutex on
-// condvar creation, so we should just remove the parameter.
 SB_EXPORT bool SbConditionVariableCreate(SbConditionVariable* out_condition,
                                          SbMutex* opt_mutex);
 
diff --git a/src/starboard/examples/window/main.cc b/src/starboard/examples/window/main.cc
index 381d428..bb5bc83 100644
--- a/src/starboard/examples/window/main.cc
+++ b/src/starboard/examples/window/main.cc
@@ -35,7 +35,7 @@
                     << ", window=" << data->window
                     << ", device_type=" << data->device_type
                     << ", device_id=" << data->device_id
-                    << ", key=" << data->key
+                    << ", key=0x" << std::hex << data->key
                     << ", character=" << data->character
                     << ", modifiers=0x" << std::hex << data->key_modifiers
                     << ", location=" << std::dec << data->key_location;
diff --git a/src/starboard/linux/x64directfb/sanitizer_options.cc b/src/starboard/linux/x64directfb/sanitizer_options.cc
new file mode 100644
index 0000000..e85d451
--- /dev/null
+++ b/src/starboard/linux/x64directfb/sanitizer_options.cc
@@ -0,0 +1,42 @@
+// 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.
+
+// Removes gallium leak warnings from x11 GL code, but defines it as a weak
+// symbol, so other code can override it if they want to.
+
+#if defined(ADDRESS_SANITIZER)
+
+// Functions returning default options are declared weak in the tools' runtime
+// libraries. To make the linker pick the strong replacements for those
+// functions from this module, we explicitly force its inclusion by passing
+// -Wl,-u_sanitizer_options_link_helper
+extern "C" void _sanitizer_options_link_helper() { }
+
+#define SANITIZER_HOOK_ATTRIBUTE          \
+  extern "C"                              \
+  __attribute__((no_sanitize_address))    \
+  __attribute__((no_sanitize_memory))     \
+  __attribute__((no_sanitize_thread))     \
+  __attribute__((visibility("default")))  \
+  __attribute__((weak))                   \
+  __attribute__((used))
+
+// Newline separated list of issues to suppress, see
+// http://clang.llvm.org/docs/AddressSanitizer.html#issue-suppression
+// http://llvm.org/svn/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_suppressions.cc
+SANITIZER_HOOK_ATTRIBUTE const char* __lsan_default_suppressions() {
+  return "leak:*eglibc-2.19*\n";
+}
+
+#endif  // defined(ADDRESS_SANITIZER)
diff --git a/src/starboard/linux/x64directfb/starboard_platform.gypi b/src/starboard/linux/x64directfb/starboard_platform.gypi
index f5d40ad..d38e23c 100644
--- a/src/starboard/linux/x64directfb/starboard_platform.gypi
+++ b/src/starboard/linux/x64directfb/starboard_platform.gypi
@@ -17,6 +17,7 @@
   'variables': {
     'starboard_platform_sources': [
         '<(DEPTH)/starboard/linux/x64directfb/main.cc',
+        '<(DEPTH)/starboard/linux/x64directfb/sanitizer_options.cc',
         '<(DEPTH)/starboard/linux/x64directfb/system_get_property.cc',
         '<(DEPTH)/starboard/shared/directfb/application_directfb.cc',
         '<(DEPTH)/starboard/shared/directfb/blitter_blit_rect_to_rect.cc',
diff --git a/src/starboard/nplb/decode_target_create_test.cc b/src/starboard/nplb/decode_target_create_test.cc
index e8f3ea4..287dc21 100644
--- a/src/starboard/nplb/decode_target_create_test.cc
+++ b/src/starboard/nplb/decode_target_create_test.cc
@@ -44,7 +44,6 @@
 
   SbDecodeTarget target =
       SbDecodeTargetCreate(kSbDecodeTargetFormat1PlaneRGBA, &surface);
-  EXPECT_TRUE(SbDecodeTargetIsValid(target));
   if (SbDecodeTargetIsValid(target)) {
     SbBlitterSurface plane =
         SbDecodeTargetGetPlane(target, kSbDecodeTargetPlaneRGBA);
diff --git a/src/starboard/nplb/storage_helpers.h b/src/starboard/nplb/storage_helpers.h
index 56b4fc2..efc422e 100644
--- a/src/starboard/nplb/storage_helpers.h
+++ b/src/starboard/nplb/storage_helpers.h
@@ -27,12 +27,12 @@
 const int64_t kStorageSize2 = kStorageSize * 2 + kStorageOffset;
 
 // Deletes the storage for the current user.
-SB_C_INLINE void ClearStorageRecord() {
+static SB_C_INLINE void ClearStorageRecord() {
   SbStorageDeleteRecord(SbUserGetCurrent());
 }
 
 // Opens the storage record for the current user, validating that it is valid.
-SB_C_INLINE SbStorageRecord OpenStorageRecord() {
+static SB_C_INLINE SbStorageRecord OpenStorageRecord() {
   SbStorageRecord record = SbStorageOpenRecord(SbUserGetCurrent());
   EXPECT_TRUE(SbStorageIsValidRecord(record));
   return record;
@@ -40,7 +40,8 @@
 
 // Writes a standard pattern of |size| bytes into the given open storage
 // |record|.
-SB_C_INLINE void WriteStorageRecord(SbStorageRecord record, int64_t size) {
+static SB_C_INLINE void WriteStorageRecord(SbStorageRecord record,
+                                           int64_t size) {
   char* data = new char[size];
   for (int64_t i = 0; i < size; ++i) {
     data[i] = static_cast<char>(i + 2 % 0xFF);
@@ -52,7 +53,8 @@
 
 // Ensures that the storage record for the current user is initialized with the
 // standard pattern for exactly |length| bytes.
-SB_C_INLINE void InitializeStorageRecord(int64_t length) {
+
+static SB_C_INLINE void InitializeStorageRecord(int64_t length) {
   ClearStorageRecord();
   SbStorageRecord record = OpenStorageRecord();
   WriteStorageRecord(record, length);
@@ -62,7 +64,7 @@
 // Checks a buffer of |total| size for the expected pattern (written in
 // WriteStorageRecord) to start at |offset| and continue for |length|, and the
 // rest of the buffer, before and after, should be set to 0.
-SB_C_INLINE void CheckStorageBuffer(char* data,
+static SB_C_INLINE void CheckStorageBuffer(char* data,
                                     int64_t offset,
                                     int64_t length,
                                     int64_t total) {
@@ -83,7 +85,7 @@
 // |offset| and reporting the buffer size as |length|, checks that the number of
 // read bytes is |expected_length| and then checks the buffer for the expected
 // pattern written in WriteStorageRecord over the expected range of the buffer.
-SB_C_INLINE void ReadAndCheckStorage(SbStorageRecord record,
+static SB_C_INLINE void ReadAndCheckStorage(SbStorageRecord record,
                                      int64_t offset,
                                      int64_t expected_length,
                                      int64_t length,
diff --git a/src/starboard/player.h b/src/starboard/player.h
index 6fbc381..cbd1ff3 100644
--- a/src/starboard/player.h
+++ b/src/starboard/player.h
@@ -173,7 +173,7 @@
 #define kSbPlayerInvalid ((SbPlayer)NULL)
 
 // Returns whether the given player handle is valid.
-SB_C_INLINE bool SbPlayerIsValid(SbPlayer player) {
+static SB_C_INLINE bool SbPlayerIsValid(SbPlayer player) {
   return player != kSbPlayerInvalid;
 }
 
diff --git a/src/starboard/raspi/1/gyp_configuration.gypi b/src/starboard/raspi/1/gyp_configuration.gypi
index fbccc08..040ca1e 100644
--- a/src/starboard/raspi/1/gyp_configuration.gypi
+++ b/src/starboard/raspi/1/gyp_configuration.gypi
@@ -32,7 +32,8 @@
     # This should have a default value in cobalt/base.gypi. See the comment
     # there for acceptable values for this variable.
     'javascript_engine': 'mozjs',
-    'cobalt_enable_jit': 1,
+    'cobalt_enable_jit': 0,
+    'cobalt_minimum_frame_time_in_milliseconds': '33',
 
     # RasPi 1 is ARMv6
     'arm_version': 6,
diff --git a/src/starboard/raspi/1/starboard_platform.gyp b/src/starboard/raspi/1/starboard_platform.gyp
index fb203a6..c39d4e3 100644
--- a/src/starboard/raspi/1/starboard_platform.gyp
+++ b/src/starboard/raspi/1/starboard_platform.gyp
@@ -39,6 +39,8 @@
         '<(DEPTH)/starboard/raspi/shared/main.cc',
         '<(DEPTH)/starboard/raspi/shared/open_max/open_max_component.cc',
         '<(DEPTH)/starboard/raspi/shared/open_max/open_max_component.h',
+        '<(DEPTH)/starboard/raspi/shared/open_max/open_max_video_decode_component.cc',
+        '<(DEPTH)/starboard/raspi/shared/open_max/open_max_video_decode_component.h',
         '<(DEPTH)/starboard/raspi/shared/open_max/video_decoder.cc',
         '<(DEPTH)/starboard/raspi/shared/open_max/video_decoder.h',
         '<(DEPTH)/starboard/raspi/shared/thread_create_priority.cc',
diff --git a/src/starboard/raspi/shared/application_dispmanx.cc b/src/starboard/raspi/shared/application_dispmanx.cc
index fcaf43f..4f9dddf 100644
--- a/src/starboard/raspi/shared/application_dispmanx.cc
+++ b/src/starboard/raspi/shared/application_dispmanx.cc
@@ -51,9 +51,7 @@
   window_ = new SbWindowPrivate(*display_, options);
   input_ = DevInput::Create(window_);
 
-  // Create the dispmanx element to display video frames.
-  int result = 0;
-  uint32_t vc_image_ptr;
+  video_renderer_.reset(new DispmanxVideoRenderer(*display_, kVideoLayer));
 
   return window_;
 }
@@ -86,14 +84,11 @@
 }
 
 void ApplicationDispmanx::AcceptFrame(SbPlayer player,
-                                      const VideoFrame& frame,
+                                      const scoped_refptr<VideoFrame>& frame,
                                       int x,
                                       int y,
                                       int width,
                                       int height) {
-  if (!video_renderer_) {
-    video_renderer_.reset(new DispmanxVideoRenderer(*display_, kVideoLayer));
-  }
   video_renderer_->Update(frame);
 }
 
diff --git a/src/starboard/raspi/shared/application_dispmanx.h b/src/starboard/raspi/shared/application_dispmanx.h
index ba49ff5..d08c406 100644
--- a/src/starboard/raspi/shared/application_dispmanx.h
+++ b/src/starboard/raspi/shared/application_dispmanx.h
@@ -49,7 +49,7 @@
   void Initialize() SB_OVERRIDE;
   void Teardown() SB_OVERRIDE;
   void AcceptFrame(SbPlayer player,
-                   const VideoFrame& frame,
+                   const scoped_refptr<VideoFrame>& frame,
                    int x,
                    int y,
                    int width,
diff --git a/src/starboard/raspi/shared/dispmanx_util.cc b/src/starboard/raspi/shared/dispmanx_util.cc
index 88c7f52..f33a441 100644
--- a/src/starboard/raspi/shared/dispmanx_util.cc
+++ b/src/starboard/raspi/shared/dispmanx_util.cc
@@ -23,6 +23,8 @@
 
 namespace {
 
+const int kElementChangeAttributesFlagSrcRect = 1 << 3;
+
 class DispmanxAutoUpdate {
  public:
   DispmanxAutoUpdate() {
@@ -52,10 +54,61 @@
 
 }  // namespace
 
+DispmanxResource::DispmanxResource(VC_IMAGE_TYPE_T image_type,
+                                   uint32_t width,
+                                   uint32_t height,
+                                   uint32_t visible_width,
+                                   uint32_t visible_height)
+    : width_(width),
+      height_(height),
+      visible_width_(visible_width),
+      visible_height_(visible_height) {
+  static const uint32_t kMaxDimension = 1 << 16;
+
+  SB_DCHECK(width_ > 0 && width_ < kMaxDimension);
+  SB_DCHECK(height_ > 0 && height_ < kMaxDimension);
+  SB_DCHECK(visible_width_ > 0 && visible_width_ < kMaxDimension);
+  SB_DCHECK(visible_height > 0 && visible_height < kMaxDimension);
+  SB_DCHECK(width_ >= visible_width_);
+  SB_DCHECK(height_ >= visible_height);
+
+  uint32_t vc_image_ptr;
+
+  handle_ = vc_dispmanx_resource_create(
+      image_type, visible_width_ | (width_ << 16),
+      visible_height | (height_ << 16), &vc_image_ptr);
+  SB_DCHECK(handle_ != DISPMANX_NO_HANDLE);
+}
+
+void DispmanxYUV420Resource::WriteData(const void* data) {
+  SB_DCHECK(handle() != DISPMANX_NO_HANDLE);
+
+  DispmanxRect dst_rect(0, 0, width(), height() * 3 / 2);
+  int32_t result = vc_dispmanx_resource_write_data(
+      handle(), VC_IMAGE_YUV420, width(), const_cast<void*>(data), &dst_rect);
+  SB_DCHECK(result == 0);
+}
+
 void DispmanxYUV420Resource::ClearWithBlack() {
-  scoped_array<uint8_t> data(new uint8_t[width_ * height_ * 3 / 2]);
-  SbMemorySet(data.get(), width_ * height_, 0);
-  SbMemorySet(data.get() + width_ * height_, width_ * height_ / 2, 0x80);
+  scoped_array<uint8_t> data(new uint8_t[width() * height() * 3 / 2]);
+  SbMemorySet(data.get(), width() * height(), 0);
+  SbMemorySet(data.get() + width() * height(), width() * height() / 2, 0x80);
+  WriteData(data.get());
+}
+
+void DispmanxRGB565Resource::WriteData(const void* data) {
+  SB_DCHECK(handle() != DISPMANX_NO_HANDLE);
+
+  DispmanxRect dst_rect(0, 0, width(), height());
+  int32_t result =
+      vc_dispmanx_resource_write_data(handle(), VC_IMAGE_RGB565, width() * 2,
+                                      const_cast<void*>(data), &dst_rect);
+  SB_DCHECK(result == 0);
+}
+
+void DispmanxRGB565Resource::ClearWithBlack() {
+  scoped_array<uint8_t> data(new uint8_t[width() * height() * 2]);
+  SbMemorySet(data.get(), width() * height() * 2, 0);
   WriteData(data.get());
 }
 
@@ -78,26 +131,37 @@
   SB_DCHECK(result == 0) << " result=" << result;
 }
 
-void DispmanxVideoRenderer::Update(const VideoFrame& video_frame) {
-  if (video_frame.IsEndOfStream()) {
-    element_.reset();
-    resource_.reset();
+void DispmanxElement::ChangeSource(const DispmanxResource& new_src) {
+  DispmanxAutoUpdate update;
+  vc_dispmanx_element_change_source(update.handle(), handle_, new_src.handle());
+}
+
+DispmanxVideoRenderer::DispmanxVideoRenderer(const DispmanxDisplay& display,
+                                             int32_t layer)
+    : black_frame_(256, 256, 256, 256) {
+  black_frame_.ClearWithBlack();
+  element_.reset(new DispmanxElement(display, layer, DispmanxRect(),
+                                     black_frame_, DispmanxRect()));
+}
+
+void DispmanxVideoRenderer::Update(
+    const scoped_refptr<VideoFrame>& video_frame) {
+  SB_DCHECK(video_frame);
+
+  if (frame_ == video_frame) {
     return;
   }
-  if (!resource_ || resource_->width() != video_frame.width() ||
-      resource_->height() != video_frame.height()) {
-    element_.reset();
-    resource_.reset();
 
-    DispmanxRect src_rect(0, 0, video_frame.width() << 16,
-                          video_frame.height() << 16);
-    resource_.reset(
-        new DispmanxYUV420Resource(video_frame.width(), video_frame.height()));
-    element_.reset(new DispmanxElement(display_, layer_, DispmanxRect(),
-                                       *resource_, src_rect));
+  if (video_frame->IsEndOfStream()) {
+    element_->ChangeSource(black_frame_);
+    frame_ = video_frame;
+    return;
   }
 
-  resource_->WriteData(video_frame.GetPlane(0).data);
+  DispmanxYUV420Resource* resource =
+      reinterpret_cast<DispmanxYUV420Resource*>(video_frame->native_texture());
+  element_->ChangeSource(*resource);
+  frame_ = video_frame;
 }
 
 }  // namespace shared
diff --git a/src/starboard/raspi/shared/dispmanx_util.h b/src/starboard/raspi/shared/dispmanx_util.h
index c4b65f6..f051e86 100644
--- a/src/starboard/raspi/shared/dispmanx_util.h
+++ b/src/starboard/raspi/shared/dispmanx_util.h
@@ -69,38 +69,57 @@
   }
 
   DISPMANX_RESOURCE_HANDLE_T handle() const { return handle_; }
+  uint32_t visible_width() const { return visible_width_; }
+  uint32_t visible_height() const { return visible_height_; }
   uint32_t width() const { return width_; }
   uint32_t height() const { return height_; }
 
  protected:
-  DispmanxResource(VC_IMAGE_TYPE_T image_type, uint32_t width, uint32_t height)
-      : width_(width), height_(height) {
-    uint32_t vc_image_ptr;
+  DispmanxResource(VC_IMAGE_TYPE_T image_type,
+                   uint32_t width,
+                   uint32_t height,
+                   uint32_t visible_width,
+                   uint32_t visible_height);
 
-    handle_ =
-        vc_dispmanx_resource_create(image_type, width, height, &vc_image_ptr);
-    SB_DCHECK(handle_ != DISPMANX_NO_HANDLE);
-  }
-
+ private:
   DISPMANX_RESOURCE_HANDLE_T handle_;
   uint32_t width_;
   uint32_t height_;
+  uint32_t visible_width_;
+  uint32_t visible_height_;
 
   SB_DISALLOW_COPY_AND_ASSIGN(DispmanxResource);
 };
 
 class DispmanxYUV420Resource : public DispmanxResource {
  public:
-  DispmanxYUV420Resource(uint32_t width, uint32_t height)
-      : DispmanxResource(VC_IMAGE_YUV420, width, height) {}
+  DispmanxYUV420Resource(uint32_t width,
+                         uint32_t height,
+                         uint32_t visible_width,
+                         uint32_t visible_height)
+      : DispmanxResource(VC_IMAGE_YUV420,
+                         width,
+                         height,
+                         visible_width,
+                         visible_height) {}
 
-  void WriteData(const void* data) {
-    SB_DCHECK(handle_ != DISPMANX_NO_HANDLE);
-    DispmanxRect dst_rect(0, 0, width(), height() * 3 / 2);
-    int32_t result = vc_dispmanx_resource_write_data(
-        handle_, VC_IMAGE_YUV420, width(), const_cast<void*>(data), &dst_rect);
-    SB_DCHECK(result == 0);
-  }
+  void WriteData(const void* data);
+  void ClearWithBlack();
+};
+
+class DispmanxRGB565Resource : public DispmanxResource {
+ public:
+  DispmanxRGB565Resource(uint32_t width,
+                         uint32_t height,
+                         uint32_t visible_width,
+                         uint32_t visible_height)
+      : DispmanxResource(VC_IMAGE_RGB565,
+                         width,
+                         height,
+                         visible_width,
+                         visible_height) {}
+
+  void WriteData(const void* data);
   void ClearWithBlack();
 };
 
@@ -114,6 +133,7 @@
   ~DispmanxElement();
 
   DISPMANX_ELEMENT_HANDLE_T handle() const { return handle_; }
+  void ChangeSource(const DispmanxResource& new_src);
 
  private:
   DISPMANX_ELEMENT_HANDLE_T handle_;
@@ -124,16 +144,18 @@
 class DispmanxVideoRenderer {
  public:
   typedef starboard::shared::starboard::player::VideoFrame VideoFrame;
-  DispmanxVideoRenderer(const DispmanxDisplay& display, int32_t layer)
-      : display_(display), layer_(layer) {}
 
-  void Update(const VideoFrame& video_frame);
+  DispmanxVideoRenderer(const DispmanxDisplay& display, int32_t layer);
+
+  void Update(const scoped_refptr<VideoFrame>& video_frame);
 
  private:
-  const DispmanxDisplay& display_;
-  int32_t layer_;
-  scoped_ptr<DispmanxYUV420Resource> resource_;
   scoped_ptr<DispmanxElement> element_;
+  scoped_refptr<VideoFrame> frame_;
+
+  // Used to fill the background with black if no video is playing so that the
+  // console does not show through.
+  DispmanxRGB565Resource black_frame_;
 
   SB_DISALLOW_COPY_AND_ASSIGN(DispmanxVideoRenderer);
 };
diff --git a/src/starboard/raspi/shared/open_max/open_max_component.cc b/src/starboard/raspi/shared/open_max/open_max_component.cc
index eb05825..bb814f6c 100644
--- a/src/starboard/raspi/shared/open_max/open_max_component.cc
+++ b/src/starboard/raspi/shared/open_max/open_max_component.cc
@@ -47,15 +47,13 @@
 
 }  // namespace
 
-OpenMaxComponent::OpenMaxComponent(const char* name, size_t minimum_output_size)
+OpenMaxComponent::OpenMaxComponent(const char* name)
     : condition_variable_(mutex_),
-      minimum_output_size_(minimum_output_size),
       handle_(NULL),
       input_port_(kInvalidPort),
       output_port_(kInvalidPort),
       output_setting_changed_(false),
-      output_buffer_(NULL),
-      output_buffer_filled_(false) {
+      output_port_enabled_(false) {
   InitializeOpenMax();
 
   OMX_CALLBACKTYPE callbacks;
@@ -99,18 +97,20 @@
   SendCommandAndWaitForCompletion(OMX_CommandFlush, output_port_);
 
   SendCommand(OMX_CommandPortDisable, input_port_);
-  for (BufferHeaders::iterator iter = unused_buffers_.begin();
-       iter != unused_buffers_.end(); ++iter) {
-    OMX_ERRORTYPE error = OMX_FreeBuffer(handle_, input_port_, *iter);
+  for (size_t i = 0; i < input_buffers_.size(); ++i) {
+    OMX_ERRORTYPE error =
+        OMX_FreeBuffer(handle_, input_port_, input_buffers_[i]);
     SB_DCHECK(error == OMX_ErrorNone);
   }
   WaitForCommandCompletion();
 
   SendCommand(OMX_CommandPortDisable, output_port_);
-  if (output_buffer_) {
-    OMX_ERRORTYPE error = OMX_FreeBuffer(handle_, output_port_, output_buffer_);
+  for (size_t i = 0; i < output_buffers_.size(); ++i) {
+    OMX_ERRORTYPE error =
+        OMX_FreeBuffer(handle_, output_port_, output_buffers_[i]);
     SB_DCHECK(error == OMX_ErrorNone);
   }
+  output_buffers_.clear();
   WaitForCommandCompletion();
 
   SendCommandAndWaitForCompletion(OMX_CommandStateSet, OMX_StateLoaded);
@@ -162,45 +162,34 @@
   SB_DCHECK(error == OMX_ErrorNone);
 }
 
-bool OpenMaxComponent::ReadVideoFrame(VideoFrame* frame) {
+OMX_BUFFERHEADERTYPE* OpenMaxComponent::PeekNextOutputBuffer() {
   {
     ScopedLock scoped_lock(mutex_);
-    if (output_buffer_ && !output_buffer_filled_) {
-      return false;
-    }
+
     if (!output_setting_changed_) {
-      return false;
+      return NULL;
     }
   }
-  SB_DCHECK(output_setting_changed_);
-  if (!output_buffer_) {
-    GetOutputPortParam(&output_port_definition_);
-    SB_DCHECK(output_port_definition_.format.video.eColorFormat ==
-              OMX_COLOR_FormatYUV420PackedPlanar);
-    EnableOutputPortAndAllocateBuffer();
-    return false;
-  }
 
-  if (output_buffer_->nFlags & OMX_BUFFERFLAG_EOS) {
-    *frame = VideoFrame();
-    return true;
+  if (!output_port_enabled_) {
+    EnableOutputPortAndAllocateBuffer();
   }
-  SbMediaTime timestamp =
-      ((output_buffer_->nTimeStamp.nHighPart * 0x100000000ull) +
-       output_buffer_->nTimeStamp.nLowPart) *
-      kSbMediaTimeSecond / kSbTimeSecond;
-  int width = output_port_definition_.format.video.nFrameWidth;
-  int height = output_port_definition_.format.video.nSliceHeight;
-  int pitch = output_port_definition_.format.video.nStride;
-  *frame = VideoFrame::CreateYV12Frame(
-      width, height, pitch, timestamp, output_buffer_->pBuffer,
-      output_buffer_->pBuffer + pitch * height,
-      output_buffer_->pBuffer + pitch * height * 5 / 4);
-  output_buffer_filled_ = false;
-  output_buffer_->nFilledLen = 0;
-  OMX_ERRORTYPE error = OMX_FillThisBuffer(handle_, output_buffer_);
+
+  ScopedLock scoped_lock(mutex_);
+  return filled_output_buffers_.empty() ? NULL : filled_output_buffers_.front();
+}
+
+void OpenMaxComponent::DropNextOutputBuffer() {
+  OMX_BUFFERHEADERTYPE* buffer = NULL;
+  {
+    ScopedLock scoped_lock(mutex_);
+    SB_DCHECK(!filled_output_buffers_.empty());
+    buffer = filled_output_buffers_.front();
+    filled_output_buffers_.pop();
+  }
+  buffer->nFilledLen = 0;
+  OMX_ERRORTYPE error = OMX_FillThisBuffer(handle_, buffer);
   SB_DCHECK(error == OMX_ErrorNone);
-  return true;
 }
 
 void OpenMaxComponent::SendCommand(OMX_COMMANDTYPE command, int param) {
@@ -234,48 +223,68 @@
 }
 
 void OpenMaxComponent::EnableInputPortAndAllocateBuffers() {
-  SB_DCHECK(unused_buffers_.empty());
+  SB_DCHECK(input_buffers_.empty());
 
   OMXParamPortDefinition port_definition;
   GetInputPortParam(&port_definition);
+  if (OnEnableInputPort(&port_definition)) {
+    SetPortParam(port_definition);
+  }
 
   SendCommand(OMX_CommandPortEnable, input_port_);
 
-  unused_buffers_.resize(port_definition.nBufferCountActual);
-  for (int i = 0; i != port_definition.nBufferCountActual; ++i) {
-    OMX_ERRORTYPE error =
-        OMX_AllocateBuffer(handle_, &unused_buffers_[i], input_port_, NULL,
-                           port_definition.nBufferSize);
+  for (int i = 0; i < port_definition.nBufferCountActual; ++i) {
+    OMX_BUFFERHEADERTYPE* buffer;
+    OMX_ERRORTYPE error = OMX_AllocateBuffer(handle_, &buffer, input_port_,
+                                             NULL, port_definition.nBufferSize);
     SB_DCHECK(error == OMX_ErrorNone);
+    input_buffers_.push_back(buffer);
+    unused_input_buffers_.push(buffer);
   }
 
   WaitForCommandCompletion();
 }
 
 void OpenMaxComponent::EnableOutputPortAndAllocateBuffer() {
-  if (output_buffer_ != NULL) {
-    return;
+  SB_DCHECK(!output_port_enabled_);
+
+  GetOutputPortParam(&output_port_definition_);
+  if (OnEnableOutputPort(&output_port_definition_)) {
+    SetPortParam(output_port_definition_);
   }
 
   SendCommand(OMX_CommandPortEnable, output_port_);
 
-  OMX_ERRORTYPE error = OMX_AllocateBuffer(
-      handle_, &output_buffer_, output_port_, NULL,
-      std::max(output_port_definition_.nBufferSize, minimum_output_size_));
-  SB_DCHECK(error == OMX_ErrorNone);
+  output_buffers_.reserve(output_port_definition_.nBufferCountActual);
+  for (int i = 0; i < output_port_definition_.nBufferCountActual; ++i) {
+    OMX_BUFFERHEADERTYPE* buffer;
+    OMX_ERRORTYPE error =
+        OMX_AllocateBuffer(handle_, &buffer, output_port_, NULL,
+                           output_port_definition_.nBufferSize);
+    SB_DCHECK(error == OMX_ErrorNone);
+    output_buffers_.push_back(buffer);
+  }
+
   WaitForCommandCompletion();
 
-  error = OMX_FillThisBuffer(handle_, output_buffer_);
-  SB_DCHECK(error == OMX_ErrorNone);
+  output_port_enabled_ = true;
+
+  for (size_t i = 0; i < output_buffers_.size(); ++i) {
+    output_buffers_[i]->nFilledLen = 0;
+    OMX_ERRORTYPE error = OMX_FillThisBuffer(handle_, output_buffers_[i]);
+    SB_DCHECK(error == OMX_ErrorNone);
+  }
 }
 
 OMX_BUFFERHEADERTYPE* OpenMaxComponent::GetUnusedInputBuffer() {
   for (;;) {
-    ScopedLock scoped_lock(mutex_);
-    if (!unused_buffers_.empty()) {
-      OMX_BUFFERHEADERTYPE* buffer_header = unused_buffers_.back();
-      unused_buffers_.pop_back();
-      return buffer_header;
+    {
+      ScopedLock scoped_lock(mutex_);
+      if (!unused_input_buffers_.empty()) {
+        OMX_BUFFERHEADERTYPE* buffer_header = unused_input_buffers_.front();
+        unused_input_buffers_.pop();
+        return buffer_header;
+      }
     }
     SbThreadSleep(kSbTimeMillisecond);
   }
@@ -312,13 +321,12 @@
 OMX_ERRORTYPE OpenMaxComponent::OnEmptyBufferDone(
     OMX_BUFFERHEADERTYPE* buffer) {
   ScopedLock scoped_lock(mutex_);
-  unused_buffers_.push_back(buffer);
+  unused_input_buffers_.push(buffer);
 }
 
 void OpenMaxComponent::OnFillBufferDone(OMX_BUFFERHEADERTYPE* buffer) {
   ScopedLock scoped_lock(mutex_);
-  SB_DCHECK(!output_buffer_filled_);
-  output_buffer_filled_ = true;
+  filled_output_buffers_.push(buffer);
 }
 
 // static
diff --git a/src/starboard/raspi/shared/open_max/open_max_component.h b/src/starboard/raspi/shared/open_max/open_max_component.h
index 9085c1b..d9b5295 100644
--- a/src/starboard/raspi/shared/open_max/open_max_component.h
+++ b/src/starboard/raspi/shared/open_max/open_max_component.h
@@ -22,13 +22,14 @@
 #include <interface/vcos/vcos.h>
 #include <interface/vcos/vcos_logging.h>
 #include <interface/vmcs_host/vchost.h>
+
+#include <queue>
 #include <vector>
 
 #include "starboard/condition_variable.h"
 #include "starboard/log.h"
 #include "starboard/mutex.h"
 #include "starboard/shared/internal_only.h"
-#include "starboard/shared/starboard/player/video_frame_internal.h"
 #include "starboard/time.h"
 
 namespace starboard {
@@ -53,10 +54,8 @@
 
 class OpenMaxComponent {
  public:
-  typedef starboard::shared::starboard::player::VideoFrame VideoFrame;
-
-  explicit OpenMaxComponent(const char* name, size_t minimum_output_size = 0);
-  ~OpenMaxComponent();
+  explicit OpenMaxComponent(const char* name);
+  virtual ~OpenMaxComponent();
 
   void Start();
   void Flush();
@@ -64,7 +63,8 @@
   void WriteData(const void* data, size_t size, SbTime timestamp);
   void WriteEOS();
 
-  bool ReadVideoFrame(VideoFrame* frame);
+  OMX_BUFFERHEADERTYPE* PeekNextOutputBuffer();
+  void DropNextOutputBuffer();
 
   template <typename ParamType>
   void GetInputPortParam(ParamType* param) const {
@@ -94,8 +94,6 @@
   }
 
  private:
-  typedef std::vector<OMX_BUFFERHEADERTYPE*> BufferHeaders;
-
   struct EventDescription {
     OMX_EVENTTYPE event;
     OMX_U32 data1;
@@ -105,6 +103,13 @@
 
   typedef std::vector<EventDescription> EventDescriptions;
 
+  virtual bool OnEnableInputPort(OMXParamPortDefinition* port_definition) {
+    return false;
+  }
+  virtual bool OnEnableOutputPort(OMXParamPortDefinition* port_definition) {
+    return false;
+  }
+
   void SendCommand(OMX_COMMANDTYPE command, int param);
   void WaitForCommandCompletion();
   void SendCommandAndWaitForCompletion(OMX_COMMANDTYPE command, int param);
@@ -134,16 +139,18 @@
 
   Mutex mutex_;
   ConditionVariable condition_variable_;
-  const size_t minimum_output_size_;
   OMX_HANDLETYPE handle_;
   int input_port_;
   int output_port_;
   bool output_setting_changed_;
   EventDescriptions event_descriptions_;
-  BufferHeaders unused_buffers_;
-  OMX_BUFFERHEADERTYPE* output_buffer_;
+  std::vector<OMX_BUFFERHEADERTYPE*> input_buffers_;
+  std::queue<OMX_BUFFERHEADERTYPE*> unused_input_buffers_;
+  std::vector<OMX_BUFFERHEADERTYPE*> output_buffers_;
+  std::queue<OMX_BUFFERHEADERTYPE*> filled_output_buffers_;
+
   OMXParamPortDefinition output_port_definition_;
-  bool output_buffer_filled_;
+  bool output_port_enabled_;
 };
 
 }  // namespace open_max
diff --git a/src/starboard/raspi/shared/open_max/open_max_video_decode_component.cc b/src/starboard/raspi/shared/open_max/open_max_video_decode_component.cc
new file mode 100644
index 0000000..0520c36
--- /dev/null
+++ b/src/starboard/raspi/shared/open_max/open_max_video_decode_component.cc
@@ -0,0 +1,165 @@
+// 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/raspi/shared/open_max/open_max_video_decode_component.h"
+
+#include <algorithm>
+
+#include "starboard/configuration.h"
+
+namespace starboard {
+namespace raspi {
+namespace shared {
+namespace open_max {
+
+namespace {
+
+const char kVideoDecodeComponentName[] = "OMX.broadcom.video_decode";
+const size_t kResourcePoolSize = 12;
+const size_t kOMXOutputBufferCount = 4;
+const int kMaxFrameWidth = 1920;
+const int kMaxFrameHeight = 1088;
+const size_t kMaxVideoFrameSize = kMaxFrameWidth * kMaxFrameHeight * 3 / 2;
+
+}  // namespace
+
+typedef OpenMaxVideoDecodeComponent::VideoFrame VideoFrame;
+
+VideoFrameResourcePool::VideoFrameResourcePool(size_t max_number_of_resources)
+    : max_number_of_resources_(max_number_of_resources),
+      number_of_resources_(0),
+      last_frame_height_(0) {}
+
+VideoFrameResourcePool::~VideoFrameResourcePool() {
+  for (ResourceMap::iterator iter = resource_map_.begin();
+       iter != resource_map_.end(); ++iter) {
+    while (!iter->second.empty()) {
+      delete iter->second.front();
+      iter->second.pop();
+      --number_of_resources_;
+    }
+  }
+  SB_DCHECK(number_of_resources_ == 0) << number_of_resources_;
+}
+
+DispmanxYUV420Resource* VideoFrameResourcePool::Alloc(int width,
+                                                      int height,
+                                                      int visible_width,
+                                                      int visible_height) {
+  ScopedLock scoped_lock(mutex_);
+
+  last_frame_height_ = height;
+
+  ResourceMap::iterator iter = resource_map_.find(height);
+  if (iter != resource_map_.end() && !iter->second.empty()) {
+    DispmanxYUV420Resource* resource = iter->second.front();
+    iter->second.pop();
+    return resource;
+  }
+
+  if (number_of_resources_ >= max_number_of_resources_) {
+    return NULL;
+  }
+
+  ++number_of_resources_;
+  return new DispmanxYUV420Resource(width, height, visible_width,
+                                    visible_height);
+}
+
+void VideoFrameResourcePool::Free(DispmanxYUV420Resource* resource) {
+  ScopedLock scoped_lock(mutex_);
+  if (resource->height() != last_frame_height_) {
+    // The video has adapted, free the resource as it won't be reused any soon.
+    delete resource;
+    --number_of_resources_;
+    return;
+  }
+  resource_map_[resource->height()].push(resource);
+}
+
+// static
+void VideoFrameResourcePool::DisposeDispmanxYUV420Resource(
+    void* context,
+    void* dispmanx_resource) {
+  SB_DCHECK(context != NULL);
+  SB_DCHECK(dispmanx_resource != NULL);
+  VideoFrameResourcePool* pool =
+      reinterpret_cast<VideoFrameResourcePool*>(context);
+  pool->Free(reinterpret_cast<DispmanxYUV420Resource*>(dispmanx_resource));
+  pool->Release();
+}
+
+OpenMaxVideoDecodeComponent::OpenMaxVideoDecodeComponent()
+    : OpenMaxComponent(kVideoDecodeComponentName),
+      resource_pool_(new VideoFrameResourcePool(kResourcePoolSize)) {}
+
+scoped_refptr<VideoFrame> OpenMaxVideoDecodeComponent::ReadVideoFrame() {
+  if (OMX_BUFFERHEADERTYPE* buffer = PeekNextOutputBuffer()) {
+    if (scoped_refptr<VideoFrame> frame = CreateVideoFrame(buffer)) {
+      DropNextOutputBuffer();
+      return frame;
+    }
+  }
+  return NULL;
+}
+
+scoped_refptr<VideoFrame> OpenMaxVideoDecodeComponent::CreateVideoFrame(
+    OMX_BUFFERHEADERTYPE* buffer) {
+  scoped_refptr<VideoFrame> frame;
+  if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
+    frame = VideoFrame::CreateEOSFrame();
+  } else {
+    OMX_VIDEO_PORTDEFINITIONTYPE& video_definition =
+        output_port_definition_.format.video;
+    DispmanxYUV420Resource* resource = resource_pool_->Alloc(
+        video_definition.nStride, video_definition.nSliceHeight,
+        video_definition.nFrameWidth, video_definition.nFrameHeight);
+    if (!resource) {
+      return NULL;
+    }
+
+    resource->WriteData(buffer->pBuffer);
+
+    SbMediaTime timestamp = ((buffer->nTimeStamp.nHighPart * 0x100000000ull) +
+                             buffer->nTimeStamp.nLowPart) *
+                            kSbMediaTimeSecond / kSbTimeSecond;
+
+    resource_pool_->AddRef();
+    frame = new VideoFrame(
+        video_definition.nFrameWidth, video_definition.nFrameHeight, timestamp,
+        resource, resource_pool_,
+        &VideoFrameResourcePool::DisposeDispmanxYUV420Resource);
+  }
+  return frame;
+}
+
+bool OpenMaxVideoDecodeComponent::OnEnableOutputPort(
+    OMXParamPortDefinition* port_definition) {
+  SB_DCHECK(port_definition);
+
+  output_port_definition_ = *port_definition;
+  SB_DCHECK(port_definition->format.video.eColorFormat ==
+            OMX_COLOR_FormatYUV420PackedPlanar);
+  port_definition->format.video.eColorFormat =
+      OMX_COLOR_FormatYUV420PackedPlanar;
+  port_definition->nBufferCountActual = kOMXOutputBufferCount;
+  port_definition->nBufferSize =
+      std::max(port_definition->nBufferSize, kMaxVideoFrameSize);
+  return true;
+}
+
+}  // namespace open_max
+}  // namespace shared
+}  // namespace raspi
+}  // namespace starboard
diff --git a/src/starboard/raspi/shared/open_max/open_max_video_decode_component.h b/src/starboard/raspi/shared/open_max/open_max_video_decode_component.h
new file mode 100644
index 0000000..94b9cda
--- /dev/null
+++ b/src/starboard/raspi/shared/open_max/open_max_video_decode_component.h
@@ -0,0 +1,84 @@
+// 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_RASPI_SHARED_OPEN_MAX_OPEN_MAX_VIDEO_DECODE_COMPONENT_H_
+#define STARBOARD_RASPI_SHARED_OPEN_MAX_OPEN_MAX_VIDEO_DECODE_COMPONENT_H_
+
+#include <map>
+#include <queue>
+
+#include "starboard/common/ref_counted.h"
+#include "starboard/raspi/shared/dispmanx_util.h"
+#include "starboard/raspi/shared/open_max/open_max_component.h"
+
+namespace starboard {
+namespace raspi {
+namespace shared {
+namespace open_max {
+
+class VideoFrameResourcePool
+    : public RefCountedThreadSafe<VideoFrameResourcePool> {
+ public:
+  explicit VideoFrameResourcePool(size_t max_number_of_resources);
+  ~VideoFrameResourcePool();
+
+  DispmanxYUV420Resource* Alloc(int width,
+                                int height,
+                                int visible_width,
+                                int visible_height);
+  void Free(DispmanxYUV420Resource* resource);
+
+  static void DisposeDispmanxYUV420Resource(void* context,
+                                            void* dispmanx_resource);
+
+ private:
+  typedef std::queue<DispmanxYUV420Resource*> ResourceQueue;
+  // Map frame height to resource handles.
+  typedef std::map<int, ResourceQueue> ResourceMap;
+
+  const size_t max_number_of_resources_;
+
+  Mutex mutex_;
+  size_t number_of_resources_;
+  int last_frame_height_;
+  ResourceMap resource_map_;
+};
+
+// Encapsulate a "OMX.broadcom.video_decode" component.  Note that member
+// functions of this class is expected to be called from ANY threads as this
+// class works with the VideoDecoder filter, the OpenMAX component, and also
+// manages the disposition of Dispmanx resource.
+class OpenMaxVideoDecodeComponent : public OpenMaxComponent {
+ public:
+  typedef starboard::shared::starboard::player::VideoFrame VideoFrame;
+
+  OpenMaxVideoDecodeComponent();
+
+  scoped_refptr<VideoFrame> ReadVideoFrame();
+
+ private:
+  scoped_refptr<VideoFrame> CreateVideoFrame(OMX_BUFFERHEADERTYPE* buffer);
+
+  bool OnEnableOutputPort(OMXParamPortDefinition* port_definition) SB_OVERRIDE;
+
+  scoped_refptr<VideoFrameResourcePool> resource_pool_;
+  OMXParamPortDefinition output_port_definition_;
+};
+
+}  // namespace open_max
+}  // namespace shared
+}  // namespace raspi
+}  // namespace starboard
+
+#endif  // STARBOARD_RASPI_SHARED_OPEN_MAX_OPEN_MAX_VIDEO_DECODE_COMPONENT_H_
diff --git a/src/starboard/raspi/shared/open_max/video_decoder.cc b/src/starboard/raspi/shared/open_max/video_decoder.cc
index 702a9f8..a238db7 100644
--- a/src/starboard/raspi/shared/open_max/video_decoder.cc
+++ b/src/starboard/raspi/shared/open_max/video_decoder.cc
@@ -23,17 +23,8 @@
 
 using starboard::shared::starboard::player::VideoFrame;
 
-namespace {
-
-const char kVideoDecodeComponentName[] = "OMX.broadcom.video_decode";
-const size_t kMaxVideoFrameSize = 1920 * 1088 * 3 / 2;
-
-}  // namespace
-
 VideoDecoder::VideoDecoder(SbMediaVideoCodec video_codec)
-    : component_(kVideoDecodeComponentName, kMaxVideoFrameSize),
-      host_(NULL),
-      stream_ended_(false) {
+    : host_(NULL), stream_ended_(false) {
   SB_DCHECK(video_codec == kSbMediaVideoCodecH264);
 
   OMXVideoParamPortFormat port_format;
@@ -61,11 +52,11 @@
   }
   component_.WriteData(input_buffer.data(), input_buffer.size(),
                        input_buffer.pts() * kSbTimeSecond / kSbMediaTimeSecond);
-
-  VideoFrame frame;
-  if (component_.ReadVideoFrame(&frame)) {
-    host_->OnDecoderStatusUpdate(kNeedMoreInput, &frame);
+  if (scoped_refptr<VideoFrame> frame = component_.ReadVideoFrame()) {
+    host_->OnDecoderStatusUpdate(kNeedMoreInput, frame);
   } else {
+    // Call the callback with NULL frame to ensure that the host know that more
+    // data is expected.
     host_->OnDecoderStatusUpdate(kNeedMoreInput, NULL);
   }
 }
diff --git a/src/starboard/raspi/shared/open_max/video_decoder.h b/src/starboard/raspi/shared/open_max/video_decoder.h
index 92850da..de684af 100644
--- a/src/starboard/raspi/shared/open_max/video_decoder.h
+++ b/src/starboard/raspi/shared/open_max/video_decoder.h
@@ -16,7 +16,7 @@
 #define STARBOARD_RASPI_SHARED_OPEN_MAX_VIDEO_DECODER_H_
 
 #include "starboard/media.h"
-#include "starboard/raspi/shared/open_max/open_max_component.h"
+#include "starboard/raspi/shared/open_max/open_max_video_decode_component.h"
 #include "starboard/shared/internal_only.h"
 #include "starboard/shared/starboard/player/filter/video_decoder_internal.h"
 
@@ -39,7 +39,7 @@
   void Reset() SB_OVERRIDE;
 
  private:
-  OpenMaxComponent component_;
+  OpenMaxVideoDecodeComponent component_;
 
   // These variables will be initialized inside ctor or SetHost() and will not
   // be changed during the life time of this class.
diff --git a/src/starboard/shared/directfb/blitter_destroy_swap_chain.cc b/src/starboard/shared/directfb/blitter_destroy_swap_chain.cc
index ba9d317..2f9505b 100644
--- a/src/starboard/shared/directfb/blitter_destroy_swap_chain.cc
+++ b/src/starboard/shared/directfb/blitter_destroy_swap_chain.cc
@@ -26,5 +26,7 @@
 
   swap_chain->render_target.surface->Release(swap_chain->render_target.surface);
 
+  delete swap_chain;
+
   return true;
 }
diff --git a/src/starboard/shared/ffmpeg/ffmpeg_video_decoder.cc b/src/starboard/shared/ffmpeg/ffmpeg_video_decoder.cc
index 7b9efed..2e05ee8 100644
--- a/src/starboard/shared/ffmpeg/ffmpeg_video_decoder.cc
+++ b/src/starboard/shared/ffmpeg/ffmpeg_video_decoder.cc
@@ -197,8 +197,7 @@
         packet.pts = 0;
       } while (DecodePacket(&packet));
 
-      VideoFrame frame = VideoFrame::CreateEOSFrame();
-      host_->OnDecoderStatusUpdate(kBufferFull, &frame);
+      host_->OnDecoderStatusUpdate(kBufferFull, VideoFrame::CreateEOSFrame());
     }
   }
 }
@@ -223,11 +222,11 @@
 
   int pitch = AlignUp(av_frame_->width, kAlignment * 2);
 
-  VideoFrame frame = VideoFrame::CreateYV12Frame(
+  scoped_refptr<VideoFrame> frame = VideoFrame::CreateYV12Frame(
       av_frame_->width, av_frame_->height, pitch,
       codec_context_->reordered_opaque, av_frame_->data[0], av_frame_->data[1],
       av_frame_->data[2]);
-  host_->OnDecoderStatusUpdate(kBufferFull, &frame);
+  host_->OnDecoderStatusUpdate(kBufferFull, frame);
   return true;
 }
 
diff --git a/src/starboard/shared/posix/socket_receive_from.cc b/src/starboard/shared/posix/socket_receive_from.cc
index c4819b6..ca0cb04 100644
--- a/src/starboard/shared/posix/socket_receive_from.cc
+++ b/src/starboard/shared/posix/socket_receive_from.cc
@@ -27,11 +27,7 @@
                         char* out_data,
                         int data_size,
                         SbSocketAddress* out_source) {
-#if defined(MSG_NOSIGNAL)
-  const int kRecvFlags = MSG_NOSIGNAL;
-#else
   const int kRecvFlags = 0;
-#endif
 
   if (!SbSocketIsValid(socket)) {
     errno = EBADF;
diff --git a/src/starboard/shared/signal/crash_signals.cc b/src/starboard/shared/signal/crash_signals.cc
index 0d74011..78b3ab2 100644
--- a/src/starboard/shared/signal/crash_signals.cc
+++ b/src/starboard/shared/signal/crash_signals.cc
@@ -32,7 +32,7 @@
 };
 
 const int kStopSignalsToTrap[] = {
-    SIGTERM, SIGINT, SIGHUP,
+    SIGHUP,
 };
 
 void Crash(int signal_id) {
diff --git a/src/starboard/shared/signal/crash_signals_sigaction.cc b/src/starboard/shared/signal/crash_signals_sigaction.cc
index 5273ab1..da318a8 100644
--- a/src/starboard/shared/signal/crash_signals_sigaction.cc
+++ b/src/starboard/shared/signal/crash_signals_sigaction.cc
@@ -32,7 +32,7 @@
 };
 
 const int kStopSignalsToTrap[] = {
-    SIGTERM, SIGINT, SIGHUP,
+    SIGHUP,
 };
 
 void SetSignalHandler(int signal_id, SignalHandlerFunction handler) {
diff --git a/src/starboard/shared/signal/suspend_signals.cc b/src/starboard/shared/signal/suspend_signals.cc
index 6bb42d8..4048a3b 100644
--- a/src/starboard/shared/signal/suspend_signals.cc
+++ b/src/starboard/shared/signal/suspend_signals.cc
@@ -15,6 +15,7 @@
 #include "starboard/shared/signal/suspend_signals.h"
 
 #include <signal.h>
+#include <sys/socket.h>
 
 #include "starboard/configuration.h"
 #include "starboard/log.h"
@@ -71,19 +72,34 @@
 
 }  // namespace
 
+#if !defined(MSG_NOSIGNAL) && defined(SO_NOSIGPIPE)
+// See "#if !defined(MSG_NOSIGNAL)" below.
+// OS X, which we do not build for today, has another mechanism which
+// should be used.
+#error On this platform, please use SO_NOSIGPIPE and leave the SIGPIPE \
+       handler at default.
+#endif
+
 void InstallSuspendSignalHandlers() {
   SetSignalHandler(SIGTSTP, &Suspend);
   UnblockSignal(SIGTSTP);
   SetSignalHandler(SIGCONT, &Resume);
 
-  // We might receive SIGPIPE after resuming. We should not terminate.
+#if !defined(MSG_NOSIGNAL)
+  // By default in POSIX, sending to a closed socket causes a SIGPIPE
+  // If we cannot disable that behavior, we must ignore SIGPIPE.
+  // Ignoring SIGPIPE means cases that use pipes to redirect the stdio
+  // log messages may behave in surprising ways, so it's not desirable.
   SetSignalHandler(SIGPIPE, &Ignore);
+#endif
 }
 
 void UninstallSuspendSignalHandlers() {
   SetSignalHandler(SIGCONT, SIG_DFL);
   SetSignalHandler(SIGTSTP, SIG_DFL);
+#if !defined(MSG_NOSIGNAL)
   SetSignalHandler(SIGPIPE, SIG_DFL);
+#endif
 }
 
 }  // namespace signal
diff --git a/src/starboard/shared/starboard/application.cc b/src/starboard/shared/starboard/application.cc
index 96efbdb..4f2e850 100644
--- a/src/starboard/shared/starboard/application.cc
+++ b/src/starboard/shared/starboard/application.cc
@@ -130,7 +130,7 @@
 
 #if SB_HAS(PLAYER) && SB_IS(PLAYER_PUNCHED_OUT)
 void Application::HandleFrame(SbPlayer player,
-                              const VideoFrame& frame,
+                              const scoped_refptr<VideoFrame>& frame,
                               int x,
                               int y,
                               int width,
diff --git a/src/starboard/shared/starboard/application.h b/src/starboard/shared/starboard/application.h
index f8609ce..4387bed 100644
--- a/src/starboard/shared/starboard/application.h
+++ b/src/starboard/shared/starboard/application.h
@@ -202,7 +202,7 @@
   // used when the application needs to composite video frames with punch-out
   // video manually (should be rare). Will be called from an external thread.
   void HandleFrame(SbPlayer player,
-                   const VideoFrame& frame,
+                   const scoped_refptr<VideoFrame>& frame,
                    int x,
                    int y,
                    int width,
@@ -224,7 +224,7 @@
   // Subclasses may override this method to accept video frames from the media
   // system. Will be called from an external thread.
   virtual void AcceptFrame(SbPlayer player,
-                           const VideoFrame& frame,
+                           const scoped_refptr<VideoFrame>& frame,
                            int x,
                            int y,
                            int width,
diff --git a/src/starboard/shared/starboard/blitter_blit_rect_to_rect_tiled.cc b/src/starboard/shared/starboard/blitter_blit_rect_to_rect_tiled.cc
index 3317806..8648663 100644
--- a/src/starboard/shared/starboard/blitter_blit_rect_to_rect_tiled.cc
+++ b/src/starboard/shared/starboard/blitter_blit_rect_to_rect_tiled.cc
@@ -248,9 +248,11 @@
     }
   }
 
-  return SbBlitterBlitRectsToRects(context, source_surface, src_rects,
-                                   dst_rects, num_tiles);
+  bool result = SbBlitterBlitRectsToRects(context, source_surface, src_rects,
+                                          dst_rects, num_tiles);
 
   delete[] src_rects;
   delete[] dst_rects;
+
+  return result;
 }
diff --git a/src/starboard/shared/starboard/file_storage/storage_internal.h b/src/starboard/shared/starboard/file_storage/storage_internal.h
index ea322b8..6bb3362 100644
--- a/src/starboard/shared/starboard/file_storage/storage_internal.h
+++ b/src/starboard/shared/starboard/file_storage/storage_internal.h
@@ -33,9 +33,9 @@
 namespace shared {
 namespace starboard {
 // Gets the path to the storage file for the given user.
-SB_C_INLINE bool GetUserStorageFilePath(SbUser user,
-                                        char* out_path,
-                                        int path_size) {
+static SB_C_INLINE bool GetUserStorageFilePath(SbUser user,
+                                               char* out_path,
+                                               int path_size) {
   bool success = SbUserGetProperty(user, kSbUserPropertyHomeDirectory, out_path,
                                    path_size);
   if (!success) {
diff --git a/src/starboard/shared/starboard/localized_strings.cc b/src/starboard/shared/starboard/localized_strings.cc
index 2639c53..0f802e6 100644
--- a/src/starboard/shared/starboard/localized_strings.cc
+++ b/src/starboard/shared/starboard/localized_strings.cc
@@ -116,7 +116,7 @@
     return false;
   }
   SB_DCHECK(file_contents.length() > 0);
-  SB_DCHECK(file_contents.back() == '\n');
+  SB_DCHECK(file_contents[file_contents.length() - 1] == '\n');
 
   // Each line of the file corresponds to one message (key/value).
   size_t pos = 0;
diff --git a/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.cc b/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.cc
index 54477cf..b73cbb2 100644
--- a/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.cc
+++ b/src/starboard/shared/starboard/player/filter/filter_based_player_worker_handler.cc
@@ -210,7 +210,7 @@
       (*player_worker_.*update_player_state_cb_)(kSbPlayerStateEndOfStream);
     }
 
-    const VideoFrame& frame =
+    scoped_refptr<VideoFrame> frame =
         video_renderer_->GetCurrentFrame(audio_renderer_->GetCurrentTime());
 
 #if SB_IS(PLAYER_PUNCHED_OUT)
@@ -230,8 +230,8 @@
 
 #if SB_IS(PLAYER_PUNCHED_OUT)
   // Clear the video frame as we terminate.
-  shared::starboard::Application::Get()->HandleFrame(player_, VideoFrame(), 0,
-                                                     0, 0, 0);
+  shared::starboard::Application::Get()->HandleFrame(
+      player_, VideoFrame::CreateEOSFrame(), 0, 0, 0, 0);
 #endif  // SB_IS(PLAYER_PUNCHED_OUT)
 }
 
diff --git a/src/starboard/shared/starboard/player/filter/video_decoder_internal.h b/src/starboard/shared/starboard/player/filter/video_decoder_internal.h
index fd32c9f..e55c685 100644
--- a/src/starboard/shared/starboard/player/filter/video_decoder_internal.h
+++ b/src/starboard/shared/starboard/player/filter/video_decoder_internal.h
@@ -37,7 +37,9 @@
     // user should only call WriteInputFrame() when |status| is kNeedMoreInput
     // or when the instance is just created.  Also note that calling Reset() or
     // dtor from this callback will result in deadlock.
-    virtual void OnDecoderStatusUpdate(Status status, VideoFrame* frame) = 0;
+    virtual void OnDecoderStatusUpdate(
+        Status status,
+        const scoped_refptr<VideoFrame>& frame) = 0;
 
    protected:
     ~Host() {}
diff --git a/src/starboard/shared/starboard/player/filter/video_renderer_internal.cc b/src/starboard/shared/starboard/player/filter/video_renderer_internal.cc
index 65ee800..35b6bf0 100644
--- a/src/starboard/shared/starboard/player/filter/video_renderer_internal.cc
+++ b/src/starboard/shared/starboard/player/filter/video_renderer_internal.cc
@@ -79,7 +79,8 @@
   frames_.clear();
 }
 
-const VideoFrame& VideoRenderer::GetCurrentFrame(SbMediaTime media_time) {
+scoped_refptr<VideoFrame> VideoRenderer::GetCurrentFrame(
+    SbMediaTime media_time) {
   SB_DCHECK(thread_checker_.CalledOnValidThread());
 
   if (frames_.empty()) {
@@ -87,7 +88,7 @@
   }
   // Remove any frames with timestamps earlier than |media_time|, but always
   // keep at least one of the frames.
-  while (frames_.size() > 1 && frames_.front().pts() < media_time) {
+  while (frames_.size() > 1 && frames_.front()->pts() < media_time) {
     frames_.pop_front();
   }
 
@@ -101,6 +102,7 @@
 
 bool VideoRenderer::CanAcceptMoreData() const {
   SB_DCHECK(thread_checker_.CalledOnValidThread());
+  ScopedLock lock(mutex_);
   return frames_.size() < kMaxCachedFrames && !end_of_stream_written_ &&
          need_more_input_;
 }
@@ -110,8 +112,9 @@
   return seeking_;
 }
 
-void VideoRenderer::OnDecoderStatusUpdate(VideoDecoder::Status status,
-                                          VideoFrame* frame) {
+void VideoRenderer::OnDecoderStatusUpdate(
+    VideoDecoder::Status status,
+    const scoped_refptr<VideoFrame>& frame) {
   ScopedLock lock(mutex_);
 
   if (frame) {
@@ -124,7 +127,7 @@
       }
     }
     if (!frame_too_early) {
-      frames_.push_back(*frame);
+      frames_.push_back(frame);
     }
 
     if (seeking_ && frames_.size() >= kPrerollFrames) {
diff --git a/src/starboard/shared/starboard/player/filter/video_renderer_internal.h b/src/starboard/shared/starboard/player/filter/video_renderer_internal.h
index 8450e59..6cc4cad 100644
--- a/src/starboard/shared/starboard/player/filter/video_renderer_internal.h
+++ b/src/starboard/shared/starboard/player/filter/video_renderer_internal.h
@@ -44,7 +44,7 @@
 
   void Seek(SbMediaTime seek_to_pts);
 
-  const VideoFrame& GetCurrentFrame(SbMediaTime media_time);
+  scoped_refptr<VideoFrame> GetCurrentFrame(SbMediaTime media_time);
 
   bool IsEndOfStreamWritten() const { return end_of_stream_written_; }
   bool IsEndOfStreamPlayed() const;
@@ -52,7 +52,7 @@
   bool IsSeekingInProgress() const;
 
  private:
-  typedef std::list<VideoFrame> Frames;
+  typedef std::list<scoped_refptr<VideoFrame> > Frames;
 
   // Preroll considered finished after either kPrerollFrames is cached or EOS
   // is reached.
@@ -65,7 +65,8 @@
 
   // VideoDecoder::Host method.
   void OnDecoderStatusUpdate(VideoDecoder::Status status,
-                             VideoFrame* frame) SB_OVERRIDE;
+                             const scoped_refptr<VideoFrame>& frame)
+      SB_OVERRIDE;
 
   ThreadChecker thread_checker_;
   ::starboard::Mutex mutex_;
@@ -77,7 +78,7 @@
   // should still display the last frame it is rendering.  This frame will be
   // kept inside |seeking_frame_|.  It is an empty/black frame before the video
   // is started.
-  VideoFrame seeking_frame_;
+  scoped_refptr<VideoFrame> seeking_frame_;
 
   SbMediaTime seeking_to_pts_;
   bool end_of_stream_written_;
diff --git a/src/starboard/shared/starboard/player/video_frame_internal.cc b/src/starboard/shared/starboard/player/video_frame_internal.cc
index 793066d..7bee2c4 100644
--- a/src/starboard/shared/starboard/player/video_frame_internal.cc
+++ b/src/starboard/shared/starboard/player/video_frame_internal.cc
@@ -73,53 +73,76 @@
 

 }  // namespace

 

-VideoFrame::VideoFrame(const VideoFrame& that) {

-  *this = that;

+VideoFrame::VideoFrame() {

+  InitializeToInvalidFrame();

 }

 

-VideoFrame& VideoFrame::operator=(const VideoFrame& that) {

-  this->format_ = that.format_;

+VideoFrame::VideoFrame(int width,

+                       int height,

+                       SbMediaTime pts,

+                       void* native_texture,

+                       void* native_texture_context,

+                       FreeNativeTextureFunc free_native_texture_func) {

+  SB_DCHECK(native_texture != NULL);

+  SB_DCHECK(free_native_texture_func != NULL);

 

-  this->pts_ = that.pts_;

-  this->planes_ = that.planes_;

-  this->pixel_buffer_ = that.pixel_buffer_;

+  InitializeToInvalidFrame();

 

-  for (int i = 0; i < GetPlaneCount(); ++i) {

-    const uint8_t* data = that.GetPlane(i).data;

-    const uint8_t* base = &that.pixel_buffer_[0];

-    ptrdiff_t offset = data - base;

-    SB_DCHECK(offset >= 0);

-    SB_DCHECK(offset < static_cast<ptrdiff_t>(that.pixel_buffer_.size()));

-    planes_[i].data = &pixel_buffer_[0] + offset;

+  format_ = kNativeTexture;

+  width_ = width;

+  height_ = height;

+  pts_ = pts;

+  native_texture_ = native_texture;

+  native_texture_context_ = native_texture_context;

+  free_native_texture_func_ = free_native_texture_func;

+}

+

+VideoFrame::~VideoFrame() {

+  if (format_ == kNativeTexture) {

+    free_native_texture_func_(native_texture_context_, native_texture_);

   }

+}

 

-  return *this;

+int VideoFrame::GetPlaneCount() const {

+  SB_DCHECK(format_ != kInvalid);

+  SB_DCHECK(format_ != kNativeTexture);

+

+  return static_cast<int>(planes_.size());

 }

 

 const VideoFrame::Plane& VideoFrame::GetPlane(int index) const {

+  SB_DCHECK(format_ != kInvalid);

+  SB_DCHECK(format_ != kNativeTexture);

   SB_DCHECK(index >= 0 && index < GetPlaneCount()) << "Invalid index: "

                                                    << index;

   return planes_[index];

 }

 

-VideoFrame VideoFrame::ConvertTo(Format target_format) const {

+void* VideoFrame::native_texture() const {

+  SB_DCHECK(format_ == kNativeTexture);

+  return native_texture_;

+}

+

+scoped_refptr<VideoFrame> VideoFrame::ConvertTo(Format target_format) const {

   SB_DCHECK(format_ == kYV12);

   SB_DCHECK(target_format == kBGRA32);

 

   EnsureYUVToRGBLookupTableInitialized();

 

-  VideoFrame target_frame;

+  scoped_refptr<VideoFrame> target_frame(new VideoFrame);

 

-  target_frame.format_ = target_format;

-  target_frame.pts_ = pts_;

-  target_frame.pixel_buffer_.resize(width() * height() * 4);

-  target_frame.planes_.push_back(

-      Plane(width(), height(), width() * 4, &target_frame.pixel_buffer_[0]));

+  target_frame->format_ = target_format;

+  target_frame->width_ = width();

+  target_frame->height_ = height();

+  target_frame->pts_ = pts_;

+  target_frame->pixel_buffer_.reset(new uint8_t[width() * height() * 4]);

+  target_frame->planes_.push_back(

+      Plane(width(), height(), width() * 4, target_frame->pixel_buffer_.get()));

 

   const uint8_t* y_data = GetPlane(0).data;

   const uint8_t* u_data = GetPlane(1).data;

   const uint8_t* v_data = GetPlane(2).data;

-  uint8_t* bgra_data = &target_frame.pixel_buffer_[0];

+  uint8_t* bgra_data = target_frame->pixel_buffer_.get();

 

   int height = this->height();

   int width = this->width();

@@ -158,21 +181,23 @@
 }

 

 // static

-VideoFrame VideoFrame::CreateEOSFrame() {

-  return VideoFrame();

+scoped_refptr<VideoFrame> VideoFrame::CreateEOSFrame() {

+  return new VideoFrame;

 }

 

 // static

-VideoFrame VideoFrame::CreateYV12Frame(int width,

-                                       int height,

-                                       int pitch_in_bytes,

-                                       SbMediaTime pts,

-                                       const uint8_t* y,

-                                       const uint8_t* u,

-                                       const uint8_t* v) {

-  VideoFrame frame;

-  frame.format_ = kYV12;

-  frame.pts_ = pts;

+scoped_refptr<VideoFrame> VideoFrame::CreateYV12Frame(int width,

+                                                      int height,

+                                                      int pitch_in_bytes,

+                                                      SbMediaTime pts,

+                                                      const uint8_t* y,

+                                                      const uint8_t* u,

+                                                      const uint8_t* v) {

+  scoped_refptr<VideoFrame> frame(new VideoFrame);

+  frame->format_ = kYV12;

+  frame->width_ = width;

+  frame->height_ = height;

+  frame->pts_ = pts;

 

   // U/V planes generally have half resolution of the Y plane.  However, in the

   // extreme case that any dimension of Y plane is odd, we want to have an

@@ -183,26 +208,38 @@
 

   int y_plane_size_in_bytes = height * pitch_in_bytes;

   int uv_plane_size_in_bytes = uv_height * uv_pitch_in_bytes;

-  frame.pixel_buffer_.reserve(y_plane_size_in_bytes +

-                              uv_plane_size_in_bytes * 2);

-  frame.pixel_buffer_.assign(y, y + y_plane_size_in_bytes);

-  frame.pixel_buffer_.insert(frame.pixel_buffer_.end(), u,

-                             u + uv_plane_size_in_bytes);

-  frame.pixel_buffer_.insert(frame.pixel_buffer_.end(), v,

-                             v + uv_plane_size_in_bytes);

+  frame->pixel_buffer_.reset(

+      new uint8_t[y_plane_size_in_bytes + uv_plane_size_in_bytes * 2]);

+  SbMemoryCopy(frame->pixel_buffer_.get(), y, y_plane_size_in_bytes);

+  SbMemoryCopy(frame->pixel_buffer_.get() + y_plane_size_in_bytes, u,

+               uv_plane_size_in_bytes);

+  SbMemoryCopy(frame->pixel_buffer_.get() + y_plane_size_in_bytes +

+                   uv_plane_size_in_bytes,

+               v, uv_plane_size_in_bytes);

 

-  frame.planes_.push_back(

-      Plane(width, height, pitch_in_bytes, &frame.pixel_buffer_[0]));

-  frame.planes_.push_back(

+  frame->planes_.push_back(

+      Plane(width, height, pitch_in_bytes, frame->pixel_buffer_.get()));

+  frame->planes_.push_back(

       Plane(uv_width, uv_height, uv_pitch_in_bytes,

-            &frame.pixel_buffer_[0] + y_plane_size_in_bytes));

-  frame.planes_.push_back(Plane(uv_width, uv_height, uv_pitch_in_bytes,

-                                &frame.pixel_buffer_[0] +

-                                    y_plane_size_in_bytes +

-                                    uv_plane_size_in_bytes));

+            frame->pixel_buffer_.get() + y_plane_size_in_bytes));

+  frame->planes_.push_back(Plane(uv_width, uv_height, uv_pitch_in_bytes,

+                                 frame->pixel_buffer_.get() +

+                                     y_plane_size_in_bytes +

+                                     uv_plane_size_in_bytes));

   return frame;

 }

 

+void VideoFrame::InitializeToInvalidFrame() {

+  format_ = kInvalid;

+  width_ = 0;

+  height_ = 0;

+

+  pts_ = 0;

+  native_texture_ = NULL;

+  native_texture_context_ = NULL;

+  free_native_texture_func_ = NULL;

+}

+

 }  // namespace player

 }  // namespace starboard

 }  // namespace shared

diff --git a/src/starboard/shared/starboard/player/video_frame_internal.h b/src/starboard/shared/starboard/player/video_frame_internal.h
index 745ec31..c956e90 100644
--- a/src/starboard/shared/starboard/player/video_frame_internal.h
+++ b/src/starboard/shared/starboard/player/video_frame_internal.h
@@ -17,6 +17,9 @@
 

 #include <vector>

 

+#include "starboard/common/ref_counted.h"

+#include "starboard/common/scoped_ptr.h"

+#include "starboard/configuration.h"

 #include "starboard/media.h"

 #include "starboard/shared/internal_only.h"

 

@@ -26,10 +29,12 @@
 namespace player {

 

 // A video frame produced by a video decoder.

-class VideoFrame {

+class VideoFrame : public RefCountedThreadSafe<VideoFrame> {

  public:

+  typedef void (*FreeNativeTextureFunc)(void* context, void* textue);

+

   enum Format {

-    kInvalid,

+    kInvalid,  // A VideoFrame in this format can be used to indicate EOS.

     // This is the native format supported by XComposite (PictStandardARGB32

     // with bytes swapped).  Remove this once we are able to pass out frames

     // as YV12 textures.

@@ -50,37 +55,55 @@
     const uint8_t* data;

   };

 

-  VideoFrame() : format_(kInvalid) {}

-  VideoFrame(const VideoFrame& that);

-

-  VideoFrame& operator=(const VideoFrame& that);

+  VideoFrame();  // Create an EOS frame.

+  VideoFrame(int width,

+             int height,

+             SbMediaTime pts,

+             void* native_texture,

+             void* native_texture_context,

+             FreeNativeTextureFunc free_native_texture_func);

+  ~VideoFrame();

 

   Format format() const { return format_; }

-  int width() const { return GetPlaneCount() == 0 ? 0 : GetPlane(0).width; }

-  int height() const { return GetPlaneCount() == 0 ? 0 : GetPlane(0).height; }

-

   bool IsEndOfStream() const { return format_ == kInvalid; }

   SbMediaTime pts() const { return pts_; }

-  int GetPlaneCount() const { return static_cast<int>(planes_.size()); }

+  int width() const { return width_; }

+  int height() const { return height_; }

+

+  int GetPlaneCount() const;

   const Plane& GetPlane(int index) const;

 

-  VideoFrame ConvertTo(Format target_format) const;

+  void* native_texture() const;

 

-  static VideoFrame CreateEOSFrame();

-  static VideoFrame CreateYV12Frame(int width,

-                                    int height,

-                                    int pitch_in_bytes,

-                                    SbMediaTime pts,

-                                    const uint8_t* y,

-                                    const uint8_t* u,

-                                    const uint8_t* v);

+  scoped_refptr<VideoFrame> ConvertTo(Format target_format) const;

+

+  static scoped_refptr<VideoFrame> CreateEOSFrame();

+  static scoped_refptr<VideoFrame> CreateYV12Frame(int width,

+                                                   int height,

+                                                   int pitch_in_bytes,

+                                                   SbMediaTime pts,

+                                                   const uint8_t* y,

+                                                   const uint8_t* u,

+                                                   const uint8_t* v);

 

  private:

-  Format format_;

+  void InitializeToInvalidFrame();

 

+  Format format_;

+  int width_;

+  int height_;

   SbMediaTime pts_;

+

+  // The following two variables are valid when the frame contains pixel data.

   std::vector<Plane> planes_;

-  std::vector<uint8_t> pixel_buffer_;

+  scoped_array<uint8_t> pixel_buffer_;

+

+  // The following three variables are valid when |format_| is `kNativeTexture`.

+  void* native_texture_;

+  void* native_texture_context_;

+  FreeNativeTextureFunc free_native_texture_func_;

+

+  SB_DISALLOW_COPY_AND_ASSIGN(VideoFrame);

 };

 

 }  // namespace player

diff --git a/src/starboard/shared/x11/application_x11.cc b/src/starboard/shared/x11/application_x11.cc
index 1457e73..797c807 100644
--- a/src/starboard/shared/x11/application_x11.cc
+++ b/src/starboard/shared/x11/application_x11.cc
@@ -679,7 +679,7 @@
         ScopedLock lock(frame_mutex_);
         if (frame_written_) {
           // Clear the old frame, now that we are done with it.
-          frame_infos_[frame_read_index_].frame = VideoFrame();
+          frame_infos_[frame_read_index_].frame = NULL;
 
           // Increment the index to the next frame, which has been written.
           frame_read_index_ = (frame_read_index_ + 1) % kNumFrames;
@@ -692,12 +692,12 @@
       }
       FrameInfo& frame_info = frame_infos_[frame_read_index_];
 
-      if (!frame_info.frame.IsEndOfStream() &&
-          frame_info.frame.format() != VideoFrame::kBGRA32) {
-        frame_info.frame = frame_info.frame.ConvertTo(VideoFrame::kBGRA32);
+      if (frame_info.frame && !frame_info.frame->IsEndOfStream() &&
+          frame_info.frame->format() != VideoFrame::kBGRA32) {
+        frame_info.frame = frame_info.frame->ConvertTo(VideoFrame::kBGRA32);
       }
       window->Composite(frame_info.x, frame_info.y, frame_info.width,
-                        frame_info.height, &frame_info.frame);
+                        frame_info.height, frame_info.frame);
     }
   }
   composite_event_id_ =
@@ -705,7 +705,7 @@
 }
 
 void ApplicationX11::AcceptFrame(SbPlayer player,
-                                 const VideoFrame& frame,
+                                 const scoped_refptr<VideoFrame>& frame,
                                  int x,
                                  int y,
                                  int width,
diff --git a/src/starboard/shared/x11/application_x11.h b/src/starboard/shared/x11/application_x11.h
index 8bd9940..efe2a24 100644
--- a/src/starboard/shared/x11/application_x11.h
+++ b/src/starboard/shared/x11/application_x11.h
@@ -49,7 +49,7 @@
 
  protected:
   void AcceptFrame(SbPlayer player,
-                   const shared::starboard::player::VideoFrame& frame,
+                   const scoped_refptr<VideoFrame>& frame,
                    int x,
                    int y,
                    int width,
@@ -71,7 +71,7 @@
 
 #if SB_IS(PLAYER_PUNCHED_OUT)
   struct FrameInfo {
-    shared::starboard::player::VideoFrame frame;
+    scoped_refptr<VideoFrame> frame;
     int x;
     int y;
     int width;
diff --git a/src/starboard/shared/x11/window_internal.cc b/src/starboard/shared/x11/window_internal.cc
index b17082a..70daeb3 100644
--- a/src/starboard/shared/x11/window_internal.cc
+++ b/src/starboard/shared/x11/window_internal.cc
@@ -30,8 +30,6 @@
 #include <X11/extensions/Xrender.h>
 #endif  // SB_IS(PLAYER_PUNCHED_OUT)
 
-using starboard::shared::starboard::player::VideoFrame;
-
 namespace {
 
 const int kWindowWidth = 1920;
@@ -148,11 +146,12 @@
 }
 
 #if SB_IS(PLAYER_PUNCHED_OUT)
-void SbWindowPrivate::Composite(int bounds_x,
-                                int bounds_y,
-                                int bounds_width,
-                                int bounds_height,
-                                VideoFrame* frame) {
+void SbWindowPrivate::Composite(
+    int bounds_x,
+    int bounds_y,
+    int bounds_width,
+    int bounds_height,
+    const starboard::scoped_refptr<VideoFrame>& frame) {
   XSynchronize(display, True);
   XWindowAttributes window_attributes;
   XGetWindowAttributes(display, window, &window_attributes);
diff --git a/src/starboard/shared/x11/window_internal.h b/src/starboard/shared/x11/window_internal.h
index 7c55cb3..e96ffdc 100644
--- a/src/starboard/shared/x11/window_internal.h
+++ b/src/starboard/shared/x11/window_internal.h
@@ -33,6 +33,8 @@
   Window window;
 
 #if SB_IS(PLAYER_PUNCHED_OUT)
+  typedef ::starboard::shared::starboard::player::VideoFrame VideoFrame;
+
   // Composites graphics and the given video frame video for this window. In
   // PLAYER_PUNCHED_OUT mode, this is the only way any graphics or video is
   // presented in the window.  The video frame will be rendered according to
@@ -41,7 +43,7 @@
                  int bounds_y,
                  int bounds_width,
                  int bounds_height,
-                 ::starboard::shared::starboard::player::VideoFrame* frame);
+                 const starboard::scoped_refptr<VideoFrame>& frame);
 
   // The cached XRender Picture that represents the window that is the
   // destination of the composition.
diff --git a/src/starboard/thread.h b/src/starboard/thread.h
index d2138e0..f642f28 100644
--- a/src/starboard/thread.h
+++ b/src/starboard/thread.h
@@ -255,7 +255,7 @@
 // Returns whether |thread| is the current thread.
 //
 // |thread|: The thread to check.
-SB_C_INLINE bool SbThreadIsCurrent(SbThread thread) {
+static SB_C_INLINE bool SbThreadIsCurrent(SbThread thread) {
   return SbThreadGetCurrent() == thread;
 }
 
diff --git a/src/third_party/glm/glm/detail/setup.hpp b/src/third_party/glm/glm/detail/setup.hpp
index 0d524b2..349dbfa 100644
--- a/src/third_party/glm/glm/detail/setup.hpp
+++ b/src/third_party/glm/glm/detail/setup.hpp
@@ -305,7 +305,9 @@
 #endif
 
 // N1988
-#if GLM_LANG & GLM_LANG_CXX11_FLAG
+#if defined(STARBOARD)
+#	define GLM_HAS_EXTENDED_INTEGER_TYPE 0
+#elif GLM_LANG & GLM_LANG_CXX11_FLAG
 #	define GLM_HAS_EXTENDED_INTEGER_TYPE 1
 #else
 #	define GLM_HAS_EXTENDED_INTEGER_TYPE (\
diff --git a/src/third_party/glm/glm/detail/type_int.hpp b/src/third_party/glm/glm/detail/type_int.hpp
index 764a32c..f37a40a 100644
--- a/src/third_party/glm/glm/detail/type_int.hpp
+++ b/src/third_party/glm/glm/detail/type_int.hpp
@@ -4,6 +4,11 @@
 #pragma once
 
 #include "setup.hpp"
+
+#if defined(STARBOARD)
+#include "starboard/types.h"
+
+#else  // defined(STARBOARD)
 #if GLM_HAS_MAKE_SIGNED
 #	include <type_traits>
 #endif
@@ -11,11 +16,22 @@
 #if GLM_HAS_EXTENDED_INTEGER_TYPE
 #	include <cstdint>
 #endif
+#endif  // defined(STARBOARD)
 
 namespace glm{
 namespace detail
 {
-#	if GLM_HAS_EXTENDED_INTEGER_TYPE
+# if defined(STARBOARD)
+		typedef int8_t				int8;
+		typedef int16_t				int16;
+		typedef int32_t				int32;
+		typedef int64_t				int64;
+
+		typedef uint8_t				uint8;
+		typedef uint16_t			uint16;
+		typedef uint32_t			uint32;
+		typedef uint64_t			uint64;
+# elif GLM_HAS_EXTENDED_INTEGER_TYPE
 		typedef std::int8_t					int8;
 		typedef std::int16_t				int16;
 		typedef std::int32_t				int32;
diff --git a/src/third_party/glm/glm/fwd.hpp b/src/third_party/glm/glm/fwd.hpp
index f90c4d0..2e04473 100644
--- a/src/third_party/glm/glm/fwd.hpp
+++ b/src/third_party/glm/glm/fwd.hpp
@@ -257,7 +257,9 @@
 	typedef detail::int64 int64;
 
 
-#if GLM_HAS_EXTENDED_INTEGER_TYPE
+#if defined(STARBOARD)
+	// Empty.
+#elif GLM_HAS_EXTENDED_INTEGER_TYPE
 	using std::int8_t;
 	using std::int16_t;
 	using std::int32_t;
@@ -866,7 +868,9 @@
 	/// @see gtc_type_precision
 	typedef detail::uint64 uint64;
 	
-#if GLM_HAS_EXTENDED_INTEGER_TYPE
+#if defined(STARBOARD)
+	// Empty.
+#elif GLM_HAS_EXTENDED_INTEGER_TYPE
 	using std::uint8_t;
 	using std::uint16_t;
 	using std::uint32_t;
diff --git a/src/third_party/libxml/src/HTMLparser.c b/src/third_party/libxml/src/HTMLparser.c
index 3cb0388..c7a0658 100644
--- a/src/third_party/libxml/src/HTMLparser.c
+++ b/src/third_party/libxml/src/HTMLparser.c
@@ -3254,12 +3254,17 @@
 	ctxt->instate = state;
 	return;
     }
+    len = 0;
+    buf[len] = 0;
     q = CUR_CHAR(ql);
+    if (!IS_CHAR(q))
+        goto unfinished;
     NEXTL(ql);
     r = CUR_CHAR(rl);
+    if (!IS_CHAR(r))
+        goto unfinished;
     NEXTL(rl);
     cur = CUR_CHAR(l);
-    len = 0;
     while (IS_CHAR(cur) &&
            ((cur != '>') ||
 	    (r != '-') || (q != '-'))) {
@@ -3290,18 +3295,19 @@
 	}
     }
     buf[len] = 0;
-    if (!IS_CHAR(cur)) {
-	htmlParseErr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
-	             "Comment not terminated \n<!--%.50s\n", buf, NULL);
-	xmlFree(buf);
-    } else {
+    if (IS_CHAR(cur)) {
         NEXT;
 	if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL) &&
 	    (!ctxt->disableSAX))
 	    ctxt->sax->comment(ctxt->userData, buf);
 	xmlFree(buf);
+	ctxt->instate = state;
+	return;
     }
-    ctxt->instate = state;
+unfinished:
+   htmlParseErr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
+		 "Comment not terminated \n<!--%.50s\n", buf, NULL);
+    xmlFree(buf);
 }
 
 /**
diff --git a/src/third_party/mozjs-45/INSTALL b/src/third_party/mozjs-45/INSTALL
new file mode 100644
index 0000000..c57135b
--- /dev/null
+++ b/src/third_party/mozjs-45/INSTALL
@@ -0,0 +1,13 @@
+Full build documentation for SpiderMonkey is hosted on MDN:
+  https://developer.mozilla.org/en-US/docs/SpiderMonkey/Build_Documentation
+
+Note that the libraries produced by the build system include symbols,
+causing the binaries to be extremely large. It is highly suggested that `strip`
+be run over the binaries before deploying them.
+
+Building with default options may be performed as follows:
+  cd js/src
+  mkdir obj
+  cd obj
+  ../configure
+  make # or mozmake on Windows
diff --git a/src/third_party/mozjs-45/LICENSE b/src/third_party/mozjs-45/LICENSE
new file mode 100644
index 0000000..14e2f77
--- /dev/null
+++ b/src/third_party/mozjs-45/LICENSE
@@ -0,0 +1,373 @@
+Mozilla Public License Version 2.0
+==================================
+
+1. Definitions
+--------------
+
+1.1. "Contributor"
+    means each individual or legal entity that creates, contributes to
+    the creation of, or owns Covered Software.
+
+1.2. "Contributor Version"
+    means the combination of the Contributions of others (if any) used
+    by a Contributor and that particular Contributor's Contribution.
+
+1.3. "Contribution"
+    means Covered Software of a particular Contributor.
+
+1.4. "Covered Software"
+    means Source Code Form to which the initial Contributor has attached
+    the notice in Exhibit A, the Executable Form of such Source Code
+    Form, and Modifications of such Source Code Form, in each case
+    including portions thereof.
+
+1.5. "Incompatible With Secondary Licenses"
+    means
+
+    (a) that the initial Contributor has attached the notice described
+        in Exhibit B to the Covered Software; or
+
+    (b) that the Covered Software was made available under the terms of
+        version 1.1 or earlier of the License, but not also under the
+        terms of a Secondary License.
+
+1.6. "Executable Form"
+    means any form of the work other than Source Code Form.
+
+1.7. "Larger Work"
+    means a work that combines Covered Software with other material, in 
+    a separate file or files, that is not Covered Software.
+
+1.8. "License"
+    means this document.
+
+1.9. "Licensable"
+    means having the right to grant, to the maximum extent possible,
+    whether at the time of the initial grant or subsequently, any and
+    all of the rights conveyed by this License.
+
+1.10. "Modifications"
+    means any of the following:
+
+    (a) any file in Source Code Form that results from an addition to,
+        deletion from, or modification of the contents of Covered
+        Software; or
+
+    (b) any new file in Source Code Form that contains any Covered
+        Software.
+
+1.11. "Patent Claims" of a Contributor
+    means any patent claim(s), including without limitation, method,
+    process, and apparatus claims, in any patent Licensable by such
+    Contributor that would be infringed, but for the grant of the
+    License, by the making, using, selling, offering for sale, having
+    made, import, or transfer of either its Contributions or its
+    Contributor Version.
+
+1.12. "Secondary License"
+    means either the GNU General Public License, Version 2.0, the GNU
+    Lesser General Public License, Version 2.1, the GNU Affero General
+    Public License, Version 3.0, or any later versions of those
+    licenses.
+
+1.13. "Source Code Form"
+    means the form of the work preferred for making modifications.
+
+1.14. "You" (or "Your")
+    means an individual or a legal entity exercising rights under this
+    License. For legal entities, "You" includes any entity that
+    controls, is controlled by, or is under common control with You. For
+    purposes of this definition, "control" means (a) the power, direct
+    or indirect, to cause the direction or management of such entity,
+    whether by contract or otherwise, or (b) ownership of more than
+    fifty percent (50%) of the outstanding shares or beneficial
+    ownership of such entity.
+
+2. License Grants and Conditions
+--------------------------------
+
+2.1. Grants
+
+Each Contributor hereby grants You a world-wide, royalty-free,
+non-exclusive license:
+
+(a) under intellectual property rights (other than patent or trademark)
+    Licensable by such Contributor to use, reproduce, make available,
+    modify, display, perform, distribute, and otherwise exploit its
+    Contributions, either on an unmodified basis, with Modifications, or
+    as part of a Larger Work; and
+
+(b) under Patent Claims of such Contributor to make, use, sell, offer
+    for sale, have made, import, and otherwise transfer either its
+    Contributions or its Contributor Version.
+
+2.2. Effective Date
+
+The licenses granted in Section 2.1 with respect to any Contribution
+become effective for each Contribution on the date the Contributor first
+distributes such Contribution.
+
+2.3. Limitations on Grant Scope
+
+The licenses granted in this Section 2 are the only rights granted under
+this License. No additional rights or licenses will be implied from the
+distribution or licensing of Covered Software under this License.
+Notwithstanding Section 2.1(b) above, no patent license is granted by a
+Contributor:
+
+(a) for any code that a Contributor has removed from Covered Software;
+    or
+
+(b) for infringements caused by: (i) Your and any other third party's
+    modifications of Covered Software, or (ii) the combination of its
+    Contributions with other software (except as part of its Contributor
+    Version); or
+
+(c) under Patent Claims infringed by Covered Software in the absence of
+    its Contributions.
+
+This License does not grant any rights in the trademarks, service marks,
+or logos of any Contributor (except as may be necessary to comply with
+the notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+No Contributor makes additional grants as a result of Your choice to
+distribute the Covered Software under a subsequent version of this
+License (see Section 10.2) or under the terms of a Secondary License (if
+permitted under the terms of Section 3.3).
+
+2.5. Representation
+
+Each Contributor represents that the Contributor believes its
+Contributions are its original creation(s) or it has sufficient rights
+to grant the rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+This License is not intended to limit any rights You have under
+applicable copyright doctrines of fair use, fair dealing, or other
+equivalents.
+
+2.7. Conditions
+
+Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
+in Section 2.1.
+
+3. Responsibilities
+-------------------
+
+3.1. Distribution of Source Form
+
+All distribution of Covered Software in Source Code Form, including any
+Modifications that You create or to which You contribute, must be under
+the terms of this License. You must inform recipients that the Source
+Code Form of the Covered Software is governed by the terms of this
+License, and how they can obtain a copy of this License. You may not
+attempt to alter or restrict the recipients' rights in the Source Code
+Form.
+
+3.2. Distribution of Executable Form
+
+If You distribute Covered Software in Executable Form then:
+
+(a) such Covered Software must also be made available in Source Code
+    Form, as described in Section 3.1, and You must inform recipients of
+    the Executable Form how they can obtain a copy of such Source Code
+    Form by reasonable means in a timely manner, at a charge no more
+    than the cost of distribution to the recipient; and
+
+(b) You may distribute such Executable Form under the terms of this
+    License, or sublicense it under different terms, provided that the
+    license for the Executable Form does not attempt to limit or alter
+    the recipients' rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+You may create and distribute a Larger Work under terms of Your choice,
+provided that You also comply with the requirements of this License for
+the Covered Software. If the Larger Work is a combination of Covered
+Software with a work governed by one or more Secondary Licenses, and the
+Covered Software is not Incompatible With Secondary Licenses, this
+License permits You to additionally distribute such Covered Software
+under the terms of such Secondary License(s), so that the recipient of
+the Larger Work may, at their option, further distribute the Covered
+Software under the terms of either this License or such Secondary
+License(s).
+
+3.4. Notices
+
+You may not remove or alter the substance of any license notices
+(including copyright notices, patent notices, disclaimers of warranty,
+or limitations of liability) contained within the Source Code Form of
+the Covered Software, except that You may alter any license notices to
+the extent required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+You may choose to offer, and to charge a fee for, warranty, support,
+indemnity or liability obligations to one or more recipients of Covered
+Software. However, You may do so only on Your own behalf, and not on
+behalf of any Contributor. You must make it absolutely clear that any
+such warranty, support, indemnity, or liability obligation is offered by
+You alone, and You hereby agree to indemnify every Contributor for any
+liability incurred by such Contributor as a result of warranty, support,
+indemnity or liability terms You offer. You may include additional
+disclaimers of warranty and limitations of liability specific to any
+jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+---------------------------------------------------
+
+If it is impossible for You to comply with any of the terms of this
+License with respect to some or all of the Covered Software due to
+statute, judicial order, or regulation then You must: (a) comply with
+the terms of this License to the maximum extent possible; and (b)
+describe the limitations and the code they affect. Such description must
+be placed in a text file included with all distributions of the Covered
+Software under this License. Except to the extent prohibited by statute
+or regulation, such description must be sufficiently detailed for a
+recipient of ordinary skill to be able to understand it.
+
+5. Termination
+--------------
+
+5.1. The rights granted under this License will terminate automatically
+if You fail to comply with any of its terms. However, if You become
+compliant, then the rights granted under this License from a particular
+Contributor are reinstated (a) provisionally, unless and until such
+Contributor explicitly and finally terminates Your grants, and (b) on an
+ongoing basis, if such Contributor fails to notify You of the
+non-compliance by some reasonable means prior to 60 days after You have
+come back into compliance. Moreover, Your grants from a particular
+Contributor are reinstated on an ongoing basis if such Contributor
+notifies You of the non-compliance by some reasonable means, this is the
+first time You have received notice of non-compliance with this License
+from such Contributor, and You become compliant prior to 30 days after
+Your receipt of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+infringement claim (excluding declaratory judgment actions,
+counter-claims, and cross-claims) alleging that a Contributor Version
+directly or indirectly infringes any patent, then the rights granted to
+You by any and all Contributors for the Covered Software under Section
+2.1 of this License shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all
+end user license agreements (excluding distributors and resellers) which
+have been validly granted by You or Your distributors under this License
+prior to termination shall survive termination.
+
+************************************************************************
+*                                                                      *
+*  6. Disclaimer of Warranty                                           *
+*  -------------------------                                           *
+*                                                                      *
+*  Covered Software is provided under this License on an "as is"       *
+*  basis, without warranty of any kind, either expressed, implied, or  *
+*  statutory, including, without limitation, warranties that the       *
+*  Covered Software is free of defects, merchantable, fit for a        *
+*  particular purpose or non-infringing. The entire risk as to the     *
+*  quality and performance of the Covered Software is with You.        *
+*  Should any Covered Software prove defective in any respect, You     *
+*  (not any Contributor) assume the cost of any necessary servicing,   *
+*  repair, or correction. This disclaimer of warranty constitutes an   *
+*  essential part of this License. No use of any Covered Software is   *
+*  authorized under this License except under this disclaimer.         *
+*                                                                      *
+************************************************************************
+
+************************************************************************
+*                                                                      *
+*  7. Limitation of Liability                                          *
+*  --------------------------                                          *
+*                                                                      *
+*  Under no circumstances and under no legal theory, whether tort      *
+*  (including negligence), contract, or otherwise, shall any           *
+*  Contributor, or anyone who distributes Covered Software as          *
+*  permitted above, be liable to You for any direct, indirect,         *
+*  special, incidental, or consequential damages of any character      *
+*  including, without limitation, damages for lost profits, loss of    *
+*  goodwill, work stoppage, computer failure or malfunction, or any    *
+*  and all other commercial damages or losses, even if such party      *
+*  shall have been informed of the possibility of such damages. This   *
+*  limitation of liability shall not apply to liability for death or   *
+*  personal injury resulting from such party's negligence to the       *
+*  extent applicable law prohibits such limitation. Some               *
+*  jurisdictions do not allow the exclusion or limitation of           *
+*  incidental or consequential damages, so this exclusion and          *
+*  limitation may not apply to You.                                    *
+*                                                                      *
+************************************************************************
+
+8. Litigation
+-------------
+
+Any litigation relating to this License may be brought only in the
+courts of a jurisdiction where the defendant maintains its principal
+place of business and such litigation shall be governed by laws of that
+jurisdiction, without reference to its conflict-of-law provisions.
+Nothing in this Section shall prevent a party's ability to bring
+cross-claims or counter-claims.
+
+9. Miscellaneous
+----------------
+
+This License represents the complete agreement concerning the subject
+matter hereof. If any provision of this License is held to be
+unenforceable, such provision shall be reformed only to the extent
+necessary to make it enforceable. Any law or regulation which provides
+that the language of a contract shall be construed against the drafter
+shall not be used to construe this License against a Contributor.
+
+10. Versions of the License
+---------------------------
+
+10.1. New Versions
+
+Mozilla Foundation is the license steward. Except as provided in Section
+10.3, no one other than the license steward has the right to modify or
+publish new versions of this License. Each version will be given a
+distinguishing version number.
+
+10.2. Effect of New Versions
+
+You may distribute the Covered Software under the terms of the version
+of the License under which You originally received the Covered Software,
+or under the terms of any subsequent version published by the license
+steward.
+
+10.3. Modified Versions
+
+If you create software not governed by this License, and you want to
+create a new license for such software, you may create and use a
+modified version of this License if you rename the license and remove
+any references to the name of the license steward (except to note that
+such modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary
+Licenses
+
+If You choose to distribute Source Code Form that is Incompatible With
+Secondary Licenses under the terms of this version of the License, the
+notice described in Exhibit B of this License must be attached.
+
+Exhibit A - Source Code Form License Notice
+-------------------------------------------
+
+  This Source Code Form is subject to the terms of the Mozilla Public
+  License, v. 2.0. If a copy of the MPL was not distributed with this
+  file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+If it is not possible or desirable to put the notice in a particular
+file, then You may include the notice in a location (such as a LICENSE
+file in a relevant directory) where a recipient would be likely to look
+for such a notice.
+
+You may add additional accurate notices of copyright ownership.
+
+Exhibit B - "Incompatible With Secondary Licenses" Notice
+---------------------------------------------------------
+
+  This Source Code Form is "Incompatible With Secondary Licenses", as
+  defined by the Mozilla Public License, v. 2.0.
diff --git a/src/third_party/mozjs-45/Makefile.in b/src/third_party/mozjs-45/Makefile.in
new file mode 100644
index 0000000..078ac34
--- /dev/null
+++ b/src/third_party/mozjs-45/Makefile.in
@@ -0,0 +1,336 @@
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+ifeq (,$(MAKE_VERSION))
+$(error GNU Make is required)
+endif
+make_min_ver := 3.81
+ifneq ($(make_min_ver),$(firstword $(sort $(make_min_ver) $(MAKE_VERSION))))
+$(error GNU Make $(make_min_ver) or higher is required)
+endif
+
+export TOPLEVEL_BUILD := 1
+
+default::
+
+ifdef MOZ_BUILD_APP
+include $(topsrcdir)/$(MOZ_BUILD_APP)/build.mk
+endif
+
+include $(topsrcdir)/config/config.mk
+
+GARBAGE_DIRS += _javagen _profile staticlib
+DIST_GARBAGE = config.cache config.log config.status* config-defs.h \
+   config/autoconf.mk \
+   mozilla-config.h \
+   netwerk/necko-config.h xpcom/xpcom-config.h xpcom/xpcom-private.h \
+   .mozconfig.mk
+
+ifdef JS_STANDALONE
+configure_dir = $(topsrcdir)/js/src
+else
+configure_dir = $(topsrcdir)
+endif
+
+ifndef TEST_MOZBUILD
+ifndef MOZ_PROFILE_USE
+# We need to explicitly put backend.RecursiveMakeBackend here
+# otherwise the rule in rules.mk doesn't run early enough.
+$(TIERS) binaries:: CLOBBER $(configure_dir)/configure config.status backend.RecursiveMakeBackend
+ifndef JS_STANDALONE
+ifdef COMPILE_ENVIRONMENT
+$(TIERS) binaries:: $(topsrcdir)/js/src/configure js/src/config.status
+endif
+endif
+endif
+endif
+
+ifdef JS_STANDALONE
+.PHONY: CLOBBER
+CLOBBER:
+else
+CLOBBER: $(topsrcdir)/CLOBBER
+	@echo 'STOP!  The CLOBBER file has changed.'
+	@echo 'Please run the build through a sanctioned build wrapper, such as'
+	@echo '"mach build" or client.mk.'
+	@exit 1
+endif
+
+$(topsrcdir)/configure: $(topsrcdir)/configure.in
+$(topsrcdir)/js/src/configure: $(topsrcdir)/js/src/configure.in
+$(topsrcdir)/configure $(topsrcdir)/js/src/configure:
+	@echo 'STOP!  $^ has changed, and your configure is out of date.'
+	@echo 'Please rerun autoconf and re-configure your build directory.'
+	@echo 'To ignore this message, touch "$@",'
+	@echo 'but your build might not succeed.'
+	@exit 1
+
+config.status: $(configure_dir)/configure
+js/src/config.status: $(topsrcdir)/js/src/configure
+config.status js/src/config.status:
+	@echo 'STOP!  $^ has changed and needs to be run again.'
+	@echo 'Please rerun it.'
+	@echo 'To ignore this message, touch "$(CURDIR)/$@",'
+	@echo 'but your build might not succeed.'
+	@exit 1
+
+# Regenerate the build backend if it is out of date. We only have this rule in
+# this main make file because having it in rules.mk and applied to partial tree
+# builds resulted in a world of hurt. Gory details are in bug 877308.
+#
+# The mach build driver will ensure the backend is up to date for partial tree
+# builds. This cleanly avoids most of the pain.
+
+ifndef TEST_MOZBUILD
+backend.RecursiveMakeBackend:
+	@echo 'Build configuration changed. Regenerating backend.'
+	$(PYTHON) config.status
+
+Makefile: backend.RecursiveMakeBackend
+	@$(TOUCH) $@
+
+include backend.RecursiveMakeBackend.pp
+
+default:: backend.RecursiveMakeBackend
+endif
+
+install_manifests := \
+  $(addprefix dist/,bin branding idl include public private sdk xpi-stage) \
+  _tests \
+  $(NULL)
+install_manifest_depends = \
+  CLOBBER \
+  $(configure_dir)/configure \
+  config.status \
+  backend.RecursiveMakeBackend \
+  $(NULL)
+
+ifndef JS_STANDALONE
+ifdef COMPILE_ENVIRONMENT
+install_manifest_depends += \
+  $(topsrcdir)/js/src/configure \
+  js/src/config.status \
+  $(NULL)
+endif
+endif
+
+.PHONY: install-manifests
+install-manifests: $(addprefix install-,$(install_manifests))
+
+# process_install_manifest needs to be invoked with --no-remove when building
+# js as standalone because automated builds are building nspr separately and
+# that would remove the resulting files.
+# Eventually, a standalone js build would just be able to build nspr itself,
+# removing the need for the former.
+ifdef JS_STANDALONE
+NO_REMOVE=1
+endif
+
+.PHONY: $(addprefix install-,$(install_manifests))
+$(addprefix install-,$(filter dist/%,$(install_manifests))): install-dist/%: $(install_manifest_depends)
+	$(call py_action,process_install_manifest,$(if $(NO_REMOVE),--no-remove )$(DIST)/$* _build_manifests/install/dist_$*)
+
+# Dummy wrapper rule to allow the faster backend to piggy back
+install-dist_%: install-dist/% ;
+
+install-_tests: $(install_manifest_depends)
+	$(call py_action,process_install_manifest,$(if $(NO_REMOVE),--no-remove )_tests _build_manifests/install/_tests)
+
+# For compatibility
+.PHONY: install-tests
+install-tests: install-_tests
+
+include $(topsrcdir)/build/moz-automation.mk
+
+# dist and _tests should be purged during cleaning. However, we don't want them
+# purged during PGO builds because they contain some auto-generated files.
+ifneq ($(filter-out maybe_clobber_profiledbuild,$(MAKECMDGOALS)),)
+GARBAGE_DIRS += dist _tests
+endif
+
+# Windows PGO builds don't perform a clean before the 2nd pass. So, we want
+# to preserve content for the 2nd pass on Windows. Everywhere else, we always
+# process the install manifests as part of export.
+# For the binaries rule, not all the install manifests matter, so force only
+# the interesting ones to be done.
+ifdef MOZ_PROFILE_USE
+ifndef NO_PROFILE_GUIDED_OPTIMIZE
+ifneq ($(OS_ARCH)_$(GNU_CC), WINNT_)
+export:: install-manifests
+binaries::
+	@$(MAKE) install-manifests NO_REMOVE=1 install_manifests=dist/include
+endif
+endif
+else # !MOZ_PROFILE_USE (normal build)
+export:: install-manifests
+binaries::
+	@$(MAKE) install-manifests NO_REMOVE=1 install_manifests=dist/include
+endif
+
+# For historical reasons that are unknown, $(DIST)/sdk is always blown away
+# with no regard for PGO passes. This decision could probably be revisited.
+export:: install-dist/sdk
+
+ifndef JS_STANDALONE
+ifdef ENABLE_TESTS
+# Additional makefile targets to call automated test suites
+include $(topsrcdir)/testing/testsuite-targets.mk
+endif
+endif
+
+default all::
+	$(call BUILDSTATUS,TIERS $(TIERS) $(if $(MOZ_AUTOMATION),$(MOZ_AUTOMATION_TIERS)))
+
+include $(topsrcdir)/config/rules.mk
+
+distclean::
+	$(RM) $(DIST_GARBAGE)
+
+ifeq ($(OS_ARCH),WINNT)
+# we want to copy PDB files on Windows
+MAKE_SYM_STORE_ARGS := -c --vcs-info
+ifdef PDBSTR_PATH
+MAKE_SYM_STORE_ARGS += -i
+endif
+DUMP_SYMS_BIN ?= $(topsrcdir)/toolkit/crashreporter/tools/win32/dump_syms_vc$(_MSC_VER).exe
+# PDB files don't get moved to dist, so we need to scan the whole objdir
+MAKE_SYM_STORE_PATH := .
+endif
+ifeq ($(OS_ARCH),Darwin)
+# need to pass arch flags for universal builds
+ifdef UNIVERSAL_BINARY
+MAKE_SYM_STORE_ARGS := -c -a 'i386 x86_64' --vcs-info
+MAKE_SYM_STORE_PATH := $(DIST)/universal
+else
+MAKE_SYM_STORE_ARGS := -c -a $(OS_TEST) --vcs-info
+MAKE_SYM_STORE_PATH := $(DIST)/bin
+endif
+DUMP_SYMS_BIN ?= $(DIST)/host/bin/dump_syms
+endif
+ifeq (,$(filter-out Linux SunOS,$(OS_ARCH)))
+MAKE_SYM_STORE_ARGS := -c --vcs-info
+DUMP_SYMS_BIN ?= $(DIST)/host/bin/dump_syms
+MAKE_SYM_STORE_PATH := $(DIST)/bin
+endif
+MAKE_SYM_STORE_ARGS += --install-manifest=$(DEPTH)/_build_manifests/install/dist_include,$(DIST)/include
+
+SYM_STORE_SOURCE_DIRS := $(topsrcdir)
+
+ifndef JS_STANDALONE
+include $(topsrcdir)/toolkit/mozapps/installer/package-name.mk
+
+ifdef MOZ_SYMBOLS_EXTRA_BUILDID
+EXTRA_BUILDID := -$(MOZ_SYMBOLS_EXTRA_BUILDID)
+endif
+
+SYMBOL_INDEX_NAME = \
+  $(MOZ_APP_NAME)-$(MOZ_APP_VERSION)-$(OS_TARGET)-$(BUILDID)-$(CPU_ARCH)$(EXTRA_BUILDID)-symbols.txt
+
+buildsymbols:
+ifdef MOZ_CRASHREPORTER
+	echo building symbol store
+	$(RM) -r $(DIST)/crashreporter-symbols
+	$(RM) '$(DIST)/$(SYMBOL_ARCHIVE_BASENAME).zip'
+	$(RM) '$(DIST)/$(SYMBOL_FULL_ARCHIVE_BASENAME).zip'
+	$(NSINSTALL) -D $(DIST)/crashreporter-symbols
+	OBJCOPY='$(OBJCOPY)' \
+	$(PYTHON) $(topsrcdir)/toolkit/crashreporter/tools/symbolstore.py \
+	  $(MAKE_SYM_STORE_ARGS)                                          \
+	  $(foreach dir,$(SYM_STORE_SOURCE_DIRS),-s $(dir))               \
+	  $(DUMP_SYMS_BIN)                                                \
+	  $(DIST)/crashreporter-symbols                                   \
+	  $(MAKE_SYM_STORE_PATH) | grep -iv test >                        \
+	  $(DIST)/crashreporter-symbols/$(SYMBOL_INDEX_NAME)
+	echo packing symbols
+	$(NSINSTALL) -D $(DIST)/$(PKG_PATH)
+	cd $(DIST)/crashreporter-symbols && \
+          zip -r9D '../$(PKG_PATH)$(SYMBOL_FULL_ARCHIVE_BASENAME).zip' . -x '*test*' -x '*Test*'
+	cd $(DIST)/crashreporter-symbols && \
+	grep 'sym' $(SYMBOL_INDEX_NAME) > $(SYMBOL_INDEX_NAME).tmp && \
+	  mv $(SYMBOL_INDEX_NAME).tmp $(SYMBOL_INDEX_NAME)
+	cd $(DIST)/crashreporter-symbols && \
+          zip -r9D '../$(PKG_PATH)$(SYMBOL_ARCHIVE_BASENAME).zip' . -i '*.sym' -i '*.txt'  -x '*test*' -x '*Test*'
+endif # MOZ_CRASHREPORTER
+
+uploadsymbols:
+ifdef MOZ_CRASHREPORTER
+ifdef SOCORRO_SYMBOL_UPLOAD_TOKEN_FILE
+	$(PYTHON) -u $(topsrcdir)/toolkit/crashreporter/tools/upload_symbols.py '$(DIST)/$(PKG_PATH)$(SYMBOL_FULL_ARCHIVE_BASENAME).zip'
+else
+	$(SHELL) $(topsrcdir)/toolkit/crashreporter/tools/upload_symbols.sh $(SYMBOL_INDEX_NAME) '$(DIST)/$(PKG_PATH)$(SYMBOL_FULL_ARCHIVE_BASENAME).zip'
+endif
+endif
+
+# MOZ_SOURCE_STAMP is defined in package-name.mk with a deferred assignment.
+# exporting it makes make run its $(shell) command for each invoked submake,
+# so transform it to an immediate assignment.
+MOZ_SOURCE_STAMP := $(MOZ_SOURCE_STAMP)
+export MOZ_SOURCE_STAMP
+endif
+
+.PHONY: update-packaging
+update-packaging:
+	$(MAKE) -C tools/update-packaging
+
+.PHONY: pretty-package
+pretty-package:
+	unset MOZ_SIGN_CMD && $(MAKE) package MOZ_PKG_PRETTYNAMES=1
+
+.PHONY: pretty-package-tests
+pretty-package-tests:
+	unset MOZ_SIGN_CMD && $(MAKE) package-tests MOZ_PKG_PRETTYNAMES=1
+
+.PHONY: pretty-l10n-check
+pretty-l10n-check:
+	unset MOZ_SIGN_CMD && $(MAKE) l10n-check MOZ_PKG_PRETTYNAMES=1
+
+.PHONY: pretty-update-packaging
+pretty-update-packaging:
+	unset MOZ_SIGN_CMD && $(MAKE) -C tools/update-packaging MOZ_PKG_PRETTYNAMES=1
+
+.PHONY: pretty-installer
+pretty-installer:
+	unset MOZ_SIGN_CMD && $(MAKE) installer MOZ_PKG_PRETTYNAMES=1
+
+#XXX: this is a hack, since we don't want to clobber for MSVC
+# PGO support, but we can't do this test in client.mk
+ifneq ($(OS_ARCH)_$(GNU_CC), WINNT_)
+# No point in clobbering if PGO has been explicitly disabled.
+ifndef NO_PROFILE_GUIDED_OPTIMIZE
+maybe_clobber_profiledbuild: clean
+else
+maybe_clobber_profiledbuild:
+endif
+else
+maybe_clobber_profiledbuild:
+	$(RM) $(DIST)/bin/*.pgc
+	find $(DIST)/$(MOZ_APP_NAME) -name '*.pgc' -exec mv {} $(DIST)/bin \;
+endif
+
+.PHONY: maybe_clobber_profiledbuild
+
+# Look for R_386_PC32 relocations in shared libs, these
+# break x86_64 builds and SELinux users.
+ifeq ($(OS_TARGET)_$(TARGET_XPCOM_ABI),Linux_x86-gcc3)
+check::
+	@relcount=`find $(DIST)/bin -name '*.so' | xargs objdump -R | grep R_386_PC32 | wc -l` && if test $$relcount -gt 0; then echo 'FAILED: R_386_PC32 relocations detected in a shared library.  Did you use a system header without adding it to config/system-headers?'; exit 1; else echo 'PASSED'; fi
+endif
+
+ifdef JS_STANDALONE
+# Delegate js-specific rules to js
+check-%:
+	$(MAKE) -C js/src $@
+
+source-package install:
+	$(MAKE) -C js/src $@
+
+# Every export rule depends on config/export, but the rule for config/export
+# doesn't exist when building js non-standalone.
+.PHONY: config/export
+config/export:
+
+endif
+
+# There used to be build interdependencies here. They are now in config/recurse.mk
diff --git a/src/third_party/mozjs-45/README b/src/third_party/mozjs-45/README
new file mode 100644
index 0000000..5a7fff7
--- /dev/null
+++ b/src/third_party/mozjs-45/README
@@ -0,0 +1,8 @@
+This directory contains SpiderMonkey 45.
+
+This release is based on a revision of Mozilla 45:
+  http://hg.mozilla.org/releases/
+The changes in the patches/ directory were applied.
+
+MDN hosts the latest SpiderMonkey 45 release notes:
+  https://developer.mozilla.org/en-US/docs/SpiderMonkey/45
diff --git a/src/third_party/mozjs-45/build/.lldbinit.in b/src/third_party/mozjs-45/build/.lldbinit.in
new file mode 100644
index 0000000..425ca0f
--- /dev/null
+++ b/src/third_party/mozjs-45/build/.lldbinit.in
@@ -0,0 +1,2 @@
+#filter substitution
+script topsrcdir = "@topsrcdir@"; lldb.debugger.HandleCommand("command source -s true '%s'" % os.path.join(topsrcdir, ".lldbinit"))
diff --git a/src/third_party/mozjs-45/build/Makefile.in b/src/third_party/mozjs-45/build/Makefile.in
new file mode 100644
index 0000000..2d82093
--- /dev/null
+++ b/src/third_party/mozjs-45/build/Makefile.in
@@ -0,0 +1,100 @@
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+USE_RCS_MK := 1
+include $(topsrcdir)/config/makefiles/makeutils.mk
+
+ifdef MOZ_APP_BASENAME
+APP_INI_DEPS = $(topsrcdir)/config/milestone.txt
+
+MOZ_APP_BUILDID := $(shell cat $(DEPTH)/config/buildid)
+APP_INI_DEPS += $(DEPTH)/config/buildid
+
+DEFINES += -DMOZ_APP_BUILDID=$(MOZ_APP_BUILDID)
+
+APP_INI_DEPS += $(DEPTH)/config/autoconf.mk
+
+MOZ_SOURCE_STAMP := $(firstword $(shell cd $(topsrcdir)/$(MOZ_BUILD_APP)/.. && hg parent --template='{node}\n' 2>/dev/null))
+ifdef MOZ_SOURCE_STAMP
+DEFINES += -DMOZ_SOURCE_STAMP='$(MOZ_SOURCE_STAMP)'
+endif
+
+ifdef MOZ_INCLUDE_SOURCE_INFO
+source_repo ?= $(call getSourceRepo,$(topsrcdir)/$(MOZ_BUILD_APP)/..)
+ifneq (,$(source_repo))
+  DEFINES += -DMOZ_SOURCE_REPO='$(source_repo)'
+endif
+endif
+
+endif
+
+# NOTE: Keep .gdbinit in the topsrcdir for people who run gdb from the topsrcdir.
+# needs to be absolute to be distinct from $(topsrcdir)/.gdbinit
+GDBINIT_OBJDIR_FILES = $(topsrcdir)/.gdbinit
+GDBINIT_OBJDIR_DEST = $(abspath $(DEPTH))
+INSTALL_TARGETS += GDBINIT_OBJDIR
+
+# Put a .lldbinit in the bin directory and the objdir, to be picked up
+# automatically by LLDB when we debug executables using either of those two
+# directories as the current working directory.  The .lldbinit file will
+# load $(topsrcdir)/.lldbinit, which is where the actual debugging commands are.
+LLDBINIT_OBJDIR := .lldbinit.in
+LLDBINIT_OBJDIR_PATH = $(DEPTH)
+LLDBINIT_OBJDIR_FLAGS += -Dtopsrcdir=$(abspath $(topsrcdir))
+PP_TARGETS += LLDBINIT_OBJDIR
+
+LLDBINIT_FINAL_TARGET_FILES := $(DEPTH)/.lldbinit
+LLDBINIT_FINAL_TARGET_DEST = $(FINAL_TARGET)
+INSTALL_TARGETS += LLDBINIT_FINAL_TARGET
+
+# Put the .ycm_extra_conf.py file at the root of the objdir. It is used by
+# the vim plugin YouCompleteMe.
+YCM_FILES := $(topsrcdir)/.ycm_extra_conf.py
+YCM_DEST := $(abspath $(DEPTH))
+YCM_TARGET := export
+INSTALL_TARGETS += YCM
+
+ifdef MOZTTDIR
+# Install the Firefox OS fonts.
+include $(MOZTTDIR)/fonts.mk
+MOZTT_DEST = $(FINAL_TARGET)/fonts
+ifdef MOZ_B2GDROID
+MOZTT_DEST = $(FINAL_TARGET)/res/fonts
+endif
+MOZTT_FILES = $(patsubst external/moztt/%,$(MOZTTDIR)/%,$(filter external/moztt/%,$(subst :, ,$(PRODUCT_COPY_FILES))))
+INSTALL_TARGETS += MOZTT
+endif
+
+ifdef MOZ_VALGRIND
+_VALGRIND_DIR = $(DEPTH)/_valgrind
+GARBAGE_DIRS += $(_VALGRIND_DIR)
+
+_VALGRIND_FILES = \
+		$(topsrcdir)/build/valgrind/cross-architecture.sup \
+		$(topsrcdir)/build/valgrind/i386-redhat-linux-gnu.sup \
+		$(topsrcdir)/build/valgrind/x86_64-redhat-linux-gnu.sup \
+		$(NULL)
+_VALGRIND_DEST = $(_VALGRIND_DIR)
+INSTALL_TARGETS += _VALGRIND
+endif
+
+include $(topsrcdir)/config/rules.mk
+
+TARGET_DEPTH = ..
+include $(srcdir)/automation-build.mk
+
+ifdef MOZ_APP_BASENAME
+$(FINAL_TARGET)/application.ini: $(APP_INI_DEPS)
+
+ifdef MOZ_APP_STATIC_INI
+application.ini.h: appini_header.py $(FINAL_TARGET)/application.ini
+	$(PYTHON) $^ > $@
+export:: application.ini.h
+GARBAGE += application.ini.h
+endif
+endif
+
+libs:: automation.py
+
diff --git a/src/third_party/mozjs-45/build/__init__.py b/src/third_party/mozjs-45/build/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/mozjs-45/build/__init__.py
diff --git a/src/third_party/mozjs-45/build/annotationProcessors/AnnotationInfo.java b/src/third_party/mozjs-45/build/annotationProcessors/AnnotationInfo.java
new file mode 100644
index 0000000..2477132
--- /dev/null
+++ b/src/third_party/mozjs-45/build/annotationProcessors/AnnotationInfo.java
@@ -0,0 +1,30 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.gecko.annotationProcessors;
+
+/**
+ * Object holding annotation data. Used by GeneratableElementIterator.
+ */
+public class AnnotationInfo {
+    public final String wrapperName;
+    public final boolean isMultithreaded;
+    public final boolean noThrow;
+    public final boolean narrowChars;
+    public final boolean catchException;
+
+    public AnnotationInfo(String aWrapperName, boolean aIsMultithreaded,
+                          boolean aNoThrow, boolean aNarrowChars, boolean aCatchException) {
+        wrapperName = aWrapperName;
+        isMultithreaded = aIsMultithreaded;
+        noThrow = aNoThrow;
+        narrowChars = aNarrowChars;
+        catchException = aCatchException;
+
+        if (noThrow && catchException) {
+            // It doesn't make sense to have these together
+            throw new IllegalArgumentException("noThrow and catchException are not allowed together");
+        }
+    }
+}
diff --git a/src/third_party/mozjs-45/build/annotationProcessors/AnnotationProcessor.java b/src/third_party/mozjs-45/build/annotationProcessors/AnnotationProcessor.java
new file mode 100644
index 0000000..f852655
--- /dev/null
+++ b/src/third_party/mozjs-45/build/annotationProcessors/AnnotationProcessor.java
@@ -0,0 +1,173 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.gecko.annotationProcessors;
+
+import org.mozilla.gecko.annotationProcessors.classloader.AnnotatableEntity;
+import org.mozilla.gecko.annotationProcessors.classloader.ClassWithOptions;
+import org.mozilla.gecko.annotationProcessors.classloader.IterableJarLoadingURLClassLoader;
+import org.mozilla.gecko.annotationProcessors.utils.GeneratableElementIterator;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Iterator;
+
+public class AnnotationProcessor {
+    public static final String SOURCE_FILE = "GeneratedJNIWrappers.cpp";
+    public static final String HEADER_FILE = "GeneratedJNIWrappers.h";
+    public static final String NATIVES_FILE = "GeneratedJNINatives.h";
+
+    public static final String GENERATED_COMMENT =
+            "// GENERATED CODE\n" +
+            "// Generated by the Java program at /build/annotationProcessors at compile time\n" +
+            "// from annotations on Java methods. To update, change the annotations on the\n" +
+            "// corresponding Java methods and rerun the build. Manually updating this file\n" +
+            "// will cause your build to fail.\n" +
+            "\n";
+
+    private static final StringBuilder headerFile = new StringBuilder(GENERATED_COMMENT);
+    private static final StringBuilder implementationFile = new StringBuilder(GENERATED_COMMENT);
+    private static final StringBuilder nativesFile = new StringBuilder(GENERATED_COMMENT);
+
+    public static void main(String[] args) {
+        // We expect a list of jars on the commandline. If missing, whinge about it.
+        if (args.length <= 1) {
+            System.err.println("Usage: java AnnotationProcessor jarfiles ...");
+            System.exit(1);
+        }
+
+        System.out.println("Processing annotations...");
+
+        // We want to produce the same output as last time as often as possible. Ordering of
+        // generated statements, therefore, needs to be consistent.
+        Arrays.sort(args);
+
+        // Start the clock!
+        long s = System.currentTimeMillis();
+
+        // Get an iterator over the classes in the jar files given...
+        Iterator<ClassWithOptions> jarClassIterator = IterableJarLoadingURLClassLoader.getIteratorOverJars(args);
+
+        headerFile.append(
+                "#ifndef " + getHeaderGuardName(HEADER_FILE) + "\n" +
+                "#define " + getHeaderGuardName(HEADER_FILE) + "\n" +
+                "\n" +
+                "#include \"mozilla/jni/Refs.h\"\n" +
+                "\n" +
+                "namespace mozilla {\n" +
+                "namespace widget {\n" +
+                "\n");
+
+        implementationFile.append(
+                "#include \"GeneratedJNIWrappers.h\"\n" +
+                "#include \"mozilla/jni/Accessors.h\"\n" +
+                "\n" +
+                "namespace mozilla {\n" +
+                "namespace widget {\n" +
+                "\n");
+
+        nativesFile.append(
+                "#ifndef " + getHeaderGuardName(NATIVES_FILE) + "\n" +
+                "#define " + getHeaderGuardName(NATIVES_FILE) + "\n" +
+                "\n" +
+                "#include \"GeneratedJNIWrappers.h\"\n" +
+                "#include \"mozilla/jni/Natives.h\"\n" +
+                "\n" +
+                "namespace mozilla {\n" +
+                "namespace widget {\n" +
+                "\n");
+
+        while (jarClassIterator.hasNext()) {
+            generateClass(jarClassIterator.next());
+        }
+
+        implementationFile.append(
+                "} /* widget */\n" +
+                "} /* mozilla */\n");
+
+        headerFile.append(
+                "} /* widget */\n" +
+                "} /* mozilla */\n" +
+                "#endif // " + getHeaderGuardName(HEADER_FILE) + "\n");
+
+        nativesFile.append(
+                "} /* widget */\n" +
+                "} /* mozilla */\n" +
+                "#endif // " + getHeaderGuardName(NATIVES_FILE) + "\n");
+
+        writeOutputFile(SOURCE_FILE, implementationFile);
+        writeOutputFile(HEADER_FILE, headerFile);
+        writeOutputFile(NATIVES_FILE, nativesFile);
+
+        long e = System.currentTimeMillis();
+        System.out.println("Annotation processing complete in " + (e - s) + "ms");
+    }
+
+    private static void generateClass(final ClassWithOptions annotatedClass) {
+        // Get an iterator over the appropriately generated methods of this class
+        final GeneratableElementIterator methodIterator
+                = new GeneratableElementIterator(annotatedClass);
+        final ClassWithOptions[] innerClasses = methodIterator.getInnerClasses();
+
+        if (!methodIterator.hasNext() && innerClasses.length == 0) {
+            return;
+        }
+
+        final CodeGenerator generatorInstance = new CodeGenerator(annotatedClass);
+        generatorInstance.generateClasses(innerClasses);
+
+        // Iterate all annotated members in this class..
+        while (methodIterator.hasNext()) {
+            AnnotatableEntity aElementTuple = methodIterator.next();
+            switch (aElementTuple.mEntityType) {
+                case METHOD:
+                    generatorInstance.generateMethod(aElementTuple);
+                    break;
+                case NATIVE:
+                    generatorInstance.generateNative(aElementTuple);
+                    break;
+                case FIELD:
+                    generatorInstance.generateField(aElementTuple);
+                    break;
+                case CONSTRUCTOR:
+                    generatorInstance.generateConstructor(aElementTuple);
+                    break;
+            }
+        }
+
+        headerFile.append(generatorInstance.getHeaderFileContents());
+        implementationFile.append(generatorInstance.getWrapperFileContents());
+        nativesFile.append(generatorInstance.getNativesFileContents());
+
+        for (ClassWithOptions innerClass : innerClasses) {
+            generateClass(innerClass);
+        }
+    }
+
+    private static String getHeaderGuardName(final String name) {
+        return name.replaceAll("\\W", "_");
+    }
+
+    private static void writeOutputFile(final String name,
+                                        final StringBuilder content) {
+        FileOutputStream outStream = null;
+        try {
+            outStream = new FileOutputStream(name);
+            outStream.write(content.toString().getBytes());
+        } catch (IOException e) {
+            System.err.println("Unable to write " + name + ". Perhaps a permissions issue?");
+            e.printStackTrace(System.err);
+        } finally {
+            if (outStream != null) {
+                try {
+                    outStream.close();
+                } catch (IOException e) {
+                    System.err.println("Unable to close outStream due to "+e);
+                    e.printStackTrace(System.err);
+                }
+            }
+        }
+    }
+}
diff --git a/src/third_party/mozjs-45/build/annotationProcessors/CodeGenerator.java b/src/third_party/mozjs-45/build/annotationProcessors/CodeGenerator.java
new file mode 100644
index 0000000..f96026e
--- /dev/null
+++ b/src/third_party/mozjs-45/build/annotationProcessors/CodeGenerator.java
@@ -0,0 +1,578 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.gecko.annotationProcessors;
+
+import org.mozilla.gecko.annotationProcessors.classloader.AnnotatableEntity;
+import org.mozilla.gecko.annotationProcessors.classloader.ClassWithOptions;
+import org.mozilla.gecko.annotationProcessors.utils.Utils;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.HashSet;
+
+public class CodeGenerator {
+    private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0];
+
+    // Buffers holding the strings to ultimately be written to the output files.
+    private final StringBuilder cpp = new StringBuilder();
+    private final StringBuilder header = new StringBuilder();
+    private final StringBuilder natives = new StringBuilder();
+    private final StringBuilder nativesInits = new StringBuilder();
+
+    private final Class<?> cls;
+    private final String clsName;
+
+    private final HashSet<String> takenMethodNames = new HashSet<String>();
+
+    public CodeGenerator(ClassWithOptions annotatedClass) {
+        this.cls = annotatedClass.wrappedClass;
+        this.clsName = annotatedClass.generatedName;
+
+        final String unqualifiedName = Utils.getUnqualifiedName(clsName);
+        header.append(
+                "class " + clsName + " : public mozilla::jni::Class<" + unqualifiedName + ">\n" +
+                "{\n" +
+                "public:\n" +
+                "    typedef mozilla::jni::Ref<" + unqualifiedName + "> Ref;\n" +
+                "    typedef mozilla::jni::LocalRef<" + unqualifiedName + "> LocalRef;\n" +
+                "    typedef mozilla::jni::GlobalRef<" + unqualifiedName + "> GlobalRef;\n" +
+                "    typedef const mozilla::jni::Param<" + unqualifiedName + ">& Param;\n" +
+                "\n" +
+                "    static constexpr char name[] =\n" +
+                "            \"" + cls.getName().replace('.', '/') + "\";\n" +
+                "\n" +
+                "protected:\n" +
+                "    " + unqualifiedName + "(jobject instance) : Class(instance) {}\n" +
+                "\n");
+
+        cpp.append(
+                "constexpr char " + clsName + "::name[];\n" +
+                "\n");
+
+        natives.append(
+                "template<class Impl>\n" +
+                "class " + clsName + "::Natives : " +
+                        "public mozilla::jni::NativeImpl<" + unqualifiedName + ", Impl>\n" +
+                "{\n");
+    }
+
+    private String getTraitsName(String uniqueName, boolean includeScope) {
+        return (includeScope ? clsName + "::" : "") + uniqueName + "_t";
+    }
+
+    /**
+     * Return the C++ type name for this class or any class within the chain
+     * of declaring classes, if the target class matches the given type.
+     *
+     * Return null if the given type does not match any class searched.
+     */
+    private String getMatchingClassType(final Class<?> type) {
+        Class<?> cls = this.cls;
+        String clsName = this.clsName;
+
+        while (cls != null) {
+            if (type.equals(cls)) {
+                return clsName;
+            }
+            cls = cls.getDeclaringClass();
+            clsName = clsName.substring(0, Math.max(0, clsName.lastIndexOf("::")));
+        }
+        return null;
+    }
+
+    private String getNativeParameterType(Class<?> type, AnnotationInfo info) {
+        final String clsName = getMatchingClassType(type);
+        if (clsName != null) {
+            return Utils.getUnqualifiedName(clsName) + "::Param";
+        }
+        return Utils.getNativeParameterType(type, info);
+    }
+
+    private String getNativeReturnType(Class<?> type, AnnotationInfo info) {
+        final String clsName = getMatchingClassType(type);
+        if (clsName != null) {
+            return Utils.getUnqualifiedName(clsName) + "::LocalRef";
+        }
+        return Utils.getNativeReturnType(type, info);
+    }
+
+    private void generateMember(AnnotationInfo info, Member member,
+                                String uniqueName, Class<?> type, Class<?>[] argTypes) {
+        final StringBuilder args = new StringBuilder();
+        for (Class<?> argType : argTypes) {
+            args.append("\n                " + getNativeParameterType(argType, info) + ",");
+        }
+        if (args.length() > 0) {
+            args.setLength(args.length() - 1);
+        }
+
+        header.append(
+                "public:\n" +
+                "    struct " + getTraitsName(uniqueName, /* includeScope */ false) + " {\n" +
+                "        typedef " + Utils.getUnqualifiedName(clsName) + " Owner;\n" +
+                "        typedef " + getNativeReturnType(type, info) + " ReturnType;\n" +
+                "        typedef " + getNativeParameterType(type, info) + " SetterType;\n" +
+                "        typedef mozilla::jni::Args<" + args + "> Args;\n" +
+                "        static constexpr char name[] = \"" +
+                        Utils.getMemberName(member) + "\";\n" +
+                "        static constexpr char signature[] =\n" +
+                "                \"" + Utils.getSignature(member) + "\";\n" +
+                "        static const bool isStatic = " + Utils.isStatic(member) + ";\n" +
+                "        static const bool isMultithreaded = " + info.isMultithreaded + ";\n" +
+                "        static const mozilla::jni::ExceptionMode exceptionMode =\n" +
+                "                " + (
+                        info.catchException ? "mozilla::jni::ExceptionMode::NSRESULT" :
+                        info.noThrow ?        "mozilla::jni::ExceptionMode::IGNORE" :
+                                              "mozilla::jni::ExceptionMode::ABORT") + ";\n" +
+                "    };\n" +
+                "\n");
+
+        cpp.append(
+                "constexpr char " + getTraitsName(uniqueName, /* includeScope */ true) +
+                        "::name[];\n" +
+                "constexpr char " + getTraitsName(uniqueName, /* includeScope */ true) +
+                        "::signature[];\n" +
+                "\n");
+    }
+
+    private String getUniqueMethodName(String basename) {
+        String newName = basename;
+        int index = 1;
+
+        while (takenMethodNames.contains(newName)) {
+            newName = basename + (++index);
+        }
+
+        takenMethodNames.add(newName);
+        return newName;
+    }
+
+    /**
+     * Generate a method prototype that includes return and argument types,
+     * without specifiers (static, const, etc.).
+     */
+    private String generatePrototype(String name, Class<?>[] argTypes,
+                                     Class<?> returnType, AnnotationInfo info,
+                                     boolean includeScope, boolean includeArgName,
+                                     boolean isConst) {
+
+        final StringBuilder proto = new StringBuilder();
+        int argIndex = 0;
+
+        proto.append("auto ");
+
+        if (includeScope) {
+            proto.append(clsName).append("::");
+        }
+
+        proto.append(name).append('(');
+
+        for (Class<?> argType : argTypes) {
+            proto.append(getNativeParameterType(argType, info));
+            if (includeArgName) {
+                proto.append(" a").append(argIndex++);
+            }
+            proto.append(", ");
+        }
+
+        if (info.catchException && !returnType.equals(void.class)) {
+            proto.append(getNativeReturnType(returnType, info)).append('*');
+            if (includeArgName) {
+                proto.append(" a").append(argIndex++);
+            }
+            proto.append(", ");
+        }
+
+        if (proto.substring(proto.length() - 2).equals(", ")) {
+            proto.setLength(proto.length() - 2);
+        }
+
+        proto.append(')');
+
+        if (isConst) {
+            proto.append(" const");
+        }
+
+        if (info.catchException) {
+            proto.append(" -> nsresult");
+        } else {
+            proto.append(" -> ").append(getNativeReturnType(returnType, info));
+        }
+        return proto.toString();
+    }
+
+    /**
+     * Generate a method declaration that includes the prototype with specifiers,
+     * but without the method body.
+     */
+    private String generateDeclaration(String name, Class<?>[] argTypes,
+                                       Class<?> returnType, AnnotationInfo info,
+                                       boolean isStatic) {
+
+        return (isStatic ? "static " : "") +
+            generatePrototype(name, argTypes, returnType, info,
+                              /* includeScope */ false, /* includeArgName */ false,
+                              /* isConst */ !isStatic) + ';';
+    }
+
+    /**
+     * Generate a method definition that includes the prototype with specifiers,
+     * and with the method body.
+     */
+    private String generateDefinition(String accessorName, String name, Class<?>[] argTypes,
+                                      Class<?> returnType, AnnotationInfo info, boolean isStatic) {
+
+        final StringBuilder def = new StringBuilder(
+                generatePrototype(name, argTypes, returnType, info,
+                                  /* includeScope */ true, /* includeArgName */ true,
+                                  /* isConst */ !isStatic));
+        def.append("\n{\n");
+
+
+        // Generate code to handle the return value, if needed.
+        // We initialize rv to NS_OK instead of NS_ERROR_* because loading NS_OK (0) uses
+        // fewer instructions. We are guaranteed to set rv to the correct value later.
+
+        if (info.catchException && returnType.equals(void.class)) {
+            def.append(
+                    "    nsresult rv = NS_OK;\n" +
+                    "    ");
+
+        } else if (info.catchException) {
+            // Non-void return type
+            final String resultArg = "a" + argTypes.length;
+            def.append(
+                    "    MOZ_ASSERT(" + resultArg + ");\n" +
+                    "    nsresult rv = NS_OK;\n" +
+                    "    *" + resultArg + " = ");
+
+        } else {
+            def.append(
+                    "    return ");
+        }
+
+
+        // Generate a call, e.g., Method<Traits>::Call(a0, a1, a2);
+
+        def.append(accessorName).append("(")
+           .append(isStatic ? "nullptr" : "this");
+
+        if (info.catchException) {
+            def.append(", &rv");
+        } else {
+            def.append(", nullptr");
+        }
+
+        // Generate the call argument list.
+        for (int argIndex = 0; argIndex < argTypes.length; argIndex++) {
+            def.append(", a").append(argIndex);
+        }
+
+        def.append(");\n");
+
+
+        if (info.catchException) {
+            def.append("    return rv;\n");
+        }
+
+        return def.append("}").toString();
+    }
+
+    /**
+     * Append the appropriate generated code to the buffers for the method provided.
+     *
+     * @param annotatedMethod The Java method, plus annotation data.
+     */
+    public void generateMethod(AnnotatableEntity annotatedMethod) {
+        // Unpack the tuple and extract some useful fields from the Method..
+        final Method method = annotatedMethod.getMethod();
+        final AnnotationInfo info = annotatedMethod.mAnnotationInfo;
+        final String uniqueName = getUniqueMethodName(info.wrapperName);
+        final Class<?>[] argTypes = method.getParameterTypes();
+        final Class<?> returnType = method.getReturnType();
+
+        if (method.isSynthetic()) {
+            return;
+        }
+
+        generateMember(info, method, uniqueName, returnType, argTypes);
+
+        final boolean isStatic = Utils.isStatic(method);
+
+        header.append(
+                "    " + generateDeclaration(info.wrapperName, argTypes,
+                                             returnType, info, isStatic) + "\n" +
+                "\n");
+
+        cpp.append(
+                generateDefinition(
+                        "mozilla::jni::Method<" +
+                                getTraitsName(uniqueName, /* includeScope */ false) + ">::Call",
+                        info.wrapperName, argTypes, returnType, info, isStatic) + "\n" +
+                "\n");
+    }
+
+    /**
+     * Append the appropriate generated code to the buffers for the native method provided.
+     *
+     * @param annotatedMethod The Java native method, plus annotation data.
+     */
+    public void generateNative(AnnotatableEntity annotatedMethod) {
+        // Unpack the tuple and extract some useful fields from the Method..
+        final Method method = annotatedMethod.getMethod();
+        final AnnotationInfo info = annotatedMethod.mAnnotationInfo;
+        final String uniqueName = getUniqueMethodName(info.wrapperName);
+        final Class<?>[] argTypes = method.getParameterTypes();
+        final Class<?> returnType = method.getReturnType();
+
+        generateMember(info, method, uniqueName, returnType, argTypes);
+
+        final String traits = getTraitsName(uniqueName, /* includeScope */ true);
+
+        if (nativesInits.length() > 0) {
+            nativesInits.append(',');
+        }
+
+        nativesInits.append(
+                "\n" +
+                "\n" +
+                "        mozilla::jni::MakeNativeMethod<" + traits + ">(\n" +
+                "                mozilla::jni::NativeStub<" + traits + ", Impl>\n" +
+                "                ::template Wrap<&Impl::" + info.wrapperName + ">)");
+    }
+
+    private String getLiteral(Object val, AnnotationInfo info) {
+        final Class<?> type = val.getClass();
+
+        if (type.equals(char.class) || type.equals(Character.class)) {
+            final char c = (char) val;
+            if (c >= 0x20 && c < 0x7F) {
+                return "'" + c + '\'';
+            }
+            return "u'\\u" + Integer.toHexString(0x10000 | (int) c).substring(1) + '\'';
+
+        } else if (type.equals(CharSequence.class) || type.equals(String.class)) {
+            final CharSequence str = (CharSequence) val;
+            final StringBuilder out = new StringBuilder(info.narrowChars ? "u8\"" : "u\"");
+            for (int i = 0; i < str.length(); i++) {
+                final char c = str.charAt(i);
+                if (c >= 0x20 && c < 0x7F) {
+                    out.append(c);
+                } else {
+                    out.append("\\u").append(Integer.toHexString(0x10000 | (int) c).substring(1));
+                }
+            }
+            return out.append('"').toString();
+        }
+
+        return String.valueOf(val);
+    }
+
+    public void generateField(AnnotatableEntity annotatedField) {
+        final Field field = annotatedField.getField();
+        final AnnotationInfo info = annotatedField.mAnnotationInfo;
+        final String uniqueName = info.wrapperName;
+        final Class<?> type = field.getType();
+
+        // Handles a peculiar case when dealing with enum types. We don't care about this field.
+        // It just gets in the way and stops our code from compiling.
+        if (field.isSynthetic() || field.getName().equals("$VALUES")) {
+            return;
+        }
+
+        final boolean isStatic = Utils.isStatic(field);
+        final boolean isFinal = Utils.isFinal(field);
+
+        if (isStatic && isFinal && (type.isPrimitive() || type.equals(String.class))) {
+            Object val = null;
+            try {
+                field.setAccessible(true);
+                val = field.get(null);
+            } catch (final IllegalAccessException e) {
+            }
+
+            if (val != null && type.isPrimitive()) {
+                // For static final primitive fields, we can use a "static const" declaration.
+                header.append(
+                    "public:\n" +
+                    "    static const " + Utils.getNativeReturnType(type, info) +
+                            ' ' + info.wrapperName + " = " + getLiteral(val, info) + ";\n" +
+                    "\n");
+                return;
+
+            } else if (val != null && type.equals(String.class)) {
+                final String nativeType = info.narrowChars ? "char" : "char16_t";
+
+                header.append(
+                    "public:\n" +
+                    "    static const " + nativeType + ' ' + info.wrapperName + "[];\n" +
+                    "\n");
+
+                cpp.append(
+                    "const " + nativeType + ' ' + clsName + "::" + info.wrapperName +
+                            "[] = " + getLiteral(val, info) + ";\n" +
+                    "\n");
+                return;
+            }
+
+            // Fall back to using accessors if we encounter an exception.
+        }
+
+        generateMember(info, field, uniqueName, type, EMPTY_CLASS_ARRAY);
+
+        final Class<?>[] getterArgs = EMPTY_CLASS_ARRAY;
+
+        header.append(
+                "    " + generateDeclaration(info.wrapperName, getterArgs,
+                                             type, info, isStatic) + "\n" +
+                "\n");
+
+        cpp.append(
+                generateDefinition(
+                        "mozilla::jni::Field<" +
+                                getTraitsName(uniqueName, /* includeScope */ false) + ">::Get",
+                        info.wrapperName, getterArgs, type, info, isStatic) + "\n" +
+                "\n");
+
+        if (isFinal) {
+            return;
+        }
+
+        final Class<?>[] setterArgs = new Class<?>[] { type };
+
+        header.append(
+                "    " + generateDeclaration(info.wrapperName, setterArgs,
+                                             void.class, info, isStatic) + "\n" +
+                "\n");
+
+        cpp.append(
+                generateDefinition(
+                        "mozilla::jni::Field<" +
+                                getTraitsName(uniqueName, /* includeScope */ false) + ">::Set",
+                        info.wrapperName, setterArgs, void.class, info, isStatic) + "\n" +
+                "\n");
+    }
+
+    public void generateConstructor(AnnotatableEntity annotatedConstructor) {
+        // Unpack the tuple and extract some useful fields from the Method..
+        final Constructor<?> method = annotatedConstructor.getConstructor();
+        final AnnotationInfo info = annotatedConstructor.mAnnotationInfo;
+        final String wrapperName = "New";
+        final String uniqueName = getUniqueMethodName(wrapperName);
+        final Class<?>[] argTypes = method.getParameterTypes();
+        final Class<?> returnType = cls;
+
+        if (method.isSynthetic()) {
+            return;
+        }
+
+        generateMember(info, method, uniqueName, returnType, argTypes);
+
+        header.append(
+                "    " + generateDeclaration(wrapperName, argTypes,
+                                             returnType, info, /* isStatic */ true) + "\n" +
+                "\n");
+
+        cpp.append(
+                generateDefinition(
+                        "mozilla::jni::Constructor<" +
+                                getTraitsName(uniqueName, /* includeScope */ false) + ">::Call",
+                        wrapperName, argTypes, returnType, info, /* isStatic */ true) + "\n" +
+                "\n");
+    }
+
+    public void generateMembers(Member[] members) {
+        for (Member m : members) {
+            if (!Modifier.isPublic(m.getModifiers())) {
+                continue;
+            }
+
+            String name = Utils.getMemberName(m);
+            name = name.substring(0, 1).toUpperCase() + name.substring(1);
+
+            final AnnotationInfo info = new AnnotationInfo(name,
+                    /* multithread */ true, /* nothrow */ false,
+                    /* narrow */ false, /* catchException */ true);
+            final AnnotatableEntity entity = new AnnotatableEntity(m, info);
+
+            if (m instanceof Constructor) {
+                generateConstructor(entity);
+            } else if (m instanceof Method) {
+                generateMethod(entity);
+            } else if (m instanceof Field) {
+                generateField(entity);
+            } else {
+                throw new IllegalArgumentException(
+                        "expected member to be Constructor, Method, or Field");
+            }
+        }
+    }
+
+    public void generateClasses(final ClassWithOptions[] classes) {
+        if (classes.length == 0) {
+            return;
+        }
+
+        header.append(
+                "public:\n");
+        for (final ClassWithOptions cls : classes) {
+            // Extract "Inner" from "Outer::Inner".
+            header.append(
+                    "    class " + Utils.getUnqualifiedName(cls.generatedName) + ";\n");
+        }
+        header.append('\n');
+    }
+
+    /**
+     * Get the finalised bytes to go into the generated wrappers file.
+     *
+     * @return The bytes to be written to the wrappers file.
+     */
+    public String getWrapperFileContents() {
+        return cpp.toString();
+    }
+
+    /**
+     * Get the finalised bytes to go into the generated header file.
+     *
+     * @return The bytes to be written to the header file.
+     */
+    public String getHeaderFileContents() {
+        if (nativesInits.length() > 0) {
+            header.append(
+                    "public:\n" +
+                    "    template<class Impl> class Natives;\n");
+        }
+        header.append(
+                "};\n" +
+                "\n");
+        return header.toString();
+    }
+
+    /**
+     * Get the finalised bytes to go into the generated natives header file.
+     *
+     * @return The bytes to be written to the header file.
+     */
+    public String getNativesFileContents() {
+        if (nativesInits.length() == 0) {
+            return "";
+        }
+        natives.append(
+                "public:\n" +
+                "    static constexpr JNINativeMethod methods[] = {" + nativesInits + '\n' +
+                "    };\n" +
+                "};\n" +
+                "\n" +
+                "template<class Impl>\n" +
+                "constexpr JNINativeMethod " + clsName + "::Natives<Impl>::methods[];\n" +
+                "\n");
+        return natives.toString();
+    }
+}
diff --git a/src/third_party/mozjs-45/build/annotationProcessors/Makefile.in b/src/third_party/mozjs-45/build/annotationProcessors/Makefile.in
new file mode 100644
index 0000000..55b455e
--- /dev/null
+++ b/src/third_party/mozjs-45/build/annotationProcessors/Makefile.in
@@ -0,0 +1,10 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+include $(topsrcdir)/config/rules.mk
+
+# Include Android specific java flags, instead of what's in rules.mk.
+include $(topsrcdir)/config/android-common.mk
+
+export:: annotationProcessors.jar
diff --git a/src/third_party/mozjs-45/build/annotationProcessors/SDKProcessor.java b/src/third_party/mozjs-45/build/annotationProcessors/SDKProcessor.java
new file mode 100644
index 0000000..8b045fa
--- /dev/null
+++ b/src/third_party/mozjs-45/build/annotationProcessors/SDKProcessor.java
@@ -0,0 +1,258 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.gecko.annotationProcessors;
+
+import com.android.tools.lint.checks.ApiLookup;
+import com.android.tools.lint.LintCliClient;
+
+import org.mozilla.gecko.annotationProcessors.classloader.AnnotatableEntity;
+import org.mozilla.gecko.annotationProcessors.classloader.ClassWithOptions;
+import org.mozilla.gecko.annotationProcessors.classloader.IterableJarLoadingURLClassLoader;
+import org.mozilla.gecko.annotationProcessors.utils.GeneratableElementIterator;
+import org.mozilla.gecko.annotationProcessors.utils.Utils;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.Scanner;
+import java.util.Vector;
+import java.net.URL;
+import java.net.URLClassLoader;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+public class SDKProcessor {
+    public static final String GENERATED_COMMENT =
+            "// GENERATED CODE\n" +
+            "// Generated by the Java program at /build/annotationProcessors at compile time\n" +
+            "// from annotations on Java methods. To update, change the annotations on the\n" +
+            "// corresponding Javamethods and rerun the build. Manually updating this file\n" +
+            "// will cause your build to fail.\n" +
+            "\n";
+
+    private static ApiLookup sApiLookup;
+    private static int sMaxSdkVersion;
+
+    public static void main(String[] args) throws Exception {
+        // We expect a list of jars on the commandline. If missing, whinge about it.
+        if (args.length < 5) {
+            System.err.println("Usage: java SDKProcessor sdkjar classlistfile outdir fileprefix max-sdk-version");
+            System.exit(1);
+        }
+
+        System.out.println("Processing platform bindings...");
+
+        String sdkJar = args[0];
+        Vector classes = getClassList(args[1]);
+        String outdir = args[2];
+        String generatedFilePrefix = args[3];
+        sMaxSdkVersion = Integer.parseInt(args[4]);
+
+        LintCliClient lintClient = new LintCliClient();
+        sApiLookup = ApiLookup.get(lintClient);
+
+        // Start the clock!
+        long s = System.currentTimeMillis();
+
+        // Get an iterator over the classes in the jar files given...
+        // Iterator<ClassWithOptions> jarClassIterator = IterableJarLoadingURLClassLoader.getIteratorOverJars(args);
+
+        StringBuilder headerFile = new StringBuilder(GENERATED_COMMENT);
+        headerFile.append(
+                "#ifndef " + generatedFilePrefix + "_h__\n" +
+                "#define " + generatedFilePrefix + "_h__\n" +
+                "\n" +
+                "#include \"mozilla/jni/Refs.h\"\n" +
+                "\n" +
+                "namespace mozilla {\n" +
+                "namespace widget {\n" +
+                "namespace sdk {\n" +
+                "\n");
+
+        StringBuilder implementationFile = new StringBuilder(GENERATED_COMMENT);
+        implementationFile.append(
+                "#include \"" + generatedFilePrefix + ".h\"\n" +
+                "#include \"mozilla/jni/Accessors.h\"\n" +
+                "\n" +
+                "namespace mozilla {\n" +
+                "namespace widget {\n" +
+                "namespace sdk {\n" +
+                "\n");
+
+        // Used to track the calls to the various class-specific initialisation functions.
+        ClassLoader loader = null;
+        try {
+            loader = URLClassLoader.newInstance(new URL[] { new URL("file://" + sdkJar) },
+                                                SDKProcessor.class.getClassLoader());
+        } catch (Exception e) {
+            throw new RuntimeException(e.toString());
+        }
+
+        for (Iterator<String> i = classes.iterator(); i.hasNext(); ) {
+            String className = i.next();
+            System.out.println("Looking up: " + className);
+
+            generateClass(Class.forName(className, true, loader),
+                          implementationFile,
+                          headerFile);
+        }
+
+        implementationFile.append(
+                "} /* sdk */\n" +
+                "} /* widget */\n" +
+                "} /* mozilla */\n");
+
+        headerFile.append(
+                "} /* sdk */\n" +
+                "} /* widget */\n" +
+                "} /* mozilla */\n" +
+                "#endif\n");
+
+        writeOutputFiles(outdir, generatedFilePrefix, headerFile, implementationFile);
+        long e = System.currentTimeMillis();
+        System.out.println("SDK processing complete in " + (e - s) + "ms");
+    }
+
+    private static int getAPIVersion(Class<?> cls, Member m) {
+        if (m instanceof Method || m instanceof Constructor) {
+            return sApiLookup.getCallVersion(
+                    cls.getName().replace('.', '/'),
+                    Utils.getMemberName(m),
+                    Utils.getSignature(m));
+        } else if (m instanceof Field) {
+            return sApiLookup.getFieldVersion(
+                    Utils.getClassDescriptor(m.getDeclaringClass()), m.getName());
+        } else {
+            throw new IllegalArgumentException("expected member to be Method, Constructor, or Field");
+        }
+    }
+
+    private static Member[] sortAndFilterMembers(Class<?> cls, Member[] members) {
+        Arrays.sort(members, new Comparator<Member>() {
+            @Override
+            public int compare(Member a, Member b) {
+                return a.getName().compareTo(b.getName());
+            }
+        });
+
+        ArrayList<Member> list = new ArrayList<>();
+        for (Member m : members) {
+            // Sometimes (e.g. Bundle) has methods that moved to/from a superclass in a later SDK
+            // version, so we check for both classes and see if we can find a minimum SDK version.
+            int version = getAPIVersion(cls, m);
+            final int version2 = getAPIVersion(m.getDeclaringClass(), m);
+            if (version2 > 0 && version2 < version) {
+                version = version2;
+            }
+            if (version > sMaxSdkVersion) {
+                System.out.println("Skipping " + m.getDeclaringClass().getName() + "." + m.getName() +
+                    ", version " + version + " > " + sMaxSdkVersion);
+                continue;
+            }
+
+            // Sometimes (e.g. KeyEvent) a field can appear in both a class and a superclass. In
+            // that case we want to filter out the version that appears in the superclass, or
+            // we'll have bindings with duplicate names.
+            try {
+                if (m instanceof Field && !m.equals(cls.getField(m.getName()))) {
+                    // m is a field in a superclass that has been hidden by
+                    // a field with the same name in a subclass.
+                    System.out.println("Skipping " + m.getName() +
+                                       " from " + m.getDeclaringClass());
+                    continue;
+                }
+            } catch (final NoSuchFieldException e) {
+            }
+
+            list.add(m);
+        }
+
+        return list.toArray(new Member[list.size()]);
+    }
+
+    private static void generateClass(Class<?> clazz,
+                                      StringBuilder implementationFile,
+                                      StringBuilder headerFile) {
+        String generatedName = clazz.getSimpleName();
+
+        CodeGenerator generator = new CodeGenerator(new ClassWithOptions(clazz, generatedName));
+
+        generator.generateMembers(sortAndFilterMembers(clazz, clazz.getConstructors()));
+        generator.generateMembers(sortAndFilterMembers(clazz, clazz.getMethods()));
+        generator.generateMembers(sortAndFilterMembers(clazz, clazz.getFields()));
+
+        headerFile.append(generator.getHeaderFileContents());
+        implementationFile.append(generator.getWrapperFileContents());
+    }
+
+    private static Vector<String> getClassList(String path) {
+        Scanner scanner = null;
+        try {
+            scanner = new Scanner(new FileInputStream(path));
+
+            Vector lines = new Vector();
+            while (scanner.hasNextLine()) {
+                lines.add(scanner.nextLine());
+            }
+            return lines;
+        } catch (Exception e) {
+            System.out.println(e.toString());
+            return null;
+        } finally {
+            if (scanner != null) {
+                scanner.close();
+            }
+        }
+    }
+
+    private static void writeOutputFiles(String aOutputDir, String aPrefix, StringBuilder aHeaderFile,
+                                         StringBuilder aImplementationFile) {
+        FileOutputStream implStream = null;
+        try {
+            implStream = new FileOutputStream(new File(aOutputDir, aPrefix + ".cpp"));
+            implStream.write(aImplementationFile.toString().getBytes());
+        } catch (IOException e) {
+            System.err.println("Unable to write " + aOutputDir + ". Perhaps a permissions issue?");
+            e.printStackTrace(System.err);
+        } finally {
+            if (implStream != null) {
+                try {
+                    implStream.close();
+                } catch (IOException e) {
+                    System.err.println("Unable to close implStream due to "+e);
+                    e.printStackTrace(System.err);
+                }
+            }
+        }
+
+        FileOutputStream headerStream = null;
+        try {
+            headerStream = new FileOutputStream(new File(aOutputDir, aPrefix + ".h"));
+            headerStream.write(aHeaderFile.toString().getBytes());
+        } catch (IOException e) {
+            System.err.println("Unable to write " + aOutputDir + ". Perhaps a permissions issue?");
+            e.printStackTrace(System.err);
+        } finally {
+            if (headerStream != null) {
+                try {
+                    headerStream.close();
+                } catch (IOException e) {
+                    System.err.println("Unable to close headerStream due to "+e);
+                    e.printStackTrace(System.err);
+                }
+            }
+        }
+    }
+}
diff --git a/src/third_party/mozjs-45/build/annotationProcessors/classloader/AnnotatableEntity.java b/src/third_party/mozjs-45/build/annotationProcessors/classloader/AnnotatableEntity.java
new file mode 100644
index 0000000..b11a6c4
--- /dev/null
+++ b/src/third_party/mozjs-45/build/annotationProcessors/classloader/AnnotatableEntity.java
@@ -0,0 +1,62 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.gecko.annotationProcessors.classloader;
+
+import org.mozilla.gecko.annotationProcessors.AnnotationInfo;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+/**
+ * Union type to hold either a method, field, or ctor. Allows us to iterate "The generatable stuff", despite
+ * the fact that such things can be of either flavour.
+ */
+public class AnnotatableEntity {
+    public enum ENTITY_TYPE {METHOD, NATIVE, FIELD, CONSTRUCTOR}
+
+    private final Member mMember;
+    public final ENTITY_TYPE mEntityType;
+
+    public final AnnotationInfo mAnnotationInfo;
+
+    public AnnotatableEntity(Member aObject, AnnotationInfo aAnnotationInfo) {
+        mMember = aObject;
+        mAnnotationInfo = aAnnotationInfo;
+
+        if (aObject instanceof Method) {
+            if (Modifier.isNative(aObject.getModifiers())) {
+                mEntityType = ENTITY_TYPE.NATIVE;
+            } else {
+                mEntityType = ENTITY_TYPE.METHOD;
+            }
+        } else if (aObject instanceof Field) {
+            mEntityType = ENTITY_TYPE.FIELD;
+        } else {
+            mEntityType = ENTITY_TYPE.CONSTRUCTOR;
+        }
+    }
+
+    public Method getMethod() {
+        if (mEntityType != ENTITY_TYPE.METHOD && mEntityType != ENTITY_TYPE.NATIVE) {
+            throw new UnsupportedOperationException("Attempt to cast to unsupported member type.");
+        }
+        return (Method) mMember;
+    }
+    public Field getField() {
+        if (mEntityType != ENTITY_TYPE.FIELD) {
+            throw new UnsupportedOperationException("Attempt to cast to unsupported member type.");
+        }
+        return (Field) mMember;
+    }
+    public Constructor<?> getConstructor() {
+        if (mEntityType != ENTITY_TYPE.CONSTRUCTOR) {
+            throw new UnsupportedOperationException("Attempt to cast to unsupported member type.");
+        }
+        return (Constructor<?>) mMember;
+    }
+}
diff --git a/src/third_party/mozjs-45/build/annotationProcessors/classloader/ClassWithOptions.java b/src/third_party/mozjs-45/build/annotationProcessors/classloader/ClassWithOptions.java
new file mode 100644
index 0000000..070cff8
--- /dev/null
+++ b/src/third_party/mozjs-45/build/annotationProcessors/classloader/ClassWithOptions.java
@@ -0,0 +1,15 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.gecko.annotationProcessors.classloader;
+
+public class ClassWithOptions {
+    public final Class<?> wrappedClass;
+    public final String generatedName;
+
+    public ClassWithOptions(Class<?> someClass, String name) {
+        wrappedClass = someClass;
+        generatedName = name;
+    }
+}
diff --git a/src/third_party/mozjs-45/build/annotationProcessors/classloader/IterableJarLoadingURLClassLoader.java b/src/third_party/mozjs-45/build/annotationProcessors/classloader/IterableJarLoadingURLClassLoader.java
new file mode 100644
index 0000000..7e74399
--- /dev/null
+++ b/src/third_party/mozjs-45/build/annotationProcessors/classloader/IterableJarLoadingURLClassLoader.java
@@ -0,0 +1,75 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.gecko.annotationProcessors.classloader;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+/**
+ * A classloader which can be initialised with a list of jar files and which can provide an iterator
+ * over the top level classes in the jar files it was initialised with.
+ * classNames is kept sorted to ensure iteration order is consistent across program invocations.
+ * Otherwise, we'd forever be reporting the outdatedness of the generated code as we permute its
+ * contents.
+ */
+public class IterableJarLoadingURLClassLoader extends URLClassLoader {
+    LinkedList<String> classNames = new LinkedList<String>();
+
+    /**
+     * Create an instance and return its iterator. Provides an iterator over the classes in the jar
+     * files provided as arguments.
+     * Inner classes are not supported.
+     *
+     * @param args A list of jar file names an iterator over the classes of which is desired.
+     * @return An iterator over the top level classes in the jar files provided, in arbitrary order.
+     */
+    public static Iterator<ClassWithOptions> getIteratorOverJars(String[] args) {
+        URL[] urlArray = new URL[args.length];
+        LinkedList<String> aClassNames = new LinkedList<String>();
+
+        for (int i = 0; i < args.length; i++) {
+            try {
+                urlArray[i] = (new File(args[i])).toURI().toURL();
+
+                Enumeration<JarEntry> entries = new JarFile(args[i]).entries();
+                while (entries.hasMoreElements()) {
+                    JarEntry e = entries.nextElement();
+                    String fName = e.getName();
+                    if (!fName.endsWith(".class")) {
+                        continue;
+                    }
+                    final String className = fName.substring(0, fName.length() - 6).replace('/', '.');
+
+                    aClassNames.add(className);
+                }
+            } catch (IOException e) {
+                System.err.println("Error loading jar file \"" + args[i] + '"');
+                e.printStackTrace(System.err);
+            }
+        }
+        Collections.sort(aClassNames);
+        return new JarClassIterator(new IterableJarLoadingURLClassLoader(urlArray, aClassNames));
+    }
+
+    /**
+     * Constructs a classloader capable of loading all classes given as URLs in urls. Used by static
+     * method above.
+     *
+     * @param urls        URLs for all classes the new instance shall be capable of loading.
+     * @param aClassNames A list of names of the classes this instance shall be capable of loading.
+     */
+    protected IterableJarLoadingURLClassLoader(URL[] urls, LinkedList<String> aClassNames) {// Array to populate with URLs for each class in the given jars.
+        super(urls);
+        classNames = aClassNames;
+    }
+}
diff --git a/src/third_party/mozjs-45/build/annotationProcessors/classloader/JarClassIterator.java b/src/third_party/mozjs-45/build/annotationProcessors/classloader/JarClassIterator.java
new file mode 100644
index 0000000..452de81
--- /dev/null
+++ b/src/third_party/mozjs-45/build/annotationProcessors/classloader/JarClassIterator.java
@@ -0,0 +1,84 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.gecko.annotationProcessors.classloader;
+
+import java.util.Iterator;
+
+/**
+ * Class for iterating over an IterableJarLoadingURLClassLoader's classes.
+ *
+ * This class is not thread safe: use it only from a single thread.
+ */
+public class JarClassIterator implements Iterator<ClassWithOptions> {
+    private IterableJarLoadingURLClassLoader mTarget;
+    private Iterator<String> mTargetClassListIterator;
+
+    private ClassWithOptions lookAhead;
+
+    public JarClassIterator(IterableJarLoadingURLClassLoader aTarget) {
+        mTarget = aTarget;
+        mTargetClassListIterator = aTarget.classNames.iterator();
+    }
+
+    @Override
+    public boolean hasNext() {
+        return fillLookAheadIfPossible();
+    }
+
+    @Override
+    public ClassWithOptions next() {
+        if (!fillLookAheadIfPossible()) {
+            throw new IllegalStateException("Failed to look ahead in next()!");
+        }
+        ClassWithOptions next = lookAhead;
+        lookAhead = null;
+        return next;
+    }
+
+    private boolean fillLookAheadIfPossible() {
+        if (lookAhead != null) {
+            return true;
+        }
+
+        if (!mTargetClassListIterator.hasNext()) {
+            return false;
+        }
+
+        String className = mTargetClassListIterator.next();
+        try {
+            Class<?> ret = mTarget.loadClass(className);
+
+            // Incremental builds can leave stale classfiles in the jar. Such classfiles will cause
+            // an exception at this point. We can safely ignore these classes - they cannot possibly
+            // ever be loaded as they conflict with their parent class and will be killed by
+            // Proguard later on anyway.
+            final Class<?> enclosingClass;
+            try {
+                enclosingClass = ret.getEnclosingClass();
+            } catch (IncompatibleClassChangeError e) {
+                return fillLookAheadIfPossible();
+            }
+
+            if (enclosingClass != null) {
+                // Anonymous inner class - unsupported.
+                // Or named inner class, which will be processed when we process the outer class.
+                return fillLookAheadIfPossible();
+            }
+
+            lookAhead = new ClassWithOptions(ret, ret.getSimpleName());
+            return true;
+        } catch (ClassNotFoundException e) {
+            System.err.println("Unable to enumerate class: " + className + ". Corrupted jar file?");
+            e.printStackTrace();
+            System.exit(2);
+        }
+        return false;
+    }
+
+    @Override
+    public void remove() {
+        throw new UnsupportedOperationException("Removal of classes from iterator not supported.");
+    }
+}
diff --git a/src/third_party/mozjs-45/build/annotationProcessors/moz.build b/src/third_party/mozjs-45/build/annotationProcessors/moz.build
new file mode 100644
index 0000000..f2200eb
--- /dev/null
+++ b/src/third_party/mozjs-45/build/annotationProcessors/moz.build
@@ -0,0 +1,24 @@
+# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+jar = add_java_jar('annotationProcessors')
+jar.sources += [
+    'AnnotationInfo.java',
+    'AnnotationProcessor.java',
+    'classloader/AnnotatableEntity.java',
+    'classloader/ClassWithOptions.java',
+    'classloader/IterableJarLoadingURLClassLoader.java',
+    'classloader/JarClassIterator.java',
+    'CodeGenerator.java',
+    'SDKProcessor.java',
+    'utils/AlphabeticAnnotatableEntityComparator.java',
+    'utils/GeneratableElementIterator.java',
+    'utils/Utils.java',
+]
+jar.extra_jars += [
+    CONFIG['ANDROID_TOOLS'] + '/lib/lint.jar',
+    CONFIG['ANDROID_TOOLS'] + '/lib/lint-checks.jar',
+]
diff --git a/src/third_party/mozjs-45/build/annotationProcessors/utils/AlphabeticAnnotatableEntityComparator.java b/src/third_party/mozjs-45/build/annotationProcessors/utils/AlphabeticAnnotatableEntityComparator.java
new file mode 100644
index 0000000..2ee2ae5
--- /dev/null
+++ b/src/third_party/mozjs-45/build/annotationProcessors/utils/AlphabeticAnnotatableEntityComparator.java
@@ -0,0 +1,81 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.gecko.annotationProcessors.utils;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.util.Comparator;
+
+public class AlphabeticAnnotatableEntityComparator<T extends Member> implements Comparator<T> {
+    @Override
+    public int compare(T aLhs, T aRhs) {
+        // Constructors, Methods, Fields.
+        boolean lIsConstructor = aLhs instanceof Constructor;
+        boolean rIsConstructor = aRhs instanceof Constructor;
+        boolean lIsMethod = aLhs instanceof Method;
+        boolean rIsField = aRhs instanceof Field;
+
+        if (lIsConstructor) {
+            if (!rIsConstructor) {
+                return -1;
+            }
+        } else if (lIsMethod) {
+            if (rIsConstructor) {
+                return 1;
+            } else if (rIsField) {
+                return -1;
+            }
+        } else {
+            if (!rIsField) {
+                return 1;
+            }
+        }
+
+        // Verify these objects are the same type and cast them.
+        if (aLhs instanceof Method) {
+            return compare((Method) aLhs, (Method) aRhs);
+        } else if (aLhs instanceof Field) {
+            return compare((Field) aLhs, (Field) aRhs);
+        } else {
+            return compare((Constructor) aLhs, (Constructor) aRhs);
+        }
+    }
+
+    // Alas, the type system fails us.
+    private static int compare(Method aLhs, Method aRhs) {
+        // Initially, attempt to differentiate the methods be name alone..
+        String lName = aLhs.getName();
+        String rName = aRhs.getName();
+
+        int ret = lName.compareTo(rName);
+        if (ret != 0) {
+            return ret;
+        }
+
+        // The names were the same, so we need to compare signatures to find their uniqueness..
+        lName = Utils.getSignature(aLhs);
+        rName = Utils.getSignature(aRhs);
+
+        return lName.compareTo(rName);
+    }
+
+    private static int compare(Constructor<?> aLhs, Constructor<?> aRhs) {
+        // The names will be the same, so we need to compare signatures to find their uniqueness..
+        String lName = Utils.getSignature(aLhs);
+        String rName = Utils.getSignature(aRhs);
+
+        return lName.compareTo(rName);
+    }
+
+    private static int compare(Field aLhs, Field aRhs) {
+        // Compare field names..
+        String lName = aLhs.getName();
+        String rName = aRhs.getName();
+
+        return lName.compareTo(rName);
+    }
+}
diff --git a/src/third_party/mozjs-45/build/annotationProcessors/utils/GeneratableElementIterator.java b/src/third_party/mozjs-45/build/annotationProcessors/utils/GeneratableElementIterator.java
new file mode 100644
index 0000000..4f27f2d
--- /dev/null
+++ b/src/third_party/mozjs-45/build/annotationProcessors/utils/GeneratableElementIterator.java
@@ -0,0 +1,220 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.gecko.annotationProcessors.utils;
+
+import org.mozilla.gecko.annotationProcessors.AnnotationInfo;
+import org.mozilla.gecko.annotationProcessors.classloader.AnnotatableEntity;
+import org.mozilla.gecko.annotationProcessors.classloader.ClassWithOptions;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.Iterator;
+
+/**
+ * Iterator over the methods in a given method list which have the WrappedJNIMethod
+ * annotation. Returns an object containing both the annotation (Which may contain interesting
+ * parameters) and the argument.
+ */
+public class GeneratableElementIterator implements Iterator<AnnotatableEntity> {
+    private final ClassWithOptions mClass;
+    private final Member[] mObjects;
+    private AnnotatableEntity mNextReturnValue;
+    private int mElementIndex;
+
+    private boolean mIterateEveryEntry;
+
+    public GeneratableElementIterator(ClassWithOptions annotatedClass) {
+        mClass = annotatedClass;
+
+        final Class<?> aClass = annotatedClass.wrappedClass;
+        // Get all the elements of this class as AccessibleObjects.
+        Member[] aMethods = aClass.getDeclaredMethods();
+        Member[] aFields = aClass.getDeclaredFields();
+        Member[] aCtors = aClass.getDeclaredConstructors();
+
+        // Shove them all into one buffer.
+        Member[] objs = new Member[aMethods.length + aFields.length + aCtors.length];
+
+        int offset = 0;
+        System.arraycopy(aMethods, 0, objs, 0, aMethods.length);
+        offset += aMethods.length;
+        System.arraycopy(aFields, 0, objs, offset, aFields.length);
+        offset += aFields.length;
+        System.arraycopy(aCtors, 0, objs, offset, aCtors.length);
+
+        // Sort the elements to ensure determinism.
+        Arrays.sort(objs, new AlphabeticAnnotatableEntityComparator<Member>());
+        mObjects = objs;
+
+        // Check for "Wrap ALL the things" flag.
+        for (Annotation annotation : aClass.getDeclaredAnnotations()) {
+            final String annotationTypeName = annotation.annotationType().getName();
+            if (annotationTypeName.equals("org.mozilla.gecko.annotation.WrapForJNI")) {
+                mIterateEveryEntry = true;
+                break;
+            }
+        }
+
+        findNextValue();
+    }
+
+    private Class<?>[] getFilteredInnerClasses() {
+        // Go through all inner classes and see which ones we want to generate.
+        final Class<?>[] candidates = mClass.wrappedClass.getDeclaredClasses();
+        int count = 0;
+
+        for (int i = 0; i < candidates.length; ++i) {
+            final GeneratableElementIterator testIterator
+                    = new GeneratableElementIterator(new ClassWithOptions(candidates[i], null));
+            if (testIterator.hasNext()
+                    || testIterator.getFilteredInnerClasses() != null) {
+                count++;
+                continue;
+            }
+            // Clear out ones that don't match.
+            candidates[i] = null;
+        }
+        return count > 0 ? candidates : null;
+    }
+
+    public ClassWithOptions[] getInnerClasses() {
+        final Class<?>[] candidates = getFilteredInnerClasses();
+        if (candidates == null) {
+            return new ClassWithOptions[0];
+        }
+
+        int count = 0;
+        for (Class<?> candidate : candidates) {
+            if (candidate != null) {
+                count++;
+            }
+        }
+
+        final ClassWithOptions[] ret = new ClassWithOptions[count];
+        count = 0;
+        for (Class<?> candidate : candidates) {
+            if (candidate != null) {
+                ret[count++] = new ClassWithOptions(
+                        candidate, mClass.generatedName + "::" + candidate.getSimpleName());
+            }
+        }
+        assert ret.length == count;
+
+        Arrays.sort(ret, new Comparator<ClassWithOptions>() {
+            @Override public int compare(ClassWithOptions lhs, ClassWithOptions rhs) {
+                return lhs.generatedName.compareTo(rhs.generatedName);
+            }
+        });
+        return ret;
+    }
+
+    /**
+     * Find and cache the next appropriately annotated method, plus the annotation parameter, if
+     * one exists. Otherwise cache null, so hasNext returns false.
+     */
+    private void findNextValue() {
+        while (mElementIndex < mObjects.length) {
+            Member candidateElement = mObjects[mElementIndex];
+            mElementIndex++;
+            for (Annotation annotation : ((AnnotatedElement) candidateElement).getDeclaredAnnotations()) {
+                // WrappedJNIMethod has parameters. Use Reflection to obtain them.
+                Class<? extends Annotation> annotationType = annotation.annotationType();
+                final String annotationTypeName = annotationType.getName();
+                if (annotationTypeName.equals("org.mozilla.gecko.annotation.WrapForJNI")) {
+                    String stubName = null;
+                    boolean isMultithreadedStub = false;
+                    boolean noThrow = false;
+                    boolean narrowChars = false;
+                    boolean catchException = false;
+                    try {
+                        // Determine the explicitly-given name of the stub to generate, if any.
+                        final Method stubNameMethod = annotationType.getDeclaredMethod("stubName");
+                        stubNameMethod.setAccessible(true);
+                        stubName = (String) stubNameMethod.invoke(annotation);
+
+                        // Determine if the generated stub is to allow calls from multiple threads.
+                        final Method multithreadedStubMethod = annotationType.getDeclaredMethod("allowMultithread");
+                        multithreadedStubMethod.setAccessible(true);
+                        isMultithreadedStub = (Boolean) multithreadedStubMethod.invoke(annotation);
+
+                        // Determine if ignoring exceptions
+                        final Method noThrowMethod = annotationType.getDeclaredMethod("noThrow");
+                        noThrowMethod.setAccessible(true);
+                        noThrow = (Boolean) noThrowMethod.invoke(annotation);
+
+                        // Determine if strings should be wide or narrow
+                        final Method narrowCharsMethod = annotationType.getDeclaredMethod("narrowChars");
+                        narrowCharsMethod.setAccessible(true);
+                        narrowChars = (Boolean) narrowCharsMethod.invoke(annotation);
+
+                        // Determine if we should catch exceptions
+                        final Method catchExceptionMethod = annotationType.getDeclaredMethod("catchException");
+                        catchExceptionMethod.setAccessible(true);
+                        catchException = (Boolean) catchExceptionMethod.invoke(annotation);
+
+                    } catch (NoSuchMethodException e) {
+                        System.err.println("Unable to find expected field on WrapForJNI annotation. Did the signature change?");
+                        e.printStackTrace(System.err);
+                        System.exit(3);
+                    } catch (IllegalAccessException e) {
+                        System.err.println("IllegalAccessException reading fields on WrapForJNI annotation. Seems the semantics of Reflection have changed...");
+                        e.printStackTrace(System.err);
+                        System.exit(4);
+                    } catch (InvocationTargetException e) {
+                        System.err.println("InvocationTargetException reading fields on WrapForJNI annotation. This really shouldn't happen.");
+                        e.printStackTrace(System.err);
+                        System.exit(5);
+                    }
+
+                    // If the method name was not explicitly given in the annotation generate one...
+                    if (stubName.isEmpty()) {
+                        stubName = Utils.getNativeName(candidateElement);
+                    }
+
+                    AnnotationInfo annotationInfo = new AnnotationInfo(
+                        stubName, isMultithreadedStub, noThrow, narrowChars, catchException);
+                    mNextReturnValue = new AnnotatableEntity(candidateElement, annotationInfo);
+                    return;
+                }
+            }
+
+            // If no annotation found, we might be expected to generate anyway
+            // using default arguments, thanks to the "Generate everything" annotation.
+            if (mIterateEveryEntry) {
+                AnnotationInfo annotationInfo = new AnnotationInfo(
+                    Utils.getNativeName(candidateElement),
+                    /* multithreaded */ true,
+                    /* noThrow */ false,
+                    /* narrowChars */ false,
+                    /* catchException */ false);
+                mNextReturnValue = new AnnotatableEntity(candidateElement, annotationInfo);
+                return;
+            }
+        }
+        mNextReturnValue = null;
+    }
+
+    @Override
+    public boolean hasNext() {
+        return mNextReturnValue != null;
+    }
+
+    @Override
+    public AnnotatableEntity next() {
+        AnnotatableEntity ret = mNextReturnValue;
+        findNextValue();
+        return ret;
+    }
+
+    @Override
+    public void remove() {
+        throw new UnsupportedOperationException("Removal of methods from GeneratableElementIterator not supported.");
+    }
+}
diff --git a/src/third_party/mozjs-45/build/annotationProcessors/utils/Utils.java b/src/third_party/mozjs-45/build/annotationProcessors/utils/Utils.java
new file mode 100644
index 0000000..0e96f72
--- /dev/null
+++ b/src/third_party/mozjs-45/build/annotationProcessors/utils/Utils.java
@@ -0,0 +1,251 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.gecko.annotationProcessors.utils;
+
+import org.mozilla.gecko.annotationProcessors.AnnotationInfo;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+
+/**
+ * A collection of utility methods used by CodeGenerator. Largely used for translating types.
+ */
+public class Utils {
+
+    // A collection of lookup tables to simplify the functions to follow...
+    private static final HashMap<String, String> NATIVE_TYPES = new HashMap<String, String>();
+
+    static {
+        NATIVE_TYPES.put("void", "void");
+        NATIVE_TYPES.put("boolean", "bool");
+        NATIVE_TYPES.put("byte", "int8_t");
+        NATIVE_TYPES.put("char", "char16_t");
+        NATIVE_TYPES.put("short", "int16_t");
+        NATIVE_TYPES.put("int", "int32_t");
+        NATIVE_TYPES.put("long", "int64_t");
+        NATIVE_TYPES.put("float", "float");
+        NATIVE_TYPES.put("double", "double");
+    }
+
+    private static final HashMap<String, String> NATIVE_ARRAY_TYPES = new HashMap<String, String>();
+
+    static {
+        NATIVE_ARRAY_TYPES.put("boolean", "mozilla::jni::BooleanArray");
+        NATIVE_ARRAY_TYPES.put("byte", "mozilla::jni::ByteArray");
+        NATIVE_ARRAY_TYPES.put("char", "mozilla::jni::CharArray");
+        NATIVE_ARRAY_TYPES.put("short", "mozilla::jni::ShortArray");
+        NATIVE_ARRAY_TYPES.put("int", "mozilla::jni::IntArray");
+        NATIVE_ARRAY_TYPES.put("long", "mozilla::jni::LongArray");
+        NATIVE_ARRAY_TYPES.put("float", "mozilla::jni::FloatArray");
+        NATIVE_ARRAY_TYPES.put("double", "mozilla::jni::DoubleArray");
+    }
+
+    private static final HashMap<String, String> CLASS_DESCRIPTORS = new HashMap<String, String>();
+
+    static {
+        CLASS_DESCRIPTORS.put("void", "V");
+        CLASS_DESCRIPTORS.put("boolean", "Z");
+        CLASS_DESCRIPTORS.put("byte", "B");
+        CLASS_DESCRIPTORS.put("char", "C");
+        CLASS_DESCRIPTORS.put("short", "S");
+        CLASS_DESCRIPTORS.put("int", "I");
+        CLASS_DESCRIPTORS.put("long", "J");
+        CLASS_DESCRIPTORS.put("float", "F");
+        CLASS_DESCRIPTORS.put("double", "D");
+    }
+
+    /**
+     * Get the C++ type corresponding to the provided type parameter.
+     *
+     * @param type Class to determine the corresponding JNI type for.
+     * @return C++ type as a String
+     */
+    public static String getNativeParameterType(Class<?> type, AnnotationInfo info) {
+        final String name = type.getName().replace('.', '/');
+
+        if (NATIVE_TYPES.containsKey(name)) {
+            return NATIVE_TYPES.get(name);
+        }
+
+        if (type.isArray()) {
+            final String compName = type.getComponentType().getName();
+            if (NATIVE_ARRAY_TYPES.containsKey(compName)) {
+                return NATIVE_ARRAY_TYPES.get(compName) + "::Param";
+            }
+            return "mozilla::jni::ObjectArray::Param";
+        }
+
+        if (type.equals(String.class) || type.equals(CharSequence.class)) {
+            return "mozilla::jni::String::Param";
+        }
+
+        if (type.equals(Class.class)) {
+            // You're doing reflection on Java objects from inside C, returning Class objects
+            // to C, generating the corresponding code using this Java program. Really?!
+            return "mozilla::jni::ClassObject::Param";
+        }
+
+        if (type.equals(Throwable.class)) {
+            return "mozilla::jni::Throwable::Param";
+        }
+
+        return "mozilla::jni::Object::Param";
+    }
+
+    public static String getNativeReturnType(Class<?> type, AnnotationInfo info) {
+        final String name = type.getName().replace('.', '/');
+
+        if (NATIVE_TYPES.containsKey(name)) {
+            return NATIVE_TYPES.get(name);
+        }
+
+        if (type.isArray()) {
+            final String compName = type.getComponentType().getName();
+            if (NATIVE_ARRAY_TYPES.containsKey(compName)) {
+                return NATIVE_ARRAY_TYPES.get(compName) + "::LocalRef";
+            }
+            return "mozilla::jni::ObjectArray::LocalRef";
+        }
+
+        if (type.equals(String.class)) {
+            return "mozilla::jni::String::LocalRef";
+        }
+
+        if (type.equals(Class.class)) {
+            // You're doing reflection on Java objects from inside C, returning Class objects
+            // to C, generating the corresponding code using this Java program. Really?!
+            return "mozilla::jni::ClassObject::LocalRef";
+        }
+
+        if (type.equals(Throwable.class)) {
+            return "mozilla::jni::Throwable::LocalRef";
+        }
+
+        return "mozilla::jni::Object::LocalRef";
+    }
+
+    /**
+     * Get the JNI class descriptor corresponding to the provided type parameter.
+     *
+     * @param type Class to determine the corresponding JNI descriptor for.
+     * @return Class descripor as a String
+     */
+    public static String getClassDescriptor(Class<?> type) {
+        final String name = type.getName().replace('.', '/');
+
+        if (CLASS_DESCRIPTORS.containsKey(name)) {
+            return CLASS_DESCRIPTORS.get(name);
+        }
+
+        if (type.isArray()) {
+            // Array names are already in class descriptor form.
+            return name;
+        }
+
+        return "L" + name + ';';
+    }
+
+    /**
+     * Get the JNI signaure for a member.
+     *
+     * @param member Member to get the signature for.
+     * @return JNI signature as a string
+     */
+    public static String getSignature(Member member) {
+        return member instanceof Field ?  getSignature((Field) member) :
+               member instanceof Method ? getSignature((Method) member) :
+                                          getSignature((Constructor<?>) member);
+    }
+
+    /**
+     * Get the JNI signaure for a field.
+     *
+     * @param member Field to get the signature for.
+     * @return JNI signature as a string
+     */
+    public static String getSignature(Field member) {
+        return getClassDescriptor(member.getType());
+    }
+
+    private static String getSignature(Class<?>[] args, Class<?> ret) {
+        final StringBuilder sig = new StringBuilder("(");
+        for (int i = 0; i < args.length; i++) {
+            sig.append(getClassDescriptor(args[i]));
+        }
+        return sig.append(')').append(getClassDescriptor(ret)).toString();
+    }
+
+    /**
+     * Get the JNI signaure for a method.
+     *
+     * @param member Method to get the signature for.
+     * @return JNI signature as a string
+     */
+    public static String getSignature(Method member) {
+        return getSignature(member.getParameterTypes(), member.getReturnType());
+    }
+
+    /**
+     * Get the JNI signaure for a constructor.
+     *
+     * @param member Constructor to get the signature for.
+     * @return JNI signature as a string
+     */
+    public static String getSignature(Constructor<?> member) {
+        return getSignature(member.getParameterTypes(), void.class);
+    }
+
+    /**
+     * Get the C++ name for a member.
+     *
+     * @param member Member to get the name for.
+     * @return JNI name as a string
+     */
+    public static String getNativeName(Member member) {
+        final String name = getMemberName(member);
+        return name.substring(0, 1).toUpperCase() + name.substring(1);
+    }
+
+    /**
+     * Get the JNI name for a member.
+     *
+     * @param member Member to get the name for.
+     * @return JNI name as a string
+     */
+    public static String getMemberName(Member member) {
+        if (member instanceof Constructor) {
+            return "<init>";
+        }
+        return member.getName();
+    }
+
+    public static String getUnqualifiedName(String name) {
+        return name.substring(name.lastIndexOf(':') + 1);
+    }
+
+    /**
+     * Determine if a member is declared static.
+     *
+     * @param member The Member to check.
+     * @return true if the member is declared static, false otherwise.
+     */
+    public static boolean isStatic(final Member member) {
+        return Modifier.isStatic(member.getModifiers());
+    }
+
+    /**
+     * Determine if a member is declared final.
+     *
+     * @param member The Member to check.
+     * @return true if the member is declared final, false otherwise.
+     */
+    public static boolean isFinal(final Member member) {
+        return Modifier.isFinal(member.getModifiers());
+    }
+}
diff --git a/src/third_party/mozjs-45/build/appini_header.py b/src/third_party/mozjs-45/build/appini_header.py
new file mode 100644
index 0000000..d637d5e
--- /dev/null
+++ b/src/third_party/mozjs-45/build/appini_header.py
@@ -0,0 +1,60 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+'''Parses a given application.ini file and outputs the corresponding
+   XULAppData structure as a C++ header file'''
+
+import ConfigParser
+import sys
+
+def main(file):
+    config = ConfigParser.RawConfigParser()
+    config.read(file)
+    flags = set()
+    try:
+        if config.getint('XRE', 'EnableProfileMigrator') == 1:
+            flags.add('NS_XRE_ENABLE_PROFILE_MIGRATOR')
+    except: pass
+    try:
+        if config.getint('Crash Reporter', 'Enabled') == 1:
+            flags.add('NS_XRE_ENABLE_CRASH_REPORTER')
+    except: pass
+    appdata = dict(("%s:%s" % (s, o), config.get(s, o)) for s in config.sections() for o in config.options(s))
+    appdata['flags'] = ' | '.join(flags) if flags else '0'
+    appdata['App:profile'] = '"%s"' % appdata['App:profile'] if 'App:profile' in appdata else 'NULL'
+    expected = ('App:vendor', 'App:name', 'App:remotingname', 'App:version', 'App:buildid',
+                'App:id', 'Gecko:minversion', 'Gecko:maxversion')
+    missing = [var for var in expected if var not in appdata]
+    if missing:
+        print >>sys.stderr, \
+            "Missing values in %s: %s" % (file, ', '.join(missing))
+        sys.exit(1)
+
+    if not 'Crash Reporter:serverurl' in appdata:
+        appdata['Crash Reporter:serverurl'] = ''
+
+    print '''#include "nsXREAppData.h"
+             static const nsXREAppData sAppData = {
+                 sizeof(nsXREAppData),
+                 NULL, // directory
+                 "%(App:vendor)s",
+                 "%(App:name)s",
+                 "%(App:remotingname)s",
+                 "%(App:version)s",
+                 "%(App:buildid)s",
+                 "%(App:id)s",
+                 NULL, // copyright
+                 %(flags)s,
+                 NULL, // xreDirectory
+                 "%(Gecko:minversion)s",
+                 "%(Gecko:maxversion)s",
+                 "%(Crash Reporter:serverurl)s",
+                 %(App:profile)s
+             };''' % appdata
+
+if __name__ == '__main__':
+    if len(sys.argv) != 1:
+        main(sys.argv[1])
+    else:
+        print >>sys.stderr, "Usage: %s /path/to/application.ini" % sys.argv[0]
diff --git a/src/third_party/mozjs-45/build/application.ini b/src/third_party/mozjs-45/build/application.ini
new file mode 100644
index 0000000..74b0139
--- /dev/null
+++ b/src/third_party/mozjs-45/build/application.ini
@@ -0,0 +1,51 @@
+#if MOZ_APP_STATIC_INI
+#ifdef MOZ_BUILD_APP_IS_BROWSER
+; This file is not used. If you modify it and want the application to use
+; your modifications, move it under the browser/ subdirectory and start with
+; the "-app /path/to/browser/application.ini" argument.
+#else
+; This file is not used. If you modify it and want the application to use
+; your modifications, start with the "-app /path/to/application.ini"
+; argument.
+#endif
+#endif
+#if 0
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#endif
+#filter substitution
+[App]
+Vendor=@MOZ_APP_VENDOR@
+Name=@MOZ_APP_BASENAME@
+RemotingName=@MOZ_APP_REMOTINGNAME@
+#ifdef MOZ_APP_DISPLAYNAME
+CodeName=@MOZ_APP_DISPLAYNAME@
+#endif
+Version=@MOZ_APP_VERSION@
+#ifdef MOZ_APP_PROFILE
+Profile=@MOZ_APP_PROFILE@
+#endif
+BuildID=@MOZ_APP_BUILDID@
+#ifdef MOZ_SOURCE_REPO
+SourceRepository=@MOZ_SOURCE_REPO@
+#endif
+#ifdef MOZ_SOURCE_STAMP
+SourceStamp=@MOZ_SOURCE_STAMP@
+#endif
+ID=@MOZ_APP_ID@
+
+[Gecko]
+MinVersion=@GRE_MILESTONE@
+MaxVersion=@GRE_MILESTONE@
+
+[XRE]
+#ifdef MOZ_PROFILE_MIGRATOR
+EnableProfileMigrator=1
+#endif
+
+#if MOZ_CRASHREPORTER
+[Crash Reporter]
+Enabled=1
+ServerURL=https://crash-reports.mozilla.com/submit?id=@MOZ_APP_ID@&version=@MOZ_APP_VERSION@&buildid=@MOZ_APP_BUILDID@
+#endif
diff --git a/src/third_party/mozjs-45/build/autoconf/acwinpaths.m4 b/src/third_party/mozjs-45/build/autoconf/acwinpaths.m4
new file mode 100644
index 0000000..ad9c754
--- /dev/null
+++ b/src/third_party/mozjs-45/build/autoconf/acwinpaths.m4
@@ -0,0 +1,31 @@
+dnl This Source Code Form is subject to the terms of the Mozilla Public
+dnl License, v. 2.0. If a copy of the MPL was not distributed with this
+dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+define(GENERATE_SUB_ABS, [
+define([AC_OUTPUT_FILES_SUB1], [
+patsubst($@, [/\*)], [/* | ?:/*)])
+])
+])
+GENERATE_SUB_ABS(defn([AC_OUTPUT_FILES]))
+
+define(GENERATE_SUB_NOSPLIT, [
+define([AC_OUTPUT_FILES], [
+patsubst($@, [-e "s%:% \$ac_given_srcdir/%g"], [])
+])
+])
+GENERATE_SUB_NOSPLIT(defn([AC_OUTPUT_FILES_SUB1]))
+
+define(GENERATE_HEADER_NOSPLIT, [
+define([AC_OUTPUT_HEADER], [
+patsubst($@, [-e "s%:% \$ac_given_srcdir/%g"], [])
+])
+])
+GENERATE_HEADER_NOSPLIT(defn([AC_OUTPUT_HEADER]))
+
+define(GENERATE_SUBDIRS_ABS, [
+define([AC_OUTPUT_SUBDIRS], [
+patsubst($@, [/\*)], [/* | ?:/*)])
+])
+])
+GENERATE_SUBDIRS_ABS(defn([AC_OUTPUT_SUBDIRS]))
diff --git a/src/third_party/mozjs-45/build/autoconf/alloc.m4 b/src/third_party/mozjs-45/build/autoconf/alloc.m4
new file mode 100644
index 0000000..8234a60
--- /dev/null
+++ b/src/third_party/mozjs-45/build/autoconf/alloc.m4
@@ -0,0 +1,53 @@
+dnl This Source Code Form is subject to the terms of the Mozilla Public
+dnl License, v. 2.0. If a copy of the MPL was not distributed with this
+dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+dnl Check for the existence of various allocation headers/functions
+AC_DEFUN([MOZ_CHECK_ALLOCATOR],[
+
+MALLOC_HEADERS="malloc.h malloc_np.h malloc/malloc.h sys/malloc.h"
+MALLOC_H=
+
+for file in $MALLOC_HEADERS; do
+  MOZ_CHECK_HEADER($file, [MALLOC_H=$file])
+  if test "$MALLOC_H" != ""; then
+    AC_DEFINE_UNQUOTED(MALLOC_H, <$MALLOC_H>)
+    break
+  fi
+done
+
+MOZ_CHECK_HEADERS(alloca.h)
+
+AC_CHECK_FUNCS(strndup posix_memalign memalign)
+
+AC_CHECK_FUNCS(malloc_usable_size)
+MALLOC_USABLE_SIZE_CONST_PTR=const
+MOZ_CHECK_HEADERS([malloc.h], [
+  AC_MSG_CHECKING([whether malloc_usable_size definition can use const argument])
+  AC_TRY_COMPILE([#include <malloc.h>
+                  #include <stddef.h>
+                  size_t malloc_usable_size(const void *ptr);],
+                  [return malloc_usable_size(0);],
+                  AC_MSG_RESULT([yes]),
+                  AC_MSG_RESULT([no])
+                  MALLOC_USABLE_SIZE_CONST_PTR=)
+])
+AC_DEFINE_UNQUOTED([MALLOC_USABLE_SIZE_CONST_PTR],[$MALLOC_USABLE_SIZE_CONST_PTR])
+
+
+dnl In newer bionic headers, valloc is built but not defined,
+dnl so we check more carefully here.
+AC_MSG_CHECKING([for valloc in malloc.h])
+AC_EGREP_HEADER(valloc, malloc.h,
+                AC_DEFINE(HAVE_VALLOC)
+                AC_MSG_RESULT([yes]),
+                AC_MSG_RESULT([no]))
+
+AC_MSG_CHECKING([for valloc in unistd.h])
+AC_EGREP_HEADER(valloc, unistd.h,
+                AC_DEFINE(HAVE_VALLOC)
+                AC_MSG_RESULT([yes]),
+                AC_MSG_RESULT([no]))
+
+
+])
diff --git a/src/third_party/mozjs-45/build/autoconf/altoptions.m4 b/src/third_party/mozjs-45/build/autoconf/altoptions.m4
new file mode 100644
index 0000000..f8c8ba9
--- /dev/null
+++ b/src/third_party/mozjs-45/build/autoconf/altoptions.m4
@@ -0,0 +1,123 @@
+dnl This Source Code Form is subject to the terms of the Mozilla Public
+dnl License, v. 2.0. If a copy of the MPL was not distributed with this
+dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+dnl altoptions.m4 - An alternative way of specifying command-line options.
+dnl    These macros are needed to support a menu-based configurator.
+dnl    This file also includes the macro, AM_READ_MYCONFIG, for reading
+dnl    the 'myconfig.m4' file.
+
+dnl Send comments, improvements, bugs to Steve Lamm (slamm@netscape.com).
+
+
+dnl MOZ_ARG_ENABLE_BOOL(           NAME, HELP, IF-YES [, IF-NO [, ELSE]])
+dnl MOZ_ARG_DISABLE_BOOL(          NAME, HELP, IF-NO [, IF-YES [, ELSE]])
+dnl MOZ_ARG_ENABLE_STRING(         NAME, HELP, IF-SET [, ELSE])
+dnl MOZ_ARG_ENABLE_BOOL_OR_STRING( NAME, HELP, IF-YES, IF-NO, IF-SET[, ELSE]]])
+dnl MOZ_ARG_WITH_BOOL(             NAME, HELP, IF-YES [, IF-NO [, ELSE])
+dnl MOZ_ARG_WITHOUT_BOOL(          NAME, HELP, IF-NO [, IF-YES [, ELSE])
+dnl MOZ_ARG_WITH_STRING(           NAME, HELP, IF-SET [, ELSE])
+dnl MOZ_ARG_HEADER(Comment)
+dnl MOZ_READ_MYCONFIG() - Read in 'myconfig.sh' file
+
+
+dnl MOZ_TWO_STRING_TEST(NAME, VAL, STR1, IF-STR1, STR2, IF-STR2 [, ELSE])
+AC_DEFUN([MOZ_TWO_STRING_TEST],
+[if test "[$2]" = "[$3]"; then
+    ifelse([$4], , :, [$4])
+  elif test "[$2]" = "[$5]"; then
+    ifelse([$6], , :, [$6])
+  else
+    ifelse([$7], ,
+      [AC_MSG_ERROR([Option, [$1], does not take an argument ([$2]).])],
+      [$7])
+  fi])
+
+dnl MOZ_ARG_ENABLE_BOOL(NAME, HELP, IF-YES [, IF-NO [, ELSE]])
+AC_DEFUN([MOZ_ARG_ENABLE_BOOL],
+[AC_ARG_ENABLE([$1], [$2], 
+ [MOZ_TWO_STRING_TEST([$1], [$enableval], yes, [$3], no, [$4])],
+ [$5])])
+
+dnl MOZ_ARG_DISABLE_BOOL(NAME, HELP, IF-NO [, IF-YES [, ELSE]])
+AC_DEFUN([MOZ_ARG_DISABLE_BOOL],
+[AC_ARG_ENABLE([$1], [$2],
+ [MOZ_TWO_STRING_TEST([$1], [$enableval], no, [$3], yes, [$4])],
+ [$5])])
+
+dnl MOZ_ARG_ENABLE_STRING(NAME, HELP, IF-SET [, ELSE])
+AC_DEFUN([MOZ_ARG_ENABLE_STRING],
+[AC_ARG_ENABLE([$1], [$2], [$3], [$4])])
+
+dnl MOZ_ARG_ENABLE_BOOL_OR_STRING(NAME, HELP, IF-YES, IF-NO, IF-SET[, ELSE]]])
+AC_DEFUN([MOZ_ARG_ENABLE_BOOL_OR_STRING],
+[ifelse([$5], , 
+ [errprint([Option, $1, needs an "IF-SET" argument.
+])
+  m4exit(1)],
+ [AC_ARG_ENABLE([$1], [$2],
+  [MOZ_TWO_STRING_TEST([$1], [$enableval], yes, [$3], no, [$4], [$5])],
+  [$6])])])
+
+dnl MOZ_ARG_WITH_BOOL(NAME, HELP, IF-YES [, IF-NO [, ELSE])
+AC_DEFUN([MOZ_ARG_WITH_BOOL],
+[AC_ARG_WITH([$1], [$2],
+ [MOZ_TWO_STRING_TEST([$1], [$withval], yes, [$3], no, [$4])],
+ [$5])])
+
+dnl MOZ_ARG_WITHOUT_BOOL(NAME, HELP, IF-NO [, IF-YES [, ELSE])
+AC_DEFUN([MOZ_ARG_WITHOUT_BOOL],
+[AC_ARG_WITH([$1], [$2],
+ [MOZ_TWO_STRING_TEST([$1], [$withval], no, [$3], yes, [$4])],
+ [$5])])
+
+dnl MOZ_ARG_WITH_STRING(NAME, HELP, IF-SET [, ELSE])
+AC_DEFUN([MOZ_ARG_WITH_STRING],
+[AC_ARG_WITH([$1], [$2], [$3], [$4])])
+
+dnl MOZ_ARG_HEADER(Comment)
+dnl This is used by webconfig to group options
+define(MOZ_ARG_HEADER, [# $1])
+
+dnl MOZ_READ_MYCONFIG() - Read in 'myconfig.sh' file
+AC_DEFUN([MOZ_READ_MOZCONFIG],
+[AC_REQUIRE([AC_INIT_BINSH])dnl
+inserted=
+dnl Shell is hard, so here is what the following does:
+dnl - Reset $@ (command line arguments)
+dnl - Add the configure options from mozconfig to $@ one by one
+dnl - Add the original command line arguments after that, one by one
+dnl
+dnl There are several tricks involved:
+dnl - It is not possible to preserve the whitespaces in $@ by assigning to
+dnl   another variable, so the two first steps above need to happen in the first
+dnl   iteration of the third step.
+dnl - We always want the configure options to be added, so the loop must be
+dnl   iterated at least once, so we add a dummy argument first, and discard it.
+dnl - something | while read line ... makes the while run in a subshell, meaning
+dnl   that anything it does is not propagated to the main shell, so we can't do
+dnl   set -- foo there. As a consequence, what the while loop reading mach
+dnl   environment output does is output a set of shell commands for the main shell
+dnl   to eval.
+dnl - Extra care is due when lines from mach environment output contain special
+dnl   shell characters, so we use ' for quoting and ensure no ' end up in between
+dnl   the quoting mark unescaped.
+dnl Some of the above is directly done in mach environment --format=configure.
+failed_eval() {
+  echo "Failed eval'ing the following:"
+  $(dirname [$]0)/[$1]/mach environment --format=configure
+  exit 1
+}
+
+set -- dummy "[$]@"
+for ac_option
+do
+  if test -z "$inserted"; then
+    set --
+    eval "$($(dirname [$]0)/[$1]/mach environment --format=configure)" || failed_eval
+    inserted=1
+  else
+    set -- "[$]@" "$ac_option"
+  fi
+done
+])
diff --git a/src/third_party/mozjs-45/build/autoconf/android.m4 b/src/third_party/mozjs-45/build/autoconf/android.m4
new file mode 100644
index 0000000..f5d7430
--- /dev/null
+++ b/src/third_party/mozjs-45/build/autoconf/android.m4
@@ -0,0 +1,512 @@
+dnl This Source Code Form is subject to the terms of the Mozilla Public
+dnl License, v. 2.0. If a copy of the MPL was not distributed with this
+dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+AC_DEFUN([MOZ_ANDROID_NDK],
+[
+
+MOZ_ARG_WITH_STRING(android-ndk,
+[  --with-android-ndk=DIR
+                          location where the Android NDK can be found],
+    android_ndk=$withval)
+
+MOZ_ARG_WITH_STRING(android-toolchain,
+[  --with-android-toolchain=DIR
+                          location of the Android toolchain],
+    android_toolchain=$withval)
+
+MOZ_ARG_WITH_STRING(android-gnu-compiler-version,
+[  --with-android-gnu-compiler-version=VER
+                          gnu compiler version to use],
+    android_gnu_compiler_version=$withval)
+
+MOZ_ARG_WITH_STRING(android-cxx-stl,
+[  --with-android-cxx-stl=VALUE
+                          use the specified C++ STL (stlport, libstdc++, libc++)],
+    android_cxx_stl=$withval,
+    android_cxx_stl=mozstlport)
+
+define([MIN_ANDROID_VERSION], [9])
+android_version=MIN_ANDROID_VERSION
+
+MOZ_ARG_WITH_STRING(android-version,
+[  --with-android-version=VER
+                          android platform version, default] MIN_ANDROID_VERSION,
+    android_version=$withval)
+
+if test $android_version -lt MIN_ANDROID_VERSION ; then
+    AC_MSG_ERROR([--with-android-version must be at least MIN_ANDROID_VERSION.])
+fi
+
+case "$target" in
+arm-*linux*-android*|*-linuxandroid*)
+    android_tool_prefix="arm-linux-androideabi"
+    ;;
+i?86-*android*)
+    android_tool_prefix="i686-linux-android"
+    ;;
+mipsel-*android*)
+    android_tool_prefix="mipsel-linux-android"
+    ;;
+*)
+    android_tool_prefix="$target_os"
+    ;;
+esac
+
+case "$target" in
+*-android*|*-linuxandroid*)
+    if test -z "$android_ndk" ; then
+        AC_MSG_ERROR([You must specify --with-android-ndk=/path/to/ndk when targeting Android.])
+    fi
+
+    if test -z "$android_toolchain" ; then
+        AC_MSG_CHECKING([for android toolchain directory])
+
+        kernel_name=`uname -s | tr "[[:upper:]]" "[[:lower:]]"`
+
+        for version in $android_gnu_compiler_version 4.9 4.8 4.7; do
+            case "$target_cpu" in
+            arm)
+                target_name=arm-linux-androideabi-$version
+                ;;
+            i?86)
+                target_name=x86-$version
+                ;;
+            mipsel)
+                target_name=mipsel-linux-android-$version
+                ;;
+            *)
+                AC_MSG_ERROR([target cpu is not supported])
+                ;;
+            esac
+            case "$host_cpu" in
+            i*86)
+                android_toolchain="$android_ndk"/toolchains/$target_name/prebuilt/$kernel_name-x86
+                ;;
+            x86_64)
+                android_toolchain="$android_ndk"/toolchains/$target_name/prebuilt/$kernel_name-x86_64
+                if ! test -d "$android_toolchain" ; then
+                    android_toolchain="$android_ndk"/toolchains/$target_name/prebuilt/$kernel_name-x86
+                fi
+                ;;
+            *)
+                AC_MSG_ERROR([No known toolchain for your host cpu])
+                ;;
+            esac
+            if test -d "$android_toolchain" ; then
+                android_gnu_compiler_version=$version
+                break
+            elif test -n "$android_gnu_compiler_version" ; then
+                AC_MSG_ERROR([not found. Your --with-android-gnu-compiler-version may be wrong.])
+            fi
+        done
+
+        if test -z "$android_gnu_compiler_version" ; then
+            AC_MSG_ERROR([not found. You have to specify --with-android-toolchain=/path/to/ndk/toolchain.])
+        else
+            AC_MSG_RESULT([$android_toolchain])
+        fi
+        NSPR_CONFIGURE_ARGS="$NSPR_CONFIGURE_ARGS --with-android-toolchain=$android_toolchain"
+    fi
+
+    NSPR_CONFIGURE_ARGS="$NSPR_CONFIGURE_ARGS --with-android-version=$android_version"
+
+    AC_MSG_CHECKING([for android platform directory])
+
+    case "$target_cpu" in
+    arm)
+        target_name=arm
+        ;;
+    i?86)
+        target_name=x86
+        ;;
+    mipsel)
+        target_name=mips
+        ;;
+    esac
+
+    android_platform="$android_ndk"/platforms/android-"$android_version"/arch-"$target_name"
+
+    if test -d "$android_platform" ; then
+        AC_MSG_RESULT([$android_platform])
+    else
+        AC_MSG_ERROR([not found. Please check your NDK. With the current configuration, it should be in $android_platform])
+    fi
+
+    dnl set up compilers
+    TOOLCHAIN_PREFIX="$android_toolchain/bin/$android_tool_prefix-"
+    AS="$android_toolchain"/bin/"$android_tool_prefix"-as
+    if test -z "$CC"; then
+        CC="$android_toolchain"/bin/"$android_tool_prefix"-gcc
+    fi
+    if test -z "$CXX"; then
+        CXX="$android_toolchain"/bin/"$android_tool_prefix"-g++
+    fi
+    if test -z "$CPP"; then
+        CPP="$android_toolchain"/bin/"$android_tool_prefix"-cpp
+    fi
+    LD="$android_toolchain"/bin/"$android_tool_prefix"-ld
+    AR="$android_toolchain"/bin/"$android_tool_prefix"-ar
+    RANLIB="$android_toolchain"/bin/"$android_tool_prefix"-ranlib
+    STRIP="$android_toolchain"/bin/"$android_tool_prefix"-strip
+    OBJCOPY="$android_toolchain"/bin/"$android_tool_prefix"-objcopy
+
+    CPPFLAGS="-idirafter $android_platform/usr/include $CPPFLAGS"
+    CFLAGS="-mandroid -fno-short-enums -fno-exceptions $CFLAGS"
+    CXXFLAGS="-mandroid -fno-short-enums -fno-exceptions -Wno-psabi $CXXFLAGS"
+    ASFLAGS="-idirafter $android_platform/usr/include -DANDROID $ASFLAGS"
+
+    dnl Add -llog by default, since we use it all over the place.
+    dnl Add --allow-shlib-undefined, because libGLESv2 links to an
+    dnl undefined symbol (present on the hardware, just not in the
+    dnl NDK.)
+    LDFLAGS="-mandroid -L$android_platform/usr/lib -Wl,-rpath-link=$android_platform/usr/lib --sysroot=$android_platform -llog -Wl,--allow-shlib-undefined $LDFLAGS"
+    dnl prevent cross compile section from using these flags as host flags
+    if test -z "$HOST_CPPFLAGS" ; then
+        HOST_CPPFLAGS=" "
+    fi
+    if test -z "$HOST_CFLAGS" ; then
+        HOST_CFLAGS=" "
+    fi
+    if test -z "$HOST_CXXFLAGS" ; then
+        HOST_CXXFLAGS=" "
+    fi
+    if test -z "$HOST_LDFLAGS" ; then
+        HOST_LDFLAGS=" "
+    fi
+
+    ANDROID_NDK="${android_ndk}"
+    ANDROID_TOOLCHAIN="${android_toolchain}"
+    ANDROID_PLATFORM="${android_platform}"
+
+    AC_DEFINE(ANDROID)
+    AC_SUBST(ANDROID_NDK)
+    AC_SUBST(ANDROID_TOOLCHAIN)
+    AC_SUBST(ANDROID_PLATFORM)
+
+    ;;
+esac
+
+])
+
+AC_DEFUN([MOZ_ANDROID_CPU_ARCH],
+[
+
+if test "$OS_TARGET" = "Android" -a -z "$gonkdir"; then
+    case "${CPU_ARCH}-${MOZ_ARCH}" in
+    arm-armv7*)
+        ANDROID_CPU_ARCH=armeabi-v7a
+        ;;
+    arm-*)
+        ANDROID_CPU_ARCH=armeabi
+        ;;
+    x86-*)
+        ANDROID_CPU_ARCH=x86
+        ;;
+    mips-*) # When target_cpu is mipsel, CPU_ARCH is mips
+        ANDROID_CPU_ARCH=mips
+        ;;
+    esac
+
+    AC_SUBST(ANDROID_CPU_ARCH)
+fi
+])
+
+AC_DEFUN([MOZ_ANDROID_STLPORT],
+[
+
+if test "$OS_TARGET" = "Android" -a -z "$gonkdir"; then
+    cpu_arch_dir="$ANDROID_CPU_ARCH"
+    if test "$MOZ_THUMB2" = 1; then
+        cpu_arch_dir="$cpu_arch_dir/thumb"
+    fi
+
+    if test -z "$STLPORT_CPPFLAGS$STLPORT_LIBS"; then
+        case "$android_cxx_stl" in
+        libstdc++)
+            # android-ndk-r8b and later
+            ndk_base="$android_ndk/sources/cxx-stl/gnu-libstdc++/$android_gnu_compiler_version"
+            ndk_libs_include="$ndk_base/libs/$ANDROID_CPU_ARCH"
+            ndk_libs="$ndk_base/libs/$cpu_arch_dir"
+            ndk_include="$ndk_base/include"
+
+            if ! test -e "$ndk_libs/libgnustl_static.a"; then
+                AC_MSG_ERROR([Couldn't find path to gnu-libstdc++ in the android ndk])
+            fi
+
+            STLPORT_LIBS="-L$ndk_libs -lgnustl_static"
+            STLPORT_CPPFLAGS="-I$ndk_include -I$ndk_include/backward -I$ndk_libs_include/include"
+            ;;
+        libc++)
+            # android-ndk-r8b and later
+            ndk_base="$android_ndk/sources/cxx-stl"
+            cxx_base="$ndk_base/llvm-libc++"
+            cxx_libs="$cxx_base/libs/$cpu_arch_dir"
+            cxx_include="$cxx_base/libcxx/include"
+            cxxabi_base="$ndk_base/llvm-libc++abi"
+            cxxabi_include="$cxxabi_base/libcxxabi/include"
+
+            if ! test -e "$cxx_libs/libc++_static.a"; then
+                AC_MSG_ERROR([Couldn't find path to llvm-libc++ in the android ndk])
+            fi
+
+            STLPORT_LIBS="-L$cxx_libs -lc++_static"
+            # Add android/support/include/ for prototyping long double math
+            # functions, locale-specific C library functions, multibyte support,
+            # etc.
+            STLPORT_CPPFLAGS="-I$android_ndk/sources/android/support/include -I$cxx_include -I$cxxabi_include"
+            ;;
+        mozstlport)
+            # We don't need to set STLPORT_LIBS, because the build system will
+            # take care of linking in our home-built stlport where it is needed.
+            STLPORT_CPPFLAGS="-isystem $_topsrcdir/build/stlport/stlport -isystem $_topsrcdir/build/stlport/overrides -isystem $android_ndk/sources/cxx-stl/system/include"
+            ;;
+        *)
+            AC_MSG_ERROR([Bad value for --enable-android-cxx-stl])
+            ;;
+        esac
+    fi
+    CXXFLAGS="$CXXFLAGS $STLPORT_CPPFLAGS"
+fi
+MOZ_ANDROID_CXX_STL=$android_cxx_stl
+AC_SUBST([MOZ_ANDROID_CXX_STL])
+AC_SUBST([STLPORT_LIBS])
+
+])
+
+
+AC_DEFUN([concat],[$1$2$3$4])
+
+dnl Find a component of an AAR.
+dnl Arg 1: variable name to expose, like ANDROID_SUPPORT_V4_LIB.
+dnl Arg 2: path to component.
+dnl Arg 3: if non-empty, expect and require component.
+AC_DEFUN([MOZ_ANDROID_AAR_COMPONENT], [
+  ifelse([$3], ,
+  [
+    if test -e "$$1" ; then
+      AC_MSG_ERROR([Found unexpected exploded $1!])
+    fi
+  ],
+  [
+    AC_MSG_CHECKING([for $1])
+    $1="$2"
+    if ! test -e "$$1" ; then
+      AC_MSG_ERROR([Could not find required exploded $1!])
+    fi
+    AC_MSG_RESULT([$$1])
+    AC_SUBST($1)
+  ])
+])
+
+dnl Find an AAR and expose variables representing its exploded components.
+dnl AC_SUBSTs ANDROID_NAME_{AAR,AAR_RES,AAR_LIB,AAR_INTERNAL_LIB}.
+dnl Arg 1: name, like play-services-base
+dnl Arg 2: version, like 7.8.0
+dnl Arg 3: extras subdirectory, either android or google
+dnl Arg 4: package subdirectory, like com/google/android/gms
+dnl Arg 5: if non-empty, expect and require internal_impl JAR.
+dnl Arg 6: if non-empty, expect and require assets/ directory.
+AC_DEFUN([MOZ_ANDROID_AAR],[
+  define([local_aar_var_base], translit($1, [-a-z], [_A-Z]))
+  define([local_aar_var], concat(ANDROID_, local_aar_var_base, _AAR))
+  local_aar_var="$ANDROID_SDK_ROOT/extras/$3/m2repository/$4/$1/$2/$1-$2.aar"
+  AC_MSG_CHECKING([for $1 AAR])
+  if ! test -e "$local_aar_var" ; then
+    AC_MSG_ERROR([You must download the $1 AAR.  Run the Android SDK tool and install the Android and Google Support Repositories under Extras.  See https://developer.android.com/tools/extras/support-library.html for more info. (Looked for $local_aar_var)])
+  fi
+  AC_SUBST(local_aar_var)
+  AC_MSG_RESULT([$local_aar_var])
+
+  if ! $PYTHON -m mozbuild.action.explode_aar --destdir=$MOZ_BUILD_ROOT/dist/exploded-aar $local_aar_var ; then
+    AC_MSG_ERROR([Could not explode $local_aar_var!])
+  fi
+
+  define([root], $MOZ_BUILD_ROOT/dist/exploded-aar/$1-$2/)
+  MOZ_ANDROID_AAR_COMPONENT(concat(local_aar_var, _LIB), concat(root, $1-$2-classes.jar), REQUIRED)
+  MOZ_ANDROID_AAR_COMPONENT(concat(local_aar_var, _RES), concat(root, res), REQUIRED)
+  MOZ_ANDROID_AAR_COMPONENT(concat(local_aar_var, _INTERNAL_LIB), concat(root, libs/$1-$2-internal_impl-$2.jar), $5)
+  MOZ_ANDROID_AAR_COMPONENT(concat(local_aar_var, _ASSETS), concat(root, assets), $6)
+])
+
+AC_DEFUN([MOZ_ANDROID_GOOGLE_PLAY_SERVICES],
+[
+
+if test -n "$MOZ_NATIVE_DEVICES" ; then
+    AC_SUBST(MOZ_NATIVE_DEVICES)
+
+    MOZ_ANDROID_AAR(play-services-base, 8.1.0, google, com/google/android/gms)
+    MOZ_ANDROID_AAR(play-services-basement, 8.1.0, google, com/google/android/gms)
+    MOZ_ANDROID_AAR(play-services-cast, 8.1.0, google, com/google/android/gms)
+    MOZ_ANDROID_AAR(mediarouter-v7, 23.0.1, android, com/android/support, REQUIRED_INTERNAL_IMPL)
+fi
+
+])
+
+AC_DEFUN([MOZ_ANDROID_GOOGLE_CLOUD_MESSAGING],
+[
+
+if test -n "$MOZ_ANDROID_GCM" ; then
+    AC_SUBST(MOZ_ANDROID_GCM)
+
+    MOZ_ANDROID_AAR(play-services-base, 8.1.0, google, com/google/android/gms)
+    MOZ_ANDROID_AAR(play-services-basement, 8.1.0, google, com/google/android/gms)
+    MOZ_ANDROID_AAR(play-services-gcm, 8.1.0, google, com/google/android/gms)
+fi
+
+])
+
+AC_DEFUN([MOZ_ANDROID_INSTALL_TRACKING],
+[
+
+if test -n "$MOZ_INSTALL_TRACKING"; then
+    AC_SUBST(MOZ_INSTALL_TRACKING)
+    MOZ_ANDROID_AAR(play-services-ads, 8.1.0, google, com/google/android/gms)
+    MOZ_ANDROID_AAR(play-services-analytics, 8.1.0, google, com/google/android/gms)
+    MOZ_ANDROID_AAR(play-services-appindexing, 8.1.0, google, com/google/android/gms)
+    MOZ_ANDROID_AAR(play-services-basement, 8.1.0, google, com/google/android/gms)
+fi
+
+])
+
+dnl Configure an Android SDK.
+dnl Arg 1: target SDK version, like 22.
+dnl Arg 2: build tools version, like 22.0.1.
+AC_DEFUN([MOZ_ANDROID_SDK],
+[
+
+MOZ_ARG_WITH_STRING(android-sdk,
+[  --with-android-sdk=DIR
+                          location where the Android SDK can be found (like ~/.mozbuild/android-sdk-linux)],
+    android_sdk_root=$withval)
+
+android_sdk_root=${withval%/platforms/android-*}
+
+case "$target" in
+*-android*|*-linuxandroid*)
+    if test -z "$android_sdk_root" ; then
+        AC_MSG_ERROR([You must specify --with-android-sdk=/path/to/sdk when targeting Android.])
+    fi
+
+    # We were given an old-style
+    # --with-android-sdk=/path/to/sdk/platforms/android-*.  We could warn, but
+    # we'll get compliance by forcing the issue.
+    if test -e "$withval"/source.properties ; then
+        AC_MSG_ERROR([Including platforms/android-* in --with-android-sdk arguments is deprecated.  Use --with-android-sdk=$android_sdk_root.])
+    fi
+
+    android_target_sdk=$1
+    AC_MSG_CHECKING([for Android SDK platform version $android_target_sdk])
+    android_sdk=$android_sdk_root/platforms/android-$android_target_sdk
+    if ! test -e "$android_sdk/source.properties" ; then
+        AC_MSG_ERROR([You must download Android SDK platform version $android_target_sdk.  Try |mach bootstrap|.  (Looked for $android_sdk)])
+    fi
+    AC_MSG_RESULT([$android_sdk])
+
+    android_build_tools="$android_sdk_root"/build-tools/$2
+    AC_MSG_CHECKING([for Android build-tools version $2])
+    if test -d "$android_build_tools" -a -f "$android_build_tools/aapt"; then
+        AC_MSG_RESULT([$android_build_tools])
+    else
+        AC_MSG_ERROR([You must install the Android build-tools version $2.  Try |mach bootstrap|.  (Looked for $android_build_tools)])
+    fi
+
+    MOZ_PATH_PROG(ZIPALIGN, zipalign, :, [$android_build_tools])
+    MOZ_PATH_PROG(DX, dx, :, [$android_build_tools])
+    MOZ_PATH_PROG(AAPT, aapt, :, [$android_build_tools])
+    MOZ_PATH_PROG(AIDL, aidl, :, [$android_build_tools])
+    if test -z "$ZIPALIGN" -o "$ZIPALIGN" = ":"; then
+      AC_MSG_ERROR([The program zipalign was not found.  Try |mach bootstrap|.])
+    fi
+    if test -z "$DX" -o "$DX" = ":"; then
+      AC_MSG_ERROR([The program dx was not found.  Try |mach bootstrap|.])
+    fi
+    if test -z "$AAPT" -o "$AAPT" = ":"; then
+      AC_MSG_ERROR([The program aapt was not found.  Try |mach bootstrap|.])
+    fi
+    if test -z "$AIDL" -o "$AIDL" = ":"; then
+      AC_MSG_ERROR([The program aidl was not found.  Try |mach bootstrap|.])
+    fi
+
+    android_platform_tools="$android_sdk_root"/platform-tools
+    AC_MSG_CHECKING([for Android platform-tools])
+    if test -d "$android_platform_tools" -a -f "$android_platform_tools/adb"; then
+        AC_MSG_RESULT([$android_platform_tools])
+    else
+        AC_MSG_ERROR([You must install the Android platform-tools.  Try |mach bootstrap|.  (Looked for $android_platform_tools)])
+    fi
+
+    MOZ_PATH_PROG(ADB, adb, :, [$android_platform_tools])
+    if test -z "$ADB" -o "$ADB" = ":"; then
+      AC_MSG_ERROR([The program adb was not found.  Try |mach bootstrap|.])
+    fi
+
+    android_tools="$android_sdk_root"/tools
+    AC_MSG_CHECKING([for Android tools])
+    if test -d "$android_tools" -a -f "$android_tools/emulator"; then
+        AC_MSG_RESULT([$android_tools])
+    else
+        AC_MSG_ERROR([You must install the Android tools.  Try |mach bootstrap|.  (Looked for $android_tools)])
+    fi
+
+    MOZ_PATH_PROG(EMULATOR, emulator, :, [$android_tools])
+    if test -z "$EMULATOR" -o "$EMULATOR" = ":"; then
+      AC_MSG_ERROR([The program emulator was not found.  Try |mach bootstrap|.])
+    fi
+
+    ANDROID_TARGET_SDK="${android_target_sdk}"
+    ANDROID_SDK="${android_sdk}"
+    ANDROID_SDK_ROOT="${android_sdk_root}"
+    ANDROID_TOOLS="${android_tools}"
+    AC_DEFINE_UNQUOTED(ANDROID_TARGET_SDK,$ANDROID_TARGET_SDK)
+    AC_SUBST(ANDROID_TARGET_SDK)
+    AC_SUBST(ANDROID_SDK_ROOT)
+    AC_SUBST(ANDROID_SDK)
+    AC_SUBST(ANDROID_TOOLS)
+
+    MOZ_ANDROID_AAR(appcompat-v7, 23.0.1, android, com/android/support)
+    MOZ_ANDROID_AAR(design, 23.0.1, android, com/android/support)
+    MOZ_ANDROID_AAR(recyclerview-v7, 23.0.1, android, com/android/support)
+    MOZ_ANDROID_AAR(support-v4, 23.0.1, android, com/android/support, REQUIRED_INTERNAL_IMPL)
+
+    ANDROID_SUPPORT_ANNOTATIONS_JAR="$ANDROID_SDK_ROOT/extras/android/m2repository/com/android/support/support-annotations/23.0.1/support-annotations-23.0.1.jar"
+    AC_MSG_CHECKING([for support-annotations JAR])
+    if ! test -e $ANDROID_SUPPORT_ANNOTATIONS_JAR ; then
+        AC_MSG_ERROR([You must download the support-annotations lib.  Run the Android SDK tool and install the Android Support Repository under Extras.  See https://developer.android.com/tools/extras/support-library.html for more info. (looked for $ANDROID_SUPPORT_ANNOTATIONS_JAR)])
+    fi
+    AC_MSG_RESULT([$ANDROID_SUPPORT_ANNOTATIONS_JAR])
+    AC_SUBST(ANDROID_SUPPORT_ANNOTATIONS_JAR)
+    ANDROID_SUPPORT_ANNOTATIONS_JAR_LIB=$ANDROID_SUPPORT_ANNOTATIONS_JAR
+    AC_SUBST(ANDROID_SUPPORT_ANNOTATIONS_JAR_LIB)
+    ;;
+esac
+
+MOZ_ARG_WITH_STRING(android-min-sdk,
+[  --with-android-min-sdk=[VER]     Impose a minimum Firefox for Android SDK version],
+[ MOZ_ANDROID_MIN_SDK_VERSION=$withval ])
+
+MOZ_ARG_WITH_STRING(android-max-sdk,
+[  --with-android-max-sdk=[VER]     Impose a maximum Firefox for Android SDK version],
+[ MOZ_ANDROID_MAX_SDK_VERSION=$withval ])
+
+if test -n "$MOZ_ANDROID_MIN_SDK_VERSION"; then
+    if test -n "$MOZ_ANDROID_MAX_SDK_VERSION"; then
+        if test $MOZ_ANDROID_MAX_SDK_VERSION -lt $MOZ_ANDROID_MIN_SDK_VERSION ; then
+            AC_MSG_ERROR([--with-android-max-sdk must be at least the value of --with-android-min-sdk.])
+        fi
+    fi
+
+    if test $MOZ_ANDROID_MIN_SDK_VERSION -gt $ANDROID_TARGET_SDK ; then
+        AC_MSG_ERROR([--with-android-min-sdk is expected to be less than $ANDROID_TARGET_SDK])
+    fi
+
+    AC_DEFINE_UNQUOTED(MOZ_ANDROID_MIN_SDK_VERSION, $MOZ_ANDROID_MIN_SDK_VERSION)
+    AC_SUBST(MOZ_ANDROID_MIN_SDK_VERSION)
+fi
+
+if test -n "$MOZ_ANDROID_MAX_SDK_VERSION"; then
+    AC_DEFINE_UNQUOTED(MOZ_ANDROID_MAX_SDK_VERSION, $MOZ_ANDROID_MAX_SDK_VERSION)
+    AC_SUBST(MOZ_ANDROID_MAX_SDK_VERSION)
+fi
+
+])
diff --git a/src/third_party/mozjs-45/build/autoconf/arch.m4 b/src/third_party/mozjs-45/build/autoconf/arch.m4
new file mode 100644
index 0000000..b62ea71
--- /dev/null
+++ b/src/third_party/mozjs-45/build/autoconf/arch.m4
@@ -0,0 +1,260 @@
+dnl This Source Code Form is subject to the terms of the Mozilla Public
+dnl License, v. 2.0. If a copy of the MPL was not distributed with this
+dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+AC_DEFUN([MOZ_ARCH_OPTS],
+[
+
+dnl ========================================================
+dnl = ARM toolchain tweaks
+dnl ========================================================
+
+MOZ_THUMB=toolchain-default
+MOZ_THUMB_INTERWORK=toolchain-default
+MOZ_FPU=toolchain-default
+MOZ_FLOAT_ABI=toolchain-default
+MOZ_SOFT_FLOAT=toolchain-default
+MOZ_ALIGN=toolchain-default
+
+MOZ_ARG_WITH_STRING(arch,
+[  --with-arch=[[type|toolchain-default]]
+                           Use specific CPU features (-march=type). Resets
+                           thumb, fpu, float-abi, etc. defaults when set],
+    if test -z "$GNU_CC"; then
+        AC_MSG_ERROR([--with-arch is not supported on non-GNU toolchains])
+    fi
+    MOZ_ARCH=$withval)
+
+if test -z "$MOZ_ARCH"; then
+    dnl Defaults
+    case "${CPU_ARCH}-${OS_TARGET}" in
+    arm-Android)
+        MOZ_THUMB=yes
+        MOZ_ARCH=armv7-a
+        MOZ_FPU=vfp
+        MOZ_FLOAT_ABI=softfp
+        MOZ_ALIGN=no
+        ;;
+    arm-Darwin)
+        MOZ_ARCH=toolchain-default
+        ;;
+    esac
+fi
+
+if test "$MOZ_ARCH" = "armv6" -a "$OS_TARGET" = "Android"; then
+   MOZ_FPU=vfp
+fi
+
+MOZ_ARG_WITH_STRING(thumb,
+[  --with-thumb[[=yes|no|toolchain-default]]]
+[                          Use Thumb instruction set (-mthumb)],
+    if test -z "$GNU_CC"; then
+        AC_MSG_ERROR([--with-thumb is not supported on non-GNU toolchains])
+    fi
+    MOZ_THUMB=$withval)
+
+MOZ_ARG_WITH_STRING(thumb-interwork,
+[  --with-thumb-interwork[[=yes|no|toolchain-default]]
+                           Use Thumb/ARM instuctions interwork (-mthumb-interwork)],
+    if test -z "$GNU_CC"; then
+        AC_MSG_ERROR([--with-thumb-interwork is not supported on non-GNU toolchains])
+    fi
+    MOZ_THUMB_INTERWORK=$withval)
+
+MOZ_ARG_WITH_STRING(fpu,
+[  --with-fpu=[[type|toolchain-default]]
+                           Use specific FPU type (-mfpu=type)],
+    if test -z "$GNU_CC"; then
+        AC_MSG_ERROR([--with-fpu is not supported on non-GNU toolchains])
+    fi
+    MOZ_FPU=$withval)
+
+MOZ_ARG_WITH_STRING(float-abi,
+[  --with-float-abi=[[type|toolchain-default]]
+                           Use specific arm float ABI (-mfloat-abi=type)],
+    if test -z "$GNU_CC"; then
+        AC_MSG_ERROR([--with-float-abi is not supported on non-GNU toolchains])
+    fi
+    MOZ_FLOAT_ABI=$withval)
+
+MOZ_ARG_WITH_STRING(soft-float,
+[  --with-soft-float[[=yes|no|toolchain-default]]
+                           Use soft float library (-msoft-float)],
+    if test -z "$GNU_CC"; then
+        AC_MSG_ERROR([--with-soft-float is not supported on non-GNU toolchains])
+    fi
+    MOZ_SOFT_FLOAT=$withval)
+
+case "$MOZ_ARCH" in
+toolchain-default|"")
+    arch_flag=""
+    ;;
+*)
+    arch_flag="-march=$MOZ_ARCH"
+    ;;
+esac
+
+case "$MOZ_THUMB" in
+yes)
+    MOZ_THUMB2=1
+    thumb_flag="-mthumb"
+    ;;
+no)
+    MOZ_THUMB2=
+    thumb_flag="-marm"
+    ;;
+*)
+    _SAVE_CFLAGS="$CFLAGS"
+    CFLAGS="$arch_flag"
+    AC_TRY_COMPILE([],[return sizeof(__thumb2__);],
+        MOZ_THUMB2=1,
+        MOZ_THUMB2=)
+    CFLAGS="$_SAVE_CFLAGS"
+    thumb_flag=""
+    ;;
+esac
+
+if test "$MOZ_THUMB2" = 1; then
+    AC_DEFINE(MOZ_THUMB2)
+fi
+
+case "$MOZ_THUMB_INTERWORK" in
+yes)
+    thumb_interwork_flag="-mthumb-interwork"
+    ;;
+no)
+    thumb_interwork_flag="-mno-thumb-interwork"
+    ;;
+*) # toolchain-default
+    thumb_interwork_flag=""
+    ;;
+esac
+
+case "$MOZ_FPU" in
+toolchain-default|"")
+    fpu_flag=""
+    ;;
+*)
+    fpu_flag="-mfpu=$MOZ_FPU"
+    ;;
+esac
+
+case "$MOZ_FLOAT_ABI" in
+toolchain-default|"")
+    float_abi_flag=""
+    ;;
+*)
+    float_abi_flag="-mfloat-abi=$MOZ_FLOAT_ABI"
+    ;;
+esac
+
+case "$MOZ_SOFT_FLOAT" in
+yes)
+    soft_float_flag="-msoft-float"
+    ;;
+no)
+    soft_float_flag="-mno-soft-float"
+    ;;
+*) # toolchain-default
+    soft_float_flag=""
+    ;;
+esac
+
+case "$MOZ_ALIGN" in
+no)
+    align_flag="-mno-unaligned-access"
+    ;;
+yes)
+    align_flag="-munaligned-access"
+    ;;
+*)
+    align_flag=""
+    ;;
+esac
+
+if test -n "$align_flag"; then
+  _SAVE_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS $align_flag"
+  AC_MSG_CHECKING(whether alignment flag ($align_flag) is supported)
+  AC_TRY_COMPILE([],[],,align_flag="")
+  CFLAGS="$_SAVE_CFLAGS"
+fi
+
+dnl Use echo to avoid accumulating space characters
+all_flags=`echo $arch_flag $thumb_flag $thumb_interwork_flag $fpu_flag $float_abi_flag $soft_float_flag $align_flag`
+if test -n "$all_flags"; then
+    _SAVE_CFLAGS="$CFLAGS"
+    CFLAGS="$all_flags"
+    AC_MSG_CHECKING(whether the chosen combination of compiler flags ($all_flags) works)
+    AC_TRY_COMPILE([],[return 0;],
+        AC_MSG_RESULT([yes]),
+        AC_MSG_ERROR([no]))
+
+    CFLAGS="$_SAVE_CFLAGS $all_flags"
+    CXXFLAGS="$CXXFLAGS $all_flags"
+    ASFLAGS="$ASFLAGS $all_flags"
+    if test -n "$thumb_flag"; then
+        LDFLAGS="$LDFLAGS $thumb_flag"
+    fi
+fi
+
+AC_SUBST(MOZ_THUMB2)
+
+if test "$CPU_ARCH" = "arm"; then
+  AC_MSG_CHECKING(for ARM SIMD support in compiler)
+  # We try to link so that this also fails when
+  # building with LTO.
+  AC_TRY_LINK([],
+                 [asm("uqadd8 r1, r1, r2");],
+                 result="yes", result="no")
+  AC_MSG_RESULT("$result")
+  if test "$result" = "yes"; then
+      AC_DEFINE(HAVE_ARM_SIMD)
+      HAVE_ARM_SIMD=1
+  fi
+
+  AC_MSG_CHECKING(ARM version support in compiler)
+  dnl Determine the target ARM architecture (5 for ARMv5, v5T, v5E, etc.; 6 for ARMv6, v6K, etc.)
+  ARM_ARCH=`${CC-cc} ${CFLAGS} -dM -E - < /dev/null | sed -n 's/.*__ARM_ARCH_\([[0-9]][[0-9]]*\).*/\1/p'`
+  AC_MSG_RESULT("$ARM_ARCH")
+
+  AC_MSG_CHECKING(for ARM NEON support in compiler)
+  # We try to link so that this also fails when
+  # building with LTO.
+  AC_TRY_LINK([],
+                 [asm(".fpu neon\n vadd.i8 d0, d0, d0");],
+                 result="yes", result="no")
+  AC_MSG_RESULT("$result")
+  if test "$result" = "yes"; then
+      AC_DEFINE(HAVE_ARM_NEON)
+      HAVE_ARM_NEON=1
+
+      dnl We don't need to build NEON support if we're targetting a non-NEON device.
+      dnl This matches media/webrtc/trunk/webrtc/build/common.gypi.
+      if test -n "$ARM_ARCH"; then
+          if test "$ARM_ARCH" -lt 7; then
+              BUILD_ARM_NEON=
+          else
+              AC_DEFINE(BUILD_ARM_NEON)
+              BUILD_ARM_NEON=1
+          fi
+      fi
+  fi
+
+fi # CPU_ARCH = arm
+
+AC_SUBST(HAVE_ARM_SIMD)
+AC_SUBST(HAVE_ARM_NEON)
+AC_SUBST(BUILD_ARM_NEON)
+AC_SUBST(ARM_ARCH)
+
+if test -n "$MOZ_ARCH"; then
+  NSPR_CONFIGURE_ARGS="$NSPR_CONFIGURE_ARGS --with-arch=$MOZ_ARCH"
+  NSPR_CONFIGURE_ARGS="$NSPR_CONFIGURE_ARGS --with-thumb=$MOZ_THUMB"
+  NSPR_CONFIGURE_ARGS="$NSPR_CONFIGURE_ARGS --with-thumb-interwork=$MOZ_THUMB_INTERWORK"
+  NSPR_CONFIGURE_ARGS="$NSPR_CONFIGURE_ARGS --with-fpu=$MOZ_FPU"
+  NSPR_CONFIGURE_ARGS="$NSPR_CONFIGURE_ARGS --with-float-abi=$MOZ_FLOAT_ABI"
+  NSPR_CONFIGURE_ARGS="$NSPR_CONFIGURE_ARGS --with-soft-float=$MOZ_SOFT_FLOAT"
+fi
+
+])
diff --git a/src/third_party/mozjs-45/build/autoconf/clang-plugin.m4 b/src/third_party/mozjs-45/build/autoconf/clang-plugin.m4
new file mode 100644
index 0000000..5618a1c
--- /dev/null
+++ b/src/third_party/mozjs-45/build/autoconf/clang-plugin.m4
@@ -0,0 +1,60 @@
+dnl This Source Code Form is subject to the terms of the Mozilla Public
+dnl License, v. 2.0. If a copy of the MPL was not distributed with this
+dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+AC_DEFUN([MOZ_CONFIG_CLANG_PLUGIN], [
+
+MOZ_ARG_ENABLE_BOOL(clang-plugin,
+[  --enable-clang-plugin   Enable building with the mozilla clang plugin ],
+   ENABLE_CLANG_PLUGIN=1,
+   ENABLE_CLANG_PLUGIN= )
+if test -n "$ENABLE_CLANG_PLUGIN"; then
+    if test -z "$CLANG_CC"; then
+        AC_MSG_ERROR([Can't use clang plugin without clang.])
+    fi
+
+    AC_MSG_CHECKING([for llvm-config])
+    if test -z "$LLVMCONFIG"; then
+      LLVMCONFIG=`$CXX -print-prog-name=llvm-config`
+    fi
+
+    if test -z "$LLVMCONFIG"; then
+      LLVMCONFIG=`which llvm-config`
+    fi
+
+    if test ! -x "$LLVMCONFIG"; then
+      AC_MSG_RESULT([not found])
+      AC_MSG_ERROR([Cannot find an llvm-config binary for building a clang plugin])
+    fi
+
+    AC_MSG_RESULT([$LLVMCONFIG])
+
+    if test -z "$LLVMCONFIG"; then
+        AC_MSG_ERROR([Cannot find an llvm-config binary for building a clang plugin])
+    fi
+    LLVM_CXXFLAGS=`$LLVMCONFIG --cxxflags`
+    dnl The clang package we use on OSX is old, and its llvm-config doesn't
+    dnl recognize --system-libs, so ask for that separately.  llvm-config's
+    dnl failure here is benign, so we can ignore it if it happens.
+    LLVM_LDFLAGS=`$LLVMCONFIG --system-libs | xargs`
+    LLVM_LDFLAGS="$LLVM_LDFLAGS `$LLVMCONFIG --ldflags --libs core mc analysis asmparser mcparser bitreader option | xargs`"
+
+    if test "${HOST_OS_ARCH}" = "Darwin"; then
+        CLANG_LDFLAGS="-lclangFrontend -lclangDriver -lclangSerialization"
+        CLANG_LDFLAGS="$CLANG_LDFLAGS -lclangParse -lclangSema -lclangAnalysis"
+        CLANG_LDFLAGS="$CLANG_LDFLAGS -lclangEdit -lclangAST -lclangLex"
+        CLANG_LDFLAGS="$CLANG_LDFLAGS -lclangBasic -lclangASTMatchers"
+    else
+        CLANG_LDFLAGS="-lclangASTMatchers"
+    fi
+
+    AC_DEFINE(MOZ_CLANG_PLUGIN)
+fi
+
+AC_SUBST(LLVM_CXXFLAGS)
+AC_SUBST(LLVM_LDFLAGS)
+AC_SUBST(CLANG_LDFLAGS)
+
+AC_SUBST(ENABLE_CLANG_PLUGIN)
+
+])
diff --git a/src/third_party/mozjs-45/build/autoconf/clean-config.sh b/src/third_party/mozjs-45/build/autoconf/clean-config.sh
new file mode 100755
index 0000000..2505547
--- /dev/null
+++ b/src/third_party/mozjs-45/build/autoconf/clean-config.sh
@@ -0,0 +1,31 @@
+#!/bin/sh
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# clean-config.sh - Removes all files generated by mozilla configure.
+#    Only removes files from the topsrcdir. To clean up an objdir,
+#    simply remove the directory and start over.
+#
+# Usage:
+#    1. cd <topsrcdir>
+#    2. build/autoconf/clean-config.sh
+#
+# Send comments, improvements, bugs to slamm@netscape.com
+
+topsrcdir=`cd \`dirname $0\`/../..; pwd`
+
+if [ ! -f configure.in ]; then
+  echo "clean-config.sh only cleans the source tree. To run," 2>&1
+  echo "  cd $topsrcdir; build/autoconf/clean-config.sh" 2>&1
+  echo "  (To clean a separate objdir, simple remove the directory.)" 2>&1
+  exit 1
+fi
+
+rm -fr \
+    config-defs.h \
+    config.cache \
+    config.log \
+    config.status \
+    $NULL
diff --git a/src/third_party/mozjs-45/build/autoconf/codeset.m4 b/src/third_party/mozjs-45/build/autoconf/codeset.m4
new file mode 100644
index 0000000..4dc1d50
--- /dev/null
+++ b/src/third_party/mozjs-45/build/autoconf/codeset.m4
@@ -0,0 +1,24 @@
+# codeset.m4 serial AM1 (gettext-0.10.40)
+dnl Copyright (C) 2000-2002 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License.  As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+
+dnl From Bruno Haible.
+
+AC_DEFUN([AM_LANGINFO_CODESET],
+[
+  AC_CACHE_CHECK([for nl_langinfo and CODESET], am_cv_langinfo_codeset,
+    [AC_TRY_LINK([#include <langinfo.h>],
+      [char* cs = nl_langinfo(CODESET);],
+      am_cv_langinfo_codeset=yes,
+      am_cv_langinfo_codeset=no)
+    ])
+  if test $am_cv_langinfo_codeset = yes; then
+    AC_DEFINE(HAVE_LANGINFO_CODESET, 1,
+      [Define if you have <langinfo.h> and nl_langinfo(CODESET).])
+      HAVE_LANGINFO_CODESET=1
+  fi
+])
diff --git a/src/third_party/mozjs-45/build/autoconf/compiler-opts.m4 b/src/third_party/mozjs-45/build/autoconf/compiler-opts.m4
new file mode 100644
index 0000000..56d6af4
--- /dev/null
+++ b/src/third_party/mozjs-45/build/autoconf/compiler-opts.m4
@@ -0,0 +1,425 @@
+dnl This Source Code Form is subject to the terms of the Mozilla Public
+dnl License, v. 2.0. If a copy of the MPL was not distributed with this
+dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+dnl Add compiler specific options
+
+AC_DEFUN([MOZ_DEFAULT_COMPILER],
+[
+dnl set DEVELOPER_OPTIONS early; MOZ_DEFAULT_COMPILER is usually the first non-setup directive
+  if test -z "$MOZILLA_OFFICIAL"; then
+    DEVELOPER_OPTIONS=1
+  fi
+  MOZ_ARG_ENABLE_BOOL(release,
+  [  --enable-release        Build with more conservative, release engineering-oriented options.
+                          This may slow down builds.],
+      DEVELOPER_OPTIONS=,
+      DEVELOPER_OPTIONS=1)
+
+  AC_SUBST(DEVELOPER_OPTIONS)
+
+dnl Default to MSVC for win32 and gcc-4.2 for darwin
+dnl ==============================================================
+if test -z "$CROSS_COMPILE"; then
+case "$target" in
+*-mingw*)
+    if test -z "$CC"; then CC=cl; fi
+    if test -z "$CXX"; then CXX=cl; fi
+    if test -z "$CPP"; then CPP="$CC -E -nologo"; fi
+    if test -z "$CXXCPP"; then CXXCPP="$CXX -TP -E -nologo"; ac_cv_prog_CXXCPP="$CXXCPP"; fi
+    if test -z "$LD"; then LD=link; fi
+    if test -z "$AS"; then
+        case "${target_cpu}" in
+        i*86)
+            AS=ml;
+            ;;
+        x86_64)
+            AS=ml64;
+            ;;
+        esac
+    fi
+    if test -z "$MIDL"; then MIDL=midl; fi
+
+    # need override this flag since we don't use $(LDFLAGS) for this.
+    if test -z "$HOST_LDFLAGS" ; then
+        HOST_LDFLAGS=" "
+    fi
+    ;;
+*-darwin*)
+    # GCC on darwin is based on gcc 4.2 and we don't support it anymore.
+    if test -z "$CC"; then
+        MOZ_PATH_PROGS(CC, clang)
+    fi
+    if test -z "$CXX"; then
+        MOZ_PATH_PROGS(CXX, clang++)
+    fi
+    IS_GCC=$($CC -v 2>&1 | grep gcc)
+    if test -n "$IS_GCC"
+    then
+      echo gcc is known to be broken on OS X, please use clang.
+      echo see http://developer.mozilla.org/en-US/docs/Developer_Guide/Build_Instructions/Mac_OS_X_Prerequisites
+      echo for more information.
+      exit 1
+    fi
+    ;;
+esac
+fi
+])
+
+dnl ============================================================================
+dnl C++ rtti
+dnl We don't use it in the code, but it can be usefull for debugging, so give
+dnl the user the option of enabling it.
+dnl ============================================================================
+AC_DEFUN([MOZ_RTTI],
+[
+MOZ_ARG_ENABLE_BOOL(cpp-rtti,
+[  --enable-cpp-rtti       Enable C++ RTTI ],
+[ _MOZ_USE_RTTI=1 ],
+[ _MOZ_USE_RTTI= ])
+
+if test -z "$_MOZ_USE_RTTI"; then
+    if test "$GNU_CC"; then
+        CXXFLAGS="$CXXFLAGS -fno-rtti"
+    else
+        case "$target" in
+        *-mingw*)
+            CXXFLAGS="$CXXFLAGS -GR-"
+        esac
+    fi
+fi
+])
+
+dnl ========================================================
+dnl =
+dnl = Debugging Options
+dnl =
+dnl ========================================================
+AC_DEFUN([MOZ_DEBUGGING_OPTS],
+[
+dnl Debug info is ON by default.
+if test -z "$MOZ_DEBUG_FLAGS"; then
+  if test -n "$_MSC_VER"; then
+    MOZ_DEBUG_FLAGS="-Zi"
+  else
+    MOZ_DEBUG_FLAGS="-g"
+  fi
+fi
+
+AC_SUBST(MOZ_DEBUG_FLAGS)
+
+MOZ_ARG_ENABLE_STRING(debug,
+[  --enable-debug[=DBG]    Enable building with developer debug info
+                           (using compiler flags DBG)],
+[ if test "$enableval" != "no"; then
+    MOZ_DEBUG=1
+    if test -n "$enableval" -a "$enableval" != "yes"; then
+        MOZ_DEBUG_FLAGS=`echo $enableval | sed -e 's|\\\ | |g'`
+        _MOZ_DEBUG_FLAGS_SET=1
+    fi
+  else
+    MOZ_DEBUG=
+  fi ],
+  MOZ_DEBUG=)
+
+if test -z "$MOZ_DEBUG" -o -n "$MOZ_ASAN"; then
+    MOZ_NO_DEBUG_RTL=1
+fi
+
+AC_SUBST(MOZ_NO_DEBUG_RTL)
+
+MOZ_DEBUG_ENABLE_DEFS="-DDEBUG -DTRACING"
+MOZ_ARG_WITH_STRING(debug-label,
+[  --with-debug-label=LABELS
+                          Define DEBUG_<value> for each comma-separated
+                          value given.],
+[ for option in `echo $withval | sed 's/,/ /g'`; do
+    MOZ_DEBUG_ENABLE_DEFS="$MOZ_DEBUG_ENABLE_DEFS -DDEBUG_${option}"
+done])
+
+if test -n "$MOZ_DEBUG"; then
+    AC_MSG_CHECKING([for valid debug flags])
+    _SAVE_CFLAGS=$CFLAGS
+    CFLAGS="$CFLAGS $MOZ_DEBUG_FLAGS"
+    AC_TRY_COMPILE([#include <stdio.h>],
+        [printf("Hello World\n");],
+        _results=yes,
+        _results=no)
+    AC_MSG_RESULT([$_results])
+    if test "$_results" = "no"; then
+        AC_MSG_ERROR([These compiler flags are invalid: $MOZ_DEBUG_FLAGS])
+    fi
+    CFLAGS=$_SAVE_CFLAGS
+
+    MOZ_DEBUG_DEFINES="$MOZ_DEBUG_ENABLE_DEFS"
+else
+    MOZ_DEBUG_DEFINES="-DNDEBUG -DTRIMMED"
+fi
+
+AC_SUBST(MOZ_DEBUG_DEFINES)
+
+dnl ========================================================
+dnl = Enable generation of debug symbols
+dnl ========================================================
+MOZ_ARG_ENABLE_STRING(debug-symbols,
+[  --enable-debug-symbols[=DBG]
+                          Enable debugging symbols (using compiler flags DBG)],
+[ if test "$enableval" != "no"; then
+      MOZ_DEBUG_SYMBOLS=1
+      if test -n "$enableval" -a "$enableval" != "yes"; then
+          if test -z "$_MOZ_DEBUG_FLAGS_SET"; then
+              MOZ_DEBUG_FLAGS=`echo $enableval | sed -e 's|\\\ | |g'`
+          else
+              AC_MSG_ERROR([--enable-debug-symbols flags cannot be used with --enable-debug flags])
+          fi
+      fi
+  else
+      MOZ_DEBUG_SYMBOLS=
+  fi ],
+  MOZ_DEBUG_SYMBOLS=1)
+
+if test -n "$MOZ_DEBUG" -o -n "$MOZ_DEBUG_SYMBOLS"; then
+    AC_DEFINE(MOZ_DEBUG_SYMBOLS)
+    export MOZ_DEBUG_SYMBOLS
+fi
+
+])
+
+dnl A high level macro for selecting compiler options.
+AC_DEFUN([MOZ_COMPILER_OPTS],
+[
+  MOZ_DEBUGGING_OPTS
+  MOZ_RTTI
+if test "$CLANG_CXX"; then
+    ## We disable return-type-c-linkage because jsval is defined as a C++ type but is
+    ## returned by C functions. This is possible because we use knowledge about the ABI
+    ## to typedef it to a C type with the same layout when the headers are included
+    ## from C.
+    _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wno-unknown-warning-option -Wno-return-type-c-linkage"
+fi
+
+AC_MSG_CHECKING([whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) actually is a C++ compiler])
+AC_LANG_SAVE
+AC_LANG_CPLUSPLUS
+_SAVE_LIBS=$LIBS
+LIBS=
+AC_TRY_LINK([#include <new>], [int *foo = new int;],,
+            AC_MSG_RESULT([no])
+            AC_MSG_ERROR([$CXX $CXXFLAGS $LDFLAGS failed to compile and link a simple C++ source.]))
+LIBS=$_SAVE_LIBS
+AC_LANG_RESTORE
+AC_MSG_RESULT([yes])
+
+if test -n "$DEVELOPER_OPTIONS"; then
+    MOZ_FORCE_GOLD=1
+fi
+
+MOZ_ARG_ENABLE_BOOL(gold,
+[  --enable-gold           Enable GNU Gold Linker when it is not already the default],
+    MOZ_FORCE_GOLD=1,
+    MOZ_FORCE_GOLD=
+    )
+
+if test "$GNU_CC" -a -n "$MOZ_FORCE_GOLD"; then
+    dnl if the default linker is BFD ld, check if gold is available and try to use it
+    dnl for local builds only.
+    if $CC -Wl,--version 2>&1 | grep -q "GNU ld"; then
+        GOLD=$($CC -print-prog-name=ld.gold)
+        case "$GOLD" in
+        /*)
+            ;;
+        *)
+            GOLD=$(which $GOLD)
+            ;;
+        esac
+        if test -n "$GOLD"; then
+            mkdir -p $_objdir/build/unix/gold
+            rm -f $_objdir/build/unix/gold/ld
+            ln -s "$GOLD" $_objdir/build/unix/gold/ld
+            if $CC -B $_objdir/build/unix/gold -Wl,--version 2>&1 | grep -q "GNU gold"; then
+                LDFLAGS="$LDFLAGS -B $_objdir/build/unix/gold"
+            else
+                rm -rf $_objdir/build/unix/gold
+            fi
+        fi
+    fi
+fi
+if test "$GNU_CC"; then
+    if $CC $LDFLAGS -Wl,--version 2>&1 | grep -q "GNU ld"; then
+        LD_IS_BFD=1
+    fi
+fi
+
+AC_SUBST([LD_IS_BFD])
+
+if test "$GNU_CC"; then
+    if test -z "$DEVELOPER_OPTIONS"; then
+        CFLAGS="$CFLAGS -ffunction-sections -fdata-sections"
+        CXXFLAGS="$CXXFLAGS -ffunction-sections -fdata-sections"
+    fi
+    CFLAGS="$CFLAGS -fno-math-errno"
+    CXXFLAGS="$CXXFLAGS -fno-exceptions -fno-math-errno"
+fi
+
+dnl ========================================================
+dnl = Identical Code Folding
+dnl ========================================================
+
+MOZ_ARG_DISABLE_BOOL(icf,
+[  --disable-icf          Disable Identical Code Folding],
+    MOZ_DISABLE_ICF=1,
+    MOZ_DISABLE_ICF= )
+
+if test "$GNU_CC" -a "$GCC_USE_GNU_LD" -a -z "$MOZ_DISABLE_ICF" -a -z "$DEVELOPER_OPTIONS"; then
+    AC_CACHE_CHECK([whether the linker supports Identical Code Folding],
+        LD_SUPPORTS_ICF,
+        [echo 'int foo() {return 42;}' \
+              'int bar() {return 42;}' \
+              'int main() {return foo() - bar();}' > conftest.${ac_ext}
+        # If the linker supports ICF, foo and bar symbols will have
+        # the same address
+        if AC_TRY_COMMAND([${CC-cc} -o conftest${ac_exeext} $LDFLAGS -Wl,--icf=safe -ffunction-sections conftest.${ac_ext} $LIBS 1>&2]) &&
+           test -s conftest${ac_exeext} &&
+           objdump -t conftest${ac_exeext} | awk changequote(<<, >>)'{a[<<$>>6] = <<$>>1} END {if (a["foo"] && (a["foo"] != a["bar"])) { exit 1 }}'changequote([, ]); then
+            LD_SUPPORTS_ICF=yes
+        else
+            LD_SUPPORTS_ICF=no
+        fi
+        rm -rf conftest*])
+    if test "$LD_SUPPORTS_ICF" = yes; then
+        _SAVE_LDFLAGS="$LDFLAGS -Wl,--icf=safe"
+        LDFLAGS="$LDFLAGS -Wl,--icf=safe -Wl,--print-icf-sections"
+        AC_TRY_LINK([], [],
+                    [LD_PRINT_ICF_SECTIONS=-Wl,--print-icf-sections],
+                    [LD_PRINT_ICF_SECTIONS=])
+        AC_SUBST([LD_PRINT_ICF_SECTIONS])
+        LDFLAGS="$_SAVE_LDFLAGS"
+    fi
+fi
+
+dnl ========================================================
+dnl = Automatically remove dead symbols
+dnl ========================================================
+
+if test "$GNU_CC" -a "$GCC_USE_GNU_LD" -a -z "$DEVELOPER_OPTIONS"; then
+    if test -n "$MOZ_DEBUG_FLAGS"; then
+        dnl See bug 670659
+        AC_CACHE_CHECK([whether removing dead symbols breaks debugging],
+            GC_SECTIONS_BREAKS_DEBUG_RANGES,
+            [echo 'int foo() {return 42;}' \
+                  'int bar() {return 1;}' \
+                  'int main() {return foo();}' > conftest.${ac_ext}
+            if AC_TRY_COMMAND([${CC-cc} -o conftest.${ac_objext} $CFLAGS $MOZ_DEBUG_FLAGS -c conftest.${ac_ext} 1>&2]) &&
+                AC_TRY_COMMAND([${CC-cc} -o conftest${ac_exeext} $LDFLAGS $MOZ_DEBUG_FLAGS -Wl,--gc-sections conftest.${ac_objext} $LIBS 1>&2]) &&
+                test -s conftest${ac_exeext} -a -s conftest.${ac_objext}; then
+                 if test "`$PYTHON -m mozbuild.configure.check_debug_ranges conftest.${ac_objext} conftest.${ac_ext}`" = \
+                         "`$PYTHON -m mozbuild.configure.check_debug_ranges conftest${ac_exeext} conftest.${ac_ext}`"; then
+                     GC_SECTIONS_BREAKS_DEBUG_RANGES=no
+                 else
+                     GC_SECTIONS_BREAKS_DEBUG_RANGES=yes
+                 fi
+             else
+                  dnl We really don't expect to get here, but just in case
+                  GC_SECTIONS_BREAKS_DEBUG_RANGES="no, but it's broken in some other way"
+             fi
+             rm -rf conftest*])
+         if test "$GC_SECTIONS_BREAKS_DEBUG_RANGES" = no; then
+             DSO_LDOPTS="$DSO_LDOPTS -Wl,--gc-sections"
+         fi
+    else
+        DSO_LDOPTS="$DSO_LDOPTS -Wl,--gc-sections"
+    fi
+fi
+
+# bionic in Android < 4.1 doesn't support PIE
+# On OSX, the linker defaults to building PIE programs when targetting OSX 10.7+,
+# but not when targetting OSX < 10.7. OSX < 10.7 doesn't support running PIE
+# programs, so as long as support for OSX 10.6 is kept, we can't build PIE.
+# Even after dropping 10.6 support, MOZ_PIE would not be useful since it's the
+# default (and clang says the -pie option is not used).
+# On other Unix systems, some file managers (Nautilus) can't start PIE programs
+if test -n "$gonkdir" && test "$ANDROID_VERSION" -ge 16; then
+    MOZ_PIE=1
+else
+    MOZ_PIE=
+fi
+
+MOZ_ARG_ENABLE_BOOL(pie,
+[  --enable-pie           Enable Position Independent Executables],
+    MOZ_PIE=1,
+    MOZ_PIE= )
+
+if test "$GNU_CC" -a -n "$MOZ_PIE"; then
+    AC_MSG_CHECKING([for PIE support])
+    _SAVE_LDFLAGS=$LDFLAGS
+    LDFLAGS="$LDFLAGS -pie"
+    AC_TRY_LINK(,,AC_MSG_RESULT([yes])
+                  [MOZ_PROGRAM_LDFLAGS="$MOZ_PROGRAM_LDFLAGS -pie"],
+                  AC_MSG_RESULT([no])
+                  AC_MSG_ERROR([--enable-pie requires PIE support from the linker.]))
+    LDFLAGS=$_SAVE_LDFLAGS
+fi
+
+AC_SUBST(MOZ_PROGRAM_LDFLAGS)
+
+dnl ASan assumes no symbols are being interposed, and when that happens,
+dnl it's not happy with it. Unconveniently, since Firefox is exporting
+dnl libffi symbols and Gtk+3 pulls system libffi via libwayland-client,
+dnl system libffi interposes libffi symbols that ASan assumes are in
+dnl libxul, so it barfs about buffer overflows.
+dnl Using -Wl,-Bsymbolic ensures no exported symbol can be interposed.
+if test -n "$GCC_USE_GNU_LD"; then
+  case "$LDFLAGS" in
+  *-fsanitize=address*)
+    LDFLAGS="$LDFLAGS -Wl,-Bsymbolic"
+    ;;
+  esac
+fi
+
+])
+
+dnl GCC and clang will fail if given an unknown warning option like -Wfoobar. 
+dnl But later versions won't fail if given an unknown negated warning option
+dnl like -Wno-foobar.  So when we are check for support of negated warning 
+dnl options, we actually test the positive form, but add the negated form to 
+dnl the flags variable.
+
+AC_DEFUN([MOZ_C_SUPPORTS_WARNING],
+[
+    AC_CACHE_CHECK(whether the C compiler supports $1$2, $3,
+        [
+            AC_LANG_SAVE
+            AC_LANG_C
+            _SAVE_CFLAGS="$CFLAGS"
+            CFLAGS="$CFLAGS -Werror -W$2"
+            AC_TRY_COMPILE([],
+                           [return(0);],
+                           $3="yes",
+                           $3="no")
+            CFLAGS="$_SAVE_CFLAGS"
+            AC_LANG_RESTORE
+        ])
+    if test "${$3}" = "yes"; then
+        _WARNINGS_CFLAGS="${_WARNINGS_CFLAGS} $1$2"
+    fi
+])
+
+AC_DEFUN([MOZ_CXX_SUPPORTS_WARNING],
+[
+    AC_CACHE_CHECK(whether the C++ compiler supports $1$2, $3,
+        [
+            AC_LANG_SAVE
+            AC_LANG_CPLUSPLUS
+            _SAVE_CXXFLAGS="$CXXFLAGS"
+            CXXFLAGS="$CXXFLAGS -Werror -W$2"
+            AC_TRY_COMPILE([],
+                           [return(0);],
+                           $3="yes",
+                           $3="no")
+            CXXFLAGS="$_SAVE_CXXFLAGS"
+            AC_LANG_RESTORE
+        ])
+    if test "${$3}" = "yes"; then
+        _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} $1$2"
+    fi
+])
diff --git a/src/third_party/mozjs-45/build/autoconf/config.guess b/src/third_party/mozjs-45/build/autoconf/config.guess
new file mode 100755
index 0000000..72625d4
--- /dev/null
+++ b/src/third_party/mozjs-45/build/autoconf/config.guess
@@ -0,0 +1,1420 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+#   Copyright 1992-2014 Free Software Foundation, Inc.
+
+timestamp='2014-02-12'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that
+# program.  This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
+#
+# Originally written by Per Bothner.
+#
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+#
+# Please send patches with a ChangeLog entry to config-patches@gnu.org.
+
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright 1992-2014 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help" >&2
+       exit 1 ;;
+    * )
+       break ;;
+  esac
+done
+
+if test $# != 0; then
+  echo "$me: too many arguments$help" >&2
+  exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,)    echo "int x;" > $dummy.c ;
+	for c in cc gcc c89 c99 ; do
+	  if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+	     CC_FOR_BUILD="$c"; break ;
+	  fi ;
+	done ;
+	if test x"$CC_FOR_BUILD" = x ; then
+	  CC_FOR_BUILD=no_compiler_found ;
+	fi
+	;;
+ ,,*)   CC_FOR_BUILD=$CC ;;
+ ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+	PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+case "${UNAME_SYSTEM}" in
+Linux|GNU|GNU/*)
+	# If the system lacks a compiler, then just pick glibc.
+	# We could probably try harder.
+	LIBC=gnu
+
+	eval $set_cc_for_build
+	cat <<-EOF > $dummy.c
+	#include <features.h>
+	#if defined(__UCLIBC__)
+	LIBC=uclibc
+	#elif defined(__dietlibc__)
+	LIBC=dietlibc
+	#else
+	LIBC=gnu
+	#endif
+	EOF
+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
+	;;
+esac
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+    *:NetBSD:*:*)
+	# NetBSD (nbsd) targets should (where applicable) match one or
+	# more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
+	# *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
+	# switched to ELF, *-*-netbsd* would select the old
+	# object file format.  This provides both forward
+	# compatibility and a consistent mechanism for selecting the
+	# object file format.
+	#
+	# Note: NetBSD doesn't particularly care about the vendor
+	# portion of the name.  We always set it to "unknown".
+	sysctl="sysctl -n hw.machine_arch"
+	UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+	    /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+	case "${UNAME_MACHINE_ARCH}" in
+	    armeb) machine=armeb-unknown ;;
+	    arm*) machine=arm-unknown ;;
+	    sh3el) machine=shl-unknown ;;
+	    sh3eb) machine=sh-unknown ;;
+	    sh5el) machine=sh5le-unknown ;;
+	    *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+	esac
+	# The Operating System including object format, if it has switched
+	# to ELF recently, or will in the future.
+	case "${UNAME_MACHINE_ARCH}" in
+	    arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+		eval $set_cc_for_build
+		if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+			| grep -q __ELF__
+		then
+		    # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+		    # Return netbsd for either.  FIX?
+		    os=netbsd
+		else
+		    os=netbsdelf
+		fi
+		;;
+	    *)
+		os=netbsd
+		;;
+	esac
+	# The OS release
+	# Debian GNU/NetBSD machines have a different userland, and
+	# thus, need a distinct triplet. However, they do not need
+	# kernel version information, so it can be replaced with a
+	# suitable tag, in the style of linux-gnu.
+	case "${UNAME_VERSION}" in
+	    Debian*)
+		release='-gnu'
+		;;
+	    *)
+		release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+		;;
+	esac
+	# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+	# contains redundant information, the shorter form:
+	# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+	echo "${machine}-${os}${release}"
+	exit ;;
+    *:Bitrig:*:*)
+	UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
+	echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE}
+	exit ;;
+    *:OpenBSD:*:*)
+	UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+	echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+	exit ;;
+    *:ekkoBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+	exit ;;
+    *:SolidBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+	exit ;;
+    macppc:MirBSD:*:*)
+	echo powerpc-unknown-mirbsd${UNAME_RELEASE}
+	exit ;;
+    *:MirBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+	exit ;;
+    alpha:OSF1:*:*)
+	case $UNAME_RELEASE in
+	*4.0)
+		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+		;;
+	*5.*)
+		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+		;;
+	esac
+	# According to Compaq, /usr/sbin/psrinfo has been available on
+	# OSF/1 and Tru64 systems produced since 1995.  I hope that
+	# covers most systems running today.  This code pipes the CPU
+	# types through head -n 1, so we only detect the type of CPU 0.
+	ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+	case "$ALPHA_CPU_TYPE" in
+	    "EV4 (21064)")
+		UNAME_MACHINE="alpha" ;;
+	    "EV4.5 (21064)")
+		UNAME_MACHINE="alpha" ;;
+	    "LCA4 (21066/21068)")
+		UNAME_MACHINE="alpha" ;;
+	    "EV5 (21164)")
+		UNAME_MACHINE="alphaev5" ;;
+	    "EV5.6 (21164A)")
+		UNAME_MACHINE="alphaev56" ;;
+	    "EV5.6 (21164PC)")
+		UNAME_MACHINE="alphapca56" ;;
+	    "EV5.7 (21164PC)")
+		UNAME_MACHINE="alphapca57" ;;
+	    "EV6 (21264)")
+		UNAME_MACHINE="alphaev6" ;;
+	    "EV6.7 (21264A)")
+		UNAME_MACHINE="alphaev67" ;;
+	    "EV6.8CB (21264C)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.8AL (21264B)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.8CX (21264D)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.9A (21264/EV69A)")
+		UNAME_MACHINE="alphaev69" ;;
+	    "EV7 (21364)")
+		UNAME_MACHINE="alphaev7" ;;
+	    "EV7.9 (21364A)")
+		UNAME_MACHINE="alphaev79" ;;
+	esac
+	# A Pn.n version is a patched version.
+	# A Vn.n version is a released version.
+	# A Tn.n version is a released field test version.
+	# A Xn.n version is an unreleased experimental baselevel.
+	# 1.2 uses "1.2" for uname -r.
+	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+	# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
+	exitcode=$?
+	trap '' 0
+	exit $exitcode ;;
+    Alpha\ *:Windows_NT*:*)
+	# How do we know it's Interix rather than the generic POSIX subsystem?
+	# Should we change UNAME_MACHINE based on the output of uname instead
+	# of the specific Alpha model?
+	echo alpha-pc-interix
+	exit ;;
+    21064:Windows_NT:50:3)
+	echo alpha-dec-winnt3.5
+	exit ;;
+    Amiga*:UNIX_System_V:4.0:*)
+	echo m68k-unknown-sysv4
+	exit ;;
+    *:[Aa]miga[Oo][Ss]:*:*)
+	echo ${UNAME_MACHINE}-unknown-amigaos
+	exit ;;
+    *:[Mm]orph[Oo][Ss]:*:*)
+	echo ${UNAME_MACHINE}-unknown-morphos
+	exit ;;
+    *:OS/390:*:*)
+	echo i370-ibm-openedition
+	exit ;;
+    *:z/VM:*:*)
+	echo s390-ibm-zvmoe
+	exit ;;
+    *:OS400:*:*)
+	echo powerpc-ibm-os400
+	exit ;;
+    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+	echo arm-acorn-riscix${UNAME_RELEASE}
+	exit ;;
+    arm*:riscos:*:*|arm*:RISCOS:*:*)
+	echo arm-unknown-riscos
+	exit ;;
+    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+	echo hppa1.1-hitachi-hiuxmpp
+	exit ;;
+    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+	# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+	if test "`(/bin/universe) 2>/dev/null`" = att ; then
+		echo pyramid-pyramid-sysv3
+	else
+		echo pyramid-pyramid-bsd
+	fi
+	exit ;;
+    NILE*:*:*:dcosx)
+	echo pyramid-pyramid-svr4
+	exit ;;
+    DRS?6000:unix:4.0:6*)
+	echo sparc-icl-nx6
+	exit ;;
+    DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+	case `/usr/bin/uname -p` in
+	    sparc) echo sparc-icl-nx7; exit ;;
+	esac ;;
+    s390x:SunOS:*:*)
+	echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4H:SunOS:5.*:*)
+	echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+	echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
+	echo i386-pc-auroraux${UNAME_RELEASE}
+	exit ;;
+    i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
+	eval $set_cc_for_build
+	SUN_ARCH="i386"
+	# If there is a compiler, see if it is configured for 64-bit objects.
+	# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
+	# This test works for both compilers.
+	if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+	    if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
+		(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+		grep IS_64BIT_ARCH >/dev/null
+	    then
+		SUN_ARCH="x86_64"
+	    fi
+	fi
+	echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:6*:*)
+	# According to config.sub, this is the proper way to canonicalize
+	# SunOS6.  Hard to guess exactly what SunOS6 will be like, but
+	# it's likely to be more like Solaris than SunOS4.
+	echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:*:*)
+	case "`/usr/bin/arch -k`" in
+	    Series*|S4*)
+		UNAME_RELEASE=`uname -v`
+		;;
+	esac
+	# Japanese Language versions have a version number like `4.1.3-JL'.
+	echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+	exit ;;
+    sun3*:SunOS:*:*)
+	echo m68k-sun-sunos${UNAME_RELEASE}
+	exit ;;
+    sun*:*:4.2BSD:*)
+	UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+	test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+	case "`/bin/arch`" in
+	    sun3)
+		echo m68k-sun-sunos${UNAME_RELEASE}
+		;;
+	    sun4)
+		echo sparc-sun-sunos${UNAME_RELEASE}
+		;;
+	esac
+	exit ;;
+    aushp:SunOS:*:*)
+	echo sparc-auspex-sunos${UNAME_RELEASE}
+	exit ;;
+    # The situation for MiNT is a little confusing.  The machine name
+    # can be virtually everything (everything which is not
+    # "atarist" or "atariste" at least should have a processor
+    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
+    # to the lowercase version "mint" (or "freemint").  Finally
+    # the system name "TOS" denotes a system which is actually not
+    # MiNT.  But MiNT is downward compatible to TOS, so this should
+    # be no problem.
+    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+	echo m68k-atari-mint${UNAME_RELEASE}
+	exit ;;
+    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+	echo m68k-atari-mint${UNAME_RELEASE}
+	exit ;;
+    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+	echo m68k-atari-mint${UNAME_RELEASE}
+	exit ;;
+    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+	echo m68k-milan-mint${UNAME_RELEASE}
+	exit ;;
+    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+	echo m68k-hades-mint${UNAME_RELEASE}
+	exit ;;
+    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+	echo m68k-unknown-mint${UNAME_RELEASE}
+	exit ;;
+    m68k:machten:*:*)
+	echo m68k-apple-machten${UNAME_RELEASE}
+	exit ;;
+    powerpc:machten:*:*)
+	echo powerpc-apple-machten${UNAME_RELEASE}
+	exit ;;
+    RISC*:Mach:*:*)
+	echo mips-dec-mach_bsd4.3
+	exit ;;
+    RISC*:ULTRIX:*:*)
+	echo mips-dec-ultrix${UNAME_RELEASE}
+	exit ;;
+    VAX*:ULTRIX*:*:*)
+	echo vax-dec-ultrix${UNAME_RELEASE}
+	exit ;;
+    2020:CLIX:*:* | 2430:CLIX:*:*)
+	echo clipper-intergraph-clix${UNAME_RELEASE}
+	exit ;;
+    mips:*:*:UMIPS | mips:*:*:RISCos)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h>  /* for printf() prototype */
+	int main (int argc, char *argv[]) {
+#else
+	int main (argc, argv) int argc; char *argv[]; {
+#endif
+	#if defined (host_mips) && defined (MIPSEB)
+	#if defined (SYSTYPE_SYSV)
+	  printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_SVR4)
+	  printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+	  printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+	#endif
+	#endif
+	  exit (-1);
+	}
+EOF
+	$CC_FOR_BUILD -o $dummy $dummy.c &&
+	  dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+	  SYSTEM_NAME=`$dummy $dummyarg` &&
+	    { echo "$SYSTEM_NAME"; exit; }
+	echo mips-mips-riscos${UNAME_RELEASE}
+	exit ;;
+    Motorola:PowerMAX_OS:*:*)
+	echo powerpc-motorola-powermax
+	exit ;;
+    Motorola:*:4.3:PL8-*)
+	echo powerpc-harris-powermax
+	exit ;;
+    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+	echo powerpc-harris-powermax
+	exit ;;
+    Night_Hawk:Power_UNIX:*:*)
+	echo powerpc-harris-powerunix
+	exit ;;
+    m88k:CX/UX:7*:*)
+	echo m88k-harris-cxux7
+	exit ;;
+    m88k:*:4*:R4*)
+	echo m88k-motorola-sysv4
+	exit ;;
+    m88k:*:3*:R3*)
+	echo m88k-motorola-sysv3
+	exit ;;
+    AViiON:dgux:*:*)
+	# DG/UX returns AViiON for all architectures
+	UNAME_PROCESSOR=`/usr/bin/uname -p`
+	if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+	then
+	    if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+	       [ ${TARGET_BINARY_INTERFACE}x = x ]
+	    then
+		echo m88k-dg-dgux${UNAME_RELEASE}
+	    else
+		echo m88k-dg-dguxbcs${UNAME_RELEASE}
+	    fi
+	else
+	    echo i586-dg-dgux${UNAME_RELEASE}
+	fi
+	exit ;;
+    M88*:DolphinOS:*:*)	# DolphinOS (SVR3)
+	echo m88k-dolphin-sysv3
+	exit ;;
+    M88*:*:R3*:*)
+	# Delta 88k system running SVR3
+	echo m88k-motorola-sysv3
+	exit ;;
+    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+	echo m88k-tektronix-sysv3
+	exit ;;
+    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+	echo m68k-tektronix-bsd
+	exit ;;
+    *:IRIX*:*:*)
+	echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+	exit ;;
+    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+	echo romp-ibm-aix     # uname -m gives an 8 hex-code CPU id
+	exit ;;               # Note that: echo "'`uname -s`'" gives 'AIX '
+    i*86:AIX:*:*)
+	echo i386-ibm-aix
+	exit ;;
+    ia64:AIX:*:*)
+	if [ -x /usr/bin/oslevel ] ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+	exit ;;
+    *:AIX:2:3)
+	if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+		eval $set_cc_for_build
+		sed 's/^		//' << EOF >$dummy.c
+		#include <sys/systemcfg.h>
+
+		main()
+			{
+			if (!__power_pc())
+				exit(1);
+			puts("powerpc-ibm-aix3.2.5");
+			exit(0);
+			}
+EOF
+		if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+		then
+			echo "$SYSTEM_NAME"
+		else
+			echo rs6000-ibm-aix3.2.5
+		fi
+	elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+		echo rs6000-ibm-aix3.2.4
+	else
+		echo rs6000-ibm-aix3.2
+	fi
+	exit ;;
+    *:AIX:*:[4567])
+	IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+	if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+		IBM_ARCH=rs6000
+	else
+		IBM_ARCH=powerpc
+	fi
+	if [ -x /usr/bin/oslevel ] ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+	exit ;;
+    *:AIX:*:*)
+	echo rs6000-ibm-aix
+	exit ;;
+    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+	echo romp-ibm-bsd4.4
+	exit ;;
+    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
+	echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
+	exit ;;                             # report: romp-ibm BSD 4.3
+    *:BOSX:*:*)
+	echo rs6000-bull-bosx
+	exit ;;
+    DPX/2?00:B.O.S.:*:*)
+	echo m68k-bull-sysv3
+	exit ;;
+    9000/[34]??:4.3bsd:1.*:*)
+	echo m68k-hp-bsd
+	exit ;;
+    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+	echo m68k-hp-bsd4.4
+	exit ;;
+    9000/[34678]??:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	case "${UNAME_MACHINE}" in
+	    9000/31? )            HP_ARCH=m68000 ;;
+	    9000/[34]?? )         HP_ARCH=m68k ;;
+	    9000/[678][0-9][0-9])
+		if [ -x /usr/bin/getconf ]; then
+		    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+		    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+		    case "${sc_cpu_version}" in
+		      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+		      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+		      532)                      # CPU_PA_RISC2_0
+			case "${sc_kernel_bits}" in
+			  32) HP_ARCH="hppa2.0n" ;;
+			  64) HP_ARCH="hppa2.0w" ;;
+			  '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
+			esac ;;
+		    esac
+		fi
+		if [ "${HP_ARCH}" = "" ]; then
+		    eval $set_cc_for_build
+		    sed 's/^		//' << EOF >$dummy.c
+
+		#define _HPUX_SOURCE
+		#include <stdlib.h>
+		#include <unistd.h>
+
+		int main ()
+		{
+		#if defined(_SC_KERNEL_BITS)
+		    long bits = sysconf(_SC_KERNEL_BITS);
+		#endif
+		    long cpu  = sysconf (_SC_CPU_VERSION);
+
+		    switch (cpu)
+			{
+			case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+			case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+			case CPU_PA_RISC2_0:
+		#if defined(_SC_KERNEL_BITS)
+			    switch (bits)
+				{
+				case 64: puts ("hppa2.0w"); break;
+				case 32: puts ("hppa2.0n"); break;
+				default: puts ("hppa2.0"); break;
+				} break;
+		#else  /* !defined(_SC_KERNEL_BITS) */
+			    puts ("hppa2.0"); break;
+		#endif
+			default: puts ("hppa1.0"); break;
+			}
+		    exit (0);
+		}
+EOF
+		    (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+		    test -z "$HP_ARCH" && HP_ARCH=hppa
+		fi ;;
+	esac
+	if [ ${HP_ARCH} = "hppa2.0w" ]
+	then
+	    eval $set_cc_for_build
+
+	    # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+	    # 32-bit code.  hppa64-hp-hpux* has the same kernel and a compiler
+	    # generating 64-bit code.  GNU and HP use different nomenclature:
+	    #
+	    # $ CC_FOR_BUILD=cc ./config.guess
+	    # => hppa2.0w-hp-hpux11.23
+	    # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+	    # => hppa64-hp-hpux11.23
+
+	    if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+		grep -q __LP64__
+	    then
+		HP_ARCH="hppa2.0w"
+	    else
+		HP_ARCH="hppa64"
+	    fi
+	fi
+	echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+	exit ;;
+    ia64:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	echo ia64-hp-hpux${HPUX_REV}
+	exit ;;
+    3050*:HI-UX:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#include <unistd.h>
+	int
+	main ()
+	{
+	  long cpu = sysconf (_SC_CPU_VERSION);
+	  /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+	     true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
+	     results, however.  */
+	  if (CPU_IS_PA_RISC (cpu))
+	    {
+	      switch (cpu)
+		{
+		  case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+		  default: puts ("hppa-hitachi-hiuxwe2"); break;
+		}
+	    }
+	  else if (CPU_IS_HP_MC68K (cpu))
+	    puts ("m68k-hitachi-hiuxwe2");
+	  else puts ("unknown-hitachi-hiuxwe2");
+	  exit (0);
+	}
+EOF
+	$CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+		{ echo "$SYSTEM_NAME"; exit; }
+	echo unknown-hitachi-hiuxwe2
+	exit ;;
+    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+	echo hppa1.1-hp-bsd
+	exit ;;
+    9000/8??:4.3bsd:*:*)
+	echo hppa1.0-hp-bsd
+	exit ;;
+    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+	echo hppa1.0-hp-mpeix
+	exit ;;
+    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+	echo hppa1.1-hp-osf
+	exit ;;
+    hp8??:OSF1:*:*)
+	echo hppa1.0-hp-osf
+	exit ;;
+    i*86:OSF1:*:*)
+	if [ -x /usr/sbin/sysversion ] ; then
+	    echo ${UNAME_MACHINE}-unknown-osf1mk
+	else
+	    echo ${UNAME_MACHINE}-unknown-osf1
+	fi
+	exit ;;
+    parisc*:Lites*:*:*)
+	echo hppa1.1-hp-lites
+	exit ;;
+    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+	echo c1-convex-bsd
+	exit ;;
+    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+	exit ;;
+    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+	echo c34-convex-bsd
+	exit ;;
+    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+	echo c38-convex-bsd
+	exit ;;
+    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+	echo c4-convex-bsd
+	exit ;;
+    CRAY*Y-MP:*:*:*)
+	echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*[A-Z]90:*:*:*)
+	echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+	| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+	      -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+	      -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*TS:*:*:*)
+	echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*T3E:*:*:*)
+	echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*SV1:*:*:*)
+	echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    *:UNICOS/mp:*:*)
+	echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+	FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+	FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+	FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+	echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+	exit ;;
+    5000:UNIX_System_V:4.*:*)
+	FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+	FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+	echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+	exit ;;
+    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+	echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+	exit ;;
+    sparc*:BSD/OS:*:*)
+	echo sparc-unknown-bsdi${UNAME_RELEASE}
+	exit ;;
+    *:BSD/OS:*:*)
+	echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+	exit ;;
+    *:FreeBSD:*:*)
+	UNAME_PROCESSOR=`/usr/bin/uname -p`
+	case ${UNAME_PROCESSOR} in
+	    amd64)
+		echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+	    *)
+		echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+	esac
+	exit ;;
+    i*:CYGWIN*:*)
+	echo ${UNAME_MACHINE}-pc-cygwin
+	exit ;;
+    *:MINGW64*:*)
+	echo ${UNAME_MACHINE}-pc-mingw64
+	exit ;;
+    *:MINGW*:*)
+	echo ${UNAME_MACHINE}-pc-mingw32
+	exit ;;
+    i*:MSYS*:*)
+	echo ${UNAME_MACHINE}-pc-msys
+	exit ;;
+    i*:windows32*:*)
+	# uname -m includes "-pc" on this system.
+	echo ${UNAME_MACHINE}-mingw32
+	exit ;;
+    i*:PW*:*)
+	echo ${UNAME_MACHINE}-pc-pw32
+	exit ;;
+    *:Interix*:*)
+	case ${UNAME_MACHINE} in
+	    x86)
+		echo i586-pc-interix${UNAME_RELEASE}
+		exit ;;
+	    authenticamd | genuineintel | EM64T)
+		echo x86_64-unknown-interix${UNAME_RELEASE}
+		exit ;;
+	    IA64)
+		echo ia64-unknown-interix${UNAME_RELEASE}
+		exit ;;
+	esac ;;
+    [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+	echo i${UNAME_MACHINE}-pc-mks
+	exit ;;
+    8664:Windows_NT:*)
+	echo x86_64-pc-mks
+	exit ;;
+    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+	# How do we know it's Interix rather than the generic POSIX subsystem?
+	# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+	# UNAME_MACHINE based on the output of uname instead of i386?
+	echo i586-pc-interix
+	exit ;;
+    i*:UWIN*:*)
+	echo ${UNAME_MACHINE}-pc-uwin
+	exit ;;
+    amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+	echo x86_64-unknown-cygwin
+	exit ;;
+    p*:CYGWIN*:*)
+	echo powerpcle-unknown-cygwin
+	exit ;;
+    prep*:SunOS:5.*:*)
+	echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    *:GNU:*:*)
+	# the GNU system
+	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+	exit ;;
+    *:GNU/*:*:*)
+	# other systems with GNU libc and userland
+	echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
+	exit ;;
+    i*86:Minix:*:*)
+	echo ${UNAME_MACHINE}-pc-minix
+	exit ;;
+    aarch64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    aarch64_be:Linux:*:*)
+	UNAME_MACHINE=aarch64_be
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    alpha:Linux:*:*)
+	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+	  EV5)   UNAME_MACHINE=alphaev5 ;;
+	  EV56)  UNAME_MACHINE=alphaev56 ;;
+	  PCA56) UNAME_MACHINE=alphapca56 ;;
+	  PCA57) UNAME_MACHINE=alphapca56 ;;
+	  EV6)   UNAME_MACHINE=alphaev6 ;;
+	  EV67)  UNAME_MACHINE=alphaev67 ;;
+	  EV68*) UNAME_MACHINE=alphaev68 ;;
+	esac
+	objdump --private-headers /bin/sh | grep -q ld.so.1
+	if test "$?" = 0 ; then LIBC="gnulibc1" ; fi
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    arc:Linux:*:* | arceb:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    arm*:Linux:*:*)
+	eval $set_cc_for_build
+	if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
+	    | grep -q __ARM_EABI__
+	then
+	    echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	else
+	    if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
+		| grep -q __ARM_PCS_VFP
+	    then
+		echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi
+	    else
+		echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf
+	    fi
+	fi
+	exit ;;
+    avr32*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    cris:Linux:*:*)
+	echo ${UNAME_MACHINE}-axis-linux-${LIBC}
+	exit ;;
+    crisv32:Linux:*:*)
+	echo ${UNAME_MACHINE}-axis-linux-${LIBC}
+	exit ;;
+    frv:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    hexagon:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    i*86:Linux:*:*)
+	echo ${UNAME_MACHINE}-pc-linux-${LIBC}
+	exit ;;
+    ia64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    m32r*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    m68*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    mips:Linux:*:* | mips64:Linux:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#undef CPU
+	#undef ${UNAME_MACHINE}
+	#undef ${UNAME_MACHINE}el
+	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+	CPU=${UNAME_MACHINE}el
+	#else
+	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+	CPU=${UNAME_MACHINE}
+	#else
+	CPU=
+	#endif
+	#endif
+EOF
+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
+	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
+	;;
+    or1k:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    or32:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    padre:Linux:*:*)
+	echo sparc-unknown-linux-${LIBC}
+	exit ;;
+    parisc64:Linux:*:* | hppa64:Linux:*:*)
+	echo hppa64-unknown-linux-${LIBC}
+	exit ;;
+    parisc:Linux:*:* | hppa:Linux:*:*)
+	# Look for CPU level
+	case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+	  PA7*) echo hppa1.1-unknown-linux-${LIBC} ;;
+	  PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;
+	  *)    echo hppa-unknown-linux-${LIBC} ;;
+	esac
+	exit ;;
+    ppc64:Linux:*:*)
+	echo powerpc64-unknown-linux-${LIBC}
+	exit ;;
+    ppc:Linux:*:*)
+	echo powerpc-unknown-linux-${LIBC}
+	exit ;;
+    ppc64le:Linux:*:*)
+	echo powerpc64le-unknown-linux-${LIBC}
+	exit ;;
+    ppcle:Linux:*:*)
+	echo powerpcle-unknown-linux-${LIBC}
+	exit ;;
+    s390:Linux:*:* | s390x:Linux:*:*)
+	echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
+	exit ;;
+    sh64*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    sh*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    sparc:Linux:*:* | sparc64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    tile*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    vax:Linux:*:*)
+	echo ${UNAME_MACHINE}-dec-linux-${LIBC}
+	exit ;;
+    x86_64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    xtensa*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    i*86:DYNIX/ptx:4*:*)
+	# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+	# earlier versions are messed up and put the nodename in both
+	# sysname and nodename.
+	echo i386-sequent-sysv4
+	exit ;;
+    i*86:UNIX_SV:4.2MP:2.*)
+	# Unixware is an offshoot of SVR4, but it has its own version
+	# number series starting with 2...
+	# I am not positive that other SVR4 systems won't match this,
+	# I just have to hope.  -- rms.
+	# Use sysv4.2uw... so that sysv4* matches it.
+	echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+	exit ;;
+    i*86:OS/2:*:*)
+	# If we were able to find `uname', then EMX Unix compatibility
+	# is probably installed.
+	echo ${UNAME_MACHINE}-pc-os2-emx
+	exit ;;
+    i*86:XTS-300:*:STOP)
+	echo ${UNAME_MACHINE}-unknown-stop
+	exit ;;
+    i*86:atheos:*:*)
+	echo ${UNAME_MACHINE}-unknown-atheos
+	exit ;;
+    i*86:syllable:*:*)
+	echo ${UNAME_MACHINE}-pc-syllable
+	exit ;;
+    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
+	echo i386-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    i*86:*DOS:*:*)
+	echo ${UNAME_MACHINE}-pc-msdosdjgpp
+	exit ;;
+    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+	UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+	if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+		echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+	else
+		echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+	fi
+	exit ;;
+    i*86:*:5:[678]*)
+	# UnixWare 7.x, OpenUNIX and OpenServer 6.
+	case `/bin/uname -X | grep "^Machine"` in
+	    *486*)	     UNAME_MACHINE=i486 ;;
+	    *Pentium)	     UNAME_MACHINE=i586 ;;
+	    *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+	esac
+	echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+	exit ;;
+    i*86:*:3.2:*)
+	if test -f /usr/options/cb.name; then
+		UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+		echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+	elif /bin/uname -X 2>/dev/null >/dev/null ; then
+		UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+		(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+		(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+			&& UNAME_MACHINE=i586
+		(/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+	else
+		echo ${UNAME_MACHINE}-pc-sysv32
+	fi
+	exit ;;
+    pc:*:*:*)
+	# Left here for compatibility:
+	# uname -m prints for DJGPP always 'pc', but it prints nothing about
+	# the processor, so we play safe by assuming i586.
+	# Note: whatever this is, it MUST be the same as what config.sub
+	# prints for the "djgpp" host, or else GDB configury will decide that
+	# this is a cross-build.
+	echo i586-pc-msdosdjgpp
+	exit ;;
+    Intel:Mach:3*:*)
+	echo i386-pc-mach3
+	exit ;;
+    paragon:*:*:*)
+	echo i860-intel-osf1
+	exit ;;
+    i860:*:4.*:*) # i860-SVR4
+	if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+	  echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+	else # Add other i860-SVR4 vendors below as they are discovered.
+	  echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
+	fi
+	exit ;;
+    mini*:CTIX:SYS*5:*)
+	# "miniframe"
+	echo m68010-convergent-sysv
+	exit ;;
+    mc68k:UNIX:SYSTEM5:3.51m)
+	echo m68k-convergent-sysv
+	exit ;;
+    M680?0:D-NIX:5.3:*)
+	echo m68k-diab-dnix
+	exit ;;
+    M68*:*:R3V[5678]*:*)
+	test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+    3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+	OS_REL=''
+	test -r /etc/.relid \
+	&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	  && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+	  && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	  && { echo i486-ncr-sysv4; exit; } ;;
+    NCR*:*:4.2:* | MPRAS*:*:4.2:*)
+	OS_REL='.3'
+	test -r /etc/.relid \
+	    && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	    && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+	    && { echo i586-ncr-sysv4.3${OS_REL}; exit; }
+	/bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
+	    && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+	echo m68k-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    mc68030:UNIX_System_V:4.*:*)
+	echo m68k-atari-sysv4
+	exit ;;
+    TSUNAMI:LynxOS:2.*:*)
+	echo sparc-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    rs6000:LynxOS:2.*:*)
+	echo rs6000-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
+	echo powerpc-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    SM[BE]S:UNIX_SV:*:*)
+	echo mips-dde-sysv${UNAME_RELEASE}
+	exit ;;
+    RM*:ReliantUNIX-*:*:*)
+	echo mips-sni-sysv4
+	exit ;;
+    RM*:SINIX-*:*:*)
+	echo mips-sni-sysv4
+	exit ;;
+    *:SINIX-*:*:*)
+	if uname -p 2>/dev/null >/dev/null ; then
+		UNAME_MACHINE=`(uname -p) 2>/dev/null`
+		echo ${UNAME_MACHINE}-sni-sysv4
+	else
+		echo ns32k-sni-sysv
+	fi
+	exit ;;
+    PENTIUM:*:4.0*:*)	# Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+			# says <Richard.M.Bartel@ccMail.Census.GOV>
+	echo i586-unisys-sysv4
+	exit ;;
+    *:UNIX_System_V:4*:FTX*)
+	# From Gerald Hewes <hewes@openmarket.com>.
+	# How about differentiating between stratus architectures? -djm
+	echo hppa1.1-stratus-sysv4
+	exit ;;
+    *:*:*:FTX*)
+	# From seanf@swdc.stratus.com.
+	echo i860-stratus-sysv4
+	exit ;;
+    i*86:VOS:*:*)
+	# From Paul.Green@stratus.com.
+	echo ${UNAME_MACHINE}-stratus-vos
+	exit ;;
+    *:VOS:*:*)
+	# From Paul.Green@stratus.com.
+	echo hppa1.1-stratus-vos
+	exit ;;
+    mc68*:A/UX:*:*)
+	echo m68k-apple-aux${UNAME_RELEASE}
+	exit ;;
+    news*:NEWS-OS:6*:*)
+	echo mips-sony-newsos6
+	exit ;;
+    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+	if [ -d /usr/nec ]; then
+		echo mips-nec-sysv${UNAME_RELEASE}
+	else
+		echo mips-unknown-sysv${UNAME_RELEASE}
+	fi
+	exit ;;
+    BeBox:BeOS:*:*)	# BeOS running on hardware made by Be, PPC only.
+	echo powerpc-be-beos
+	exit ;;
+    BeMac:BeOS:*:*)	# BeOS running on Mac or Mac clone, PPC only.
+	echo powerpc-apple-beos
+	exit ;;
+    BePC:BeOS:*:*)	# BeOS running on Intel PC compatible.
+	echo i586-pc-beos
+	exit ;;
+    BePC:Haiku:*:*)	# Haiku running on Intel PC compatible.
+	echo i586-pc-haiku
+	exit ;;
+    x86_64:Haiku:*:*)
+	echo x86_64-unknown-haiku
+	exit ;;
+    SX-4:SUPER-UX:*:*)
+	echo sx4-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-5:SUPER-UX:*:*)
+	echo sx5-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-6:SUPER-UX:*:*)
+	echo sx6-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-7:SUPER-UX:*:*)
+	echo sx7-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-8:SUPER-UX:*:*)
+	echo sx8-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-8R:SUPER-UX:*:*)
+	echo sx8r-nec-superux${UNAME_RELEASE}
+	exit ;;
+    Power*:Rhapsody:*:*)
+	echo powerpc-apple-rhapsody${UNAME_RELEASE}
+	exit ;;
+    *:Rhapsody:*:*)
+	echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+	exit ;;
+    *:Darwin:*:*)
+	UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+	eval $set_cc_for_build
+	if test "$UNAME_PROCESSOR" = unknown ; then
+	    UNAME_PROCESSOR=powerpc
+	fi
+	if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
+	    if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+		if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+		    (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+		    grep IS_64BIT_ARCH >/dev/null
+		then
+		    case $UNAME_PROCESSOR in
+			i386) UNAME_PROCESSOR=x86_64 ;;
+			powerpc) UNAME_PROCESSOR=powerpc64 ;;
+		    esac
+		fi
+	    fi
+	elif test "$UNAME_PROCESSOR" = i386 ; then
+	    # Avoid executing cc on OS X 10.9, as it ships with a stub
+	    # that puts up a graphical alert prompting to install
+	    # developer tools.  Any system running Mac OS X 10.7 or
+	    # later (Darwin 11 and later) is required to have a 64-bit
+	    # processor. This is not true of the ARM version of Darwin
+	    # that Apple uses in portable devices.
+	    UNAME_PROCESSOR=x86_64
+	fi
+	echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+	exit ;;
+    *:procnto*:*:* | *:QNX:[0123456789]*:*)
+	UNAME_PROCESSOR=`uname -p`
+	if test "$UNAME_PROCESSOR" = "x86"; then
+		UNAME_PROCESSOR=i386
+		UNAME_MACHINE=pc
+	fi
+	echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+	exit ;;
+    *:QNX:*:4*)
+	echo i386-pc-qnx
+	exit ;;
+    NEO-?:NONSTOP_KERNEL:*:*)
+	echo neo-tandem-nsk${UNAME_RELEASE}
+	exit ;;
+    NSE-*:NONSTOP_KERNEL:*:*)
+	echo nse-tandem-nsk${UNAME_RELEASE}
+	exit ;;
+    NSR-?:NONSTOP_KERNEL:*:*)
+	echo nsr-tandem-nsk${UNAME_RELEASE}
+	exit ;;
+    *:NonStop-UX:*:*)
+	echo mips-compaq-nonstopux
+	exit ;;
+    BS2000:POSIX*:*:*)
+	echo bs2000-siemens-sysv
+	exit ;;
+    DS/*:UNIX_System_V:*:*)
+	echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+	exit ;;
+    *:Plan9:*:*)
+	# "uname -m" is not consistent, so use $cputype instead. 386
+	# is converted to i386 for consistency with other x86
+	# operating systems.
+	if test "$cputype" = "386"; then
+	    UNAME_MACHINE=i386
+	else
+	    UNAME_MACHINE="$cputype"
+	fi
+	echo ${UNAME_MACHINE}-unknown-plan9
+	exit ;;
+    *:TOPS-10:*:*)
+	echo pdp10-unknown-tops10
+	exit ;;
+    *:TENEX:*:*)
+	echo pdp10-unknown-tenex
+	exit ;;
+    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+	echo pdp10-dec-tops20
+	exit ;;
+    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+	echo pdp10-xkl-tops20
+	exit ;;
+    *:TOPS-20:*:*)
+	echo pdp10-unknown-tops20
+	exit ;;
+    *:ITS:*:*)
+	echo pdp10-unknown-its
+	exit ;;
+    SEI:*:*:SEIUX)
+	echo mips-sei-seiux${UNAME_RELEASE}
+	exit ;;
+    *:DragonFly:*:*)
+	echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+	exit ;;
+    *:*VMS:*:*)
+	UNAME_MACHINE=`(uname -p) 2>/dev/null`
+	case "${UNAME_MACHINE}" in
+	    A*) echo alpha-dec-vms ; exit ;;
+	    I*) echo ia64-dec-vms ; exit ;;
+	    V*) echo vax-dec-vms ; exit ;;
+	esac ;;
+    *:XENIX:*:SysV)
+	echo i386-pc-xenix
+	exit ;;
+    i*86:skyos:*:*)
+	echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+	exit ;;
+    i*86:rdos:*:*)
+	echo ${UNAME_MACHINE}-pc-rdos
+	exit ;;
+    i*86:AROS:*:*)
+	echo ${UNAME_MACHINE}-pc-aros
+	exit ;;
+    x86_64:VMkernel:*:*)
+	echo ${UNAME_MACHINE}-unknown-esx
+	exit ;;
+esac
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+and
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo               = `(hostinfo) 2>/dev/null`
+/bin/universe          = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch              = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM  = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/src/third_party/mozjs-45/build/autoconf/config.status.m4 b/src/third_party/mozjs-45/build/autoconf/config.status.m4
new file mode 100644
index 0000000..05f402a
--- /dev/null
+++ b/src/third_party/mozjs-45/build/autoconf/config.status.m4
@@ -0,0 +1,243 @@
+dnl This Source Code Form is subject to the terms of the Mozilla Public
+dnl License, v. 2.0. If a copy of the MPL was not distributed with this
+dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+dnl For use in AC_SUBST replacement
+define([MOZ_DIVERSION_SUBST], 11)
+
+dnl Replace AC_SUBST to store values in a format suitable for python.
+dnl The necessary comma after the tuple can't be put here because it
+dnl can mess around with things like:
+dnl    AC_SOMETHING(foo,AC_SUBST(),bar)
+define([AC_SUBST],
+[ifdef([AC_SUBST_SET_$1], [m4_fatal([Cannot use AC_SUBST and AC_SUBST_SET on the same variable ($1)])],
+[ifdef([AC_SUBST_LIST_$1], [m4_fatal([Cannot use AC_SUBST and AC_SUBST_LIST on the same variable ($1)])],
+[ifdef([AC_SUBST_$1], ,
+[define([AC_SUBST_$1], )dnl
+AC_DIVERT_PUSH(MOZ_DIVERSION_SUBST)dnl
+    (''' $1 ''', r''' [$]$1 ''')
+AC_DIVERT_POP()dnl
+])])])])
+
+dnl Like AC_SUBST, but makes the value available as a set in python,
+dnl with values got from the value of the environment variable, split on
+dnl whitespaces.
+define([AC_SUBST_SET],
+[ifdef([AC_SUBST_$1], [m4_fatal([Cannot use AC_SUBST and AC_SUBST_SET on the same variable ($1)])],
+[ifdef([AC_SUBST_LIST$1], [m4_fatal([Cannot use AC_SUBST_LIST and AC_SUBST_SET on the same variable ($1)])],
+[ifdef([AC_SUBST_SET_$1], ,
+[define([AC_SUBST_SET_$1], )dnl
+AC_DIVERT_PUSH(MOZ_DIVERSION_SUBST)dnl
+    (''' $1 ''', unique_list(r''' [$]$1 '''.split()))
+AC_DIVERT_POP()dnl
+])])])])
+
+dnl Like AC_SUBST, but makes the value available as a list in python,
+dnl with values got from the value of the environment variable, split on
+dnl whitespaces.
+define([AC_SUBST_LIST],
+[ifdef([AC_SUBST_$1], [m4_fatal([Cannot use AC_SUBST and AC_SUBST_LIST on the same variable ($1)])],
+[ifdef([AC_SUBST_SET_$1], [m4_fatal([Cannot use AC_SUBST_SET and AC_SUBST_LIST on the same variable ($1)])],
+[ifdef([AC_SUBST_LIST_$1], ,
+[define([AC_SUBST_LIST_$1], )dnl
+AC_DIVERT_PUSH(MOZ_DIVERSION_SUBST)dnl
+    (''' $1 ''', list(r''' [$]$1 '''.split()))
+AC_DIVERT_POP()dnl
+])])])])
+
+dnl Ignore AC_SUBSTs for variables we don't have use for but that autoconf
+dnl itself exports.
+define([AC_SUBST_CFLAGS], )
+define([AC_SUBST_CPPFLAGS], )
+define([AC_SUBST_CXXFLAGS], )
+define([AC_SUBST_FFLAGS], )
+define([AC_SUBST_DEFS], )
+define([AC_SUBST_LDFLAGS], )
+define([AC_SUBST_LIBS], )
+
+dnl Wrap AC_DEFINE to store values in a format suitable for python.
+dnl autoconf's AC_DEFINE still needs to be used to fill confdefs.h,
+dnl which is #included during some compile checks.
+dnl The necessary comma after the tuple can't be put here because it
+dnl can mess around with things like:
+dnl    AC_SOMETHING(foo,AC_DEFINE(),bar)
+define([_MOZ_AC_DEFINE], defn([AC_DEFINE]))
+define([AC_DEFINE],
+[cat >> confdefs.pytmp <<\EOF
+    (''' $1 ''', ifelse($#, 2, [r''' $2 '''], $#, 3, [r''' $2 '''], ' 1 '))
+EOF
+ifelse($#, 2, _MOZ_AC_DEFINE([$1], [$2]), $#, 3, _MOZ_AC_DEFINE([$1], [$2], [$3]),_MOZ_AC_DEFINE([$1]))dnl
+])
+
+dnl Wrap AC_DEFINE_UNQUOTED to store values in a format suitable for
+dnl python.
+define([_MOZ_AC_DEFINE_UNQUOTED], defn([AC_DEFINE_UNQUOTED]))
+define([AC_DEFINE_UNQUOTED],
+[cat >> confdefs.pytmp <<EOF
+    (''' $1 ''', ifelse($#, 2, [r''' $2 '''], $#, 3, [r''' $2 '''], ' 1 '))
+EOF
+ifelse($#, 2, _MOZ_AC_DEFINE_UNQUOTED($1, $2), $#, 3, _MOZ_AC_DEFINE_UNQUOTED($1, $2, $3),_MOZ_AC_DEFINE_UNQUOTED($1))dnl
+])
+
+dnl Replace AC_OUTPUT to create and call a python config.status
+define([MOZ_CREATE_CONFIG_STATUS],
+[dnl Top source directory in Windows format (as opposed to msys format).
+WIN_TOP_SRC=
+encoding=utf-8
+case "$host_os" in
+mingw*)
+    WIN_TOP_SRC=`cd $srcdir; pwd -W`
+    encoding=mbcs
+    ;;
+esac
+AC_SUBST(WIN_TOP_SRC)
+
+dnl Used in all Makefile.in files
+top_srcdir=$srcdir
+AC_SUBST(top_srcdir)
+
+dnl Picked from autoconf 2.13
+trap '' 1 2 15
+AC_CACHE_SAVE
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+: ${CONFIG_STATUS=./config.status}
+
+dnl We're going to need [ ] for python syntax.
+changequote(<<<, >>>)dnl
+echo creating $CONFIG_STATUS
+
+extra_python_path=${COMM_BUILD:+"'mozilla', "}
+
+cat > $CONFIG_STATUS <<EOF
+#!${PYTHON}
+# coding=$encoding
+
+import os
+import types
+dnl topsrcdir is the top source directory in native form, as opposed to a
+dnl form suitable for make.
+topsrcdir = '''${WIN_TOP_SRC:-$srcdir}'''
+if not os.path.isabs(topsrcdir):
+    rel = os.path.join(os.path.dirname(<<<__file__>>>), topsrcdir)
+    topsrcdir = os.path.abspath(rel)
+topsrcdir = os.path.normpath(topsrcdir)
+
+topobjdir = os.path.abspath(os.path.dirname(<<<__file__>>>))
+
+def unique_list(l):
+    result = []
+    for i in l:
+        if l not in result:
+            result.append(i)
+    return result
+
+dnl All defines and substs are stored with an additional space at the beginning
+dnl and at the end of the string, to avoid any problem with values starting or
+dnl ending with quotes.
+defines = [(name[1:-1], value[1:-1]) for name, value in [
+EOF
+
+dnl confdefs.pytmp contains AC_DEFINEs, in the expected format, but
+dnl lacks the final comma (see above).
+sed 's/$/,/' confdefs.pytmp >> $CONFIG_STATUS
+rm confdefs.pytmp confdefs.h
+
+cat >> $CONFIG_STATUS <<\EOF
+] ]
+
+substs = [(name[1:-1], value[1:-1] if isinstance(value, types.StringTypes) else value) for name, value in [
+EOF
+
+dnl The MOZ_DIVERSION_SUBST output diversion contains AC_SUBSTs, in the
+dnl expected format, but lacks the final comma (see above).
+sed 's/$/,/' >> $CONFIG_STATUS <<EOF
+undivert(MOZ_DIVERSION_SUBST)dnl
+EOF
+
+dnl Add in the output from the subconfigure script
+for ac_subst_arg in $_subconfigure_ac_subst_args; do
+  variable='$'$ac_subst_arg
+  echo "    (''' $ac_subst_arg ''', r''' `eval echo $variable` ''')," >> $CONFIG_STATUS
+done
+
+cat >> $CONFIG_STATUS <<\EOF
+] ]
+
+dnl List of AC_DEFINEs that aren't to be exposed in ALLDEFINES
+non_global_defines = [
+EOF
+
+if test -n "$_NON_GLOBAL_ACDEFINES"; then
+  for var in $_NON_GLOBAL_ACDEFINES; do
+    echo "    '$var'," >> $CONFIG_STATUS
+  done
+fi
+
+cat >> $CONFIG_STATUS <<EOF
+]
+
+__all__ = ['topobjdir', 'topsrcdir', 'defines', 'non_global_defines', 'substs']
+EOF
+
+# We don't want js/src/config.status to do anything in gecko builds.
+if test -z "$BUILDING_JS" -o -n "$JS_STANDALONE"; then
+
+    cat >> $CONFIG_STATUS <<EOF
+dnl Do the actual work
+if __name__ == '__main__':
+    args = dict([(name, globals()[name]) for name in __all__])
+    from mozbuild.config_status import config_status
+    config_status(**args)
+EOF
+
+fi
+
+changequote([, ])
+
+chmod +x $CONFIG_STATUS
+])
+
+define([MOZ_RUN_CONFIG_STATUS],
+[
+
+MOZ_RUN_ALL_SUBCONFIGURES()
+
+rm -fr confdefs* $ac_clean_files
+dnl Execute config.status, unless --no-create was passed to configure.
+if test "$no_create" != yes && ! ${PYTHON} $CONFIG_STATUS; then
+    trap '' EXIT
+    exit 1
+fi
+])
+
+define([m4_fatal],[
+errprint([$1
+])
+m4exit(1)
+])
+
+define([AC_OUTPUT], [ifelse($#_$1, 1_, [MOZ_CREATE_CONFIG_STATUS()
+MOZ_RUN_CONFIG_STATUS()],
+[m4_fatal([Use CONFIGURE_SUBST_FILES in moz.build files to create substituted files.])]
+)])
+
+define([AC_CONFIG_HEADER],
+[m4_fatal([Use CONFIGURE_DEFINE_FILES in moz.build files to produce header files.])
+])
+
+define([MOZ_BUILD_BACKEND],
+[
+BUILD_BACKENDS="RecursiveMake"
+
+MOZ_ARG_ENABLE_STRING(build-backend,
+[  --enable-build-backend={AndroidEclipse,CppEclipse,VisualStudio,FasterMake,CompileDB}
+                         Enable additional build backends],
+[ BUILD_BACKENDS="RecursiveMake `echo $enableval | sed 's/,/ /g'`"])
+
+AC_SUBST_SET([BUILD_BACKENDS])
+])
diff --git a/src/third_party/mozjs-45/build/autoconf/config.sub b/src/third_party/mozjs-45/build/autoconf/config.sub
new file mode 100755
index 0000000..91476e8
--- /dev/null
+++ b/src/third_party/mozjs-45/build/autoconf/config.sub
@@ -0,0 +1,1795 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+#   Copyright 1992-2014 Free Software Foundation, Inc.
+
+timestamp='2014-01-01'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that
+# program.  This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
+
+
+# Please send patches with a ChangeLog entry to config-patches@gnu.org.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support.  The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+#	CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+#	CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+       $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright 1992-2014 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help"
+       exit 1 ;;
+
+    *local*)
+       # First pass through any local machine types.
+       echo $1
+       exit ;;
+
+    * )
+       break ;;
+  esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+    exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+    exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+  nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | \
+  linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
+  knetbsd*-gnu* | netbsd*-gnu* | \
+  kopensolaris*-gnu* | \
+  storm-chaos* | os2-emx* | rtmk-nova*)
+    os=-$maybe_os
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+    ;;
+  *)
+    basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+    if [ $basic_machine != $1 ]
+    then os=`echo $1 | sed 's/.*-/-/'`
+    else os=; fi
+    ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work.  We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+	-sun*os*)
+		# Prevent following clause from handling this invalid input.
+		;;
+	-dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+	-att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+	-unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+	-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+	-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+	-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+	-apple | -axis | -knuth | -cray | -microblaze*)
+		os=
+		basic_machine=$1
+		;;
+	-bluegene*)
+		os=-cnk
+		;;
+	-sim | -cisco | -oki | -wec | -winbond)
+		os=
+		basic_machine=$1
+		;;
+	-scout)
+		;;
+	-wrs)
+		os=-vxworks
+		basic_machine=$1
+		;;
+	-chorusos*)
+		os=-chorusos
+		basic_machine=$1
+		;;
+	-chorusrdb)
+		os=-chorusrdb
+		basic_machine=$1
+		;;
+	-hiux*)
+		os=-hiuxwe2
+		;;
+	-sco6)
+		os=-sco5v6
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco5)
+		os=-sco3.2v5
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco4)
+		os=-sco3.2v4
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2.[4-9]*)
+		os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2v[4-9]*)
+		# Don't forget version if it is 3.2v4 or newer.
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco5v6*)
+		# Don't forget version if it is 3.2v4 or newer.
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco*)
+		os=-sco3.2v2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-udk*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-isc)
+		os=-isc2.2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-clix*)
+		basic_machine=clipper-intergraph
+		;;
+	-isc*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-lynx*178)
+		os=-lynxos178
+		;;
+	-lynx*5)
+		os=-lynxos5
+		;;
+	-lynx*)
+		os=-lynxos
+		;;
+	-ptx*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+		;;
+	-windowsnt*)
+		os=`echo $os | sed -e 's/windowsnt/winnt/'`
+		;;
+	-psos*)
+		os=-psos
+		;;
+	-mint | -mint[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+	# Recognize the basic CPU types without company name.
+	# Some are omitted here because they have special meanings below.
+	1750a | 580 \
+	| a29k \
+	| aarch64 | aarch64_be \
+	| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+	| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+	| am33_2.0 \
+	| arc | arceb \
+	| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
+	| avr | avr32 \
+	| be32 | be64 \
+	| bfin \
+	| c4x | c8051 | clipper \
+	| d10v | d30v | dlx | dsp16xx \
+	| epiphany \
+	| fido | fr30 | frv \
+	| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+	| hexagon \
+	| i370 | i860 | i960 | ia64 \
+	| ip2k | iq2000 \
+	| k1om \
+	| le32 | le64 \
+	| lm32 \
+	| m32c | m32r | m32rle | m68000 | m68k | m88k \
+	| maxq | mb | microblaze | microblazeel | mcore | mep | metag \
+	| mips | mipsbe | mipseb | mipsel | mipsle \
+	| mips16 \
+	| mips64 | mips64el \
+	| mips64octeon | mips64octeonel \
+	| mips64orion | mips64orionel \
+	| mips64r5900 | mips64r5900el \
+	| mips64vr | mips64vrel \
+	| mips64vr4100 | mips64vr4100el \
+	| mips64vr4300 | mips64vr4300el \
+	| mips64vr5000 | mips64vr5000el \
+	| mips64vr5900 | mips64vr5900el \
+	| mipsisa32 | mipsisa32el \
+	| mipsisa32r2 | mipsisa32r2el \
+	| mipsisa64 | mipsisa64el \
+	| mipsisa64r2 | mipsisa64r2el \
+	| mipsisa64sb1 | mipsisa64sb1el \
+	| mipsisa64sr71k | mipsisa64sr71kel \
+	| mipsr5900 | mipsr5900el \
+	| mipstx39 | mipstx39el \
+	| mn10200 | mn10300 \
+	| moxie \
+	| mt \
+	| msp430 \
+	| nds32 | nds32le | nds32be \
+	| nios | nios2 | nios2eb | nios2el \
+	| ns16k | ns32k \
+	| open8 \
+	| or1k | or32 \
+	| pdp10 | pdp11 | pj | pjl \
+	| powerpc | powerpc64 | powerpc64le | powerpcle \
+	| pyramid \
+	| rl78 | rx \
+	| score \
+	| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+	| sh64 | sh64le \
+	| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+	| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+	| spu \
+	| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
+	| ubicom32 \
+	| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
+	| we32k \
+	| x86 | xc16x | xstormy16 | xtensa \
+	| z8k | z80)
+		basic_machine=$basic_machine-unknown
+		;;
+	c54x)
+		basic_machine=tic54x-unknown
+		;;
+	c55x)
+		basic_machine=tic55x-unknown
+		;;
+	c6x)
+		basic_machine=tic6x-unknown
+		;;
+	m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
+		basic_machine=$basic_machine-unknown
+		os=-none
+		;;
+	m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+		;;
+	ms1)
+		basic_machine=mt-unknown
+		;;
+
+	strongarm | thumb | xscale)
+		basic_machine=arm-unknown
+		;;
+	xgate)
+		basic_machine=$basic_machine-unknown
+		os=-none
+		;;
+	xscaleeb)
+		basic_machine=armeb-unknown
+		;;
+
+	xscaleel)
+		basic_machine=armel-unknown
+		;;
+
+	# We use `pc' rather than `unknown'
+	# because (1) that's what they normally are, and
+	# (2) the word "unknown" tends to confuse beginning users.
+	i*86 | x86_64)
+	  basic_machine=$basic_machine-pc
+	  ;;
+	# Object if more than one company name word.
+	*-*-*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+	# Recognize the basic CPU types with company name.
+	580-* \
+	| a29k-* \
+	| aarch64-* | aarch64_be-* \
+	| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+	| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
+	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
+	| avr-* | avr32-* \
+	| be32-* | be64-* \
+	| bfin-* | bs2000-* \
+	| c[123]* | c30-* | [cjt]90-* | c4x-* \
+	| c8051-* | clipper-* | craynv-* | cydra-* \
+	| d10v-* | d30v-* | dlx-* \
+	| elxsi-* \
+	| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
+	| h8300-* | h8500-* \
+	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+	| hexagon-* \
+	| i*86-* | i860-* | i960-* | ia64-* \
+	| ip2k-* | iq2000-* \
+	| k1om-* \
+	| le32-* | le64-* \
+	| lm32-* \
+	| m32c-* | m32r-* | m32rle-* \
+	| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+	| m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
+	| microblaze-* | microblazeel-* \
+	| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+	| mips16-* \
+	| mips64-* | mips64el-* \
+	| mips64octeon-* | mips64octeonel-* \
+	| mips64orion-* | mips64orionel-* \
+	| mips64r5900-* | mips64r5900el-* \
+	| mips64vr-* | mips64vrel-* \
+	| mips64vr4100-* | mips64vr4100el-* \
+	| mips64vr4300-* | mips64vr4300el-* \
+	| mips64vr5000-* | mips64vr5000el-* \
+	| mips64vr5900-* | mips64vr5900el-* \
+	| mipsisa32-* | mipsisa32el-* \
+	| mipsisa32r2-* | mipsisa32r2el-* \
+	| mipsisa64-* | mipsisa64el-* \
+	| mipsisa64r2-* | mipsisa64r2el-* \
+	| mipsisa64sb1-* | mipsisa64sb1el-* \
+	| mipsisa64sr71k-* | mipsisa64sr71kel-* \
+	| mipsr5900-* | mipsr5900el-* \
+	| mipstx39-* | mipstx39el-* \
+	| mmix-* \
+	| mt-* \
+	| msp430-* \
+	| nds32-* | nds32le-* | nds32be-* \
+	| nios-* | nios2-* | nios2eb-* | nios2el-* \
+	| none-* | np1-* | ns16k-* | ns32k-* \
+	| open8-* \
+	| orion-* \
+	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
+	| pyramid-* \
+	| rl78-* | romp-* | rs6000-* | rx-* \
+	| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+	| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+	| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
+	| sparclite-* \
+	| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
+	| tahoe-* \
+	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+	| tile*-* \
+	| tron-* \
+	| ubicom32-* \
+	| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
+	| vax-* \
+	| we32k-* \
+	| x86-* | x86_64-* | xc16x-* | xps100-* \
+	| xstormy16-* | xtensa*-* \
+	| ymp-* \
+	| z8k-* | z80-*)
+		;;
+	# Recognize the basic CPU types without company name, with glob match.
+	xtensa*)
+		basic_machine=$basic_machine-unknown
+		;;
+	# Recognize the various machine names and aliases which stand
+	# for a CPU type and a company and sometimes even an OS.
+	386bsd)
+		basic_machine=i386-unknown
+		os=-bsd
+		;;
+	3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+		basic_machine=m68000-att
+		;;
+	3b*)
+		basic_machine=we32k-att
+		;;
+	a29khif)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	abacus)
+		basic_machine=abacus-unknown
+		;;
+	adobe68k)
+		basic_machine=m68010-adobe
+		os=-scout
+		;;
+	alliant | fx80)
+		basic_machine=fx80-alliant
+		;;
+	altos | altos3068)
+		basic_machine=m68k-altos
+		;;
+	am29k)
+		basic_machine=a29k-none
+		os=-bsd
+		;;
+	amd64)
+		basic_machine=x86_64-pc
+		;;
+	amd64-*)
+		basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	amdahl)
+		basic_machine=580-amdahl
+		os=-sysv
+		;;
+	amiga | amiga-*)
+		basic_machine=m68k-unknown
+		;;
+	amigaos | amigados)
+		basic_machine=m68k-unknown
+		os=-amigaos
+		;;
+	amigaunix | amix)
+		basic_machine=m68k-unknown
+		os=-sysv4
+		;;
+	apollo68)
+		basic_machine=m68k-apollo
+		os=-sysv
+		;;
+	apollo68bsd)
+		basic_machine=m68k-apollo
+		os=-bsd
+		;;
+	aros)
+		basic_machine=i386-pc
+		os=-aros
+		;;
+	aux)
+		basic_machine=m68k-apple
+		os=-aux
+		;;
+	balance)
+		basic_machine=ns32k-sequent
+		os=-dynix
+		;;
+	blackfin)
+		basic_machine=bfin-unknown
+		os=-linux
+		;;
+	blackfin-*)
+		basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
+	bluegene*)
+		basic_machine=powerpc-ibm
+		os=-cnk
+		;;
+	c54x-*)
+		basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	c55x-*)
+		basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	c6x-*)
+		basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	c90)
+		basic_machine=c90-cray
+		os=-unicos
+		;;
+	cegcc)
+		basic_machine=arm-unknown
+		os=-cegcc
+		;;
+	convex-c1)
+		basic_machine=c1-convex
+		os=-bsd
+		;;
+	convex-c2)
+		basic_machine=c2-convex
+		os=-bsd
+		;;
+	convex-c32)
+		basic_machine=c32-convex
+		os=-bsd
+		;;
+	convex-c34)
+		basic_machine=c34-convex
+		os=-bsd
+		;;
+	convex-c38)
+		basic_machine=c38-convex
+		os=-bsd
+		;;
+	cray | j90)
+		basic_machine=j90-cray
+		os=-unicos
+		;;
+	craynv)
+		basic_machine=craynv-cray
+		os=-unicosmp
+		;;
+	cr16 | cr16-*)
+		basic_machine=cr16-unknown
+		os=-elf
+		;;
+	crds | unos)
+		basic_machine=m68k-crds
+		;;
+	crisv32 | crisv32-* | etraxfs*)
+		basic_machine=crisv32-axis
+		;;
+	cris | cris-* | etrax*)
+		basic_machine=cris-axis
+		;;
+	crx)
+		basic_machine=crx-unknown
+		os=-elf
+		;;
+	da30 | da30-*)
+		basic_machine=m68k-da30
+		;;
+	decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+		basic_machine=mips-dec
+		;;
+	decsystem10* | dec10*)
+		basic_machine=pdp10-dec
+		os=-tops10
+		;;
+	decsystem20* | dec20*)
+		basic_machine=pdp10-dec
+		os=-tops20
+		;;
+	delta | 3300 | motorola-3300 | motorola-delta \
+	      | 3300-motorola | delta-motorola)
+		basic_machine=m68k-motorola
+		;;
+	delta88)
+		basic_machine=m88k-motorola
+		os=-sysv3
+		;;
+	dicos)
+		basic_machine=i686-pc
+		os=-dicos
+		;;
+	djgpp)
+		basic_machine=i586-pc
+		os=-msdosdjgpp
+		;;
+	dpx20 | dpx20-*)
+		basic_machine=rs6000-bull
+		os=-bosx
+		;;
+	dpx2* | dpx2*-bull)
+		basic_machine=m68k-bull
+		os=-sysv3
+		;;
+	ebmon29k)
+		basic_machine=a29k-amd
+		os=-ebmon
+		;;
+	elxsi)
+		basic_machine=elxsi-elxsi
+		os=-bsd
+		;;
+	encore | umax | mmax)
+		basic_machine=ns32k-encore
+		;;
+	es1800 | OSE68k | ose68k | ose | OSE)
+		basic_machine=m68k-ericsson
+		os=-ose
+		;;
+	fx2800)
+		basic_machine=i860-alliant
+		;;
+	genix)
+		basic_machine=ns32k-ns
+		;;
+	gmicro)
+		basic_machine=tron-gmicro
+		os=-sysv
+		;;
+	go32)
+		basic_machine=i386-pc
+		os=-go32
+		;;
+	h3050r* | hiux*)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	h8300hms)
+		basic_machine=h8300-hitachi
+		os=-hms
+		;;
+	h8300xray)
+		basic_machine=h8300-hitachi
+		os=-xray
+		;;
+	h8500hms)
+		basic_machine=h8500-hitachi
+		os=-hms
+		;;
+	harris)
+		basic_machine=m88k-harris
+		os=-sysv3
+		;;
+	hp300-*)
+		basic_machine=m68k-hp
+		;;
+	hp300bsd)
+		basic_machine=m68k-hp
+		os=-bsd
+		;;
+	hp300hpux)
+		basic_machine=m68k-hp
+		os=-hpux
+		;;
+	hp3k9[0-9][0-9] | hp9[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k2[0-9][0-9] | hp9k31[0-9])
+		basic_machine=m68000-hp
+		;;
+	hp9k3[2-9][0-9])
+		basic_machine=m68k-hp
+		;;
+	hp9k6[0-9][0-9] | hp6[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k7[0-79][0-9] | hp7[0-79][0-9])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k78[0-9] | hp78[0-9])
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][13679] | hp8[0-9][13679])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][0-9] | hp8[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hppa-next)
+		os=-nextstep3
+		;;
+	hppaosf)
+		basic_machine=hppa1.1-hp
+		os=-osf
+		;;
+	hppro)
+		basic_machine=hppa1.1-hp
+		os=-proelf
+		;;
+	i370-ibm* | ibm*)
+		basic_machine=i370-ibm
+		;;
+	i*86v32)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv32
+		;;
+	i*86v4*)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv4
+		;;
+	i*86v)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv
+		;;
+	i*86sol2)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-solaris2
+		;;
+	i386mach)
+		basic_machine=i386-mach
+		os=-mach
+		;;
+	i386-vsta | vsta)
+		basic_machine=i386-unknown
+		os=-vsta
+		;;
+	iris | iris4d)
+		basic_machine=mips-sgi
+		case $os in
+		    -irix*)
+			;;
+		    *)
+			os=-irix4
+			;;
+		esac
+		;;
+	isi68 | isi)
+		basic_machine=m68k-isi
+		os=-sysv
+		;;
+	m68knommu)
+		basic_machine=m68k-unknown
+		os=-linux
+		;;
+	m68knommu-*)
+		basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
+	m88k-omron*)
+		basic_machine=m88k-omron
+		;;
+	magnum | m3230)
+		basic_machine=mips-mips
+		os=-sysv
+		;;
+	merlin)
+		basic_machine=ns32k-utek
+		os=-sysv
+		;;
+	microblaze*)
+		basic_machine=microblaze-xilinx
+		;;
+	mingw64)
+		basic_machine=x86_64-pc
+		os=-mingw64
+		;;
+	mingw32)
+		basic_machine=i686-pc
+		os=-mingw32
+		;;
+	mingw32ce)
+		basic_machine=arm-unknown
+		os=-mingw32ce
+		;;
+	miniframe)
+		basic_machine=m68000-convergent
+		;;
+	*mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
+	mips3*-*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+		;;
+	mips3*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+		;;
+	monitor)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	morphos)
+		basic_machine=powerpc-unknown
+		os=-morphos
+		;;
+	msdos)
+		basic_machine=i386-pc
+		os=-msdos
+		;;
+	ms1-*)
+		basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+		;;
+	msys)
+		basic_machine=i686-pc
+		os=-msys
+		;;
+	mvs)
+		basic_machine=i370-ibm
+		os=-mvs
+		;;
+	nacl)
+		basic_machine=le32-unknown
+		os=-nacl
+		;;
+	ncr3000)
+		basic_machine=i486-ncr
+		os=-sysv4
+		;;
+	netbsd386)
+		basic_machine=i386-unknown
+		os=-netbsd
+		;;
+	netwinder)
+		basic_machine=armv4l-rebel
+		os=-linux
+		;;
+	news | news700 | news800 | news900)
+		basic_machine=m68k-sony
+		os=-newsos
+		;;
+	news1000)
+		basic_machine=m68030-sony
+		os=-newsos
+		;;
+	news-3600 | risc-news)
+		basic_machine=mips-sony
+		os=-newsos
+		;;
+	necv70)
+		basic_machine=v70-nec
+		os=-sysv
+		;;
+	next | m*-next )
+		basic_machine=m68k-next
+		case $os in
+		    -nextstep* )
+			;;
+		    -ns2*)
+		      os=-nextstep2
+			;;
+		    *)
+		      os=-nextstep3
+			;;
+		esac
+		;;
+	nh3000)
+		basic_machine=m68k-harris
+		os=-cxux
+		;;
+	nh[45]000)
+		basic_machine=m88k-harris
+		os=-cxux
+		;;
+	nindy960)
+		basic_machine=i960-intel
+		os=-nindy
+		;;
+	mon960)
+		basic_machine=i960-intel
+		os=-mon960
+		;;
+	nonstopux)
+		basic_machine=mips-compaq
+		os=-nonstopux
+		;;
+	np1)
+		basic_machine=np1-gould
+		;;
+	neo-tandem)
+		basic_machine=neo-tandem
+		;;
+	nse-tandem)
+		basic_machine=nse-tandem
+		;;
+	nsr-tandem)
+		basic_machine=nsr-tandem
+		;;
+	op50n-* | op60c-*)
+		basic_machine=hppa1.1-oki
+		os=-proelf
+		;;
+	openrisc | openrisc-*)
+		basic_machine=or32-unknown
+		;;
+	os400)
+		basic_machine=powerpc-ibm
+		os=-os400
+		;;
+	OSE68000 | ose68000)
+		basic_machine=m68000-ericsson
+		os=-ose
+		;;
+	os68k)
+		basic_machine=m68k-none
+		os=-os68k
+		;;
+	pa-hitachi)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	paragon)
+		basic_machine=i860-intel
+		os=-osf
+		;;
+	parisc)
+		basic_machine=hppa-unknown
+		os=-linux
+		;;
+	parisc-*)
+		basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
+	pbd)
+		basic_machine=sparc-tti
+		;;
+	pbb)
+		basic_machine=m68k-tti
+		;;
+	pc532 | pc532-*)
+		basic_machine=ns32k-pc532
+		;;
+	pc98)
+		basic_machine=i386-pc
+		;;
+	pc98-*)
+		basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentium | p5 | k5 | k6 | nexgen | viac3)
+		basic_machine=i586-pc
+		;;
+	pentiumpro | p6 | 6x86 | athlon | athlon_*)
+		basic_machine=i686-pc
+		;;
+	pentiumii | pentium2 | pentiumiii | pentium3)
+		basic_machine=i686-pc
+		;;
+	pentium4)
+		basic_machine=i786-pc
+		;;
+	pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+		basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentiumpro-* | p6-* | 6x86-* | athlon-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentium4-*)
+		basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pn)
+		basic_machine=pn-gould
+		;;
+	power)	basic_machine=power-ibm
+		;;
+	ppc | ppcbe)	basic_machine=powerpc-unknown
+		;;
+	ppc-* | ppcbe-*)
+		basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppcle | powerpclittle | ppc-le | powerpc-little)
+		basic_machine=powerpcle-unknown
+		;;
+	ppcle-* | powerpclittle-*)
+		basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppc64)	basic_machine=powerpc64-unknown
+		;;
+	ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+		basic_machine=powerpc64le-unknown
+		;;
+	ppc64le-* | powerpc64little-*)
+		basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ps2)
+		basic_machine=i386-ibm
+		;;
+	pw32)
+		basic_machine=i586-unknown
+		os=-pw32
+		;;
+	rdos | rdos64)
+		basic_machine=x86_64-pc
+		os=-rdos
+		;;
+	rdos32)
+		basic_machine=i386-pc
+		os=-rdos
+		;;
+	rom68k)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	rm[46]00)
+		basic_machine=mips-siemens
+		;;
+	rtpc | rtpc-*)
+		basic_machine=romp-ibm
+		;;
+	s390 | s390-*)
+		basic_machine=s390-ibm
+		;;
+	s390x | s390x-*)
+		basic_machine=s390x-ibm
+		;;
+	sa29200)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	sb1)
+		basic_machine=mipsisa64sb1-unknown
+		;;
+	sb1el)
+		basic_machine=mipsisa64sb1el-unknown
+		;;
+	sde)
+		basic_machine=mipsisa32-sde
+		os=-elf
+		;;
+	sei)
+		basic_machine=mips-sei
+		os=-seiux
+		;;
+	sequent)
+		basic_machine=i386-sequent
+		;;
+	sh)
+		basic_machine=sh-hitachi
+		os=-hms
+		;;
+	sh5el)
+		basic_machine=sh5le-unknown
+		;;
+	sh64)
+		basic_machine=sh64-unknown
+		;;
+	sparclite-wrs | simso-wrs)
+		basic_machine=sparclite-wrs
+		os=-vxworks
+		;;
+	sps7)
+		basic_machine=m68k-bull
+		os=-sysv2
+		;;
+	spur)
+		basic_machine=spur-unknown
+		;;
+	st2000)
+		basic_machine=m68k-tandem
+		;;
+	stratus)
+		basic_machine=i860-stratus
+		os=-sysv4
+		;;
+	strongarm-* | thumb-*)
+		basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	sun2)
+		basic_machine=m68000-sun
+		;;
+	sun2os3)
+		basic_machine=m68000-sun
+		os=-sunos3
+		;;
+	sun2os4)
+		basic_machine=m68000-sun
+		os=-sunos4
+		;;
+	sun3os3)
+		basic_machine=m68k-sun
+		os=-sunos3
+		;;
+	sun3os4)
+		basic_machine=m68k-sun
+		os=-sunos4
+		;;
+	sun4os3)
+		basic_machine=sparc-sun
+		os=-sunos3
+		;;
+	sun4os4)
+		basic_machine=sparc-sun
+		os=-sunos4
+		;;
+	sun4sol2)
+		basic_machine=sparc-sun
+		os=-solaris2
+		;;
+	sun3 | sun3-*)
+		basic_machine=m68k-sun
+		;;
+	sun4)
+		basic_machine=sparc-sun
+		;;
+	sun386 | sun386i | roadrunner)
+		basic_machine=i386-sun
+		;;
+	sv1)
+		basic_machine=sv1-cray
+		os=-unicos
+		;;
+	symmetry)
+		basic_machine=i386-sequent
+		os=-dynix
+		;;
+	t3e)
+		basic_machine=alphaev5-cray
+		os=-unicos
+		;;
+	t90)
+		basic_machine=t90-cray
+		os=-unicos
+		;;
+	tile*)
+		basic_machine=$basic_machine-unknown
+		os=-linux-gnu
+		;;
+	tx39)
+		basic_machine=mipstx39-unknown
+		;;
+	tx39el)
+		basic_machine=mipstx39el-unknown
+		;;
+	toad1)
+		basic_machine=pdp10-xkl
+		os=-tops20
+		;;
+	tower | tower-32)
+		basic_machine=m68k-ncr
+		;;
+	tpf)
+		basic_machine=s390x-ibm
+		os=-tpf
+		;;
+	udi29k)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	ultra3)
+		basic_machine=a29k-nyu
+		os=-sym1
+		;;
+	v810 | necv810)
+		basic_machine=v810-nec
+		os=-none
+		;;
+	vaxv)
+		basic_machine=vax-dec
+		os=-sysv
+		;;
+	vms)
+		basic_machine=vax-dec
+		os=-vms
+		;;
+	vpp*|vx|vx-*)
+		basic_machine=f301-fujitsu
+		;;
+	vxworks960)
+		basic_machine=i960-wrs
+		os=-vxworks
+		;;
+	vxworks68)
+		basic_machine=m68k-wrs
+		os=-vxworks
+		;;
+	vxworks29k)
+		basic_machine=a29k-wrs
+		os=-vxworks
+		;;
+	w65*)
+		basic_machine=w65-wdc
+		os=-none
+		;;
+	w89k-*)
+		basic_machine=hppa1.1-winbond
+		os=-proelf
+		;;
+	xbox)
+		basic_machine=i686-pc
+		os=-mingw32
+		;;
+	xps | xps100)
+		basic_machine=xps100-honeywell
+		;;
+	xscale-* | xscalee[bl]-*)
+		basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
+		;;
+	ymp)
+		basic_machine=ymp-cray
+		os=-unicos
+		;;
+	z8k-*-coff)
+		basic_machine=z8k-unknown
+		os=-sim
+		;;
+	z80-*-coff)
+		basic_machine=z80-unknown
+		os=-sim
+		;;
+	none)
+		basic_machine=none-none
+		os=-none
+		;;
+
+# Here we handle the default manufacturer of certain CPU types.  It is in
+# some cases the only manufacturer, in others, it is the most popular.
+	w89k)
+		basic_machine=hppa1.1-winbond
+		;;
+	op50n)
+		basic_machine=hppa1.1-oki
+		;;
+	op60c)
+		basic_machine=hppa1.1-oki
+		;;
+	romp)
+		basic_machine=romp-ibm
+		;;
+	mmix)
+		basic_machine=mmix-knuth
+		;;
+	rs6000)
+		basic_machine=rs6000-ibm
+		;;
+	vax)
+		basic_machine=vax-dec
+		;;
+	pdp10)
+		# there are many clones, so DEC is not a safe bet
+		basic_machine=pdp10-unknown
+		;;
+	pdp11)
+		basic_machine=pdp11-dec
+		;;
+	we32k)
+		basic_machine=we32k-att
+		;;
+	sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
+		basic_machine=sh-unknown
+		;;
+	sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
+		basic_machine=sparc-sun
+		;;
+	cydra)
+		basic_machine=cydra-cydrome
+		;;
+	orion)
+		basic_machine=orion-highlevel
+		;;
+	orion105)
+		basic_machine=clipper-highlevel
+		;;
+	mac | mpw | mac-mpw)
+		basic_machine=m68k-apple
+		;;
+	pmac | pmac-mpw)
+		basic_machine=powerpc-apple
+		;;
+	*-unknown)
+		# Make sure to match an already-canonicalized machine name.
+		;;
+	*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+	*-digital*)
+		basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+		;;
+	*-commodore*)
+		basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+		;;
+	*)
+		;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+	# First match some system type aliases
+	# that might get confused with valid system types.
+	# -solaris* is a basic system type, with this one exception.
+	-auroraux)
+		os=-auroraux
+		;;
+	-solaris1 | -solaris1.*)
+		os=`echo $os | sed -e 's|solaris1|sunos4|'`
+		;;
+	-solaris)
+		os=-solaris2
+		;;
+	-svr4*)
+		os=-sysv4
+		;;
+	-unixware*)
+		os=-sysv4.2uw
+		;;
+	-gnu/linux*)
+		os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+		;;
+	# First accept the basic system types.
+	# The portable systems comes first.
+	# Each alternative MUST END IN A *, to match a version number.
+	# -sysv* is not here because it comes later, after sysvr4.
+	-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+	      | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
+	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
+	      | -sym* | -kopensolaris* | -plan9* \
+	      | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+	      | -aos* | -aros* \
+	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+	      | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
+	      | -bitrig* | -openbsd* | -solidbsd* \
+	      | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+	      | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+	      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+	      | -chorusos* | -chorusrdb* | -cegcc* \
+	      | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+	      | -mingw32* | -mingw64* | -linux-gnu* \
+	      | -linux-newlib* | -linux-musl* | -linux-uclibc* \
+	      | -uxpv* | -beos* | -mpeix* | -udk* \
+	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+	      | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+	      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+	      | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*)
+	# Remember, each alternative MUST END IN *, to match a version number.
+		;;
+	-qnx*)
+		case $basic_machine in
+		    x86-* | i*86-*)
+			;;
+		    *)
+			os=-nto$os
+			;;
+		esac
+		;;
+	-nto-qnx*)
+		;;
+	-nto*)
+		os=`echo $os | sed -e 's|nto|nto-qnx|'`
+		;;
+	-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+	      | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+	      | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+		;;
+	-mac*)
+		os=`echo $os | sed -e 's|mac|macos|'`
+		;;
+	-linux-dietlibc)
+		os=-linux-dietlibc
+		;;
+	-linux*)
+		os=`echo $os | sed -e 's|linux|linux-gnu|'`
+		;;
+	-sunos5*)
+		os=`echo $os | sed -e 's|sunos5|solaris2|'`
+		;;
+	-sunos6*)
+		os=`echo $os | sed -e 's|sunos6|solaris3|'`
+		;;
+	-opened*)
+		os=-openedition
+		;;
+	-os400*)
+		os=-os400
+		;;
+	-wince*)
+		os=-wince
+		;;
+	-osfrose*)
+		os=-osfrose
+		;;
+	-osf*)
+		os=-osf
+		;;
+	-utek*)
+		os=-bsd
+		;;
+	-dynix*)
+		os=-bsd
+		;;
+	-acis*)
+		os=-aos
+		;;
+	-atheos*)
+		os=-atheos
+		;;
+	-syllable*)
+		os=-syllable
+		;;
+	-386bsd)
+		os=-bsd
+		;;
+	-ctix* | -uts*)
+		os=-sysv
+		;;
+	-nova*)
+		os=-rtmk-nova
+		;;
+	-ns2 )
+		os=-nextstep2
+		;;
+	-nsk*)
+		os=-nsk
+		;;
+	# Preserve the version number of sinix5.
+	-sinix5.*)
+		os=`echo $os | sed -e 's|sinix|sysv|'`
+		;;
+	-sinix*)
+		os=-sysv4
+		;;
+	-tpf*)
+		os=-tpf
+		;;
+	-triton*)
+		os=-sysv3
+		;;
+	-oss*)
+		os=-sysv3
+		;;
+	-svr4)
+		os=-sysv4
+		;;
+	-svr3)
+		os=-sysv3
+		;;
+	-sysvr4)
+		os=-sysv4
+		;;
+	# This must come after -sysvr4.
+	-sysv*)
+		;;
+	-ose*)
+		os=-ose
+		;;
+	-es1800*)
+		os=-ose
+		;;
+	-xenix)
+		os=-xenix
+		;;
+	-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+		os=-mint
+		;;
+	-aros*)
+		os=-aros
+		;;
+	-zvmoe)
+		os=-zvmoe
+		;;
+	-dicos*)
+		os=-dicos
+		;;
+        -android*)
+	        os=-android
+                ;;
+	-nacl*)
+		;;
+	-none)
+		;;
+	*)
+		# Get rid of the `-' at the beginning of $os.
+		os=`echo $os | sed 's/[^-]*-//'`
+		echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+		exit 1
+		;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system.  Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+	score-*)
+		os=-elf
+		;;
+	spu-*)
+		os=-elf
+		;;
+	*-acorn)
+		os=-riscix1.2
+		;;
+	arm*-rebel)
+		os=-linux
+		;;
+	arm*-semi)
+		os=-aout
+		;;
+	c4x-* | tic4x-*)
+		os=-coff
+		;;
+	c8051-*)
+		os=-elf
+		;;
+	hexagon-*)
+		os=-elf
+		;;
+	tic54x-*)
+		os=-coff
+		;;
+	tic55x-*)
+		os=-coff
+		;;
+	tic6x-*)
+		os=-coff
+		;;
+	# This must come before the *-dec entry.
+	pdp10-*)
+		os=-tops20
+		;;
+	pdp11-*)
+		os=-none
+		;;
+	*-dec | vax-*)
+		os=-ultrix4.2
+		;;
+	m68*-apollo)
+		os=-domain
+		;;
+	i386-sun)
+		os=-sunos4.0.2
+		;;
+	m68000-sun)
+		os=-sunos3
+		;;
+	m68*-cisco)
+		os=-aout
+		;;
+	mep-*)
+		os=-elf
+		;;
+	mips*-cisco)
+		os=-elf
+		;;
+	mips*-*)
+		os=-elf
+		;;
+	or1k-*)
+		os=-elf
+		;;
+	or32-*)
+		os=-coff
+		;;
+	*-tti)	# must be before sparc entry or we get the wrong os.
+		os=-sysv3
+		;;
+	sparc-* | *-sun)
+		os=-sunos4.1.1
+		;;
+	*-be)
+		os=-beos
+		;;
+	*-haiku)
+		os=-haiku
+		;;
+	*-ibm)
+		os=-aix
+		;;
+	*-knuth)
+		os=-mmixware
+		;;
+	*-wec)
+		os=-proelf
+		;;
+	*-winbond)
+		os=-proelf
+		;;
+	*-oki)
+		os=-proelf
+		;;
+	*-hp)
+		os=-hpux
+		;;
+	*-hitachi)
+		os=-hiux
+		;;
+	i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+		os=-sysv
+		;;
+	*-cbm)
+		os=-amigaos
+		;;
+	*-dg)
+		os=-dgux
+		;;
+	*-dolphin)
+		os=-sysv3
+		;;
+	m68k-ccur)
+		os=-rtu
+		;;
+	m88k-omron*)
+		os=-luna
+		;;
+	*-next )
+		os=-nextstep
+		;;
+	*-sequent)
+		os=-ptx
+		;;
+	*-crds)
+		os=-unos
+		;;
+	*-ns)
+		os=-genix
+		;;
+	i370-*)
+		os=-mvs
+		;;
+	*-next)
+		os=-nextstep3
+		;;
+	*-gould)
+		os=-sysv
+		;;
+	*-highlevel)
+		os=-bsd
+		;;
+	*-encore)
+		os=-bsd
+		;;
+	*-sgi)
+		os=-irix
+		;;
+	*-siemens)
+		os=-sysv4
+		;;
+	*-masscomp)
+		os=-rtu
+		;;
+	f30[01]-fujitsu | f700-fujitsu)
+		os=-uxpv
+		;;
+	*-rom68k)
+		os=-coff
+		;;
+	*-*bug)
+		os=-coff
+		;;
+	*-apple)
+		os=-macos
+		;;
+	*-atari*)
+		os=-mint
+		;;
+	*)
+		os=-none
+		;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer.  We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+	*-unknown)
+		case $os in
+			-riscix*)
+				vendor=acorn
+				;;
+			-sunos*)
+				vendor=sun
+				;;
+			-cnk*|-aix*)
+				vendor=ibm
+				;;
+			-beos*)
+				vendor=be
+				;;
+			-hpux*)
+				vendor=hp
+				;;
+			-mpeix*)
+				vendor=hp
+				;;
+			-hiux*)
+				vendor=hitachi
+				;;
+			-unos*)
+				vendor=crds
+				;;
+			-dgux*)
+				vendor=dg
+				;;
+			-luna*)
+				vendor=omron
+				;;
+			-genix*)
+				vendor=ns
+				;;
+			-mvs* | -opened*)
+				vendor=ibm
+				;;
+			-os400*)
+				vendor=ibm
+				;;
+			-ptx*)
+				vendor=sequent
+				;;
+			-tpf*)
+				vendor=ibm
+				;;
+			-vxsim* | -vxworks* | -windiss*)
+				vendor=wrs
+				;;
+			-aux*)
+				vendor=apple
+				;;
+			-hms*)
+				vendor=hitachi
+				;;
+			-mpw* | -macos*)
+				vendor=apple
+				;;
+			-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+				vendor=atari
+				;;
+			-vos*)
+				vendor=stratus
+				;;
+			*-android*|*-linuxandroid*)
+				vendor=linux-
+				;;
+		esac
+		basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+		;;
+esac
+
+echo $basic_machine$os
+exit
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/src/third_party/mozjs-45/build/autoconf/expandlibs.m4 b/src/third_party/mozjs-45/build/autoconf/expandlibs.m4
new file mode 100644
index 0000000..898e5ce
--- /dev/null
+++ b/src/third_party/mozjs-45/build/autoconf/expandlibs.m4
@@ -0,0 +1,66 @@
+dnl This Source Code Form is subject to the terms of the Mozilla Public
+dnl License, v. 2.0. If a copy of the MPL was not distributed with this
+dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+AC_DEFUN([MOZ_EXPAND_LIBS],
+[
+dnl ========================================================
+dnl =
+dnl = Check what kind of list files are supported by the
+dnl = linker
+dnl =
+dnl ========================================================
+
+AC_CACHE_CHECK(what kind of list files are supported by the linker,
+    EXPAND_LIBS_LIST_STYLE,
+    [echo "int main() {return 0;}" > conftest.${ac_ext}
+     if AC_TRY_COMMAND(${CC-cc} -o conftest.${OBJ_SUFFIX} -c $CFLAGS $CPPFLAGS conftest.${ac_ext} 1>&5) && test -s conftest.${OBJ_SUFFIX}; then
+         echo "INPUT(conftest.${OBJ_SUFFIX})" > conftest.list
+         if AC_TRY_COMMAND(${CC-cc} -o conftest${ac_exeext} $LDFLAGS conftest.list $LIBS 1>&5) && test -s conftest${ac_exeext}; then
+             EXPAND_LIBS_LIST_STYLE=linkerscript
+         else
+             echo "conftest.${OBJ_SUFFIX}" > conftest.list
+             dnl -filelist is for the OS X linker.  We need to try -filelist
+             dnl first because clang understands @file, but may pass an
+             dnl oversized argument list to the linker depending on the
+             dnl contents of @file.
+             if AC_TRY_COMMAND(${CC-cc} -o conftest${ac_exeext} $LDFLAGS [-Wl,-filelist,conftest.list] $LIBS 1>&5) && test -s conftest${ac_exeext}; then
+                 EXPAND_LIBS_LIST_STYLE=filelist
+             elif AC_TRY_COMMAND(${CC-cc} -o conftest${ac_exeext} $LDFLAGS @conftest.list $LIBS 1>&5) && test -s conftest${ac_exeext}; then
+                 EXPAND_LIBS_LIST_STYLE=list
+             else
+                 EXPAND_LIBS_LIST_STYLE=none
+             fi
+         fi
+     else
+         dnl We really don't expect to get here, but just in case
+         AC_ERROR([couldn't compile a simple C file])
+     fi
+     rm -rf conftest*])
+
+LIBS_DESC_SUFFIX=desc
+AC_SUBST(LIBS_DESC_SUFFIX)
+AC_SUBST(EXPAND_LIBS_LIST_STYLE)
+
+if test "$GCC_USE_GNU_LD"; then
+    AC_CACHE_CHECK(what kind of ordering can be done with the linker,
+        EXPAND_LIBS_ORDER_STYLE,
+        [> conftest.order
+         _SAVE_LDFLAGS="$LDFLAGS"
+         LDFLAGS="${LDFLAGS} -Wl,--section-ordering-file,conftest.order"
+         AC_TRY_LINK([], [],
+             EXPAND_LIBS_ORDER_STYLE=section-ordering-file,
+             EXPAND_LIBS_ORDER_STYLE=)
+         LDFLAGS="$_SAVE_LDFLAGS"
+         if test -z "$EXPAND_LIBS_ORDER_STYLE"; then
+             if AC_TRY_COMMAND(${CC-cc} ${DSO_LDOPTS} ${LDFLAGS} -o ${DLL_PREFIX}conftest${DLL_SUFFIX} -Wl,--verbose 2> /dev/null | sed -n '/^===/,/^===/p' | grep '\.text'); then
+                 EXPAND_LIBS_ORDER_STYLE=linkerscript
+             else
+                 EXPAND_LIBS_ORDER_STYLE=none
+             fi
+             rm -f ${DLL_PREFIX}conftest${DLL_SUFFIX}
+         fi])
+fi
+AC_SUBST(EXPAND_LIBS_ORDER_STYLE)
+
+])
diff --git a/src/third_party/mozjs-45/build/autoconf/ffi.m4 b/src/third_party/mozjs-45/build/autoconf/ffi.m4
new file mode 100644
index 0000000..e775c61
--- /dev/null
+++ b/src/third_party/mozjs-45/build/autoconf/ffi.m4
@@ -0,0 +1,100 @@
+dnl This Source Code Form is subject to the terms of the Mozilla Public
+dnl License, v. 2.0. If a copy of the MPL was not distributed with this
+dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+AC_DEFUN([MOZ_CONFIG_FFI], [
+
+MOZ_ARG_ENABLE_BOOL(system-ffi,
+[  --enable-system-ffi       Use system libffi (located with pkgconfig)],
+    MOZ_NATIVE_FFI=1 )
+
+if test -n "$MOZ_NATIVE_FFI"; then
+    # Vanilla libffi 3.0.9 needs a few patches from upcoming version 3.0.10
+    # for non-GCC compilers.
+    if test -z "$GNU_CC"; then
+        PKG_CHECK_MODULES(MOZ_FFI, libffi > 3.0.9)
+    else
+        PKG_CHECK_MODULES(MOZ_FFI, libffi >= 3.0.9)
+    fi
+fi
+
+AC_SUBST(MOZ_NATIVE_FFI)
+
+])
+
+AC_DEFUN([MOZ_SUBCONFIGURE_FFI], [
+if test -z "$BUILDING_JS" -o -n "$JS_STANDALONE"; then
+
+  if test "$BUILD_CTYPES" -a -z "$MOZ_NATIVE_FFI"; then
+    # Run the libffi 'configure' script.
+    ac_configure_args="--disable-shared --enable-static --disable-raw-api"
+    if test "$MOZ_DEBUG"; then
+      ac_configure_args="$ac_configure_args --enable-debug"
+    fi
+    if test "$DSO_PIC_CFLAGS"; then
+      ac_configure_args="$ac_configure_args --with-pic"
+    fi
+    for var in AS CC CXX CPP LD AR RANLIB STRIP; do
+      ac_configure_args="$ac_configure_args $var='`eval echo \\${${var}}`'"
+    done
+    if test "$CROSS_COMPILE"; then
+      export CPPFLAGS CFLAGS LDFLAGS
+    fi
+    ac_configure_args="$ac_configure_args --build=$build --host=$target"
+    if test "$_MSC_VER"; then
+      # Use a wrapper script for cl and ml that looks more like gcc.
+      # autotools can't quite handle an MSVC build environment yet.
+      LDFLAGS=
+      CFLAGS=
+      ac_configure_args="$ac_configure_args LD=link CPP=\"$CC -nologo -EP\" \
+                         CXXCPP=\"$CXX -nologo -EP\" SHELL=sh.exe"
+      flags=
+      if test -z "$MOZ_NO_DEBUG_RTL" -a -n "$MOZ_DEBUG"; then
+        flags=" -DUSE_DEBUG_RTL"
+      fi
+      if test -n "$CLANG_CL"; then
+        flags="$flags -clang-cl"
+      fi
+      case "${target_cpu}" in
+      x86_64)
+        # Need target since MSYS tools into mozilla-build may be 32bit
+        ac_configure_args="$ac_configure_args \
+                           CC=\"$_topsrcdir/js/src/ctypes/libffi/msvcc.sh -m64$flags\" \
+                           CXX=\"$_topsrcdir/js/src/ctypes/libffi/msvcc.sh -m64$flags\""
+        ;;
+      *)
+        ac_configure_args="$ac_configure_args \
+                           CC=\"$_topsrcdir/js/src/ctypes/libffi/msvcc.sh$flags\" \
+                           CXX=\"$_topsrcdir/js/src/ctypes/libffi/msvcc.sh$flags\""
+        ;;
+      esac
+    fi
+    if test "$SOLARIS_SUNPRO_CC"; then
+      # Always use gcc for libffi on Solaris
+      if test ! "$HAVE_64BIT_BUILD"; then
+        ac_configure_args="$ac_configure_args CC=gcc CFLAGS=-m32 LD= LDFLAGS="
+      else
+        ac_configure_args="$ac_configure_args CC=gcc CFLAGS=-m64 LD= LDFLAGS="
+      fi
+    fi
+    if test "$AIX_IBM_XLC"; then
+      # Always use gcc for libffi on IBM AIX5/AIX6
+      if test ! "$HAVE_64BIT_BUILD"; then
+        ac_configure_args="$ac_configure_args CC=gcc CFLAGS=-maix32"
+      else
+        ac_configure_args="$ac_configure_args CC=gcc CFLAGS=-maix64"
+      fi
+    fi
+
+    # Use a separate cache file for libffi, since it does things differently
+    # from our configure.
+    old_config_files=$CONFIG_FILES
+    unset CONFIG_FILES
+    AC_OUTPUT_SUBDIRS(js/src/ctypes/libffi)
+    ac_configure_args="$_SUBDIR_CONFIG_ARGS"
+    CONFIG_FILES=$old_config_files
+  fi
+
+fi
+])
+
diff --git a/src/third_party/mozjs-45/build/autoconf/frameptr.m4 b/src/third_party/mozjs-45/build/autoconf/frameptr.m4
new file mode 100644
index 0000000..428b1fb
--- /dev/null
+++ b/src/third_party/mozjs-45/build/autoconf/frameptr.m4
@@ -0,0 +1,41 @@
+dnl This Source Code Form is subject to the terms of the Mozilla Public
+dnl License, v. 2.0. If a copy of the MPL was not distributed with this
+dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+dnl Set MOZ_FRAMEPTR_FLAGS to the flags that should be used for enabling or
+dnl disabling frame pointers in this architecture based on the configure
+dnl options
+
+AC_DEFUN([MOZ_SET_FRAMEPTR_FLAGS], [
+  case "$target" in
+  *android*)
+    unwind_tables="-funwind-tables"
+    ;;
+  esac
+  if test "$GNU_CC"; then
+    MOZ_ENABLE_FRAME_PTR="-fno-omit-frame-pointer $unwind_tables"
+    MOZ_DISABLE_FRAME_PTR="-fomit-frame-pointer"
+    if test "$CPU_ARCH" = arm; then
+      # http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54398
+      MOZ_ENABLE_FRAME_PTR="$unwind_tables"
+    fi
+  else
+    case "$target" in
+    *-mingw*)
+      MOZ_ENABLE_FRAME_PTR="-Oy-"
+      MOZ_DISABLE_FRAME_PTR="-Oy"
+    ;;
+    esac
+  fi
+
+  # if we are debugging, profiling or using sanitizers, we want a frame pointer.
+  if test -z "$MOZ_OPTIMIZE" -o \
+          -n "$MOZ_PROFILING" -o \
+          -n "$MOZ_DEBUG" -o \
+          -n "$MOZ_MSAN" -o \
+          -n "$MOZ_ASAN"; then
+    MOZ_FRAMEPTR_FLAGS="$MOZ_ENABLE_FRAME_PTR"
+  else
+    MOZ_FRAMEPTR_FLAGS="$MOZ_DISABLE_FRAME_PTR"
+  fi
+])
diff --git a/src/third_party/mozjs-45/build/autoconf/hooks.m4 b/src/third_party/mozjs-45/build/autoconf/hooks.m4
new file mode 100644
index 0000000..2a321ee
--- /dev/null
+++ b/src/third_party/mozjs-45/build/autoconf/hooks.m4
@@ -0,0 +1,87 @@
+dnl This Source Code Form is subject to the terms of the Mozilla Public
+dnl License, v. 2.0. If a copy of the MPL was not distributed with this
+dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+dnl Output the contents of config.log when configure exits with an
+dnl error code.
+define([MOZ_CONFIG_LOG_TRAP],
+[changequote(<<<, >>>)dnl
+trap '[ "$?" != 0 ] && echo "------ config.log ------" && tail -n 25 config.log' EXIT
+changequote([, ])dnl
+])
+
+dnl Wrap AC_INIT_PREPARE to add the above trap.
+define([_MOZ_AC_INIT_PREPARE], defn([AC_INIT_PREPARE]))
+define([AC_INIT_PREPARE],
+[_MOZ_AC_INIT_PREPARE($1)
+MOZ_CONFIG_LOG_TRAP
+> subconfigures
+> skip_subconfigures
+])
+
+define([AC_OUTPUT_SUBDIRS],
+[for moz_config_dir in $1; do
+  _CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
+  case "$moz_config_dir" in
+  *:*)
+    objdir=$(echo $moz_config_dir | awk -F: '{print [$]2}')
+    ;;
+  *)
+    objdir=$moz_config_dir
+    ;;
+  esac
+  dnl Because config.status, storing AC_SUBSTs, is written before any
+  dnl subconfigure runs, we need to use a file. Moreover, some subconfigures
+  dnl are started from a subshell, and variable modifications from a subshell
+  dnl wouldn't be preserved.
+  echo $objdir >> subconfigures
+
+  dumpenv="true | "
+  case "$host" in
+  *-mingw*)
+    _CONFIG_SHELL=$(cd $(dirname $_CONFIG_SHELL); pwd -W)/$(basename $_CONFIG_SHELL)
+    if test ! -e "$_CONFIG_SHELL" -a -e "${_CONFIG_SHELL}.exe"; then
+        _CONFIG_SHELL="${_CONFIG_SHELL}.exe"
+    fi
+    dnl Yes, this is horrible. But since msys doesn't preserve environment
+    dnl variables and command line arguments as they are when transitioning
+    dnl from msys (this script) to python (below), we have to resort to hacks,
+    dnl storing the environment and command line arguments from a msys process
+    dnl (perl), and reading it from python.
+    dumpenv="$PERL $_topsrcdir/build/win32/dumpenv4python.pl $ac_configure_args | "
+    ;;
+  esac
+
+  eval $dumpenv $PYTHON $_topsrcdir/build/subconfigure.py --prepare "$srcdir" "$moz_config_dir" "$_CONFIG_SHELL" $ac_configure_args ifelse($2,,,--cache-file="$2")
+
+  dnl Actual subconfigure execution happens in MOZ_RUN_CONFIG_STATUS
+done
+])
+
+define([AC_OUTPUT_SUBDIRS_NOW],
+[
+for moz_config_dir_ in $1; do
+  AC_OUTPUT_SUBDIRS($moz_config_dir_,$2)
+  tail -1 subconfigures >> skip_subconfigures
+  MOZ_RUN_SUBCONFIGURES(`tail -1 skip_subconfigures`)
+done
+])
+
+define([MOZ_RUN_SUBCONFIGURES],
+[dnl Execute subconfigure, unless --no-recursion was passed to configure.
+if test "$no_recursion" != yes; then
+  trap '' EXIT
+  if ! $PYTHON $_topsrcdir/build/subconfigure.py $1; then
+      exit 1
+  fi
+  MOZ_CONFIG_LOG_TRAP
+fi
+])
+
+define([MOZ_RUN_ALL_SUBCONFIGURES],[
+MOZ_RUN_SUBCONFIGURES([--list subconfigures --skip skip_subconfigures])
+])
+
+dnl Print error messages in config.log as well as stderr
+define([AC_MSG_ERROR],
+[{ echo "configure: error: $1" 1>&2; echo "configure: error: $1" 1>&5; exit 1; }])
diff --git a/src/third_party/mozjs-45/build/autoconf/hotfixes.m4 b/src/third_party/mozjs-45/build/autoconf/hotfixes.m4
new file mode 100644
index 0000000..1522df9
--- /dev/null
+++ b/src/third_party/mozjs-45/build/autoconf/hotfixes.m4
@@ -0,0 +1,24 @@
+dnl This Source Code Form is subject to the terms of the Mozilla Public
+dnl dnl License, v. 2.0. If a copy of the MPL was not distributed with this
+dnl dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+dnl Set of hotfixes to address issues in autoconf 2.13
+
+dnl Divert AC_CHECK_FUNC so that the #includes it uses can't interfere
+dnl with the function it tests.
+dnl So, when testing e.g. posix_memalign, any #include that AC_CHECK_FUNC
+dnl prints is replaced with:
+dnl   #define posix_memalign innocuous_posix_memalign
+dnl   #include "theinclude"
+dnl   #undef posix_memalign
+dnl This avoids double declaration of that function when the header normally
+dnl declares it, while the test itself is just expecting the function not to be
+dnl declared at all, and declares it differently (which doesn't matter for the
+dnl test itself).
+dnl More recent versions of autoconf are essentially doing this.
+define([ac_cv_func_], [ac_cv_func2_])dnl
+define([_AC_CHECK_FUNC],defn([AC_CHECK_FUNC]))dnl
+define([AC_CHECK_FUNC], [dnl
+patsubst(_AC_CHECK_FUNC($@), [#include.*$], [#define $1 innocuous_$1
+\&
+#undef $1])])dnl
diff --git a/src/third_party/mozjs-45/build/autoconf/icu.m4 b/src/third_party/mozjs-45/build/autoconf/icu.m4
new file mode 100644
index 0000000..65d10cd
--- /dev/null
+++ b/src/third_party/mozjs-45/build/autoconf/icu.m4
@@ -0,0 +1,306 @@
+dnl This Source Code Form is subject to the terms of the Mozilla Public
+dnl License, v. 2.0. If a copy of the MPL was not distributed with this
+dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+dnl Set the MOZ_ICU_VERSION variable to denote the current version of the
+dnl ICU library, and also the MOZ_SHARED_ICU which would be true if we are
+dnl linking against a shared library of ICU, either one that we build from
+dnl our copy of ICU or the system provided library.
+
+AC_DEFUN([MOZ_CONFIG_ICU], [
+
+ICU_LIB_NAMES=
+MOZ_NATIVE_ICU=
+MOZ_ARG_WITH_BOOL(system-icu,
+[  --with-system-icu
+                          Use system ICU (located with pkgconfig)],
+    MOZ_NATIVE_ICU=1)
+
+if test -n "$MOZ_NATIVE_ICU"; then
+    PKG_CHECK_MODULES(MOZ_ICU, icu-i18n >= 50.1)
+    MOZ_SHARED_ICU=1
+else
+    MOZ_ICU_INCLUDES="/intl/icu/source/common /intl/icu/source/i18n"
+fi
+
+AC_SUBST_LIST(MOZ_ICU_INCLUDES)
+AC_SUBST(MOZ_NATIVE_ICU)
+
+MOZ_ARG_WITH_STRING(intl-api,
+[  --with-intl-api, --with-intl-api=build, --without-intl-api
+    Determine the status of the ECMAScript Internationalization API.  The first
+    (or lack of any of these) builds and exposes the API.  The second builds it
+    but doesn't use ICU or expose the API to script.  The third doesn't build
+    ICU at all.],
+    _INTL_API=$withval)
+
+ENABLE_INTL_API=
+EXPOSE_INTL_API=
+case "$_INTL_API" in
+no)
+    ;;
+build)
+    ENABLE_INTL_API=1
+    ;;
+yes)
+    ENABLE_INTL_API=1
+    EXPOSE_INTL_API=1
+    ;;
+*)
+    AC_MSG_ERROR([Invalid value passed to --with-intl-api: $_INTL_API])
+    ;;
+esac
+
+if test -n "$ENABLE_INTL_API"; then
+    USE_ICU=1
+fi
+
+if test -n "$EXPOSE_INTL_API"; then
+    AC_DEFINE(EXPOSE_INTL_API)
+fi
+
+if test -n "$ENABLE_INTL_API"; then
+    AC_DEFINE(ENABLE_INTL_API)
+fi
+
+dnl Settings for the implementation of the ECMAScript Internationalization API
+if test -n "$USE_ICU"; then
+    icudir="$_topsrcdir/intl/icu/source"
+    if test ! -d "$icudir"; then
+        icudir="$_topsrcdir/../../intl/icu/source"
+        if test ! -d "$icudir"; then
+            AC_MSG_ERROR([Cannot find the ICU directory])
+        fi
+    fi
+
+    version=`sed -n 's/^[[:space:]]*#[[:space:]]*define[[:space:]][[:space:]]*U_ICU_VERSION_MAJOR_NUM[[:space:]][[:space:]]*\([0-9][0-9]*\)[[:space:]]*$/\1/p' "$icudir/common/unicode/uvernum.h"`
+    if test x"$version" = x; then
+       AC_MSG_ERROR([cannot determine icu version number from uvernum.h header file $lineno])
+    fi
+    MOZ_ICU_VERSION="$version"
+
+    if test "$OS_TARGET" = WINNT; then
+        MOZ_SHARED_ICU=1
+    fi
+
+    if test -z "${JS_STANDALONE}" -a -n "${JS_SHARED_LIBRARY}${MOZ_NATIVE_ICU}"; then
+        MOZ_SHARED_ICU=1
+    fi
+
+    AC_SUBST(MOZ_ICU_VERSION)
+    AC_SUBST(MOZ_SHARED_ICU)
+
+    if test -z "$MOZ_NATIVE_ICU"; then
+        case "$OS_TARGET" in
+            WINNT)
+                ICU_LIB_NAMES="icuin icuuc icudt"
+                MOZ_ICU_DBG_SUFFIX=
+                if test -n "$MOZ_DEBUG" -a -z "$MOZ_NO_DEBUG_RTL"; then
+                    MOZ_ICU_DBG_SUFFIX=d
+                fi
+                ;;
+            Darwin|Linux|DragonFly|FreeBSD|NetBSD|OpenBSD|GNU/kFreeBSD|SunOS|Android)
+                ICU_LIB_NAMES="icui18n icuuc icudata"
+                ;;
+            *)
+                AC_MSG_ERROR([ECMAScript Internationalization API is not yet supported on this platform])
+        esac
+    fi
+fi
+
+AC_SUBST(MOZ_ICU_DBG_SUFFIX)
+AC_SUBST(ENABLE_INTL_API)
+AC_SUBST(USE_ICU)
+AC_SUBST_LIST(ICU_LIB_NAMES)
+
+if test -n "$USE_ICU" -a -z "$MOZ_NATIVE_ICU"; then
+    dnl We build ICU as a static library for non-shared js builds and as a shared library for shared js builds.
+    if test -z "$MOZ_SHARED_ICU"; then
+        AC_DEFINE(U_STATIC_IMPLEMENTATION)
+    fi
+    dnl Source files that use ICU should have control over which parts of the ICU
+    dnl namespace they want to use.
+    AC_DEFINE(U_USING_ICU_NAMESPACE,0)
+fi
+
+
+])
+
+AC_DEFUN([MOZ_SUBCONFIGURE_ICU], [
+
+if test -z "$BUILDING_JS" -o -n "$JS_STANDALONE"; then
+
+    if test -n "$USE_ICU" -a -z "$MOZ_NATIVE_ICU"; then
+        # Set ICU compile options
+        ICU_CPPFLAGS=""
+        # don't use icu namespace automatically in client code
+        ICU_CPPFLAGS="$ICU_CPPFLAGS -DU_USING_ICU_NAMESPACE=0"
+        # don't include obsolete header files
+        ICU_CPPFLAGS="$ICU_CPPFLAGS -DU_NO_DEFAULT_INCLUDE_UTF_HEADERS=1"
+        # remove chunks of the library that we don't need (yet)
+        ICU_CPPFLAGS="$ICU_CPPFLAGS -DUCONFIG_NO_LEGACY_CONVERSION"
+        ICU_CPPFLAGS="$ICU_CPPFLAGS -DUCONFIG_NO_TRANSLITERATION"
+        ICU_CPPFLAGS="$ICU_CPPFLAGS -DUCONFIG_NO_REGULAR_EXPRESSIONS"
+        ICU_CPPFLAGS="$ICU_CPPFLAGS -DUCONFIG_NO_BREAK_ITERATION"
+        # we don't need to pass data to and from legacy char* APIs
+        ICU_CPPFLAGS="$ICU_CPPFLAGS -DU_CHARSET_IS_UTF8"
+        # make sure to not accidentally pick up system-icu headers
+        ICU_CPPFLAGS="$ICU_CPPFLAGS -I$icudir/common -I$icudir/i18n"
+
+        ICU_CROSS_BUILD_OPT=""
+
+        if test "$CROSS_COMPILE"; then
+            # Remove _DEPEND_CFLAGS from HOST_FLAGS to avoid configure error
+            HOST_ICU_CFLAGS="$HOST_CFLAGS"
+            HOST_ICU_CXXFLAGS="$HOST_CXXFLAGS"
+
+            HOST_ICU_CFLAGS=`echo $HOST_ICU_CFLAGS | sed "s|$_DEPEND_CFLAGS||g"`
+            HOST_ICU_CXXFLAGS=`echo $HOST_ICU_CFXXLAGS | sed "s|$_DEPEND_CFLAGS||g"`
+
+            # ICU requires RTTI
+            if test "$GNU_CC"; then
+                HOST_ICU_CXXFLAGS=`echo $HOST_ICU_CXXFLAGS | sed 's|-fno-rtti|-frtti|g'`
+            elif test "$_MSC_VER"; then
+                HOST_ICU_CXXFLAGS=`echo $HOST_ICU_CXXFLAGS | sed 's|-GR-|-GR|g'`
+            fi
+
+            HOST_ICU_BUILD_OPTS=""
+            if test -n "$MOZ_DEBUG"; then
+                HOST_ICU_BUILD_OPTS="$HOST_ICU_BUILD_OPTS --enable-debug"
+            fi
+
+            abs_srcdir=`(cd $srcdir; pwd)`
+            mkdir -p $_objdir/intl/icu/host
+            (export AR="$HOST_AR"
+             export RANLIB="$HOST_RANLIB"
+             export CC="$HOST_CC"
+             export CXX="$HOST_CXX"
+             export CPP="$HOST_CPP"
+             export LD="$HOST_LD"
+             export CFLAGS="$HOST_ICU_CFLAGS $HOST_OPTIMIZE_FLAGS"
+             export CPPFLAGS="$ICU_CPPFLAGS"
+             export CXXFLAGS="$HOST_ICU_CXXFLAGS $HOST_OPTIMIZE_FLAGS"
+             export LDFLAGS="$HOST_LDFLAGS"
+             ac_configure_args="$HOST_ICU_BUILD_OPTS"
+             ac_configure_args="$ac_configure_args --enable-static --disable-shared --enable-extras=no --enable-icuio=no --enable-layout=no --enable-tests=no --enable-samples=no"
+             AC_OUTPUT_SUBDIRS_NOW(intl/icu/source:intl/icu/host)
+            ) || exit 1
+            # generate config/icucross.mk
+            $GMAKE -C $_objdir/intl/icu/host/ config/icucross.mk
+
+            # --with-cross-build requires absolute path
+            ICU_HOST_PATH=`cd $_objdir/intl/icu/host && pwd`
+            ICU_CROSS_BUILD_OPT="--with-cross-build=$ICU_HOST_PATH --disable-tools"
+            ICU_TARGET_OPT="--build=$build --host=$target"
+        else
+            # CROSS_COMPILE isn't set build and target are i386 and x86-64.
+            # So we must set target for --build and --host.
+            ICU_TARGET_OPT="--build=$target --host=$target"
+        fi
+
+        if test -z "$MOZ_SHARED_ICU"; then
+            # To reduce library size, use static linking
+            ICU_LINK_OPTS="--enable-static --disable-shared"
+        else
+            ICU_LINK_OPTS="--disable-static --enable-shared"
+        fi
+        # Force the ICU static libraries to be position independent code
+        ICU_CFLAGS="$DSO_PIC_CFLAGS $CFLAGS"
+        ICU_CXXFLAGS="$DSO_PIC_CFLAGS $CXXFLAGS"
+
+        ICU_BUILD_OPTS=""
+        if test -n "$MOZ_DEBUG" -o "MOZ_DEBUG_SYMBOLS"; then
+            ICU_CFLAGS="$ICU_CFLAGS $MOZ_DEBUG_FLAGS"
+            ICU_CXXFLAGS="$ICU_CXXFLAGS $MOZ_DEBUG_FLAGS"
+            if test -n "$CROSS_COMPILE" -a "$OS_TARGET" = "Darwin" \
+                    -a "$HOST_OS_ARCH" != "Darwin"
+            then
+                # Bug 951758: Cross-OSX builds with non-Darwin hosts have issues
+                # with -g and friends (like -gdwarf and -gfull) because they try
+                # to run dsymutil
+                changequote(,)
+                ICU_CFLAGS=`echo $ICU_CFLAGS | sed 's|-g[^ \t]*||g'`
+                ICU_CXXFLAGS=`echo $ICU_CXXFLAGS | sed 's|-g[^ \t]*||g'`
+                changequote([,])
+            fi
+
+            ICU_LDFLAGS="$MOZ_DEBUG_LDFLAGS"
+            if test -z "$MOZ_DEBUG"; then
+                # To generate debug symbols, it requires MOZ_DEBUG_FLAGS.
+                # But, not debug build.
+                ICU_CFLAGS="$ICU_CFLAGS -UDEBUG -DNDEBUG"
+                ICU_CXXFLAGS="$ICU_CXXFLAGS -UDEBUG -DNDEBUG"
+            elif test -z "$MOZ_NO_DEBUG_RTL"; then
+                ICU_BUILD_OPTS="$ICU_BUILD_OPTS --enable-debug"
+            fi
+        fi
+        if test -z "$MOZ_OPTIMIZE"; then
+            ICU_BUILD_OPTS="$ICU_BUILD_OPTS --disable-release"
+        else
+            ICU_CFLAGS="$ICU_CFLAGS $MOZ_OPTIMIZE_FLAGS"
+            ICU_CXXFLAGS="$ICU_CXXFLAGS $MOZ_OPTIMIZE_FLAGS"
+        fi
+
+        if test "$am_cv_langinfo_codeset" = "no"; then
+            # ex. Android
+            ICU_CPPFLAGS="$ICU_CPPFLAGS -DU_HAVE_NL_LANGINFO_CODESET=0"
+        fi
+
+        # ICU requires RTTI
+        if test "$GNU_CC"; then
+            ICU_CXXFLAGS=`echo $ICU_CXXFLAGS | sed 's|-fno-rtti|-frtti|g'`
+        else
+            if test "$_MSC_VER"; then
+                ICU_CXXFLAGS=`echo $ICU_CXXFLAGS | sed 's|-GR-|-GR|g'`
+            fi
+
+            # Add RTL flags for MSVCRT.DLL
+            if test -n "$MOZ_DEBUG" -a -z "$MOZ_NO_DEBUG_RTL"; then
+                ICU_CFLAGS="$ICU_CFLAGS -MDd"
+                ICU_CXXFLAGS="$ICU_CXXFLAGS -MDd"
+            else
+                ICU_CFLAGS="$ICU_CFLAGS -MD"
+                ICU_CXXFLAGS="$ICU_CXXFLAGS -MD"
+            fi
+
+            # add disable optimize flag for workaround for bug 899948
+            if test -z "$MOZ_OPTIMIZE"; then
+                ICU_CFLAGS="$ICU_CFLAGS -Od"
+                ICU_CXXFLAGS="$ICU_CXXFLAGS -Od"
+            fi
+        fi
+
+        if test -n "$gonkdir"; then
+            ICU_CXXFLAGS="-I$gonkdir/abi/cpp/include $ICU_CXXFLAGS"
+        elif test "$OS_TARGET" = Android -a "$MOZ_ANDROID_CXX_STL" = mozstlport; then
+            ICU_CXXFLAGS="-I$_topsrcdir/build/gabi++/include $ICU_CXXFLAGS"
+        fi
+
+        if test -z "$MOZ_SHARED_ICU"; then
+          ICU_CXXFLAGS="$ICU_CXXFLAGS -DU_STATIC_IMPLEMENTATION"
+          ICU_CFLAGS="$ICU_CFLAGS -DU_STATIC_IMPLEMENTATION"
+          if test "$GNU_CC"; then
+            ICU_CFLAGS="$ICU_CFLAGS -fvisibility=hidden"
+            ICU_CXXFLAGS="$ICU_CXXFLAGS -fvisibility=hidden"
+          fi
+        fi
+
+        (export AR="$AR"
+         export RANLIB="$RANLIB"
+         export CC="$CC"
+         export CXX="$CXX"
+         export LD="$LD"
+         export ARFLAGS="$ARFLAGS"
+         export CPPFLAGS="$ICU_CPPFLAGS $CPPFLAGS"
+         export CFLAGS="$ICU_CFLAGS"
+         export CXXFLAGS="$ICU_CXXFLAGS"
+         export LDFLAGS="$ICU_LDFLAGS $LDFLAGS"
+         ac_configure_args="$ICU_BUILD_OPTS $ICU_CROSS_BUILD_OPT $ICU_LINK_OPTS $ICU_TARGET_OPT"
+         ac_configure_args="$ac_configure_args --disable-extras --disable-icuio --disable-layout --disable-tests --disable-samples --disable-strict"
+         AC_OUTPUT_SUBDIRS(intl/icu/source:intl/icu/target)
+        ) || exit 1
+    fi
+
+fi
+
+])
diff --git a/src/third_party/mozjs-45/build/autoconf/install-sh b/src/third_party/mozjs-45/build/autoconf/install-sh
new file mode 100755
index 0000000..a4be13e
--- /dev/null
+++ b/src/third_party/mozjs-45/build/autoconf/install-sh
@@ -0,0 +1,123 @@
+#!/bin/sh
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+
+#
+# install - install a program, script, or datafile
+# This comes from X11R5; it is not part of GNU.
+#
+# $XConsortium: install.sh,v 1.2 89/12/18 14:47:22 jim Exp $
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+#
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+
+instcmd="$mvprog"
+chmodcmd=""
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+
+while [ x"$1" != x ]; do
+    case $1 in
+	-c) instcmd="$cpprog"
+	    shift
+	    continue;;
+
+	-m) chmodcmd="$chmodprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-o) chowncmd="$chownprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-g) chgrpcmd="$chgrpprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-s) stripcmd="$stripprog"
+	    shift
+	    continue;;
+
+	*)  if [ x"$src" = x ]
+	    then
+		src=$1
+	    else
+		dst=$1
+	    fi
+	    shift
+	    continue;;
+    esac
+done
+
+if [ x"$src" = x ]
+then
+	echo "install:  no input file specified"
+	exit 1
+fi
+
+if [ x"$dst" = x ]
+then
+	echo "install:  no destination specified"
+	exit 1
+fi
+
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+if [ -d $dst ]
+then
+	dst="$dst"/`basename $src`
+fi
+
+# Make a temp file name in the proper directory.
+
+dstdir=`dirname $dst`
+dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+$doit $instcmd $src $dsttmp
+
+# and set any options; do chmod last to preserve setuid bits
+
+if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; fi
+if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; fi
+if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; fi
+if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; fi
+
+# Now rename the file to the real destination.
+
+$doit $rmcmd $dst
+$doit $mvcmd $dsttmp $dst
+
+
+exit 0
diff --git a/src/third_party/mozjs-45/build/autoconf/ios.m4 b/src/third_party/mozjs-45/build/autoconf/ios.m4
new file mode 100644
index 0000000..b341cda
--- /dev/null
+++ b/src/third_party/mozjs-45/build/autoconf/ios.m4
@@ -0,0 +1,108 @@
+dnl This Source Code Form is subject to the terms of the Mozilla Public
+dnl License, v. 2.0. If a copy of the MPL was not distributed with this
+dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+AC_DEFUN([MOZ_IOS_PATH_PROG],
+[
+changequote({,})
+_prog_name=ifelse($2, {}, `echo $1 | tr "[:upper:]" "[:lower:]"`, $2)
+changequote([,])
+AC_CACHE_CHECK([for $_prog_name in iOS SDK],
+ac_cv_ios_path_$1,
+[
+_path=`xcrun --sdk $ios_sdk --find $_prog_name 2>/dev/null`
+_res=$?
+if test $_res -ne 0; then
+   AC_MSG_ERROR([Could not find '$_prog_name' in the iOS SDK])
+fi
+ac_cv_ios_path_$1=$_path
+])
+$1="${ac_cv_ios_path_$1}$3"
+])
+
+AC_DEFUN([MOZ_IOS_SDK],
+[
+
+MOZ_ARG_WITH_STRING(ios-sdk,
+[  --with-ios-sdk=TYPE
+                          Type of iOS SDK to use (iphonesimulator, iphoneos)
+                          and optionally version (like iphoneos8.2)],
+    ios_sdk=$withval)
+
+MOZ_ARG_ENABLE_STRING(ios-target,
+                      [  --enable-ios-target=VER (default=8.0)
+                          Set the minimum iOS version needed at runtime],
+                      [_IOS_TARGET=$enableval])
+_IOS_TARGET_DEFAULT=8.0
+
+case "$target" in
+arm*-apple-darwin*)
+    if test -z "$ios_sdk" -o "$ios_sdk" = "yes"; then
+       ios_sdk=iphoneos
+    fi
+    case "$ios_sdk" in
+         iphoneos*)
+                ios_target_arg="-miphoneos-version-min"
+                ;;
+         *)
+                AC_MSG_ERROR([Only 'iphoneos' SDKs are valid when targeting iOS device, don't know what to do with '$ios_sdk'.])
+                ;;
+    esac
+    ;;
+*-apple-darwin*)
+    ios_target_arg="-mios-simulator-version-min"
+    case "$ios_sdk" in
+         # Empty SDK is okay, this might be an OS X desktop build.
+         ""|iphonesimulator*)
+                ;;
+         # Default to iphonesimulator
+         yes)
+                ios_sdk=iphonesimulator
+                ;;
+         *)
+                AC_MSG_ERROR([Only 'iphonesimulator' SDKs are valid when targeting iOS simulator.])
+                ;;
+    esac
+    ;;
+esac
+
+
+if test -n "$ios_sdk"; then
+   if test -z "$_IOS_TARGET"; then
+      _IOS_TARGET=$_IOS_TARGET_DEFAULT
+      ios_target_arg="${ios_target_arg}=${_IOS_TARGET}"
+   fi
+   # Ensure that xcrun knows where this SDK is.
+   ios_sdk_path=`xcrun --sdk $ios_sdk --show-sdk-path 2>/dev/null`
+   _ret=$?
+   if test $_ret -ne 0; then
+      AC_MSG_ERROR([iOS SDK '$ios_sdk' could not be found.])
+   fi
+   MOZ_IOS=1
+   export HOST_CC=clang
+   export HOST_CXX=clang++
+   # Add isysroot, arch, and ios target arguments
+   case "$target_cpu" in
+        arm*)
+                ARGS="-arch armv7"
+                ;;
+        *)
+                # Unfortunately simulator builds need this.
+                export CROSS_COMPILE=1
+                ;;
+   esac
+   ARGS=" $ARGS -isysroot $ios_sdk_path $ios_target_arg"
+   # Now find our tools
+   MOZ_IOS_PATH_PROG(CC, clang, $ARGS)
+   MOZ_IOS_PATH_PROG(CXX, clang++, $ARGS)
+   export CPP="$CC -E"
+   export LD="$CXX"
+   MOZ_IOS_PATH_PROG(AR)
+   MOZ_IOS_PATH_PROG(AS, as, $ARGS)
+   MOZ_IOS_PATH_PROG(OTOOL)
+   MOZ_IOS_PATH_PROG(STRIP)
+   export PKG_CONFIG_PATH=${ios_sdk_path}/usr/lib/pkgconfig/
+fi
+
+AC_SUBST(MOZ_IOS)
+])
diff --git a/src/third_party/mozjs-45/build/autoconf/jemalloc.m4 b/src/third_party/mozjs-45/build/autoconf/jemalloc.m4
new file mode 100644
index 0000000..b6c30c0
--- /dev/null
+++ b/src/third_party/mozjs-45/build/autoconf/jemalloc.m4
@@ -0,0 +1,100 @@
+dnl This Source Code Form is subject to the terms of the Mozilla Public
+dnl License, v. 2.0. If a copy of the MPL was not distributed with this
+dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+AC_DEFUN([MOZ_SUBCONFIGURE_JEMALLOC], [
+
+if test -z "$BUILDING_JS" -o -n "$JS_STANDALONE"; then
+
+  # Run jemalloc configure script
+
+  if test -z "$MOZ_NATIVE_JEMALLOC" -a "$MOZ_MEMORY" && test -n "$MOZ_JEMALLOC4" -o -n "$MOZ_REPLACE_MALLOC"; then
+    ac_configure_args="--build=$build --host=$target --enable-stats --with-jemalloc-prefix=je_ --disable-valgrind"
+    # We're using memalign for _aligned_malloc in memory/build/mozmemory_wrap.c
+    # on Windows, so just export memalign on all platforms.
+    ac_configure_args="$ac_configure_args ac_cv_func_memalign=yes"
+    if test -n "$MOZ_REPLACE_MALLOC"; then
+      # When using replace_malloc, we always want valloc exported from jemalloc.
+      ac_configure_args="$ac_configure_args ac_cv_func_valloc=yes"
+      if test "${OS_ARCH}" = Darwin; then
+        # We also need to enable pointer validation on Mac because jemalloc's
+        # zone allocator is not used.
+        ac_configure_args="$ac_configure_args --enable-ivsalloc"
+      fi
+    fi
+    if test -n "$MOZ_JEMALLOC4"; then
+      case "${OS_ARCH}" in
+        WINNT|Darwin)
+          # We want jemalloc functions to be kept hidden on both Mac and Windows
+          # See memory/build/mozmemory_wrap.h for details.
+          ac_configure_args="$ac_configure_args --without-export"
+          ;;
+      esac
+      if test "${OS_ARCH}" = WINNT; then
+        # Lazy lock initialization doesn't play well with lazy linking of
+        # mozglue.dll on Windows XP (leads to startup crash), so disable it.
+        ac_configure_args="$ac_configure_args --disable-lazy-lock"
+      fi
+    elif test "${OS_ARCH}" = Darwin; then
+      # When building as a replace-malloc lib, disabling the zone allocator
+      # forces to use pthread_atfork.
+      ac_configure_args="$ac_configure_args --disable-zone-allocator"
+    fi
+    _MANGLE="malloc posix_memalign aligned_alloc calloc realloc free memalign valloc malloc_usable_size"
+    JEMALLOC_WRAPPER=
+    if test -z "$MOZ_REPLACE_MALLOC"; then
+      case "$OS_ARCH" in
+        Linux|DragonFly|FreeBSD|NetBSD|OpenBSD)
+          MANGLE=$_MANGLE
+          ;;
+      esac
+    elif test -z "$MOZ_JEMALLOC4"; then
+      MANGLE=$_MANGLE
+      JEMALLOC_WRAPPER=replace_
+    fi
+    if test -n "$MANGLE"; then
+      MANGLED=
+      for mangle in ${MANGLE}; do
+        if test -n "$MANGLED"; then
+          MANGLED="$mangle:$JEMALLOC_WRAPPER$mangle,$MANGLED"
+        else
+          MANGLED="$mangle:$JEMALLOC_WRAPPER$mangle"
+        fi
+      done
+      ac_configure_args="$ac_configure_args --with-mangling=$MANGLED"
+    fi
+    unset CONFIG_FILES
+    if test -z "$MOZ_TLS"; then
+      ac_configure_args="$ac_configure_args --disable-tls"
+    fi
+    EXTRA_CFLAGS="$CFLAGS"
+    for var in AS CC CXX CPP LD AR RANLIB STRIP CPPFLAGS EXTRA_CFLAGS LDFLAGS; do
+      ac_configure_args="$ac_configure_args $var='`eval echo \\${${var}}`'"
+    done
+    # Force disable DSS support in jemalloc.
+    ac_configure_args="$ac_configure_args ac_cv_func_sbrk=false"
+
+    # Make Linux builds munmap freed chunks instead of recycling them.
+    ac_configure_args="$ac_configure_args --enable-munmap"
+
+    # Disable cache oblivious behavior that appears to have a performance
+    # impact on Firefox.
+    ac_configure_args="$ac_configure_args --disable-cache-oblivious"
+
+    if ! test -e memory/jemalloc; then
+      mkdir -p memory/jemalloc
+    fi
+
+    # jemalloc's configure runs git to determine the version. But when building
+    # from a gecko git clone, the git commands it uses is going to pick gecko's
+    # information, not jemalloc's, which is useless. So pretend we don't have git
+    # at all. That will make jemalloc's configure pick the in-tree VERSION file.
+    (PATH="$srcdir/memory/jemalloc/helper:$PATH";
+    AC_OUTPUT_SUBDIRS(memory/jemalloc/src)
+    ) || exit 1
+    ac_configure_args="$_SUBDIR_CONFIG_ARGS"
+  fi
+
+fi
+
+])
diff --git a/src/third_party/mozjs-45/build/autoconf/linux.m4 b/src/third_party/mozjs-45/build/autoconf/linux.m4
new file mode 100644
index 0000000..10a8cab
--- /dev/null
+++ b/src/third_party/mozjs-45/build/autoconf/linux.m4
@@ -0,0 +1,39 @@
+dnl This Source Code Form is subject to the terms of the Mozilla Public
+dnl License, v. 2.0. If a copy of the MPL was not distributed with this
+dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+AC_DEFUN([MOZ_LINUX_PERF_EVENT],
+[
+
+MOZ_ARG_WITH_STRING(linux-headers,
+[  --with-linux-headers=DIR
+                          location where the Linux kernel headers can be found],
+    linux_headers=$withval)
+
+LINUX_HEADERS_INCLUDES=
+
+if test "$linux_headers"; then
+    LINUX_HEADERS_INCLUDES="-I$linux_headers"
+fi
+
+_SAVE_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS $LINUX_HEADERS_INCLUDES"
+
+dnl Performance measurement headers.
+MOZ_CHECK_HEADER(linux/perf_event.h,
+    [AC_CACHE_CHECK(for perf_event_open system call,ac_cv_perf_event_open,
+        [AC_TRY_COMPILE([#include <asm/unistd.h>],[return sizeof(__NR_perf_event_open);],
+        ac_cv_perf_event_open=yes,
+        ac_cv_perf_event_open=no)])])
+if test "$ac_cv_perf_event_open" = "yes"; then
+    HAVE_LINUX_PERF_EVENT_H=1
+else
+    HAVE_LINUX_PERF_EVENT_H=
+    LINUX_HEADERS_INCLUDES=
+fi
+AC_SUBST(HAVE_LINUX_PERF_EVENT_H)
+AC_SUBST(LINUX_HEADERS_INCLUDES)
+
+CFLAGS="$_SAVE_CFLAGS"
+
+])
diff --git a/src/third_party/mozjs-45/build/autoconf/lto.m4 b/src/third_party/mozjs-45/build/autoconf/lto.m4
new file mode 100644
index 0000000..572a04b
--- /dev/null
+++ b/src/third_party/mozjs-45/build/autoconf/lto.m4
@@ -0,0 +1,19 @@
+dnl This Source Code Form is subject to the terms of the Mozilla Public
+dnl License, v. 2.0. If a copy of the MPL was not distributed with this
+dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+dnl check if the build is using lto. This is really primitive and only detects llvm based
+dnl compilers right now.
+AC_DEFUN([MOZ_DOING_LTO],
+[
+  cat > conftest.c <<EOF
+                  int foo = 1;
+EOF
+  $1=no
+  if ${CC-cc} ${CFLAGS} -S conftest.c -o conftest.s >/dev/null 2>&1; then
+    if grep '^target triple =' conftest.s; then
+      $1=yes
+    fi
+  fi
+  rm -f conftest.[cs]
+])
diff --git a/src/third_party/mozjs-45/build/autoconf/mozcommonheader.m4 b/src/third_party/mozjs-45/build/autoconf/mozcommonheader.m4
new file mode 100644
index 0000000..2765217
--- /dev/null
+++ b/src/third_party/mozjs-45/build/autoconf/mozcommonheader.m4
@@ -0,0 +1,9 @@
+dnl This Source Code Form is subject to the terms of the Mozilla Public
+dnl License, v. 2.0. If a copy of the MPL was not distributed with this
+dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+AC_DEFUN(MOZ_CHECK_COMMON_HEADERS,
+	MOZ_CHECK_HEADERS(sys/byteorder.h compat.h getopt.h sys/bitypes.h \
+        memory.h unistd.h gnu/libc-version.h nl_types.h malloc.h \
+        X11/XKBlib.h io.h cpuid.h)
+)
diff --git a/src/third_party/mozjs-45/build/autoconf/mozheader.m4 b/src/third_party/mozjs-45/build/autoconf/mozheader.m4
new file mode 100644
index 0000000..e99e35a
--- /dev/null
+++ b/src/third_party/mozjs-45/build/autoconf/mozheader.m4
@@ -0,0 +1,32 @@
+dnl This Source Code Form is subject to the terms of the Mozilla Public
+dnl License, v. 2.0. If a copy of the MPL was not distributed with this
+dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+dnl MOZ_CHECK_HEADER(HEADER-FILE, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, INCLUDES]]])
+AC_DEFUN([MOZ_CHECK_HEADER],
+[ dnl Do the transliteration at runtime so arg 1 can be a shell variable.
+  ac_safe=`echo "$1" | sed 'y%./+-%__p_%'`
+  AC_MSG_CHECKING([for $1])
+  AC_CACHE_VAL(ac_cv_header_$ac_safe,
+ [ AC_TRY_COMPILE([$4
+#include <$1>], ,
+                  eval "ac_cv_header_$ac_safe=yes",
+                  eval "ac_cv_header_$ac_safe=no") ])
+  if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+    AC_MSG_RESULT(yes)
+    ifelse([$2], , :, [$2])
+  else
+    AC_MSG_RESULT(no)
+    ifelse([$3], , , [$3])
+  fi
+])
+
+dnl MOZ_CHECK_HEADERS(HEADER-FILE... [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, INCLUDES]]])
+AC_DEFUN([MOZ_CHECK_HEADERS],
+[ for ac_hdr in $1
+  do
+    MOZ_CHECK_HEADER($ac_hdr,
+                     [ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+                       AC_DEFINE_UNQUOTED($ac_tr_hdr) $2], $3, [$4])
+  done
+])
diff --git a/src/third_party/mozjs-45/build/autoconf/mozprog.m4 b/src/third_party/mozjs-45/build/autoconf/mozprog.m4
new file mode 100644
index 0000000..08747b4
--- /dev/null
+++ b/src/third_party/mozjs-45/build/autoconf/mozprog.m4
@@ -0,0 +1,42 @@
+dnl This Source Code Form is subject to the terms of the Mozilla Public
+dnl License, v. 2.0. If a copy of the MPL was not distributed with this
+dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+AC_DEFUN([MOZ_PROG_CHECKMSYS],
+[AC_REQUIRE([AC_INIT_BINSH])dnl
+if test `uname -s | grep -c MINGW 2>/dev/null` != "0"; then
+  msyshost=1
+fi
+])
+
+AC_DEFUN([MOZ_PATH_PROG],
+[ AC_PATH_PROG($1,$2,$3,$4)
+  if test "$msyshost"; then
+    case "[$]$1" in
+    /*)
+      tmp_DIRNAME=`dirname "[$]$1"`
+      tmp_BASENAME=`basename "[$]$1"`
+      tmp_PWD=`cd "$tmp_DIRNAME" && pwd -W`
+      $1="$tmp_PWD/$tmp_BASENAME"
+      if test -e "[$]$1.exe"; then
+        $1="[$]$1.exe"
+      fi
+    esac
+  fi
+])
+
+AC_DEFUN([MOZ_PATH_PROGS],
+[  AC_PATH_PROGS($1,$2,$3,$4)
+  if test "$msyshost"; then
+    case "[$]$1" in
+    /*)
+      tmp_DIRNAME=`dirname "[$]$1"`
+      tmp_BASENAME=`basename "[$]$1"`
+      tmp_PWD=`cd "$tmp_DIRNAME" && pwd -W`
+      $1="$tmp_PWD/$tmp_BASENAME"
+      if test -e "[$]$1.exe"; then
+        $1="[$]$1.exe"
+      fi
+    esac
+  fi
+])
diff --git a/src/third_party/mozjs-45/build/autoconf/nspr-build.m4 b/src/third_party/mozjs-45/build/autoconf/nspr-build.m4
new file mode 100644
index 0000000..970e1e7
--- /dev/null
+++ b/src/third_party/mozjs-45/build/autoconf/nspr-build.m4
@@ -0,0 +1,258 @@
+dnl This Source Code Form is subject to the terms of the Mozilla Public
+dnl License, v. 2.0. If a copy of the MPL was not distributed with this
+dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+AC_DEFUN([MOZ_CONFIG_NSPR], [
+
+ifelse([$1],,define(CONFIGURING_JS,yes))
+
+dnl Possible ways this can be called:
+dnl   from toplevel configure:
+dnl     JS_STANDALONE=  BUILDING_JS=
+dnl   from js/src/configure invoked by toplevel configure:
+dnl     JS_STANDALONE=  BUILDING_JS=1
+dnl   from standalone js/src/configure:
+dnl     JS_STANDALONE=1 BUILDING_JS=1
+
+dnl ========================================================
+dnl = Find the right NSPR to use.
+dnl ========================================================
+MOZ_ARG_WITH_STRING(nspr-cflags,
+[  --with-nspr-cflags=FLAGS
+                          Pass FLAGS to CC when building code that uses NSPR.
+                          Use this when there's no accurate nspr-config
+                          script available.  This is the case when building
+                          SpiderMonkey as part of the Mozilla tree: the
+                          top-level configure script computes NSPR flags
+                          that accomodate the quirks of that environment.],
+    NSPR_CFLAGS=$withval)
+MOZ_ARG_WITH_STRING(nspr-libs,
+[  --with-nspr-libs=LIBS   Pass LIBS to LD when linking code that uses NSPR.
+                          See --with-nspr-cflags for more details.],
+    NSPR_LIBS=$withval)
+
+ifdef([CONFIGURING_JS],[
+    MOZ_ARG_ENABLE_BOOL(nspr-build,
+[  --enable-nspr-build     Configure and build NSPR from source tree],
+        MOZ_BUILD_NSPR=1,
+        MOZ_BUILD_NSPR=)
+])
+
+if test -z "$BUILDING_JS" || test -n "$JS_STANDALONE"; then
+  _IS_OUTER_CONFIGURE=1
+fi
+
+MOZ_ARG_WITH_BOOL(system-nspr,
+[  --with-system-nspr      Use an NSPR that is already built and installed.
+                          Use the 'nspr-config' script in the current path,
+                          or look for the script in the directories given with
+                          --with-nspr-exec-prefix or --with-nspr-prefix.
+                          (Those flags are only checked if you specify
+                          --with-system-nspr.)],
+    _USE_SYSTEM_NSPR=1 )
+
+JS_POSIX_NSPR=unset
+ifdef([CONFIGURING_JS],[
+    if test -n "$JS_STANDALONE"; then
+      case "$target" in
+        *linux*|*darwin*|*dragonfly*|*freebsd*|*netbsd*|*openbsd*)
+          if test -z "$_HAS_NSPR"; then
+            JS_POSIX_NSPR_DEFAULT=1
+          fi
+          ;;
+      esac
+    fi
+
+    MOZ_ARG_ENABLE_BOOL(posix-nspr-emulation,
+[  --enable-posix-nspr-emulation
+                          Enable emulation of NSPR for POSIX systems],
+    JS_POSIX_NSPR=1,
+    JS_POSIX_NSPR=)
+])
+
+dnl Pass at most one of
+dnl   --with-system-nspr
+dnl   --with-nspr-cflags/libs
+dnl   --enable-nspr-build
+dnl   --enable-posix-nspr-emulation
+
+AC_MSG_CHECKING([NSPR selection])
+nspr_opts=
+which_nspr=default
+if test -n "$_USE_SYSTEM_NSPR"; then
+    nspr_opts="x$nspr_opts"
+    which_nspr="system"
+fi
+if test -n "$NSPR_CFLAGS" -o -n "$NSPR_LIBS"; then
+    nspr_opts="x$nspr_opts"
+    which_nspr="command-line"
+fi
+if test -n "$MOZ_BUILD_NSPR"; then
+    nspr_opts="x$nspr_opts"
+    which_nspr="source-tree"
+fi
+if test "$JS_POSIX_NSPR" = unset; then
+    JS_POSIX_NSPR=
+else
+    nspr_opts="x$nspr_opts"
+    which_nspr="posix-wrapper"
+fi
+
+if test -z "$nspr_opts"; then
+    if test -z "$BUILDING_JS"; then
+      dnl Toplevel configure defaults to using nsprpub from the source tree
+      MOZ_BUILD_NSPR=1
+      which_nspr="source-tree"
+    else
+      dnl JS configure defaults to emulated NSPR if available, falling back
+      dnl to nsprpub.
+      JS_POSIX_NSPR="$JS_POSIX_NSPR_DEFAULT"
+      if test -z "$JS_POSIX_NSPR"; then
+        MOZ_BUILD_NSPR=1
+        which_nspr="source-tree"
+      else
+        which_nspr="posix-wrapper"
+      fi
+   fi
+fi
+
+if test -z "$nspr_opts" || test "$nspr_opts" = x; then
+    AC_MSG_RESULT($which_nspr)
+else
+    AC_MSG_ERROR([only one way of using NSPR may be selected. See 'configure --help'.])
+fi
+
+AC_SUBST(MOZ_BUILD_NSPR)
+
+if test -n "$BUILDING_JS"; then
+  if test "$JS_POSIX_NSPR" = 1; then
+    AC_DEFINE(JS_POSIX_NSPR)
+  fi
+  AC_SUBST(JS_POSIX_NSPR)
+fi
+
+# A (sub)configure invoked by the toplevel configure will always receive
+# --with-nspr-libs on the command line. It will never need to figure out
+# anything itself.
+if test -n "$_IS_OUTER_CONFIGURE"; then
+
+if test -n "$_USE_SYSTEM_NSPR"; then
+    AM_PATH_NSPR($NSPR_MINVER, [MOZ_NATIVE_NSPR=1], [AC_MSG_ERROR([you do not have NSPR installed or your version is older than $NSPR_MINVER.])])
+fi
+
+if test -n "$MOZ_NATIVE_NSPR" -o -n "$NSPR_CFLAGS" -o -n "$NSPR_LIBS"; then
+    _SAVE_CFLAGS=$CFLAGS
+    CFLAGS="$CFLAGS $NSPR_CFLAGS"
+    AC_TRY_COMPILE([#include "prtypes.h"],
+                [#ifndef PR_STATIC_ASSERT
+                 #error PR_STATIC_ASSERT not defined or requires including prtypes.h
+                 #endif],
+                ,
+                AC_MSG_ERROR([system NSPR does not support PR_STATIC_ASSERT or including prtypes.h does not provide it]))
+    AC_TRY_COMPILE([#include "prtypes.h"],
+                [#ifndef PR_UINT64
+                 #error PR_UINT64 not defined or requires including prtypes.h
+                 #endif],
+                ,
+                AC_MSG_ERROR([system NSPR does not support PR_UINT64 or including prtypes.h does not provide it]))
+    CFLAGS=$_SAVE_CFLAGS
+elif test -z "$JS_POSIX_NSPR"; then
+    NSPR_CFLAGS="-I${DIST}/include/nspr"
+    if test -n "$GNU_CC"; then
+        NSPR_LIBS="-L${DIST}/lib -lnspr${NSPR_VERSION} -lplc${NSPR_VERSION} -lplds${NSPR_VERSION}"
+    else
+        NSPR_LIBS="${DIST}/lib/nspr${NSPR_VERSION}.lib ${DIST}/lib/plc${NSPR_VERSION}.lib ${DIST}/lib/plds${NSPR_VERSION}.lib "
+    fi
+fi
+
+AC_SUBST_LIST(NSPR_CFLAGS)
+
+NSPR_PKGCONF_CHECK="nspr"
+if test -n "$MOZ_NATIVE_NSPR"; then
+    # piggy back on $MOZ_NATIVE_NSPR to set a variable for the nspr check for js.pc
+    NSPR_PKGCONF_CHECK="nspr >= $NSPR_MINVER"
+
+    _SAVE_CFLAGS=$CFLAGS
+    CFLAGS="$CFLAGS $NSPR_CFLAGS"
+    AC_TRY_COMPILE([#include "prlog.h"],
+                [#ifndef PR_STATIC_ASSERT
+                 #error PR_STATIC_ASSERT not defined
+                 #endif],
+                ,
+                AC_MSG_ERROR([system NSPR does not support PR_STATIC_ASSERT]))
+    CFLAGS=$_SAVE_CFLAGS
+fi
+AC_SUBST(NSPR_PKGCONF_CHECK)
+
+fi # _IS_OUTER_CONFIGURE
+
+])
+
+AC_DEFUN([MOZ_SUBCONFIGURE_NSPR], [
+
+if test -z "$MOZ_NATIVE_NSPR"; then
+    ac_configure_args="$_SUBDIR_CONFIG_ARGS --with-dist-prefix=$MOZ_BUILD_ROOT/dist --with-mozilla"
+    if test -n "$MOZ_USING_CCACHE"; then
+        # Avoid double prepending ccache by omitting --with-ccache in building NSPR.
+        ac_configure_args="`echo $ac_configure_args | sed -e 's/--with-ccache[[^ ]]*//'`"
+    fi
+
+    if test -z "$MOZ_DEBUG"; then
+        ac_configure_args="$ac_configure_args --disable-debug"
+    else
+        ac_configure_args="$ac_configure_args --enable-debug"
+        if test -n "$MOZ_NO_DEBUG_RTL"; then
+            ac_configure_args="$ac_configure_args --disable-debug-rtl"
+        fi
+    fi
+    if test "$MOZ_OPTIMIZE" = "1"; then
+        ac_configure_args="$ac_configure_args --enable-optimize"
+    elif test -z "$MOZ_OPTIMIZE"; then
+        ac_configure_args="$ac_configure_args --disable-optimize"
+    fi
+    if test -n "$HAVE_64BIT_BUILD"; then
+        ac_configure_args="$ac_configure_args --enable-64bit"
+    fi
+    if test -n "$USE_ARM_KUSER"; then
+        ac_configure_args="$ac_configure_args --with-arm-kuser"
+    fi
+    # A configure script generated by autoconf 2.68 does not allow the cached
+    # values of "precious" variables such as CFLAGS and LDFLAGS to differ from
+    # the values passed to the configure script. Since we modify CFLAGS and
+    # LDFLAGS before passing them to NSPR's configure script, we cannot share
+    # config.cache with NSPR. As a result, we cannot pass AS, CC, CXX, etc. to
+    # NSPR via a shared config.cache file and must pass them to NSPR on the
+    # configure command line.
+    for var in AS CC CXX CPP LD AR RANLIB STRIP; do
+        ac_configure_args="$ac_configure_args $var='`eval echo \\${${var}}`'"
+    done
+    # A configure script generated by autoconf 2.68 warns if --host is
+    # specified but --build isn't. So we always pass --build to NSPR's
+    # configure script.
+    ac_configure_args="$ac_configure_args --build=$build"
+    ac_configure_args="$ac_configure_args $NSPR_CONFIGURE_ARGS"
+
+    # Save these, so we can mess with them for the subconfigure ..
+    _SAVE_CFLAGS="$CFLAGS"
+    _SAVE_CPPFLAGS="$CPPFLAGS"
+    _SAVE_LDFLAGS="$LDFLAGS"
+
+    if test -n "$MOZ_LINKER" -a "$ac_cv_func_dladdr" = no ; then
+      # dladdr is supported by the new linker, even when the system linker doesn't
+      # support it. Trick nspr into using dladdr when it's not supported.
+      export CPPFLAGS="-include $_topsrcdir/mozglue/linker/dladdr.h $CPPFLAGS"
+    fi
+    export LDFLAGS="$LDFLAGS $NSPR_LDFLAGS"
+    export CFLAGS="$CFLAGS $MOZ_FRAMEPTR_FLAGS $MOZ_FOLD_LIBS_FLAGS"
+
+    AC_OUTPUT_SUBDIRS(nsprpub)
+
+    # .. and restore them
+    CFLAGS="$_SAVE_CFLAGS"
+    CPPFLAGS="$_SAVE_CPPFLAGS"
+    LDFLAGS="$_SAVE_LDFLAGS"
+
+    ac_configure_args="$_SUBDIR_CONFIG_ARGS"
+fi
+
+])
diff --git a/src/third_party/mozjs-45/build/autoconf/nspr.m4 b/src/third_party/mozjs-45/build/autoconf/nspr.m4
new file mode 100644
index 0000000..cccc882
--- /dev/null
+++ b/src/third_party/mozjs-45/build/autoconf/nspr.m4
@@ -0,0 +1,110 @@
+# -*- tab-width: 4; -*-
+# Configure paths for NSPR
+# Public domain - Chris Seawood <cls@seawood.org> 2001-04-05
+# Based upon gtk.m4 (also PD) by Owen Taylor
+
+dnl AM_PATH_NSPR([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
+dnl Test for NSPR, and define NSPR_CFLAGS and NSPR_LIBS
+dnl
+dnl If the nspr-config script is available, use it to find the
+dnl appropriate CFLAGS and LIBS, and to check for the required
+dnl version, and run ACTION-IF-FOUND.
+dnl
+dnl Otherwise, if NO_NSPR_CONFIG_SYSTEM_VERSION is set, we use it,
+dnl NO_NSPR_CONFIG_SYSTEM_CFLAGS, and NO_NSPR_CONFIG_SYSTEM_LIBS to
+dnl provide default values, and run ACTION-IF-FOUND.  (Some systems
+dnl ship NSPR without nspr-config, but can glean the appropriate flags
+dnl and version.)
+dnl
+dnl Otherwise, run ACTION-IF-NOT-FOUND.
+AC_DEFUN([AM_PATH_NSPR],
+[dnl
+
+AC_ARG_WITH(nspr-prefix,
+	[  --with-nspr-prefix=PFX  Prefix where NSPR is installed],
+	nspr_config_prefix="$withval",
+	nspr_config_prefix="")
+
+AC_ARG_WITH(nspr-exec-prefix,
+	[  --with-nspr-exec-prefix=PFX
+                          Exec prefix where NSPR is installed],
+	nspr_config_exec_prefix="$withval",
+	nspr_config_exec_prefix="")
+
+	if test -n "$nspr_config_exec_prefix"; then
+		nspr_config_args="$nspr_config_args --exec-prefix=$nspr_config_exec_prefix"
+		if test -z "$NSPR_CONFIG"; then
+			NSPR_CONFIG=$nspr_config_exec_prefix/bin/nspr-config
+		fi
+	fi
+	if test -n "$nspr_config_prefix"; then
+		nspr_config_args="$nspr_config_args --prefix=$nspr_config_prefix"
+		if test -z "$NSPR_CONFIG"; then
+			NSPR_CONFIG=$nspr_config_prefix/bin/nspr-config
+		fi
+	fi
+
+	unset ac_cv_path_NSPR_CONFIG
+	AC_PATH_PROG(NSPR_CONFIG, nspr-config, no)
+	min_nspr_version=ifelse([$1], ,4.0.0,$1)
+	AC_MSG_CHECKING(for NSPR - version >= $min_nspr_version)
+
+	no_nspr=""
+	if test "$NSPR_CONFIG" != "no"; then
+		NSPR_CFLAGS=`$NSPR_CONFIG $nspr_config_args --cflags`
+		NSPR_LIBS=`$NSPR_CONFIG $nspr_config_args --libs`
+		NSPR_VERSION_STRING=`$NSPR_CONFIG $nspr_config_args --version`	
+	elif test -n "${NO_NSPR_CONFIG_SYSTEM_VERSION}"; then
+	    NSPR_CFLAGS="${NO_NSPR_CONFIG_SYSTEM_CFLAGS}"
+		NSPR_LIBS="${NO_NSPR_CONFIG_SYSTEM_LDFLAGS}"
+		NSPR_VERSION_STRING="$NO_NSPR_CONFIG_SYSTEM_VERSION"
+	else
+	    no_nspr="yes"
+	fi
+
+	if test -z "$no_nspr"; then
+		nspr_config_major_version=`echo $NSPR_VERSION_STRING | \
+			sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\(\.\([[0-9]]*\)\)\{0,1\}/\1/'`
+		nspr_config_minor_version=`echo $NSPR_VERSION_STRING | \
+			sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\(\.\([[0-9]]*\)\)\{0,1\}/\2/'`
+		nspr_config_micro_version=`echo $NSPR_VERSION_STRING | \
+			sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\(\.\([[0-9]]*\)\)\{0,1\}/\4/'`
+		if test -z "$nspr_config_micro_version"; then
+			nspr_config_micro_version="0"
+		fi
+
+		min_nspr_major_version=`echo $min_nspr_version | \
+			sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\(\.\([[0-9]]*\)\)\{0,1\}/\1/'`
+		min_nspr_minor_version=`echo $min_nspr_version | \
+			sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\(\.\([[0-9]]*\)\)\{0,1\}/\2/'`
+		min_nspr_micro_version=`echo $min_nspr_version | \
+			sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\(\.\([[0-9]]*\)\)\{0,1\}/\4/'`
+		if test -z "$min_nspr_micro_version"; then
+			min_nspr_micro_version="0"
+		fi
+
+		if test "$nspr_config_major_version" -ne "$min_nspr_major_version"; then
+			no_nspr="yes"
+		elif test "$nspr_config_major_version" -eq "$min_nspr_major_version" &&
+		     test "$nspr_config_minor_version" -lt "$min_nspr_minor_version"; then
+			no_nspr="yes"
+		elif test "$nspr_config_major_version" -eq "$min_nspr_major_version" &&
+		     test "$nspr_config_minor_version" -eq "$min_nspr_minor_version" &&
+		     test "$nspr_config_micro_version" -lt "$min_nspr_micro_version"; then
+			no_nspr="yes"
+		fi
+	fi
+
+	if test -z "$no_nspr"; then
+		AC_MSG_RESULT(yes)
+		ifelse([$2], , :, [$2])     
+	else
+		AC_MSG_RESULT(no)
+		ifelse([$3], , :, [$3])
+	fi
+
+
+	AC_SUBST_LIST(NSPR_CFLAGS)
+	AC_SUBST_LIST(NSPR_LIBS)
+
+])
diff --git a/src/third_party/mozjs-45/build/autoconf/nss.m4 b/src/third_party/mozjs-45/build/autoconf/nss.m4
new file mode 100644
index 0000000..07efb00
--- /dev/null
+++ b/src/third_party/mozjs-45/build/autoconf/nss.m4
@@ -0,0 +1,91 @@
+# -*- tab-width: 4; -*-
+# Configure paths for NSS
+# Public domain - Chris Seawood <cls@seawood.org> 2001-04-05
+# Based upon gtk.m4 (also PD) by Owen Taylor
+
+dnl AM_PATH_NSS([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
+dnl Test for NSS, and define NSS_CFLAGS and NSS_LIBS
+AC_DEFUN([AM_PATH_NSS],
+[dnl
+
+AC_ARG_WITH(nss-prefix,
+	[  --with-nss-prefix=PFX   Prefix where NSS is installed],
+	nss_config_prefix="$withval",
+	nss_config_prefix="")
+
+AC_ARG_WITH(nss-exec-prefix,
+	[  --with-nss-exec-prefix=PFX
+                          Exec prefix where NSS is installed],
+	nss_config_exec_prefix="$withval",
+	nss_config_exec_prefix="")
+
+	if test -n "$nss_config_exec_prefix"; then
+		nss_config_args="$nss_config_args --exec-prefix=$nss_config_exec_prefix"
+		if test -z "$NSS_CONFIG"; then
+			NSS_CONFIG=$nss_config_exec_prefix/bin/nss-config
+		fi
+	fi
+	if test -n "$nss_config_prefix"; then
+		nss_config_args="$nss_config_args --prefix=$nss_config_prefix"
+		if test -z "$NSS_CONFIG"; then
+			NSS_CONFIG=$nss_config_prefix/bin/nss-config
+		fi
+	fi
+
+	unset ac_cv_path_NSS_CONFIG
+	AC_PATH_PROG(NSS_CONFIG, nss-config, no)
+	min_nss_version=ifelse([$1], ,3.0.0,$1)
+	AC_MSG_CHECKING(for NSS - version >= $min_nss_version)
+
+	no_nss=""
+	if test "$NSS_CONFIG" = "no"; then
+		no_nss="yes"
+	else
+		NSS_CFLAGS=`$NSS_CONFIG $nss_config_args --cflags`
+		NSS_LIBS=`$NSS_CONFIG $nss_config_args --libs`
+
+		nss_config_major_version=`$NSS_CONFIG $nss_config_args --version | \
+			sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\(\.\([[0-9]]*\)\)\{0,1\}/\1/'`
+		nss_config_minor_version=`$NSS_CONFIG $nss_config_args --version | \
+			sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\(\.\([[0-9]]*\)\)\{0,1\}/\2/'`
+		nss_config_micro_version=`$NSS_CONFIG $nss_config_args --version | \
+			sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\(\.\([[0-9]]*\)\)\{0,1\}/\4/'`
+		if test -z "$nss_config_micro_version"; then
+			nss_config_micro_version="0"
+		fi
+
+		min_nss_major_version=`echo $min_nss_version | \
+			sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\(\.\([[0-9]]*\)\)\{0,1\}/\1/'`
+		min_nss_minor_version=`echo $min_nss_version | \
+			sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\(\.\([[0-9]]*\)\)\{0,1\}/\2/'`
+		min_nss_micro_version=`echo $min_nss_version | \
+			sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\(\.\([[0-9]]*\)\)\{0,1\}/\4/'`
+		if test -z "$min_nss_micro_version"; then
+			min_nss_micro_version="0"
+		fi
+
+		if test "$nss_config_major_version" -lt "$min_nss_major_version"; then
+			no_nss="yes"
+		elif test "$nss_config_major_version" -eq "$min_nss_major_version" &&
+		     test "$nss_config_minor_version" -lt "$min_nss_minor_version"; then
+			no_nss="yes"
+		elif test "$nss_config_major_version" -eq "$min_nss_major_version" &&
+		     test "$nss_config_minor_version" -eq "$min_nss_minor_version" &&
+		     test "$nss_config_micro_version" -lt "$min_nss_micro_version"; then
+			no_nss="yes"
+		fi
+	fi
+
+	if test -z "$no_nss"; then
+		AC_MSG_RESULT(yes)
+		ifelse([$2], , :, [$2])     
+	else
+		AC_MSG_RESULT(no)
+		ifelse([$3], , :, [$3])
+	fi
+
+
+	AC_SUBST_LIST(NSS_CFLAGS)
+	AC_SUBST_LIST(NSS_LIBS)
+
+])
diff --git a/src/third_party/mozjs-45/build/autoconf/pkg.m4 b/src/third_party/mozjs-45/build/autoconf/pkg.m4
new file mode 100644
index 0000000..74b438f
--- /dev/null
+++ b/src/third_party/mozjs-45/build/autoconf/pkg.m4
@@ -0,0 +1,63 @@
+dnl This Source Code Form is subject to the terms of the Mozilla Public
+dnl License, v. 2.0. If a copy of the MPL was not distributed with this
+dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# PKG_CHECK_MODULES(GSTUFF, gtk+-2.0 >= 1.3 glib = 1.3.4, action-if, action-not)
+# defines GSTUFF_LIBS, GSTUFF_CFLAGS, see pkg-config man page
+# also defines GSTUFF_PKG_ERRORS on error
+AC_DEFUN([PKG_CHECK_MODULES],
+[succeeded=no
+
+  if test -z "$PKG_CONFIG"; then
+    AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
+  fi
+
+  if test "$PKG_CONFIG" = "no" ; then
+     echo "*** The pkg-config script could not be found. Make sure it is"
+     echo "*** in your path, or set the PKG_CONFIG environment variable"
+     echo "*** to the full path to pkg-config."
+     echo "*** Or see http://www.freedesktop.org/software/pkgconfig to get pkg-config."
+  else
+     PKG_CONFIG_MIN_VERSION=0.9.0
+     if $PKG_CONFIG --atleast-pkgconfig-version $PKG_CONFIG_MIN_VERSION; then
+        AC_MSG_CHECKING(for $2)
+
+        if $PKG_CONFIG --exists "$2" ; then
+            AC_MSG_RESULT(yes)
+            succeeded=yes
+
+            AC_MSG_CHECKING($1_CFLAGS)
+            $1_CFLAGS=`$PKG_CONFIG --cflags "$2"`
+            AC_MSG_RESULT($$1_CFLAGS)
+
+            AC_MSG_CHECKING($1_LIBS)
+            ## Remove evil flags like -Wl,--export-dynamic
+            $1_LIBS="`$PKG_CONFIG --libs \"$2\" |sed s/-Wl,--export-dynamic//g`"
+            AC_MSG_RESULT($$1_LIBS)
+        else
+            $1_CFLAGS=""
+            $1_LIBS=""
+            ## If we have a custom action on failure, don't print errors, but 
+            ## do set a variable so people can do so.
+            $1_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"`
+            ifelse([$4], ,echo $$1_PKG_ERRORS,)
+        fi
+
+        AC_SUBST_LIST($1_CFLAGS)
+        AC_SUBST_LIST($1_LIBS)
+     else
+        echo "*** Your version of pkg-config is too old. You need version $PKG_CONFIG_MIN_VERSION or newer."
+        echo "*** See http://www.freedesktop.org/software/pkgconfig"
+     fi
+  fi
+
+  if test $succeeded = yes; then
+     ifelse([$3], , :, [$3])
+  else
+     if test "$COMPILE_ENVIRONMENT"; then 
+       ifelse([$4], , AC_MSG_ERROR([Library requirements ($2) not met; consider adjusting the PKG_CONFIG_PATH environment variable if your libraries are in a nonstandard prefix so pkg-config can find them.]), [$4])
+     fi
+  fi
+])
+
+
diff --git a/src/third_party/mozjs-45/build/autoconf/python-virtualenv.m4 b/src/third_party/mozjs-45/build/autoconf/python-virtualenv.m4
new file mode 100644
index 0000000..e7dd990
--- /dev/null
+++ b/src/third_party/mozjs-45/build/autoconf/python-virtualenv.m4
@@ -0,0 +1,85 @@
+dnl This Source Code Form is subject to the terms of the Mozilla Public
+dnl License, v. 2.0. If a copy of the MPL was not distributed with this
+dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+AC_DEFUN([MOZ_PYTHON],
+[
+
+dnl We honor the Python path defined in an environment variable. This is used
+dnl to pass the virtualenv's Python from the main configure to SpiderMonkey's
+dnl configure, for example.
+if test -z "$PYTHON"; then
+  MOZ_PATH_PROGS(PYTHON, $PYTHON python2.7 python)
+  if test -z "$PYTHON"; then
+      AC_MSG_ERROR([python was not found in \$PATH])
+  fi
+else
+  AC_MSG_RESULT([Using Python from environment variable \$PYTHON])
+fi
+
+_virtualenv_topsrcdir=
+_virtualenv_populate_path=
+
+dnl If this is a mozilla-central, we'll find the virtualenv in the top
+dnl source directory. If this is a SpiderMonkey build, we assume we're at
+dnl js/src and try to find the virtualenv from the mozilla-central root.
+for base in $MOZILLA_CENTRAL_PATH $_topsrcdir $_topsrcdir/../..; do
+  possible=$base/python/mozbuild/mozbuild/virtualenv.py
+
+  if test -e $possible; then
+    _virtualenv_topsrcdir=$base
+    _virtualenv_populate_path=$possible
+    break
+  fi
+done
+
+if test -z $_virtualenv_populate_path; then
+    AC_MSG_ERROR([Unable to find Virtualenv population script. In order
+to build, you will need mozilla-central's virtualenv.
+
+If you are building from a mozilla-central checkout, you should never see this
+message. If you are building from a source archive, the source archive was
+likely not created properly (it is missing the virtualenv files).
+
+If you have a copy of mozilla-central available, define the
+MOZILLA_CENTRAL_PATH environment variable to the top source directory of
+mozilla-central and relaunch configure.])
+
+fi
+
+if test -z $DONT_POPULATE_VIRTUALENV; then
+  AC_MSG_RESULT([Creating Python environment])
+  dnl This verifies our Python version is sane and ensures the Python
+  dnl virtualenv is present and up to date. It sanitizes the environment
+  dnl for us, so we don't need to clean anything out.
+  $PYTHON $_virtualenv_populate_path \
+    $_virtualenv_topsrcdir $MOZ_BUILD_ROOT $MOZ_BUILD_ROOT/_virtualenv \
+    $_virtualenv_topsrcdir/build/virtualenv_packages.txt || exit 1
+
+  case "$host_os" in
+  mingw*)
+    PYTHON=`cd $MOZ_BUILD_ROOT && pwd -W`/_virtualenv/Scripts/python.exe
+    ;;
+  *)
+    PYTHON=$MOZ_BUILD_ROOT/_virtualenv/bin/python
+    ;;
+  esac
+fi
+
+AC_SUBST(PYTHON)
+
+AC_MSG_CHECKING([Python environment is Mozilla virtualenv])
+$PYTHON -c "import mozbuild.base"
+if test "$?" != 0; then
+    AC_MSG_ERROR([Python environment does not appear to be sane.])
+fi
+AC_MSG_RESULT([yes])
+
+PYTHON_SITE_PACKAGES=`$PYTHON -c "import distutils.sysconfig; print distutils.sysconfig.get_python_lib()"`
+if test -z "$PYTHON_SITE_PACKAGES"; then
+    AC_MSG_ERROR([Could not determine python site packages directory.])
+fi
+AC_SUBST([PYTHON_SITE_PACKAGES])
+
+])
+
diff --git a/src/third_party/mozjs-45/build/autoconf/rust.m4 b/src/third_party/mozjs-45/build/autoconf/rust.m4
new file mode 100644
index 0000000..a4d014a
--- /dev/null
+++ b/src/third_party/mozjs-45/build/autoconf/rust.m4
@@ -0,0 +1,36 @@
+dnl This Source Code Form is subject to the terms of the Mozilla Public
+dnl License, v. 2.0. If a copy of the MPL was not distributed with this
+dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+AC_DEFUN([MOZ_RUST_SUPPORT], [
+  MOZ_PATH_PROG(RUSTC, rustc)
+  if test -n "$RUSTC"; then
+    AC_MSG_CHECKING([rustc version])
+    RUSTC_VERSION=`$RUSTC --version | cut -d ' ' -f 2`
+    # Parse out semversion elements.
+    _RUSTC_MAJOR_VERSION=`echo ${RUSTC_VERSION} | cut -d . -f 1`
+    _RUSTC_MINOR_VERSION=`echo ${RUSTC_VERSION} | cut -d . -f 2`
+    _RUSTC_EXTRA_VERSION=`echo ${RUSTC_VERSION} | cut -d . -f 3 | cut -d + -f 1`
+    _RUSTC_PATCH_VERSION=`echo ${_RUSTC_EXTRA_VERSION} | cut -d '-' -f 1`
+    AC_MSG_RESULT([$RUSTC_VERSION (v${_RUSTC_MAJOR_VERSION}.${_RUSTC_MINOR_VERSION}.${_RUSTC_PATCH_VERSION})])
+  fi
+  MOZ_ARG_ENABLE_BOOL([rust],
+                      [  --enable-rust           Include Rust language sources],
+                      [MOZ_RUST=1],
+                      [MOZ_RUST= ])
+  if test -z "$RUSTC" -a -n "$MOZ_RUST"; then
+    AC_MSG_ERROR([Rust compiler not found.
+      To compile rust language sources, you must have 'rustc' in your path.
+      See http://www.rust-lang.org/ for more information.])
+  fi
+  if test -n "$MOZ_RUST" && test -z "$_RUSTC_MAJOR_VERSION" -o \
+    "$_RUSTC_MAJOR_VERSION" -lt 1 -o \
+    \( "$_RUSTC_MAJOR_VERSION" -eq 1 -a "$_RUSTC_MINOR_VERSION" -lt 4 \); then
+    AC_MSG_ERROR([Rust compiler ${RUSTC_VERSION} is too old.
+      To compile Rust language sources please install at least
+      version 1.4 of the 'rustc' toolchain and make sure it is
+      first in your path.
+      You can verify this by typing 'rustc --version'.])
+  fi
+  AC_SUBST(MOZ_RUST)
+])
diff --git a/src/third_party/mozjs-45/build/autoconf/subconfigure.m4 b/src/third_party/mozjs-45/build/autoconf/subconfigure.m4
new file mode 100644
index 0000000..56c00cf
--- /dev/null
+++ b/src/third_party/mozjs-45/build/autoconf/subconfigure.m4
@@ -0,0 +1,46 @@
+dnl We are not running in a real autoconf environment. So we're using real m4
+dnl here, not the crazier environment that autoconf provides.
+
+dnl Autoconf expects [] for quotes; give it to them
+changequote([, ])
+
+dnl AC_DEFUN is provided to use instead of define in autoconf. Provide it too.
+define([AC_DEFUN], [define($1, [$2])])
+
+dnl AC_ARG_ENABLE(FEATURE, HELP-STRING, IF-TRUE[, IF-FALSE])
+dnl We have to ignore the help string due to how help works in autoconf...
+AC_DEFUN([AC_ARG_ENABLE],
+[#] Check whether --enable-[$1] or --disable-[$1] was given.
+[if test "[${enable_]patsubst([$1], -, _)+set}" = set; then
+  enableval="[$enable_]patsubst([$1], -, _)"
+  $3
+ifelse([$4], , , [else
+  $4
+])dnl
+fi
+])
+
+dnl AC_MSG_ERROR(error-description)
+AC_DEFUN([AC_MSG_ERROR], [{ echo "configure: error: $1" 1>&2; exit 1; }])
+
+AC_DEFUN([AC_MSG_WARN],  [ echo "configure: warning: $1" 1>&2 ])
+
+dnl Add the variable to the list of substitution variables
+AC_DEFUN([AC_SUBST],
+[
+_subconfigure_ac_subst_args="$_subconfigure_ac_subst_args $1"
+])
+
+dnl Override for AC_DEFINE.
+AC_DEFUN([AC_DEFINE],
+[
+cat >>confdefs.h <<\EOF
+[#define] $1 ifelse($#, 2, [$2], $#, 3, [$2], 1)
+EOF
+cat >> confdefs.pytmp <<\EOF
+    (''' $1 ''', ifelse($#, 2, [r''' $2 '''], $#, 3, [r''' $2 '''], ' 1 '))
+EOF
+])
+
+dnl AC_OUTPUT_SUBDIRS(subdirectory)
+AC_DEFUN([AC_OUTPUT_SUBDIRS], [do_output_subdirs "$1"])
diff --git a/src/third_party/mozjs-45/build/autoconf/toolchain.m4 b/src/third_party/mozjs-45/build/autoconf/toolchain.m4
new file mode 100644
index 0000000..90d8528
--- /dev/null
+++ b/src/third_party/mozjs-45/build/autoconf/toolchain.m4
@@ -0,0 +1,332 @@
+dnl This Source Code Form is subject to the terms of the Mozilla Public
+dnl License, v. 2.0. If a copy of the MPL was not distributed with this
+dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+AC_DEFUN([MOZ_TOOL_VARIABLES],
+[
+GNU_AS=
+GNU_LD=
+GNU_CC=
+GNU_CXX=
+CC_VERSION='N/A'
+CXX_VERSION='N/A'
+cat <<EOF > conftest.c
+#if defined(_MSC_VER)
+#if defined(__clang__)
+COMPILER clang-cl _MSC_VER
+#else
+COMPILER msvc _MSC_FULL_VER
+#endif
+#elif defined(__clang__)
+COMPILER clang __clang_major__.__clang_minor__.__clang_patchlevel__
+#elif defined(__GNUC__)
+COMPILER gcc __GNUC__.__GNUC_MINOR__.__GNUC_PATCHLEVEL__
+#elif defined(__INTEL_COMPILER)
+COMPILER icc __INTEL_COMPILER
+#endif
+EOF
+read dummy compiler CC_VERSION <<EOF
+$($CC -E $CPPFLAGS $CFLAGS conftest.c 2>/dev/null | grep COMPILER)
+EOF
+read dummy cxxcompiler CXX_VERSION <<EOF
+$($CXX -E $CPPFLAGS $CXXFLAGS conftest.c 2>/dev/null | grep COMPILER)
+EOF
+if test "$compiler" != "$cxxcompiler"; then
+    AC_MSG_ERROR([Your C and C++ compilers are different.  You need to use the same compiler.])
+fi
+if test "$CC_VERSION" != "$CXX_VERSION"; then
+    # This may not be strictly necessary, but if we want to drop it, we
+    # should make sure any version checks below apply to both the C and
+    # C++ compiler versions.
+    AC_MSG_ERROR([Your C and C++ compiler versions are different.  You need to use the same compiler version.])
+fi
+CC_VERSION=`echo "$CC_VERSION" | sed 's/ //g'`
+CXX_VERSION=`echo "$CXX_VERSION" | sed 's/ //g'`
+if test "$compiler" = "gcc"; then
+    GNU_CC=1
+    GNU_CXX=1
+    changequote(<<,>>)
+    GCC_VERSION_FULL="$CXX_VERSION"
+    GCC_VERSION=`echo "$GCC_VERSION_FULL" | $PERL -pe '(split(/\./))[0]>=4&&s/(^\d*\.\d*).*/<<$>>1/;'`
+
+    GCC_MAJOR_VERSION=`echo ${GCC_VERSION} | $AWK -F\. '{ print <<$>>1 }'`
+    GCC_MINOR_VERSION=`echo ${GCC_VERSION} | $AWK -F\. '{ print <<$>>2 }'`
+    changequote([,])
+fi
+
+if test "`echo | $AS -o conftest.out -v 2>&1 | grep -c GNU`" != "0"; then
+    GNU_AS=1
+fi
+rm -f conftest.out
+if test "`echo | $LD -v 2>&1 | grep -c GNU`" != "0"; then
+    GNU_LD=1
+fi
+
+if test "$compiler" = "msvc"; then
+     MSVC_VERSION_FULL="$CXX_VERSION"
+     CC_VERSION=`echo ${CC_VERSION} | cut -c 1-4`
+     CXX_VERSION=`echo ${CXX_VERSION} | cut -c 1-4`
+fi
+
+INTEL_CC=
+INTEL_CXX=
+if test "$compiler" = "icc"; then
+   INTEL_CC=1
+   INTEL_CXX=1
+fi
+
+CLANG_CC=
+CLANG_CXX=
+CLANG_CL=
+if test "$compiler" = "clang"; then
+    GNU_CC=1
+    GNU_CXX=1
+    CLANG_CC=1
+    CLANG_CXX=1
+fi
+if test "$compiler" = "clang-cl"; then
+    CLANG_CL=1
+    # We force clang-cl to emulate Visual C++ 2013 in configure.in, but that
+    # is based on the CLANG_CL variable defined here, so make sure that we're
+    # getting the right version here manually.
+    CC_VERSION=1800
+    CXX_VERSION=1800
+    MSVC_VERSION_FULL=180030723
+    # Build on clang-cl with MSVC 2013 Update 3 with fallback emulation.
+    CFLAGS="$CFLAGS -fms-compatibility-version=18.00.30723 -fallback"
+    CXXFLAGS="$CXXFLAGS -fms-compatibility-version=18.00.30723 -fallback"
+fi
+
+if test "$GNU_CC"; then
+    if `$CC -print-prog-name=ld` -v 2>&1 | grep -c GNU >/dev/null; then
+        GCC_USE_GNU_LD=1
+    fi
+fi
+
+AC_SUBST(CLANG_CXX)
+AC_SUBST(CLANG_CL)
+
+if test -n "$GNU_CC" -a -z "$CLANG_CC" ; then
+    if test "$GCC_MAJOR_VERSION" -eq 4 -a "$GCC_MINOR_VERSION" -lt 7 ||
+       test "$GCC_MAJOR_VERSION" -lt 4; then
+        AC_MSG_ERROR([Only GCC 4.7 or newer supported])
+    fi
+fi
+])
+
+AC_DEFUN([MOZ_CROSS_COMPILER],
+[
+echo "cross compiling from $host to $target"
+
+_SAVE_CC="$CC"
+_SAVE_CFLAGS="$CFLAGS"
+_SAVE_LDFLAGS="$LDFLAGS"
+
+AC_MSG_CHECKING([for host c compiler])
+AC_CHECK_PROGS(HOST_CC, cc gcc clang cl, "")
+if test -z "$HOST_CC"; then
+    AC_MSG_ERROR([no acceptable c compiler found in \$PATH])
+fi
+AC_MSG_RESULT([$HOST_CC])
+AC_MSG_CHECKING([for host c++ compiler])
+AC_CHECK_PROGS(HOST_CXX, c++ g++ clang++ cl, "")
+if test -z "$HOST_CXX"; then
+    AC_MSG_ERROR([no acceptable c++ compiler found in \$PATH])
+fi
+AC_MSG_RESULT([$HOST_CXX])
+
+if test -z "$HOST_CFLAGS"; then
+    HOST_CFLAGS="$CFLAGS"
+fi
+if test -z "$HOST_CXXFLAGS"; then
+    HOST_CXXFLAGS="$CXXFLAGS"
+fi
+if test -z "$HOST_LDFLAGS"; then
+    HOST_LDFLAGS="$LDFLAGS"
+fi
+if test -z "$HOST_AR_FLAGS"; then
+    HOST_AR_FLAGS="$AR_FLAGS"
+fi
+AC_CHECK_PROGS(HOST_RANLIB, $HOST_RANLIB ranlib, ranlib, :)
+AC_CHECK_PROGS(HOST_AR, $HOST_AR ar, ar, :)
+CC="$HOST_CC"
+CFLAGS="$HOST_CFLAGS"
+LDFLAGS="$HOST_LDFLAGS"
+
+AC_MSG_CHECKING([whether the host c compiler ($HOST_CC $HOST_CFLAGS $HOST_LDFLAGS) works])
+AC_TRY_COMPILE([], [return(0);],
+    [ac_cv_prog_hostcc_works=1 AC_MSG_RESULT([yes])],
+    AC_MSG_ERROR([installation or configuration problem: host compiler $HOST_CC cannot create executables.]) )
+
+CC="$HOST_CXX"
+CFLAGS="$HOST_CXXFLAGS"
+AC_MSG_CHECKING([whether the host c++ compiler ($HOST_CXX $HOST_CXXFLAGS $HOST_LDFLAGS) works])
+AC_TRY_COMPILE([], [return(0);],
+    [ac_cv_prog_hostcxx_works=1 AC_MSG_RESULT([yes])],
+    AC_MSG_ERROR([installation or configuration problem: host compiler $HOST_CXX cannot create executables.]) )
+
+CC=$_SAVE_CC
+CFLAGS=$_SAVE_CFLAGS
+LDFLAGS=$_SAVE_LDFLAGS
+
+AC_CHECK_PROGS(CC, "${target_alias}-gcc" "${target}-gcc", :)
+unset ac_cv_prog_CC
+AC_PROG_CC
+AC_CHECK_PROGS(CXX, "${target_alias}-g++" "${target}-g++", :)
+unset ac_cv_prog_CXX
+AC_PROG_CXX
+
+AC_CHECK_PROGS(RANLIB, "${target_alias}-ranlib" "${target}-ranlib", :)
+AC_CHECK_PROGS(AR, "${target_alias}-ar" "${target}-ar", :)
+AC_CHECK_PROGS(AS, "${target_alias}-as" "${target}-as", :)
+AC_CHECK_PROGS(LD, "${target_alias}-ld" "${target}-ld", :)
+AC_CHECK_PROGS(STRIP, "${target_alias}-strip" "${target}-strip", :)
+AC_CHECK_PROGS(WINDRES, "${target_alias}-windres" "${target}-windres", :)
+AC_CHECK_PROGS(OTOOL, "${target_alias}-otool" "${target}-otool", :)
+AC_DEFINE(CROSS_COMPILE)
+CROSS_COMPILE=1
+
+dnl If we cross compile for ppc on Mac OS X x86, cross_compiling will
+dnl dnl have erroneously been set to "no", because the x86 build host is
+dnl dnl able to run ppc code in a translated environment, making a cross
+dnl dnl compiler appear native.  So we override that here.
+cross_compiling=yes
+])
+
+AC_DEFUN([MOZ_CXX11],
+[
+dnl Check whether gcc's c++0x mode works
+dnl Updates to the test below should be duplicated further below for the
+dnl cross-compiling case.
+AC_LANG_CPLUSPLUS
+if test "$GNU_CXX"; then
+    CXXFLAGS="$CXXFLAGS -std=gnu++0x"
+    _ADDED_CXXFLAGS="-std=gnu++0x"
+
+    AC_CACHE_CHECK(for gcc c++0x headers bug without rtti,
+        ac_cv_cxx0x_headers_bug,
+        [AC_TRY_COMPILE([#include <memory>], [],
+                        ac_cv_cxx0x_headers_bug="no",
+                        ac_cv_cxx0x_headers_bug="yes")])
+
+    if test "$CLANG_CXX" -a "$ac_cv_cxx0x_headers_bug" = "yes"; then
+        CXXFLAGS="$CXXFLAGS -I$_topsrcdir/build/unix/headers"
+        _ADDED_CXXFLAGS="$_ADDED_CXXFLAGS -I$_topsrcdir/build/unix/headers"
+        AC_CACHE_CHECK(whether workaround for gcc c++0x headers conflict with clang works,
+            ac_cv_cxx0x_clang_workaround,
+            [AC_TRY_COMPILE([#include <memory>], [],
+                            ac_cv_cxx0x_clang_workaround="yes",
+                            ac_cv_cxx0x_clang_workaround="no")])
+
+        if test "ac_cv_cxx0x_clang_workaround" = "no"; then
+            AC_MSG_ERROR([Your toolchain does not support C++0x/C++11 mode properly. Please upgrade your toolchain])
+        fi
+    elif test "$ac_cv_cxx0x_headers_bug" = "yes"; then
+        AC_MSG_ERROR([Your toolchain does not support C++0x/C++11 mode properly. Please upgrade your toolchain])
+    fi
+
+    AC_CACHE_CHECK([whether 64-bits std::atomic requires -latomic],
+        ac_cv_needs_atomic,
+        AC_TRY_LINK(
+            [#include <cstdint>
+             #include <atomic>],
+            [ std::atomic<uint64_t> foo; foo = 1; ],
+            ac_cv_needs_atomic=no,
+            _SAVE_LIBS="$LIBS"
+            LIBS="$LIBS -latomic"
+            AC_TRY_LINK(
+                [#include <cstdint>
+                 #include <atomic>],
+                [ std::atomic<uint64_t> foo; foo = 1; ],
+                ac_cv_needs_atomic=yes,
+                ac_cv_needs_atomic="do not know; assuming no")
+            LIBS="$_SAVE_LIBS"
+        )
+    )
+    if test "$ac_cv_needs_atomic" = yes; then
+      MOZ_NEEDS_LIBATOMIC=1
+    else
+      MOZ_NEEDS_LIBATOMIC=
+    fi
+    AC_SUBST(MOZ_NEEDS_LIBATOMIC)
+fi
+
+if test -n "$CROSS_COMPILE"; then
+    dnl When cross compile, we have no variable telling us what the host compiler is. Figure it out.
+    cat > conftest.C <<EOF
+#if defined(__clang__)
+COMPILER CLANG __clang_major__.__clang_minor__.__clang_patchlevel__
+#elif defined(__GNUC__)
+COMPILER GCC __GNUC__.__GNUC_MINOR__.__GNUC_PATCHLEVEL__
+#endif
+EOF
+read dummy host_compiler HOST_CC_VERSION <<EOF
+$($HOST_CC -E conftest.C 2>/dev/null | grep COMPILER)
+EOF
+read dummy host_cxxcompiler HOST_CXX_VERSION <<EOF
+$($HOST_CXX -E conftest.C 2>/dev/null | grep COMPILER)
+EOF
+    rm conftest.C
+    if test "$host_compiler" != "$host_cxxcompiler"; then
+        AC_MSG_ERROR([Your C and C++ host compilers are different.  You need to use the same compiler.])
+    fi
+    if test "$HOST_CC_VERSION" != "$HOST_CXX_VERSION"; then
+        # This may not be strictly necessary, but if we want to drop it,
+        # we should make sure any version checks below apply to both the
+        # C and C++ compiler versions.
+        AC_MSG_ERROR([Your C and C++ host compiler versions are different.  You need to use the same compiler version.])
+    fi
+    if test -n "$host_compiler"; then
+        if test "$host_compiler" = "GCC" ; then
+            changequote(<<,>>)
+            HOST_GCC_VERSION_FULL="$HOST_CXX_VERSION"
+            HOST_GCC_VERSION=`echo "$HOST_GCC_VERSION_FULL" | $PERL -pe '(split(/\./))[0]>=4&&s/(^\d*\.\d*).*/<<$>>1/;'`
+
+            HOST_GCC_MAJOR_VERSION=`echo ${HOST_GCC_VERSION} | $AWK -F\. '{ print <<$>>1 }'`
+            HOST_GCC_MINOR_VERSION=`echo ${HOST_GCC_VERSION} | $AWK -F\. '{ print <<$>>2 }'`
+            changequote([,])
+
+            if test "$HOST_GCC_MAJOR_VERSION" -eq 4 -a "$HOST_GCC_MINOR_VERSION" -lt 7 ||
+               test "$HOST_GCC_MAJOR_VERSION" -lt 4; then
+                AC_MSG_ERROR([Only GCC 4.7 or newer supported for host compiler])
+            fi
+        fi
+
+        HOST_CXXFLAGS="$HOST_CXXFLAGS -std=gnu++0x"
+
+        _SAVE_CXXFLAGS="$CXXFLAGS"
+        _SAVE_CPPFLAGS="$CPPFLAGS"
+        _SAVE_CXX="$CXX"
+        CXXFLAGS="$HOST_CXXFLAGS"
+        CPPFLAGS="$HOST_CPPFLAGS"
+        CXX="$HOST_CXX"
+        AC_CACHE_CHECK(for host gcc c++0x headers bug without rtti,
+            ac_cv_host_cxx0x_headers_bug,
+            [AC_TRY_COMPILE([#include <memory>], [],
+                            ac_cv_host_cxx0x_headers_bug="no",
+                            ac_cv_host_cxx0x_headers_bug="yes")])
+
+        if test "$host_compiler" = CLANG -a "$ac_cv_host_cxx0x_headers_bug" = "yes"; then
+            CXXFLAGS="$CXXFLAGS -I$_topsrcdir/build/unix/headers"
+            AC_CACHE_CHECK(whether workaround for host gcc c++0x headers conflict with host clang works,
+                ac_cv_host_cxx0x_clang_workaround,
+                [AC_TRY_COMPILE([#include <memory>], [],
+                                ac_cv_host_cxx0x_clang_workaround="yes",
+                                ac_cv_host_cxx0x_clang_workaround="no")])
+
+            if test "ac_cv_host_cxx0x_clang_workaround" = "no"; then
+                AC_MSG_ERROR([Your host toolchain does not support C++0x/C++11 mode properly. Please upgrade your toolchain])
+            fi
+            HOST_CXXFLAGS="$CXXFLAGS"
+        elif test "$ac_cv_host_cxx0x_headers_bug" = "yes"; then
+            AC_MSG_ERROR([Your host toolchain does not support C++0x/C++11 mode properly. Please upgrade your toolchain])
+        fi
+        CXXFLAGS="$_SAVE_CXXFLAGS"
+        CPPFLAGS="$_SAVE_CPPFLAGS"
+        CXX="$_SAVE_CXX"
+    fi
+elif test "$GNU_CXX"; then
+    HOST_CXXFLAGS="$HOST_CXXFLAGS $_ADDED_CXXFLAGS"
+fi
+AC_LANG_C
+])
diff --git a/src/third_party/mozjs-45/build/autoconf/winsdk.m4 b/src/third_party/mozjs-45/build/autoconf/winsdk.m4
new file mode 100644
index 0000000..fb512da
--- /dev/null
+++ b/src/third_party/mozjs-45/build/autoconf/winsdk.m4
@@ -0,0 +1,22 @@
+dnl This Source Code Form is subject to the terms of the Mozilla Public
+dnl License, v. 2.0. If a copy of the MPL was not distributed with this
+dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+dnl Identify which version of the SDK we're building with
+dnl Windows Server 2008 and newer SDKs have WinSDKVer.h, get the version
+dnl from there
+AC_DEFUN([MOZ_FIND_WINSDK_VERSION], [
+  AC_CACHE_CHECK(for highest Windows version supported by this SDK,
+                 ac_cv_winsdk_maxver,
+                 [cat > conftest.h <<EOF
+#include <winsdkver.h>
+
+WINVER_MAXVER
+EOF
+                      ac_cv_winsdk_maxver=`$CPP conftest.h 2>/dev/null | tail -n1`
+                      rm -f conftest.h
+                     ])
+      dnl WinSDKVer.h returns the version number in 4-digit format while many
+      dnl consumers expect 8. Therefore, pad the result with an extra 4 zeroes.
+      MOZ_WINSDK_MAXVER=${ac_cv_winsdk_maxver}0000
+])
diff --git a/src/third_party/mozjs-45/build/autoconf/wrapper.m4 b/src/third_party/mozjs-45/build/autoconf/wrapper.m4
new file mode 100644
index 0000000..ebe8250
--- /dev/null
+++ b/src/third_party/mozjs-45/build/autoconf/wrapper.m4
@@ -0,0 +1,75 @@
+dnl This Source Code Form is subject to the terms of the Mozilla Public
+dnl License, v. 2.0. If a copy of the MPL was not distributed with this
+dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+dnl =======================================================================
+dnl = Enable compiling with various compiler wrappers (distcc, ccache, etc)
+dnl =======================================================================
+AC_DEFUN([MOZ_CHECK_COMPILER_WRAPPER],
+[
+MOZ_ARG_WITH_STRING(compiler_wrapper,
+[  --with-compiler-wrapper[=path/to/wrapper]
+    Enable compiling with wrappers such as distcc and ccache],
+    COMPILER_WRAPPER=$withval, COMPILER_WRAPPER="no")
+
+MOZ_ARG_WITH_STRING(ccache,
+[  --with-ccache[=path/to/ccache]
+                          Enable compiling with ccache],
+    CCACHE=$withval, CCACHE="no")
+
+if test "$CCACHE" != "no"; then
+    if test -z "$CCACHE" -o "$CCACHE" = "yes"; then
+        CCACHE=
+    else
+        if test ! -e "$CCACHE"; then
+            AC_MSG_ERROR([$CCACHE not found])
+        fi
+    fi
+    MOZ_PATH_PROGS(CCACHE, $CCACHE ccache)
+    if test -z "$CCACHE" -o "$CCACHE" = ":"; then
+        AC_MSG_ERROR([ccache not found])
+    elif test -x "$CCACHE"; then
+        if test "$COMPILER_WRAPPER" != "no"; then
+            COMPILER_WRAPPER="$CCACHE $COMPILER_WRAPPER"
+        else
+            COMPILER_WRAPPER="$CCACHE"
+        fi
+        MOZ_USING_CCACHE=1
+    else
+        AC_MSG_ERROR([$CCACHE is not executable])
+    fi
+fi
+
+AC_SUBST(MOZ_USING_CCACHE)
+
+if test "$COMPILER_WRAPPER" != "no"; then
+    case "$target" in
+    *-mingw*)
+        dnl When giving a windows path with backslashes, js/src/configure
+        dnl fails because of double wrapping because the test further below
+        dnl doesn't work with backslashes. While fixing that test to work
+        dnl might seem better, a lot of the make build backend actually
+        dnl doesn't like backslashes, so normalize windows paths to use
+        dnl forward slashes.
+        COMPILER_WRAPPER=`echo "$COMPILER_WRAPPER" | tr '\\' '/'`
+        ;;
+    esac
+
+    case "$CC" in
+    $COMPILER_WRAPPER\ *)
+        :
+        ;;
+    *)
+        CC="$COMPILER_WRAPPER $CC"
+        CXX="$COMPILER_WRAPPER $CXX"
+        _SUBDIR_CC="$CC"
+        _SUBDIR_CXX="$CXX"
+        ac_cv_prog_CC="$CC"
+        ac_cv_prog_CXX="$CXX"
+        ;;
+    esac
+    MOZ_USING_COMPILER_WRAPPER=1
+fi
+
+AC_SUBST(MOZ_USING_COMPILER_WRAPPER)
+])
diff --git a/src/third_party/mozjs-45/build/autoconf/zlib.m4 b/src/third_party/mozjs-45/build/autoconf/zlib.m4
new file mode 100644
index 0000000..c23b135
--- /dev/null
+++ b/src/third_party/mozjs-45/build/autoconf/zlib.m4
@@ -0,0 +1,54 @@
+dnl This Source Code Form is subject to the terms of the Mozilla Public
+dnl License, v. 2.0. If a copy of the MPL was not distributed with this
+dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+dnl Usage: MOZ_ZLIB_CHECK([version])
+
+AC_DEFUN([MOZ_ZLIB_CHECK],
+[
+
+MOZZLIB=$1
+
+MOZ_ARG_WITH_STRING(system-zlib,
+[  --with-system-zlib[=PFX]
+                          Use system libz [installed at prefix PFX]],
+    ZLIB_DIR=$withval)
+
+if test -z "$MOZ_ZLIB_LIBS$MOZ_ZLIB_CFLAGS$SKIP_LIBRARY_CHECKS"; then
+    _SAVE_CFLAGS=$CFLAGS
+    _SAVE_LDFLAGS=$LDFLAGS
+    _SAVE_LIBS=$LIBS
+
+    if test -n "${ZLIB_DIR}" -a "${ZLIB_DIR}" != "yes"; then
+        MOZ_ZLIB_CFLAGS="-I${ZLIB_DIR}/include"
+        MOZ_ZLIB_LIBS="-L${ZLIB_DIR}/lib"
+        CFLAGS="$MOZ_ZLIB_CFLAGS $CFLAGS"
+        LDFLAGS="$MOZ_ZLIB_LIBS $LDFLAGS"
+    fi
+    if test -z "$ZLIB_DIR" -o "$ZLIB_DIR" = no; then
+        MOZ_NATIVE_ZLIB=
+    else
+        AC_CHECK_LIB(z, gzread, [MOZ_NATIVE_ZLIB=1 MOZ_ZLIB_LIBS="$MOZ_ZLIB_LIBS -lz"],
+            [MOZ_NATIVE_ZLIB=])
+        if test "$MOZ_NATIVE_ZLIB" = 1; then
+            MOZZLIBNUM=`echo $MOZZLIB | awk -F. changequote(<<, >>)'{printf "0x%x\n", (((<<$>>1 * 16 + <<$>>2) * 16) + <<$>>3) * 16 + <<$>>4}'changequote([, ])`
+            AC_TRY_COMPILE([ #include <stdio.h>
+                             #include <string.h>
+                             #include <zlib.h> ],
+                           [ #if ZLIB_VERNUM < $MOZZLIBNUM
+                             #error "Insufficient zlib version ($MOZZLIBNUM required)."
+                             #endif ],
+                           MOZ_NATIVE_ZLIB=1,
+                           AC_MSG_ERROR([Insufficient zlib version for --with-system-zlib ($MOZZLIB required)]))
+        fi
+    fi
+    CFLAGS=$_SAVE_CFLAGS
+    LDFLAGS=$_SAVE_LDFLAGS
+    LIBS=$_SAVE_LIBS
+fi
+
+AC_SUBST_LIST(MOZ_ZLIB_CFLAGS)
+AC_SUBST_LIST(MOZ_ZLIB_LIBS)
+AC_SUBST(MOZ_NATIVE_ZLIB)
+
+])
diff --git a/src/third_party/mozjs-45/build/automation-build.mk b/src/third_party/mozjs-45/build/automation-build.mk
new file mode 100644
index 0000000..e25f90c
--- /dev/null
+++ b/src/third_party/mozjs-45/build/automation-build.mk
@@ -0,0 +1,67 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+include $(MOZILLA_DIR)/build/binary-location.mk
+
+browser_path := '"$(browser_path)"'
+
+_PROFILE_DIR = $(TARGET_DEPTH)/_profile/pgo
+
+ABSOLUTE_TOPSRCDIR = $(abspath $(MOZILLA_DIR))
+_CERTS_SRC_DIR = $(ABSOLUTE_TOPSRCDIR)/build/pgo/certs
+
+AUTOMATION_PPARGS = 	\
+			-DBROWSER_PATH=$(browser_path) \
+			-DXPC_BIN_PATH='"$(DIST)/bin"' \
+			-DBIN_SUFFIX='"$(BIN_SUFFIX)"' \
+			-DPROFILE_DIR='"$(_PROFILE_DIR)"' \
+			-DCERTS_SRC_DIR='"$(_CERTS_SRC_DIR)"' \
+			-DPERL='"$(PERL)"' \
+			$(NULL)
+
+ifeq ($(OS_ARCH),Darwin)
+AUTOMATION_PPARGS += -DIS_MAC=1
+else
+AUTOMATION_PPARGS += -DIS_MAC=0
+endif
+
+ifeq ($(OS_ARCH),Linux)
+AUTOMATION_PPARGS += -DIS_LINUX=1
+else
+AUTOMATION_PPARGS += -DIS_LINUX=0
+endif
+
+ifeq ($(host_os), cygwin)
+AUTOMATION_PPARGS += -DIS_CYGWIN=1
+endif
+
+ifeq ($(ENABLE_TESTS), 1)
+AUTOMATION_PPARGS += -DIS_TEST_BUILD=1
+else
+AUTOMATION_PPARGS += -DIS_TEST_BUILD=0
+endif
+
+ifeq ($(MOZ_DEBUG), 1)
+AUTOMATION_PPARGS += -DIS_DEBUG_BUILD=1
+else
+AUTOMATION_PPARGS += -DIS_DEBUG_BUILD=0
+endif
+
+ifdef MOZ_CRASHREPORTER
+AUTOMATION_PPARGS += -DCRASHREPORTER=1
+else
+AUTOMATION_PPARGS += -DCRASHREPORTER=0
+endif
+
+ifdef MOZ_ASAN
+AUTOMATION_PPARGS += -DIS_ASAN=1
+else
+AUTOMATION_PPARGS += -DIS_ASAN=0
+endif
+
+automation.py: $(MOZILLA_DIR)/build/automation.py.in $(MOZILLA_DIR)/build/automation-build.mk
+	$(call py_action,preprocessor, \
+	$(AUTOMATION_PPARGS) $(DEFINES) $(ACDEFINES) $< -o $@)
+
+GARBAGE += automation.py automation.pyc
diff --git a/src/third_party/mozjs-45/build/automation.py.in b/src/third_party/mozjs-45/build/automation.py.in
new file mode 100644
index 0000000..e92f174
--- /dev/null
+++ b/src/third_party/mozjs-45/build/automation.py.in
@@ -0,0 +1,601 @@
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+from __future__ import with_statement
+import logging
+import os
+import re
+import select
+import signal
+import subprocess
+import sys
+import tempfile
+from datetime import datetime, timedelta
+
+SCRIPT_DIR = os.path.abspath(os.path.realpath(os.path.dirname(sys.argv[0])))
+sys.path.insert(0, SCRIPT_DIR)
+
+# --------------------------------------------------------------
+# TODO: this is a hack for mozbase without virtualenv, remove with bug 849900
+# These paths refer to relative locations to test.zip, not the OBJDIR or SRCDIR
+here = os.path.dirname(os.path.realpath(__file__))
+mozbase = os.path.realpath(os.path.join(os.path.dirname(here), 'mozbase'))
+
+if os.path.isdir(mozbase):
+    for package in os.listdir(mozbase):
+        package_path = os.path.join(mozbase, package)
+        if package_path not in sys.path:
+            sys.path.append(package_path)
+
+import mozcrash
+from mozscreenshot import printstatus, dump_screen
+
+
+# ---------------------------------------------------------------
+
+_DEFAULT_PREFERENCE_FILE = os.path.join(SCRIPT_DIR, 'prefs_general.js')
+_DEFAULT_APPS_FILE = os.path.join(SCRIPT_DIR, 'webapps_mochitest.json')
+
+_DEFAULT_WEB_SERVER = "127.0.0.1"
+_DEFAULT_HTTP_PORT = 8888
+_DEFAULT_SSL_PORT = 4443
+_DEFAULT_WEBSOCKET_PORT = 9988
+
+# from nsIPrincipal.idl
+_APP_STATUS_NOT_INSTALLED = 0
+_APP_STATUS_INSTALLED     = 1
+_APP_STATUS_PRIVILEGED    = 2
+_APP_STATUS_CERTIFIED     = 3
+
+#expand _DIST_BIN = __XPC_BIN_PATH__
+#expand _IS_WIN32 = len("__WIN32__") != 0
+#expand _IS_MAC = __IS_MAC__ != 0
+#expand _IS_LINUX = __IS_LINUX__ != 0
+#ifdef IS_CYGWIN
+#expand _IS_CYGWIN = __IS_CYGWIN__ == 1
+#else
+_IS_CYGWIN = False
+#endif
+#expand _BIN_SUFFIX = __BIN_SUFFIX__
+
+#expand _DEFAULT_APP = "./" + __BROWSER_PATH__
+#expand _CERTS_SRC_DIR = __CERTS_SRC_DIR__
+#expand _IS_TEST_BUILD = __IS_TEST_BUILD__
+#expand _IS_DEBUG_BUILD = __IS_DEBUG_BUILD__
+#expand _CRASHREPORTER = __CRASHREPORTER__ == 1
+#expand _IS_ASAN = __IS_ASAN__ == 1
+
+
+if _IS_WIN32:
+  import ctypes, ctypes.wintypes, time, msvcrt
+else:
+  import errno
+
+def resetGlobalLog(log):
+  while _log.handlers:
+    _log.removeHandler(_log.handlers[0])
+  handler = logging.StreamHandler(log)
+  _log.setLevel(logging.INFO)
+  _log.addHandler(handler)
+
+# We use the logging system here primarily because it'll handle multiple
+# threads, which is needed to process the output of the server and application
+# processes simultaneously.
+_log = logging.getLogger()
+resetGlobalLog(sys.stdout)
+
+
+#################
+# PROFILE SETUP #
+#################
+
+class Automation(object):
+  """
+  Runs the browser from a script, and provides useful utilities
+  for setting up the browser environment.
+  """
+
+  DIST_BIN = _DIST_BIN
+  IS_WIN32 = _IS_WIN32
+  IS_MAC = _IS_MAC
+  IS_LINUX = _IS_LINUX
+  IS_CYGWIN = _IS_CYGWIN
+  BIN_SUFFIX = _BIN_SUFFIX
+
+  UNIXISH = not IS_WIN32 and not IS_MAC
+
+  DEFAULT_APP = _DEFAULT_APP
+  CERTS_SRC_DIR = _CERTS_SRC_DIR
+  IS_TEST_BUILD = _IS_TEST_BUILD
+  IS_DEBUG_BUILD = _IS_DEBUG_BUILD
+  CRASHREPORTER = _CRASHREPORTER
+  IS_ASAN = _IS_ASAN
+
+  # timeout, in seconds
+  DEFAULT_TIMEOUT = 60.0
+  DEFAULT_WEB_SERVER = _DEFAULT_WEB_SERVER
+  DEFAULT_HTTP_PORT = _DEFAULT_HTTP_PORT
+  DEFAULT_SSL_PORT = _DEFAULT_SSL_PORT
+  DEFAULT_WEBSOCKET_PORT = _DEFAULT_WEBSOCKET_PORT
+
+  def __init__(self):
+    self.log = _log
+    self.lastTestSeen = "automation.py"
+    self.haveDumpedScreen = False
+
+  def setServerInfo(self, 
+                    webServer = _DEFAULT_WEB_SERVER, 
+                    httpPort = _DEFAULT_HTTP_PORT, 
+                    sslPort = _DEFAULT_SSL_PORT,
+                    webSocketPort = _DEFAULT_WEBSOCKET_PORT):
+    self.webServer = webServer
+    self.httpPort = httpPort
+    self.sslPort = sslPort
+    self.webSocketPort = webSocketPort
+
+  @property
+  def __all__(self):
+    return [
+           "UNIXISH",
+           "IS_WIN32",
+           "IS_MAC",
+           "log",
+           "runApp",
+           "Process",
+           "DIST_BIN",
+           "DEFAULT_APP",
+           "CERTS_SRC_DIR",
+           "environment",
+           "IS_TEST_BUILD",
+           "IS_DEBUG_BUILD",
+           "DEFAULT_TIMEOUT",
+          ]
+
+  class Process(subprocess.Popen):
+    """
+    Represents our view of a subprocess.
+    It adds a kill() method which allows it to be stopped explicitly.
+    """
+
+    def __init__(self,
+                 args,
+                 bufsize=0,
+                 executable=None,
+                 stdin=None,
+                 stdout=None,
+                 stderr=None,
+                 preexec_fn=None,
+                 close_fds=False,
+                 shell=False,
+                 cwd=None,
+                 env=None,
+                 universal_newlines=False,
+                 startupinfo=None,
+                 creationflags=0):
+      _log.info("INFO | automation.py | Launching: %s", subprocess.list2cmdline(args))
+      subprocess.Popen.__init__(self, args, bufsize, executable,
+                                stdin, stdout, stderr,
+                                preexec_fn, close_fds,
+                                shell, cwd, env,
+                                universal_newlines, startupinfo, creationflags)
+      self.log = _log
+
+    def kill(self):
+      if Automation().IS_WIN32:
+        import platform
+        pid = "%i" % self.pid
+        if platform.release() == "2000":
+          # Windows 2000 needs 'kill.exe' from the 
+          #'Windows 2000 Resource Kit tools'. (See bug 475455.)
+          try:
+            subprocess.Popen(["kill", "-f", pid]).wait()
+          except:
+            self.log.info("TEST-UNEXPECTED-FAIL | automation.py | Missing 'kill' utility to kill process with pid=%s. Kill it manually!", pid)
+        else:
+          # Windows XP and later.
+          subprocess.Popen(["taskkill", "/F", "/PID", pid]).wait()
+      else:
+        os.kill(self.pid, signal.SIGKILL)
+
+  def environment(self, env=None, xrePath=None, crashreporter=True, debugger=False, dmdPath=None, lsanPath=None):
+    if xrePath == None:
+      xrePath = self.DIST_BIN
+    if env == None:
+      env = dict(os.environ)
+
+    ldLibraryPath = os.path.abspath(os.path.join(SCRIPT_DIR, xrePath))
+    dmdLibrary = None
+    preloadEnvVar = None
+    if self.UNIXISH or self.IS_MAC:
+      envVar = "LD_LIBRARY_PATH"
+      preloadEnvVar = "LD_PRELOAD"
+      if self.IS_MAC:
+        envVar = "DYLD_LIBRARY_PATH"
+        dmdLibrary = "libdmd.dylib"
+      else: # unixish
+        env['MOZILLA_FIVE_HOME'] = xrePath
+        dmdLibrary = "libdmd.so"
+      if envVar in env:
+        ldLibraryPath = ldLibraryPath + ":" + env[envVar]
+      env[envVar] = ldLibraryPath
+    elif self.IS_WIN32:
+      env["PATH"] = env["PATH"] + ";" + str(ldLibraryPath)
+      dmdLibrary = "dmd.dll"
+      preloadEnvVar = "MOZ_REPLACE_MALLOC_LIB"
+
+    if dmdPath and dmdLibrary and preloadEnvVar:
+      env[preloadEnvVar] = os.path.join(dmdPath, dmdLibrary)
+
+    if crashreporter and not debugger:
+      env['MOZ_CRASHREPORTER_NO_REPORT'] = '1'
+      env['MOZ_CRASHREPORTER'] = '1'
+    else:
+      env['MOZ_CRASHREPORTER_DISABLE'] = '1'
+
+    # Crash on non-local network connections by default.
+    # MOZ_DISABLE_NONLOCAL_CONNECTIONS can be set to "0" to temporarily
+    # enable non-local connections for the purposes of local testing.  Don't
+    # override the user's choice here.  See bug 1049688.
+    env.setdefault('MOZ_DISABLE_NONLOCAL_CONNECTIONS', '1')
+
+    env['GNOME_DISABLE_CRASH_DIALOG'] = '1'
+    env['XRE_NO_WINDOWS_CRASH_DIALOG'] = '1'
+
+    # Set WebRTC logging in case it is not set yet
+    env.setdefault('NSPR_LOG_MODULES', 'signaling:3,mtransport:4,datachannel:4,jsep:4,MediaPipelineFactory:4')
+    env.setdefault('R_LOG_LEVEL', '6')
+    env.setdefault('R_LOG_DESTINATION', 'stderr')
+    env.setdefault('R_LOG_VERBOSE', '1')
+
+    # ASan specific environment stuff
+    if self.IS_ASAN and (self.IS_LINUX or self.IS_MAC):
+      # Symbolizer support
+      llvmsym = os.path.join(xrePath, "llvm-symbolizer")
+      if os.path.isfile(llvmsym):
+        env["ASAN_SYMBOLIZER_PATH"] = llvmsym
+        self.log.info("INFO | automation.py | ASan using symbolizer at %s", llvmsym)
+      else:
+        self.log.info("TEST-UNEXPECTED-FAIL | automation.py | Failed to find ASan symbolizer at %s", llvmsym)
+
+      try:
+        totalMemory = int(os.popen("free").readlines()[1].split()[1])
+
+        # Only 4 GB RAM or less available? Use custom ASan options to reduce
+        # the amount of resources required to do the tests. Standard options 
+        # will otherwise lead to OOM conditions on the current test slaves.
+        if totalMemory <= 1024 * 1024 * 4:
+          self.log.info("INFO | automation.py | ASan running in low-memory configuration")
+          env["ASAN_OPTIONS"] = "quarantine_size=50331648:malloc_context_size=5"
+        else:
+          self.log.info("INFO | automation.py | ASan running in default memory configuration")
+      except OSError,err:
+        self.log.info("Failed determine available memory, disabling ASan low-memory configuration: %s", err.strerror)
+      except:
+        self.log.info("Failed determine available memory, disabling ASan low-memory configuration")
+
+    return env
+
+  def killPid(self, pid):
+    try:
+      os.kill(pid, getattr(signal, "SIGKILL", signal.SIGTERM))
+    except WindowsError:
+      self.log.info("Failed to kill process %d." % pid)
+
+  if IS_WIN32:
+    PeekNamedPipe = ctypes.windll.kernel32.PeekNamedPipe
+    GetLastError = ctypes.windll.kernel32.GetLastError
+
+    def readWithTimeout(self, f, timeout):
+      """
+      Try to read a line of output from the file object |f|. |f| must be a
+      pipe, like the |stdout| member of a subprocess.Popen object created
+      with stdout=PIPE. Returns a tuple (line, did_timeout), where |did_timeout|
+      is True if the read timed out, and False otherwise. If no output is
+      received within |timeout| seconds, returns a blank line.
+      """
+
+      if timeout is None:
+        timeout = 0
+
+      x = msvcrt.get_osfhandle(f.fileno())
+      l = ctypes.c_long()
+      done = time.time() + timeout
+
+      buffer = ""
+      while timeout == 0 or time.time() < done:
+        if self.PeekNamedPipe(x, None, 0, None, ctypes.byref(l), None) == 0:
+          err = self.GetLastError()
+          if err == 38 or err == 109: # ERROR_HANDLE_EOF || ERROR_BROKEN_PIPE
+            return ('', False)
+          else:
+            self.log.error("readWithTimeout got error: %d", err)
+        # read a character at a time, checking for eol. Return once we get there.
+        index = 0
+        while index < l.value:
+          char = f.read(1)
+          buffer += char
+          if char == '\n':
+            return (buffer, False)
+          index = index + 1
+        time.sleep(0.01)
+      return (buffer, True)
+
+    def isPidAlive(self, pid):
+      STILL_ACTIVE = 259
+      PROCESS_QUERY_LIMITED_INFORMATION = 0x1000
+      pHandle = ctypes.windll.kernel32.OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, 0, pid)
+      if not pHandle:
+        return False
+      pExitCode = ctypes.wintypes.DWORD()
+      ctypes.windll.kernel32.GetExitCodeProcess(pHandle, ctypes.byref(pExitCode))
+      ctypes.windll.kernel32.CloseHandle(pHandle)
+      return pExitCode.value == STILL_ACTIVE
+
+  else:
+
+    def readWithTimeout(self, f, timeout):
+      """Try to read a line of output from the file object |f|. If no output
+      is received within |timeout| seconds, return a blank line.
+      Returns a tuple (line, did_timeout), where |did_timeout| is True
+      if the read timed out, and False otherwise."""
+      (r, w, e) = select.select([f], [], [], timeout)
+      if len(r) == 0:
+        return ('', True)
+      return (f.readline(), False)
+
+    def isPidAlive(self, pid):
+      try:
+        # kill(pid, 0) checks for a valid PID without actually sending a signal
+        # The method throws OSError if the PID is invalid, which we catch below.
+        os.kill(pid, 0)
+
+        # Wait on it to see if it's a zombie. This can throw OSError.ECHILD if
+        # the process terminates before we get to this point.
+        wpid, wstatus = os.waitpid(pid, os.WNOHANG)
+        return wpid == 0
+      except OSError, err:
+        # Catch the errors we might expect from os.kill/os.waitpid, 
+        # and re-raise any others
+        if err.errno == errno.ESRCH or err.errno == errno.ECHILD:
+          return False
+        raise
+
+  def dumpScreen(self, utilityPath):
+    if self.haveDumpedScreen:
+      self.log.info("Not taking screenshot here: see the one that was previously logged")
+      return
+
+    self.haveDumpedScreen = True;
+    dump_screen(utilityPath, self.log)
+
+
+  def killAndGetStack(self, processPID, utilityPath, debuggerInfo):
+    """Kill the process, preferrably in a way that gets us a stack trace.
+       Also attempts to obtain a screenshot before killing the process."""
+    if not debuggerInfo:
+      self.dumpScreen(utilityPath)
+    self.killAndGetStackNoScreenshot(processPID, utilityPath, debuggerInfo)
+
+  def killAndGetStackNoScreenshot(self, processPID, utilityPath, debuggerInfo):
+    """Kill the process, preferrably in a way that gets us a stack trace."""
+    if self.CRASHREPORTER and not debuggerInfo:
+      if not self.IS_WIN32:
+        # ABRT will get picked up by Breakpad's signal handler
+        os.kill(processPID, signal.SIGABRT)
+        return
+      else:
+        # We should have a "crashinject" program in our utility path
+        crashinject = os.path.normpath(os.path.join(utilityPath, "crashinject.exe"))
+        if os.path.exists(crashinject):
+          status = subprocess.Popen([crashinject, str(processPID)]).wait()
+          printstatus("crashinject", status)
+          if status == 0:
+            return
+    self.log.info("Can't trigger Breakpad, just killing process")
+    self.killPid(processPID)
+
+  def waitForFinish(self, proc, utilityPath, timeout, maxTime, startTime, debuggerInfo, symbolsPath):
+    """ Look for timeout or crashes and return the status after the process terminates """
+    stackFixerFunction = None
+    didTimeout = False
+    hitMaxTime = False
+    if proc.stdout is None:
+      self.log.info("TEST-INFO: Not logging stdout or stderr due to debugger connection")
+    else:
+      logsource = proc.stdout
+
+      if self.IS_DEBUG_BUILD and symbolsPath and os.path.exists(symbolsPath):
+        # Run each line through a function in fix_stack_using_bpsyms.py (uses breakpad symbol files)
+        # This method is preferred for Tinderbox builds, since native symbols may have been stripped.
+        sys.path.insert(0, utilityPath)
+        import fix_stack_using_bpsyms as stackFixerModule
+        stackFixerFunction = lambda line: stackFixerModule.fixSymbols(line, symbolsPath)
+        del sys.path[0]
+      elif self.IS_DEBUG_BUILD and self.IS_MAC:
+        # Run each line through a function in fix_macosx_stack.py (uses atos)
+        sys.path.insert(0, utilityPath)
+        import fix_macosx_stack as stackFixerModule
+        stackFixerFunction = lambda line: stackFixerModule.fixSymbols(line)
+        del sys.path[0]
+      elif self.IS_DEBUG_BUILD and self.IS_LINUX:
+        # Run each line through a function in fix_linux_stack.py (uses addr2line)
+        # This method is preferred for developer machines, so we don't have to run "make buildsymbols".
+        sys.path.insert(0, utilityPath)
+        import fix_linux_stack as stackFixerModule
+        stackFixerFunction = lambda line: stackFixerModule.fixSymbols(line)
+        del sys.path[0]
+
+      # With metro browser runs this script launches the metro test harness which launches the browser.
+      # The metro test harness hands back the real browser process id via log output which we need to
+      # pick up on and parse out. This variable tracks the real browser process id if we find it.
+      browserProcessId = -1
+
+      (line, didTimeout) = self.readWithTimeout(logsource, timeout)
+      while line != "" and not didTimeout:
+        if stackFixerFunction:
+          line = stackFixerFunction(line)
+        self.log.info(line.rstrip().decode("UTF-8", "ignore"))
+        if "TEST-START" in line and "|" in line:
+          self.lastTestSeen = line.split("|")[1].strip()
+        if not debuggerInfo and "TEST-UNEXPECTED-FAIL" in line and "Test timed out" in line:
+          self.dumpScreen(utilityPath)
+
+        (line, didTimeout) = self.readWithTimeout(logsource, timeout)
+
+        if not hitMaxTime and maxTime and datetime.now() - startTime > timedelta(seconds = maxTime):
+          # Kill the application.
+          hitMaxTime = True
+          self.log.info("TEST-UNEXPECTED-FAIL | %s | application ran for longer than allowed maximum time of %d seconds", self.lastTestSeen, int(maxTime))
+          self.killAndGetStack(proc.pid, utilityPath, debuggerInfo)
+      if didTimeout:
+        if line:
+          self.log.info(line.rstrip().decode("UTF-8", "ignore"))
+        self.log.info("TEST-UNEXPECTED-FAIL | %s | application timed out after %d seconds with no output", self.lastTestSeen, int(timeout))
+        if browserProcessId == -1:
+          browserProcessId = proc.pid
+        self.killAndGetStack(browserProcessId, utilityPath, debuggerInfo)
+
+    status = proc.wait()
+    printstatus("Main app process", status)
+    if status == 0:
+      self.lastTestSeen = "Main app process exited normally"
+    if status != 0 and not didTimeout and not hitMaxTime:
+      self.log.info("TEST-UNEXPECTED-FAIL | %s | Exited with code %d during test run", self.lastTestSeen, status)
+    return status
+
+  def buildCommandLine(self, app, debuggerInfo, profileDir, testURL, extraArgs):
+    """ build the application command line """
+
+    cmd = os.path.abspath(app)
+    if self.IS_MAC and os.path.exists(cmd + "-bin"):
+      # Prefer 'app-bin' in case 'app' is a shell script.
+      # We can remove this hack once bug 673899 etc are fixed.
+      cmd += "-bin"
+
+    args = []
+
+    if debuggerInfo:
+      args.extend(debuggerInfo.args)
+      args.append(cmd)
+      cmd = os.path.abspath(debuggerInfo.path)
+
+    if self.IS_MAC:
+      args.append("-foreground")
+
+    if self.IS_CYGWIN:
+      profileDirectory = commands.getoutput("cygpath -w \"" + profileDir + "/\"")
+    else:
+      profileDirectory = profileDir + "/"
+
+    args.extend(("-no-remote", "-profile", profileDirectory))
+    if testURL is not None:
+      args.append((testURL))
+    args.extend(extraArgs)
+    return cmd, args
+
+  def checkForZombies(self, processLog, utilityPath, debuggerInfo):
+    """ Look for hung processes """
+    if not os.path.exists(processLog):
+      self.log.info('Automation Error: PID log not found: %s', processLog)
+      # Whilst no hung process was found, the run should still display as a failure
+      return True
+
+    foundZombie = False
+    self.log.info('INFO | zombiecheck | Reading PID log: %s', processLog)
+    processList = []
+    pidRE = re.compile(r'launched child process (\d+)$')
+    processLogFD = open(processLog)
+    for line in processLogFD:
+      self.log.info(line.rstrip())
+      m = pidRE.search(line)
+      if m:
+        processList.append(int(m.group(1)))
+    processLogFD.close()
+
+    for processPID in processList:
+      self.log.info("INFO | zombiecheck | Checking for orphan process with PID: %d", processPID)
+      if self.isPidAlive(processPID):
+        foundZombie = True
+        self.log.info("TEST-UNEXPECTED-FAIL | zombiecheck | child process %d still alive after shutdown", processPID)
+        self.killAndGetStack(processPID, utilityPath, debuggerInfo)
+    return foundZombie
+
+  def checkForCrashes(self, minidumpDir, symbolsPath):
+    return mozcrash.check_for_crashes(minidumpDir, symbolsPath, test_name=self.lastTestSeen)
+
+  def runApp(self, testURL, env, app, profileDir, extraArgs, utilityPath = None,
+             xrePath = None, certPath = None,
+             debuggerInfo = None, symbolsPath = None,
+             timeout = -1, maxTime = None, onLaunch = None,
+             detectShutdownLeaks = False, screenshotOnFail=False, testPath=None, bisectChunk=None,
+             valgrindPath=None, valgrindArgs=None, valgrindSuppFiles=None):
+    """
+    Run the app, log the duration it took to execute, return the status code.
+    Kills the app if it runs for longer than |maxTime| seconds, or outputs nothing for |timeout| seconds.
+    """
+
+    if utilityPath == None:
+      utilityPath = self.DIST_BIN
+    if xrePath == None:
+      xrePath = self.DIST_BIN
+    if certPath == None:
+      certPath = self.CERTS_SRC_DIR
+    if timeout == -1:
+      timeout = self.DEFAULT_TIMEOUT
+
+    # copy env so we don't munge the caller's environment
+    env = dict(env);
+    env["NO_EM_RESTART"] = "1"
+    tmpfd, processLog = tempfile.mkstemp(suffix='pidlog')
+    os.close(tmpfd)
+    env["MOZ_PROCESS_LOG"] = processLog
+
+
+    cmd, args = self.buildCommandLine(app, debuggerInfo, profileDir, testURL, extraArgs)
+    startTime = datetime.now()
+
+    if debuggerInfo and debuggerInfo.interactive:
+      # If an interactive debugger is attached, don't redirect output,
+      # don't use timeouts, and don't capture ctrl-c.
+      timeout = None
+      maxTime = None
+      outputPipe = None
+      signal.signal(signal.SIGINT, lambda sigid, frame: None)
+    else:
+      outputPipe = subprocess.PIPE
+
+    self.lastTestSeen = "automation.py"
+    proc = self.Process([cmd] + args,
+                 env = self.environment(env, xrePath = xrePath,
+                                   crashreporter = not debuggerInfo),
+                 stdout = outputPipe,
+                 stderr = subprocess.STDOUT)
+    self.log.info("INFO | automation.py | Application pid: %d", proc.pid)
+
+    if onLaunch is not None:
+      # Allow callers to specify an onLaunch callback to be fired after the
+      # app is launched.
+      onLaunch()
+
+    status = self.waitForFinish(proc, utilityPath, timeout, maxTime, startTime, debuggerInfo, symbolsPath)
+    self.log.info("INFO | automation.py | Application ran for: %s", str(datetime.now() - startTime))
+
+    # Do a final check for zombie child processes.
+    zombieProcesses = self.checkForZombies(processLog, utilityPath, debuggerInfo)
+
+    crashed = self.checkForCrashes(os.path.join(profileDir, "minidumps"), symbolsPath)
+
+    if crashed or zombieProcesses:
+      status = 1
+
+    if os.path.exists(processLog):
+      os.unlink(processLog)
+
+    return status
+
+  def elf_arm(self, filename):
+    data = open(filename, 'rb').read(20)
+    return data[:4] == "\x7fELF" and ord(data[18]) == 40 # EM_ARM
+
diff --git a/src/third_party/mozjs-45/build/binary-location.mk b/src/third_party/mozjs-45/build/binary-location.mk
new file mode 100644
index 0000000..19ae4b5
--- /dev/null
+++ b/src/third_party/mozjs-45/build/binary-location.mk
@@ -0,0 +1,19 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# finds the location of the browser and puts it in the variable $(browser_path)
+
+ifneq (,$(filter WINNT,$(OS_ARCH)))
+program = $(MOZ_APP_NAME)$(BIN_SUFFIX)
+else
+program = $(MOZ_APP_NAME)-bin$(BIN_SUFFIX)
+endif
+
+TARGET_DIST = $(TARGET_DEPTH)/dist
+
+ifeq ($(OS_ARCH),Darwin)
+browser_path = $(TARGET_DIST)/$(MOZ_MACBUNDLE_NAME)/Contents/MacOS/$(program)
+else
+browser_path = $(TARGET_DIST)/bin/$(program)
+endif
diff --git a/src/third_party/mozjs-45/build/buildconfig.py b/src/third_party/mozjs-45/build/buildconfig.py
new file mode 100644
index 0000000..8a1865b
--- /dev/null
+++ b/src/third_party/mozjs-45/build/buildconfig.py
@@ -0,0 +1,30 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+import imp
+import os
+import sys
+
+path = os.path.dirname(__file__)
+while not os.path.exists(os.path.join(path, 'config.status')):
+    parent = os.path.normpath(os.path.join(path, os.pardir))
+    if parent == path:
+        raise Exception("Can't find config.status")
+    path = parent
+
+path = os.path.join(path, 'config.status')
+config = imp.load_module('_buildconfig', open(path), path, ('', 'r', imp.PY_SOURCE))
+
+# Copy values from the config.status namespace into this module namespace.
+# This effectively imports topsrcdir, topobjdir, defines, substs, files,
+# headers and non_global_defines
+for var in config.__all__:
+    value = getattr(config, var)
+    if isinstance(value, list) and value and isinstance(value[0], tuple):
+        value = dict(value)
+    setattr(sys.modules[__name__], var, value)
+
+for var in os.environ:
+    if var != 'SHELL' and var in substs:
+        substs[var] = os.environ[var]
diff --git a/src/third_party/mozjs-45/build/checksums.py b/src/third_party/mozjs-45/build/checksums.py
new file mode 100755
index 0000000..9b13b50
--- /dev/null
+++ b/src/third_party/mozjs-45/build/checksums.py
@@ -0,0 +1,158 @@
+#!/usr/bin/python
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+from __future__ import with_statement
+
+from optparse import OptionParser
+import logging
+import os
+try:
+    import hashlib
+except:
+    hashlib = None
+
+def digest_file(filename, digest, chunk_size=1024):
+    '''Produce a checksum for the file specified by 'filename'.  'filename'
+    is a string path to a file that is opened and read in this function.  The
+    checksum algorithm is specified by 'digest' and is a valid OpenSSL
+    algorithm.  If the digest used is not valid or Python's hashlib doesn't
+    work, the None object will be returned instead.  The size of blocks
+    that this function will read from the file object it opens based on
+    'filename' can be specified by 'chunk_size', which defaults to 1K'''
+    assert not os.path.isdir(filename), 'this function only works with files'
+    logger = logging.getLogger('checksums.py')
+    if hashlib is not None:
+        logger.debug('Creating new %s object' % digest)
+        h = hashlib.new(digest)
+        with open(filename, 'rb') as f:
+            while True:
+                data = f.read(chunk_size)
+                if not data:
+                    logger.debug('Finished reading in file')
+                    break
+                h.update(data)
+        hash = h.hexdigest()
+        logger.debug('Hash for %s is %s' % (filename, hash))
+        return hash
+    else:
+        # In this case we could subprocess.Popen and .communicate with
+        # sha1sum or md5sum
+        logger.warn('The python module for hashlib is missing!')
+        return None
+
+
+def process_files(files, output_filename, digests, strip):
+    '''This function takes a list of file names, 'files'.  It will then
+    compute the checksum for each of the files by opening the files.
+    Once each file is read and its checksum is computed, this function
+    will write the information to the file specified by 'output_filename'.
+    The path written in the output file will have anything specified by 'strip'
+    removed from the path.  The output file is closed before returning nothing
+    The algorithm to compute checksums with can be specified by 'digests' 
+    and needs to be a list of valid OpenSSL algorithms.
+
+    The output file is written in the format:
+        <hash> <algorithm> <filesize> <filepath>
+    Example:
+        d1fa09a<snip>e4220 sha1 14250744 firefox-4.0b6pre.en-US.mac64.dmg
+    '''
+
+    logger = logging.getLogger('checksums.py')
+    if os.path.exists(output_filename):
+        logger.debug('Overwriting existing checksums file "%s"' %
+                     output_filename)
+    else:
+        logger.debug('Creating a new checksums file "%s"' % output_filename)
+    with open(output_filename, 'w+') as output:
+        for file in files:
+            if os.path.isdir(file):
+                logger.warn('%s is a directory, skipping' % file)
+            else:
+                for digest in digests:
+                    hash = digest_file(file, digest)
+                    if hash is None:
+                        logger.warn('Unable to generate a hash for %s. ' +
+                                    'Skipping.' % file)
+                        continue
+                    if file.startswith(strip):
+                        short_file = file[len(strip):]
+                        short_file = short_file.lstrip('/')
+                    else:
+                        short_file = file
+                    print >>output, '%s %s %s %s' % (hash, digest,
+                                                     os.path.getsize(file),
+                                                     short_file)
+
+def setup_logging(level=logging.DEBUG):
+    '''This function sets up the logging module using a speficiable logging
+    module logging level.  The default log level is DEBUG.
+
+    The output is in the format:
+        <level> - <message>
+    Example:
+        DEBUG - Finished reading in file
+'''
+
+    logger = logging.getLogger('checksums.py')
+    logger.setLevel(logging.DEBUG)
+    handler = logging.StreamHandler()
+    handler.setLevel(level)
+    formatter = logging.Formatter("%(levelname)s - %(message)s")
+    handler.setFormatter(formatter)
+    logger.addHandler(handler)
+
+def main():
+    '''This is a main function that parses arguments, sets up logging
+    and generates a checksum file'''
+    # Parse command line arguments
+    parser = OptionParser()
+    parser.add_option('-d', '--digest', help='checksum algorithm to use',
+                      action='append', dest='digests')
+    parser.add_option('-o', '--output', help='output file to use',
+                      action='store', dest='outfile', default='checksums')
+    parser.add_option('-v', '--verbose',
+                      help='Be noisy (takes precedence over quiet)',
+                      action='store_true', dest='verbose', default=False)
+    parser.add_option('-q', '--quiet', help='Be quiet', action='store_true',
+                      dest='quiet', default=False)
+    parser.add_option('-s', '--strip',
+                      help='strip this path from the filenames',
+                      dest='strip', default=os.getcwd())
+    options, args = parser.parse_args()
+
+    #Figure out which logging level to use
+    if options.verbose:
+        loglevel = logging.DEBUG
+    elif options.quiet:
+        loglevel = logging.ERROR
+    else:
+        loglevel = logging.INFO
+
+    #Set up logging
+    setup_logging(loglevel)
+    logger = logging.getLogger('checksums.py')
+
+    # Validate the digest type to use
+    if not options.digests:
+        options.digests = ['sha1']
+    try:
+        for digest in options.digests:
+            hashlib.new(digest)
+    except ValueError, ve:
+        logger.error('Could not create a "%s" hash object (%s)' %
+                     (digest, ve.args[0]))
+        exit(1)
+
+    # Validate the files to checksum
+    files = []
+    for i in args:
+        if os.path.exists(i):
+            files.append(i)
+        else:
+            logger.info('File "%s" was not found on the filesystem' % i)
+    process_files(files, options.outfile, options.digests, options.strip)
+
+if __name__ == '__main__':
+    main()
diff --git a/src/third_party/mozjs-45/build/clang-plugin/.clang-format b/src/third_party/mozjs-45/build/clang-plugin/.clang-format
new file mode 100644
index 0000000..9b3aa8b
--- /dev/null
+++ b/src/third_party/mozjs-45/build/clang-plugin/.clang-format
@@ -0,0 +1 @@
+BasedOnStyle: LLVM
diff --git a/src/third_party/mozjs-45/build/clang-plugin/Makefile.in b/src/third_party/mozjs-45/build/clang-plugin/Makefile.in
new file mode 100644
index 0000000..ecea11e
--- /dev/null
+++ b/src/third_party/mozjs-45/build/clang-plugin/Makefile.in
@@ -0,0 +1,38 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# LLVM_CXXFLAGS comes with its own optimization flags.
+MOZ_OPTIMIZE =
+
+include $(topsrcdir)/config/config.mk
+
+# In the current moz.build world, we need to override essentially every
+# variable to limit ourselves to what we need to build the clang plugin.
+OS_CXXFLAGS := $(LLVM_CXXFLAGS) -fno-rtti -fno-exceptions
+OS_COMPILE_CXXFLAGS :=
+OS_LDFLAGS := $(LLVM_LDFLAGS) $(CLANG_LDFLAGS)
+DSO_LDOPTS := -shared
+
+ifeq ($(HOST_OS_ARCH)_$(OS_ARCH),Linux_Darwin)
+# Use the host compiler instead of the target compiler.
+CXX := $(HOST_CXX)
+# expandlibs doesn't know the distinction between host and target toolchains,
+# and on cross linux/darwin builds, the options to give to the linker for file
+# lists differ between both, so don't use file lists.
+EXPAND_MKSHLIB_ARGS :=
+# Don't pass OSX linker arguments.
+MOZ_FIX_LINK_PATHS :=
+endif
+
+# Use the default OS X deployment target to enable using the libc++ headers
+# correctly.  Note that the binary produced here is a host tool and doesn't need
+# to be distributed.
+MACOSX_DEPLOYMENT_TARGET :=
+
+# Temporarily relax the requirements for libstdc++ symbol versions on static
+# analysis plugin in order to use a recent clang by accepting libstdc++ from
+# gcc 4.4.0 (GLIBCXX_3.4.11).
+ifdef CHECK_STDCXX
+CHECK_STDCXX = $(call CHECK_SYMBOLS,$(1),GLIBCXX,libstdc++,v[1] > 3 || (v[1] == 3 && v[2] == 4 && v[3] > 11))
+endif
diff --git a/src/third_party/mozjs-45/build/clang-plugin/clang-plugin.cpp b/src/third_party/mozjs-45/build/clang-plugin/clang-plugin.cpp
new file mode 100644
index 0000000..cc081b0
--- /dev/null
+++ b/src/third_party/mozjs-45/build/clang-plugin/clang-plugin.cpp
@@ -0,0 +1,1499 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Basic/Version.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendPluginRegistry.h"
+#include "clang/Frontend/MultiplexConsumer.h"
+#include "clang/Sema/Sema.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include <memory>
+
+#define CLANG_VERSION_FULL (CLANG_VERSION_MAJOR * 100 + CLANG_VERSION_MINOR)
+
+using namespace llvm;
+using namespace clang;
+
+#if CLANG_VERSION_FULL >= 306
+typedef std::unique_ptr<ASTConsumer> ASTConsumerPtr;
+#else
+typedef ASTConsumer *ASTConsumerPtr;
+#endif
+
+namespace {
+
+using namespace clang::ast_matchers;
+class DiagnosticsMatcher {
+public:
+  DiagnosticsMatcher();
+
+  ASTConsumerPtr makeASTConsumer() { return astMatcher.newASTConsumer(); }
+
+private:
+  class ScopeChecker : public MatchFinder::MatchCallback {
+  public:
+    virtual void run(const MatchFinder::MatchResult &Result);
+  };
+
+  class ArithmeticArgChecker : public MatchFinder::MatchCallback {
+  public:
+    virtual void run(const MatchFinder::MatchResult &Result);
+  };
+
+  class TrivialCtorDtorChecker : public MatchFinder::MatchCallback {
+  public:
+    virtual void run(const MatchFinder::MatchResult &Result);
+  };
+
+  class NaNExprChecker : public MatchFinder::MatchCallback {
+  public:
+    virtual void run(const MatchFinder::MatchResult &Result);
+  };
+
+  class NoAddRefReleaseOnReturnChecker : public MatchFinder::MatchCallback {
+  public:
+    virtual void run(const MatchFinder::MatchResult &Result);
+  };
+
+  class RefCountedInsideLambdaChecker : public MatchFinder::MatchCallback {
+  public:
+    virtual void run(const MatchFinder::MatchResult &Result);
+  };
+
+  class ExplicitOperatorBoolChecker : public MatchFinder::MatchCallback {
+  public:
+    virtual void run(const MatchFinder::MatchResult &Result);
+  };
+
+  class NoDuplicateRefCntMemberChecker : public MatchFinder::MatchCallback {
+  public:
+    virtual void run(const MatchFinder::MatchResult &Result);
+  };
+
+  class NeedsNoVTableTypeChecker : public MatchFinder::MatchCallback {
+  public:
+    virtual void run(const MatchFinder::MatchResult &Result);
+  };
+
+  class NonMemMovableChecker : public MatchFinder::MatchCallback {
+  public:
+    virtual void run(const MatchFinder::MatchResult &Result);
+  };
+
+  class ExplicitImplicitChecker : public MatchFinder::MatchCallback {
+  public:
+    virtual void run(const MatchFinder::MatchResult &Result);
+  };
+
+  class NoAutoTypeChecker : public MatchFinder::MatchCallback {
+  public:
+    virtual void run(const MatchFinder::MatchResult &Result);
+  };
+
+  class NoExplicitMoveConstructorChecker : public MatchFinder::MatchCallback {
+  public:
+    virtual void run(const MatchFinder::MatchResult &Result);
+  };
+
+  class RefCountedCopyConstructorChecker : public MatchFinder::MatchCallback {
+  public:
+    virtual void run(const MatchFinder::MatchResult &Result);
+  };
+
+  ScopeChecker scopeChecker;
+  ArithmeticArgChecker arithmeticArgChecker;
+  TrivialCtorDtorChecker trivialCtorDtorChecker;
+  NaNExprChecker nanExprChecker;
+  NoAddRefReleaseOnReturnChecker noAddRefReleaseOnReturnChecker;
+  RefCountedInsideLambdaChecker refCountedInsideLambdaChecker;
+  ExplicitOperatorBoolChecker explicitOperatorBoolChecker;
+  NoDuplicateRefCntMemberChecker noDuplicateRefCntMemberChecker;
+  NeedsNoVTableTypeChecker needsNoVTableTypeChecker;
+  NonMemMovableChecker nonMemMovableChecker;
+  ExplicitImplicitChecker explicitImplicitChecker;
+  NoAutoTypeChecker noAutoTypeChecker;
+  NoExplicitMoveConstructorChecker noExplicitMoveConstructorChecker;
+  RefCountedCopyConstructorChecker refCountedCopyConstructorChecker;
+  MatchFinder astMatcher;
+};
+
+namespace {
+
+std::string getDeclarationNamespace(const Decl *decl) {
+  const DeclContext *DC =
+      decl->getDeclContext()->getEnclosingNamespaceContext();
+  const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC);
+  if (!ND) {
+    return "";
+  }
+
+  while (const DeclContext *ParentDC = ND->getParent()) {
+    if (!isa<NamespaceDecl>(ParentDC)) {
+      break;
+    }
+    ND = cast<NamespaceDecl>(ParentDC);
+  }
+
+  const auto &name = ND->getName();
+  return name;
+}
+
+bool isInIgnoredNamespaceForImplicitCtor(const Decl *decl) {
+  std::string name = getDeclarationNamespace(decl);
+  if (name == "") {
+    return false;
+  }
+
+  return name == "std" ||               // standard C++ lib
+         name == "__gnu_cxx" ||         // gnu C++ lib
+         name == "boost" ||             // boost
+         name == "webrtc" ||            // upstream webrtc
+         name == "rtc" ||               // upstream webrtc 'base' package
+         name.substr(0, 4) == "icu_" || // icu
+         name == "google" ||            // protobuf
+         name == "google_breakpad" ||   // breakpad
+         name == "soundtouch" ||        // libsoundtouch
+         name == "stagefright" ||       // libstagefright
+         name == "MacFileUtilities" ||  // MacFileUtilities
+         name == "dwarf2reader" ||      // dwarf2reader
+         name == "arm_ex_to_module" ||  // arm_ex_to_module
+         name == "testing";             // gtest
+}
+
+bool isInIgnoredNamespaceForImplicitConversion(const Decl *decl) {
+  std::string name = getDeclarationNamespace(decl);
+  if (name == "") {
+    return false;
+  }
+
+  return name == "std" ||             // standard C++ lib
+         name == "__gnu_cxx" ||       // gnu C++ lib
+         name == "google_breakpad" || // breakpad
+         name == "testing";           // gtest
+}
+
+bool isIgnoredPathForImplicitCtor(const Decl *decl) {
+  SourceLocation Loc = decl->getLocation();
+  const SourceManager &SM = decl->getASTContext().getSourceManager();
+  SmallString<1024> FileName = SM.getFilename(Loc);
+  llvm::sys::fs::make_absolute(FileName);
+  llvm::sys::path::reverse_iterator begin = llvm::sys::path::rbegin(FileName),
+                                    end = llvm::sys::path::rend(FileName);
+  for (; begin != end; ++begin) {
+    if (begin->compare_lower(StringRef("skia")) == 0 ||
+        begin->compare_lower(StringRef("angle")) == 0 ||
+        begin->compare_lower(StringRef("harfbuzz")) == 0 ||
+        begin->compare_lower(StringRef("hunspell")) == 0 ||
+        begin->compare_lower(StringRef("scoped_ptr.h")) == 0 ||
+        begin->compare_lower(StringRef("graphite2")) == 0) {
+      return true;
+    }
+    if (begin->compare_lower(StringRef("chromium")) == 0) {
+      // Ignore security/sandbox/chromium but not ipc/chromium.
+      ++begin;
+      return begin != end && begin->compare_lower(StringRef("sandbox")) == 0;
+    }
+  }
+  return false;
+}
+
+bool isIgnoredPathForImplicitConversion(const Decl *decl) {
+  decl = decl->getCanonicalDecl();
+  SourceLocation Loc = decl->getLocation();
+  const SourceManager &SM = decl->getASTContext().getSourceManager();
+  SmallString<1024> FileName = SM.getFilename(Loc);
+  llvm::sys::fs::make_absolute(FileName);
+  llvm::sys::path::reverse_iterator begin = llvm::sys::path::rbegin(FileName),
+                                    end = llvm::sys::path::rend(FileName);
+  for (; begin != end; ++begin) {
+    if (begin->compare_lower(StringRef("graphite2")) == 0) {
+      return true;
+    }
+  }
+  return false;
+}
+
+bool isInterestingDeclForImplicitConversion(const Decl *decl) {
+  return !isInIgnoredNamespaceForImplicitConversion(decl) &&
+         !isIgnoredPathForImplicitConversion(decl);
+}
+
+bool isIgnoredExprForMustUse(const Expr *E) {
+  if (const CXXOperatorCallExpr *OpCall = dyn_cast<CXXOperatorCallExpr>(E)) {
+    switch (OpCall->getOperator()) {
+    case OO_Equal:
+    case OO_PlusEqual:
+    case OO_MinusEqual:
+    case OO_StarEqual:
+    case OO_SlashEqual:
+    case OO_PercentEqual:
+    case OO_CaretEqual:
+    case OO_AmpEqual:
+    case OO_PipeEqual:
+    case OO_LessLessEqual:
+    case OO_GreaterGreaterEqual:
+      return true;
+    default:
+      return false;
+    }
+  }
+
+  if (const BinaryOperator *Op = dyn_cast<BinaryOperator>(E)) {
+    return Op->isAssignmentOp();
+  }
+
+  return false;
+}
+}
+
+class CustomTypeAnnotation {
+  enum ReasonKind {
+    RK_None,
+    RK_Direct,
+    RK_ArrayElement,
+    RK_BaseClass,
+    RK_Field,
+    RK_TemplateInherited,
+  };
+  struct AnnotationReason {
+    QualType Type;
+    ReasonKind Kind;
+    const FieldDecl *Field;
+
+    bool valid() const { return Kind != RK_None; }
+  };
+  typedef DenseMap<void *, AnnotationReason> ReasonCache;
+
+  const char *Spelling;
+  const char *Pretty;
+  ReasonCache Cache;
+
+public:
+  CustomTypeAnnotation(const char *Spelling, const char *Pretty)
+      : Spelling(Spelling), Pretty(Pretty){};
+
+  virtual ~CustomTypeAnnotation() {}
+
+  // Checks if this custom annotation "effectively affects" the given type.
+  bool hasEffectiveAnnotation(QualType T) {
+    return directAnnotationReason(T).valid();
+  }
+  void dumpAnnotationReason(DiagnosticsEngine &Diag, QualType T,
+                            SourceLocation Loc);
+
+  void reportErrorIfPresent(DiagnosticsEngine &Diag, QualType T,
+                            SourceLocation Loc, unsigned ErrorID,
+                            unsigned NoteID) {
+    if (hasEffectiveAnnotation(T)) {
+      Diag.Report(Loc, ErrorID) << T;
+      Diag.Report(Loc, NoteID);
+      dumpAnnotationReason(Diag, T, Loc);
+    }
+  }
+
+private:
+  bool hasLiteralAnnotation(QualType T) const;
+  AnnotationReason directAnnotationReason(QualType T);
+
+protected:
+  // Allow subclasses to apply annotations to external code:
+  virtual bool hasFakeAnnotation(const TagDecl *D) const { return false; }
+};
+
+static CustomTypeAnnotation StackClass =
+    CustomTypeAnnotation("moz_stack_class", "stack");
+static CustomTypeAnnotation GlobalClass =
+    CustomTypeAnnotation("moz_global_class", "global");
+static CustomTypeAnnotation NonHeapClass =
+    CustomTypeAnnotation("moz_nonheap_class", "non-heap");
+static CustomTypeAnnotation HeapClass =
+    CustomTypeAnnotation("moz_heap_class", "heap");
+static CustomTypeAnnotation NonTemporaryClass =
+    CustomTypeAnnotation("moz_non_temporary_class", "non-temporary");
+static CustomTypeAnnotation MustUse =
+    CustomTypeAnnotation("moz_must_use", "must-use");
+
+class MemMoveAnnotation final : public CustomTypeAnnotation {
+public:
+  MemMoveAnnotation()
+      : CustomTypeAnnotation("moz_non_memmovable", "non-memmove()able") {}
+
+  virtual ~MemMoveAnnotation() {}
+
+protected:
+  bool hasFakeAnnotation(const TagDecl *D) const override {
+    // Annotate everything in ::std, with a few exceptions; see bug
+    // 1201314 for discussion.
+    if (getDeclarationNamespace(D) == "std") {
+      // This doesn't check that it's really ::std::pair and not
+      // ::std::something_else::pair, but should be good enough.
+      StringRef Name = D->getName();
+      if (Name == "pair" || Name == "atomic" || Name == "__atomic_base") {
+        return false;
+      }
+      return true;
+    }
+    return false;
+  }
+};
+
+static MemMoveAnnotation NonMemMovable = MemMoveAnnotation();
+
+class MozChecker : public ASTConsumer, public RecursiveASTVisitor<MozChecker> {
+  DiagnosticsEngine &Diag;
+  const CompilerInstance &CI;
+  DiagnosticsMatcher matcher;
+
+public:
+  MozChecker(const CompilerInstance &CI) : Diag(CI.getDiagnostics()), CI(CI) {}
+
+  ASTConsumerPtr getOtherConsumer() { return matcher.makeASTConsumer(); }
+
+  virtual void HandleTranslationUnit(ASTContext &ctx) {
+    TraverseDecl(ctx.getTranslationUnitDecl());
+  }
+
+  static bool hasCustomAnnotation(const Decl *D, const char *Spelling) {
+    iterator_range<specific_attr_iterator<AnnotateAttr>> Attrs =
+        D->specific_attrs<AnnotateAttr>();
+
+    for (AnnotateAttr *Attr : Attrs) {
+      if (Attr->getAnnotation() == Spelling) {
+        return true;
+      }
+    }
+
+    return false;
+  }
+
+  void HandleUnusedExprResult(const Stmt *stmt) {
+    const Expr *E = dyn_cast_or_null<Expr>(stmt);
+    if (E) {
+      QualType T = E->getType();
+      if (MustUse.hasEffectiveAnnotation(T) && !isIgnoredExprForMustUse(E)) {
+        unsigned errorID = Diag.getDiagnosticIDs()->getCustomDiagID(
+            DiagnosticIDs::Error, "Unused value of must-use type %0");
+
+        Diag.Report(E->getLocStart(), errorID) << T;
+        MustUse.dumpAnnotationReason(Diag, T, E->getLocStart());
+      }
+    }
+  }
+
+  bool VisitCXXRecordDecl(CXXRecordDecl *d) {
+    // We need definitions, not declarations
+    if (!d->isThisDeclarationADefinition())
+      return true;
+
+    // Look through all of our immediate bases to find methods that need to be
+    // overridden
+    typedef std::vector<CXXMethodDecl *> OverridesVector;
+    OverridesVector must_overrides;
+    for (CXXRecordDecl::base_class_iterator base = d->bases_begin(),
+                                            e = d->bases_end();
+         base != e; ++base) {
+      // The base is either a class (CXXRecordDecl) or it's a templated class...
+      CXXRecordDecl *parent = base->getType()
+                                  .getDesugaredType(d->getASTContext())
+                                  ->getAsCXXRecordDecl();
+      // The parent might not be resolved to a type yet. In this case, we can't
+      // do any checking here. For complete correctness, we should visit
+      // template instantiations, but this case is likely to be rare, so we will
+      // ignore it until it becomes important.
+      if (!parent) {
+        continue;
+      }
+      parent = parent->getDefinition();
+      for (CXXRecordDecl::method_iterator M = parent->method_begin();
+           M != parent->method_end(); ++M) {
+        if (hasCustomAnnotation(*M, "moz_must_override"))
+          must_overrides.push_back(*M);
+      }
+    }
+
+    for (OverridesVector::iterator it = must_overrides.begin();
+         it != must_overrides.end(); ++it) {
+      bool overridden = false;
+      for (CXXRecordDecl::method_iterator M = d->method_begin();
+           !overridden && M != d->method_end(); ++M) {
+        // The way that Clang checks if a method M overrides its parent method
+        // is if the method has the same name but would not overload.
+        if (M->getName() == (*it)->getName() &&
+            !CI.getSema().IsOverload(*M, (*it), false)) {
+          overridden = true;
+          break;
+        }
+      }
+      if (!overridden) {
+        unsigned overrideID = Diag.getDiagnosticIDs()->getCustomDiagID(
+            DiagnosticIDs::Error, "%0 must override %1");
+        unsigned overrideNote = Diag.getDiagnosticIDs()->getCustomDiagID(
+            DiagnosticIDs::Note, "function to override is here");
+        Diag.Report(d->getLocation(), overrideID) << d->getDeclName()
+                                                  << (*it)->getDeclName();
+        Diag.Report((*it)->getLocation(), overrideNote);
+      }
+    }
+
+    return true;
+  }
+
+  bool VisitSwitchCase(SwitchCase *stmt) {
+    HandleUnusedExprResult(stmt->getSubStmt());
+    return true;
+  }
+  bool VisitCompoundStmt(CompoundStmt *stmt) {
+    for (CompoundStmt::body_iterator it = stmt->body_begin(),
+                                     e = stmt->body_end();
+         it != e; ++it) {
+      HandleUnusedExprResult(*it);
+    }
+    return true;
+  }
+  bool VisitIfStmt(IfStmt *Stmt) {
+    HandleUnusedExprResult(Stmt->getThen());
+    HandleUnusedExprResult(Stmt->getElse());
+    return true;
+  }
+  bool VisitWhileStmt(WhileStmt *Stmt) {
+    HandleUnusedExprResult(Stmt->getBody());
+    return true;
+  }
+  bool VisitDoStmt(DoStmt *Stmt) {
+    HandleUnusedExprResult(Stmt->getBody());
+    return true;
+  }
+  bool VisitForStmt(ForStmt *Stmt) {
+    HandleUnusedExprResult(Stmt->getBody());
+    HandleUnusedExprResult(Stmt->getInit());
+    HandleUnusedExprResult(Stmt->getInc());
+    return true;
+  }
+  bool VisitBinComma(BinaryOperator *Op) {
+    HandleUnusedExprResult(Op->getLHS());
+    return true;
+  }
+};
+
+/// A cached data of whether classes are refcounted or not.
+typedef DenseMap<const CXXRecordDecl *, std::pair<const Decl *, bool>>
+    RefCountedMap;
+RefCountedMap refCountedClasses;
+
+bool classHasAddRefRelease(const CXXRecordDecl *D) {
+  const RefCountedMap::iterator &it = refCountedClasses.find(D);
+  if (it != refCountedClasses.end()) {
+    return it->second.second;
+  }
+
+  bool seenAddRef = false;
+  bool seenRelease = false;
+  for (CXXRecordDecl::method_iterator method = D->method_begin();
+       method != D->method_end(); ++method) {
+    const auto &name = method->getName();
+    if (name == "AddRef") {
+      seenAddRef = true;
+    } else if (name == "Release") {
+      seenRelease = true;
+    }
+  }
+  refCountedClasses[D] = std::make_pair(D, seenAddRef && seenRelease);
+  return seenAddRef && seenRelease;
+}
+
+bool isClassRefCounted(QualType T);
+
+bool isClassRefCounted(const CXXRecordDecl *D) {
+  // Normalize so that D points to the definition if it exists.
+  if (!D->hasDefinition())
+    return false;
+  D = D->getDefinition();
+  // Base class: anyone with AddRef/Release is obviously a refcounted class.
+  if (classHasAddRefRelease(D))
+    return true;
+
+  // Look through all base cases to figure out if the parent is a refcounted
+  // class.
+  for (CXXRecordDecl::base_class_const_iterator base = D->bases_begin();
+       base != D->bases_end(); ++base) {
+    bool super = isClassRefCounted(base->getType());
+    if (super) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
+bool isClassRefCounted(QualType T) {
+  while (const ArrayType *arrTy = T->getAsArrayTypeUnsafe())
+    T = arrTy->getElementType();
+  CXXRecordDecl *clazz = T->getAsCXXRecordDecl();
+  return clazz ? isClassRefCounted(clazz) : false;
+}
+
+template <class T> bool IsInSystemHeader(const ASTContext &AC, const T &D) {
+  auto &SourceManager = AC.getSourceManager();
+  auto ExpansionLoc = SourceManager.getExpansionLoc(D.getLocStart());
+  if (ExpansionLoc.isInvalid()) {
+    return false;
+  }
+  return SourceManager.isInSystemHeader(ExpansionLoc);
+}
+
+const FieldDecl *getClassRefCntMember(const CXXRecordDecl *D) {
+  for (RecordDecl::field_iterator field = D->field_begin(), e = D->field_end();
+       field != e; ++field) {
+    if (field->getName() == "mRefCnt") {
+      return *field;
+    }
+  }
+  return 0;
+}
+
+const FieldDecl *getBaseRefCntMember(QualType T);
+
+const FieldDecl *getBaseRefCntMember(const CXXRecordDecl *D) {
+  const FieldDecl *refCntMember = getClassRefCntMember(D);
+  if (refCntMember && isClassRefCounted(D)) {
+    return refCntMember;
+  }
+
+  for (CXXRecordDecl::base_class_const_iterator base = D->bases_begin(),
+                                                e = D->bases_end();
+       base != e; ++base) {
+    refCntMember = getBaseRefCntMember(base->getType());
+    if (refCntMember) {
+      return refCntMember;
+    }
+  }
+  return 0;
+}
+
+const FieldDecl *getBaseRefCntMember(QualType T) {
+  while (const ArrayType *arrTy = T->getAsArrayTypeUnsafe())
+    T = arrTy->getElementType();
+  CXXRecordDecl *clazz = T->getAsCXXRecordDecl();
+  return clazz ? getBaseRefCntMember(clazz) : 0;
+}
+
+bool typeHasVTable(QualType T) {
+  while (const ArrayType *arrTy = T->getAsArrayTypeUnsafe())
+    T = arrTy->getElementType();
+  CXXRecordDecl *offender = T->getAsCXXRecordDecl();
+  return offender && offender->hasDefinition() && offender->isDynamicClass();
+}
+}
+
+namespace clang {
+namespace ast_matchers {
+
+/// This matcher will match any function declaration that is declared as a heap
+/// allocator.
+AST_MATCHER(FunctionDecl, heapAllocator) {
+  return MozChecker::hasCustomAnnotation(&Node, "moz_heap_allocator");
+}
+
+/// This matcher will match any declaration that is marked as not accepting
+/// arithmetic expressions in its arguments.
+AST_MATCHER(Decl, noArithmeticExprInArgs) {
+  return MozChecker::hasCustomAnnotation(&Node, "moz_no_arith_expr_in_arg");
+}
+
+/// This matcher will match any C++ class that is marked as having a trivial
+/// constructor and destructor.
+AST_MATCHER(CXXRecordDecl, hasTrivialCtorDtor) {
+  return MozChecker::hasCustomAnnotation(&Node, "moz_trivial_ctor_dtor");
+}
+
+/// This matcher will match any function declaration that is marked to prohibit
+/// calling AddRef or Release on its return value.
+AST_MATCHER(FunctionDecl, hasNoAddRefReleaseOnReturnAttr) {
+  return MozChecker::hasCustomAnnotation(&Node,
+                                         "moz_no_addref_release_on_return");
+}
+
+/// This matcher will match all arithmetic binary operators.
+AST_MATCHER(BinaryOperator, binaryArithmeticOperator) {
+  BinaryOperatorKind opcode = Node.getOpcode();
+  return opcode == BO_Mul || opcode == BO_Div || opcode == BO_Rem ||
+         opcode == BO_Add || opcode == BO_Sub || opcode == BO_Shl ||
+         opcode == BO_Shr || opcode == BO_And || opcode == BO_Xor ||
+         opcode == BO_Or || opcode == BO_MulAssign || opcode == BO_DivAssign ||
+         opcode == BO_RemAssign || opcode == BO_AddAssign ||
+         opcode == BO_SubAssign || opcode == BO_ShlAssign ||
+         opcode == BO_ShrAssign || opcode == BO_AndAssign ||
+         opcode == BO_XorAssign || opcode == BO_OrAssign;
+}
+
+/// This matcher will match all arithmetic unary operators.
+AST_MATCHER(UnaryOperator, unaryArithmeticOperator) {
+  UnaryOperatorKind opcode = Node.getOpcode();
+  return opcode == UO_PostInc || opcode == UO_PostDec || opcode == UO_PreInc ||
+         opcode == UO_PreDec || opcode == UO_Plus || opcode == UO_Minus ||
+         opcode == UO_Not;
+}
+
+/// This matcher will match == and != binary operators.
+AST_MATCHER(BinaryOperator, binaryEqualityOperator) {
+  BinaryOperatorKind opcode = Node.getOpcode();
+  return opcode == BO_EQ || opcode == BO_NE;
+}
+
+/// This matcher will match floating point types.
+AST_MATCHER(QualType, isFloat) { return Node->isRealFloatingType(); }
+
+/// This matcher will match locations in system headers.  This is adopted from
+/// isExpansionInSystemHeader in newer clangs, but modified in order to work
+/// with old clangs that we use on infra.
+AST_MATCHER(BinaryOperator, isInSystemHeader) {
+  return IsInSystemHeader(Finder->getASTContext(), Node);
+}
+
+/// This matcher will match locations in SkScalar.h.  This header contains a
+/// known NaN-testing expression which we would like to whitelist.
+AST_MATCHER(BinaryOperator, isInSkScalarDotH) {
+  SourceLocation Loc = Node.getOperatorLoc();
+  auto &SourceManager = Finder->getASTContext().getSourceManager();
+  SmallString<1024> FileName = SourceManager.getFilename(Loc);
+  return llvm::sys::path::rbegin(FileName)->equals("SkScalar.h");
+}
+
+/// This matcher will match all accesses to AddRef or Release methods.
+AST_MATCHER(MemberExpr, isAddRefOrRelease) {
+  ValueDecl *Member = Node.getMemberDecl();
+  CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Member);
+  if (Method) {
+    const auto &Name = Method->getName();
+    return Name == "AddRef" || Name == "Release";
+  }
+  return false;
+}
+
+/// This matcher will select classes which are refcounted.
+AST_MATCHER(CXXRecordDecl, hasRefCntMember) {
+  return isClassRefCounted(&Node) && getClassRefCntMember(&Node);
+}
+
+AST_MATCHER(QualType, hasVTable) { return typeHasVTable(Node); }
+
+AST_MATCHER(CXXRecordDecl, hasNeedsNoVTableTypeAttr) {
+  return MozChecker::hasCustomAnnotation(&Node, "moz_needs_no_vtable_type");
+}
+
+/// This matcher will select classes which are non-memmovable
+AST_MATCHER(QualType, isNonMemMovable) {
+  return NonMemMovable.hasEffectiveAnnotation(Node);
+}
+
+/// This matcher will select classes which require a memmovable template arg
+AST_MATCHER(CXXRecordDecl, needsMemMovable) {
+  return MozChecker::hasCustomAnnotation(&Node, "moz_needs_memmovable_type");
+}
+
+AST_MATCHER(CXXConstructorDecl, isInterestingImplicitCtor) {
+  const CXXConstructorDecl *decl = Node.getCanonicalDecl();
+  return
+      // Skip ignored namespaces and paths
+      !isInIgnoredNamespaceForImplicitCtor(decl) &&
+      !isIgnoredPathForImplicitCtor(decl) &&
+      // We only want Converting constructors
+      decl->isConvertingConstructor(false) &&
+      // We don't want copy of move constructors, as those are allowed to be
+      // implicit
+      !decl->isCopyOrMoveConstructor() &&
+      // We don't want deleted constructors.
+      !decl->isDeleted();
+}
+
+// We can't call this "isImplicit" since it clashes with an existing matcher in
+// clang.
+AST_MATCHER(CXXConstructorDecl, isMarkedImplicit) {
+  return MozChecker::hasCustomAnnotation(&Node, "moz_implicit");
+}
+
+AST_MATCHER(CXXRecordDecl, isConcreteClass) { return !Node.isAbstract(); }
+
+AST_MATCHER(QualType, autoNonAutoableType) {
+  if (const AutoType *T = Node->getContainedAutoType()) {
+    if (const CXXRecordDecl *Rec = T->getAsCXXRecordDecl()) {
+      return MozChecker::hasCustomAnnotation(Rec, "moz_non_autoable");
+    }
+  }
+  return false;
+}
+
+AST_MATCHER(CXXConstructorDecl, isExplicitMoveConstructor) {
+  return Node.isExplicit() && Node.isMoveConstructor();
+}
+
+AST_MATCHER(CXXConstructorDecl, isCompilerProvidedCopyConstructor) {
+  return !Node.isUserProvided() && Node.isCopyConstructor();
+}
+}
+}
+
+namespace {
+
+void CustomTypeAnnotation::dumpAnnotationReason(DiagnosticsEngine &Diag,
+                                                QualType T,
+                                                SourceLocation Loc) {
+  unsigned InheritsID = Diag.getDiagnosticIDs()->getCustomDiagID(
+      DiagnosticIDs::Note,
+      "%1 is a %0 type because it inherits from a %0 type %2");
+  unsigned MemberID = Diag.getDiagnosticIDs()->getCustomDiagID(
+      DiagnosticIDs::Note, "%1 is a %0 type because member %2 is a %0 type %3");
+  unsigned ArrayID = Diag.getDiagnosticIDs()->getCustomDiagID(
+      DiagnosticIDs::Note,
+      "%1 is a %0 type because it is an array of %0 type %2");
+  unsigned TemplID = Diag.getDiagnosticIDs()->getCustomDiagID(
+      DiagnosticIDs::Note,
+      "%1 is a %0 type because it has a template argument %0 type %2");
+
+  AnnotationReason Reason = directAnnotationReason(T);
+  for (;;) {
+    switch (Reason.Kind) {
+    case RK_ArrayElement:
+      Diag.Report(Loc, ArrayID) << Pretty << T << Reason.Type;
+      break;
+    case RK_BaseClass: {
+      const CXXRecordDecl *Decl = T->getAsCXXRecordDecl();
+      assert(Decl && "This type should be a C++ class");
+
+      Diag.Report(Decl->getLocation(), InheritsID) << Pretty << T
+                                                   << Reason.Type;
+      break;
+    }
+    case RK_Field:
+      Diag.Report(Reason.Field->getLocation(), MemberID)
+          << Pretty << T << Reason.Field << Reason.Type;
+      break;
+    case RK_TemplateInherited: {
+      const CXXRecordDecl *Decl = T->getAsCXXRecordDecl();
+      assert(Decl && "This type should be a C++ class");
+
+      Diag.Report(Decl->getLocation(), TemplID) << Pretty << T << Reason.Type;
+      break;
+    }
+    default:
+      // FIXME (bug 1203263): note the original annotation.
+      return;
+    }
+
+    T = Reason.Type;
+    Reason = directAnnotationReason(T);
+  }
+}
+
+bool CustomTypeAnnotation::hasLiteralAnnotation(QualType T) const {
+#if CLANG_VERSION_FULL >= 306
+  if (const TagDecl *D = T->getAsTagDecl()) {
+#else
+  if (const CXXRecordDecl *D = T->getAsCXXRecordDecl()) {
+#endif
+    return hasFakeAnnotation(D) || MozChecker::hasCustomAnnotation(D, Spelling);
+  }
+  return false;
+}
+
+CustomTypeAnnotation::AnnotationReason
+CustomTypeAnnotation::directAnnotationReason(QualType T) {
+  if (hasLiteralAnnotation(T)) {
+    AnnotationReason Reason = {T, RK_Direct, nullptr};
+    return Reason;
+  }
+
+  // Check if we have a cached answer
+  void *Key = T.getAsOpaquePtr();
+  ReasonCache::iterator Cached = Cache.find(T.getAsOpaquePtr());
+  if (Cached != Cache.end()) {
+    return Cached->second;
+  }
+
+  // Check if we have a type which we can recurse into
+  if (const ArrayType *Array = T->getAsArrayTypeUnsafe()) {
+    if (hasEffectiveAnnotation(Array->getElementType())) {
+      AnnotationReason Reason = {Array->getElementType(), RK_ArrayElement,
+                                 nullptr};
+      Cache[Key] = Reason;
+      return Reason;
+    }
+  }
+
+  // Recurse into base classes
+  if (const CXXRecordDecl *Decl = T->getAsCXXRecordDecl()) {
+    if (Decl->hasDefinition()) {
+      Decl = Decl->getDefinition();
+
+      for (const CXXBaseSpecifier &Base : Decl->bases()) {
+        if (hasEffectiveAnnotation(Base.getType())) {
+          AnnotationReason Reason = {Base.getType(), RK_BaseClass, nullptr};
+          Cache[Key] = Reason;
+          return Reason;
+        }
+      }
+
+      // Recurse into members
+      for (const FieldDecl *Field : Decl->fields()) {
+        if (hasEffectiveAnnotation(Field->getType())) {
+          AnnotationReason Reason = {Field->getType(), RK_Field, Field};
+          Cache[Key] = Reason;
+          return Reason;
+        }
+      }
+
+      // Recurse into template arguments if the annotation
+      // MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS is present
+      if (MozChecker::hasCustomAnnotation(
+              Decl, "moz_inherit_type_annotations_from_template_args")) {
+        const ClassTemplateSpecializationDecl *Spec =
+            dyn_cast<ClassTemplateSpecializationDecl>(Decl);
+        if (Spec) {
+          const TemplateArgumentList &Args = Spec->getTemplateArgs();
+
+          for (const TemplateArgument &Arg : Args.asArray()) {
+            if (Arg.getKind() == TemplateArgument::Type) {
+              QualType Type = Arg.getAsType();
+
+              if (hasEffectiveAnnotation(Type)) {
+                AnnotationReason Reason = {Type, RK_TemplateInherited, nullptr};
+                Cache[Key] = Reason;
+                return Reason;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+
+  AnnotationReason Reason = {QualType(), RK_None, nullptr};
+  Cache[Key] = Reason;
+  return Reason;
+}
+
+bool isPlacementNew(const CXXNewExpr *Expr) {
+  // Regular new expressions aren't placement new
+  if (Expr->getNumPlacementArgs() == 0)
+    return false;
+  const FunctionDecl *Decl = Expr->getOperatorNew();
+  if (Decl && MozChecker::hasCustomAnnotation(Decl, "moz_heap_allocator")) {
+    return false;
+  }
+  return true;
+}
+
+DiagnosticsMatcher::DiagnosticsMatcher() {
+  astMatcher.addMatcher(varDecl().bind("node"), &scopeChecker);
+  astMatcher.addMatcher(newExpr().bind("node"), &scopeChecker);
+  astMatcher.addMatcher(materializeTemporaryExpr().bind("node"), &scopeChecker);
+  astMatcher.addMatcher(
+      callExpr(callee(functionDecl(heapAllocator()))).bind("node"),
+      &scopeChecker);
+  astMatcher.addMatcher(parmVarDecl().bind("parm_vardecl"), &scopeChecker);
+
+  astMatcher.addMatcher(
+      callExpr(allOf(hasDeclaration(noArithmeticExprInArgs()),
+                     anyOf(hasDescendant(
+                               binaryOperator(
+                                   allOf(binaryArithmeticOperator(),
+                                         hasLHS(hasDescendant(declRefExpr())),
+                                         hasRHS(hasDescendant(declRefExpr()))))
+                                   .bind("node")),
+                           hasDescendant(
+                               unaryOperator(
+                                   allOf(unaryArithmeticOperator(),
+                                         hasUnaryOperand(allOf(
+                                             hasType(builtinType()),
+                                             anyOf(hasDescendant(declRefExpr()),
+                                                   declRefExpr())))))
+                                   .bind("node")))))
+          .bind("call"),
+      &arithmeticArgChecker);
+  astMatcher.addMatcher(
+      constructExpr(
+          allOf(hasDeclaration(noArithmeticExprInArgs()),
+                anyOf(hasDescendant(
+                          binaryOperator(
+                              allOf(binaryArithmeticOperator(),
+                                    hasLHS(hasDescendant(declRefExpr())),
+                                    hasRHS(hasDescendant(declRefExpr()))))
+                              .bind("node")),
+                      hasDescendant(
+                          unaryOperator(
+                              allOf(unaryArithmeticOperator(),
+                                    hasUnaryOperand(allOf(
+                                        hasType(builtinType()),
+                                        anyOf(hasDescendant(declRefExpr()),
+                                              declRefExpr())))))
+                              .bind("node")))))
+          .bind("call"),
+      &arithmeticArgChecker);
+
+  astMatcher.addMatcher(recordDecl(hasTrivialCtorDtor()).bind("node"),
+                        &trivialCtorDtorChecker);
+
+  astMatcher.addMatcher(
+      binaryOperator(
+          allOf(binaryEqualityOperator(),
+                hasLHS(has(
+                    declRefExpr(hasType(qualType((isFloat())))).bind("lhs"))),
+                hasRHS(has(
+                    declRefExpr(hasType(qualType((isFloat())))).bind("rhs"))),
+                unless(anyOf(isInSystemHeader(), isInSkScalarDotH()))))
+          .bind("node"),
+      &nanExprChecker);
+
+  // First, look for direct parents of the MemberExpr.
+  astMatcher.addMatcher(
+      callExpr(
+          callee(functionDecl(hasNoAddRefReleaseOnReturnAttr()).bind("func")),
+          hasParent(memberExpr(isAddRefOrRelease(), hasParent(callExpr()))
+                        .bind("member")))
+          .bind("node"),
+      &noAddRefReleaseOnReturnChecker);
+  // Then, look for MemberExpr that need to be casted to the right type using
+  // an intermediary CastExpr before we get to the CallExpr.
+  astMatcher.addMatcher(
+      callExpr(
+          callee(functionDecl(hasNoAddRefReleaseOnReturnAttr()).bind("func")),
+          hasParent(castExpr(
+              hasParent(memberExpr(isAddRefOrRelease(), hasParent(callExpr()))
+                            .bind("member")))))
+          .bind("node"),
+      &noAddRefReleaseOnReturnChecker);
+
+  // Match declrefs with type "pointer to object of ref-counted type" inside a
+  // lambda, where the declaration they reference is not inside the lambda.
+  // This excludes arguments and local variables, leaving only captured
+  // variables.
+  astMatcher.addMatcher(lambdaExpr().bind("lambda"), &refCountedInsideLambdaChecker);
+
+  // Older clang versions such as the ones used on the infra recognize these
+  // conversions as 'operator _Bool', but newer clang versions recognize these
+  // as 'operator bool'.
+  astMatcher.addMatcher(
+      methodDecl(anyOf(hasName("operator bool"), hasName("operator _Bool")))
+          .bind("node"),
+      &explicitOperatorBoolChecker);
+
+  astMatcher.addMatcher(
+      recordDecl(allOf(decl().bind("decl"), hasRefCntMember())),
+      &noDuplicateRefCntMemberChecker);
+
+  astMatcher.addMatcher(
+      classTemplateSpecializationDecl(
+          allOf(hasAnyTemplateArgument(refersToType(hasVTable())),
+                hasNeedsNoVTableTypeAttr()))
+          .bind("node"),
+      &needsNoVTableTypeChecker);
+
+  // Handle non-mem-movable template specializations
+  astMatcher.addMatcher(
+      classTemplateSpecializationDecl(
+          allOf(needsMemMovable(),
+                hasAnyTemplateArgument(refersToType(isNonMemMovable()))))
+          .bind("specialization"),
+      &nonMemMovableChecker);
+
+  astMatcher.addMatcher(
+      constructorDecl(isInterestingImplicitCtor(),
+                      ofClass(allOf(isConcreteClass(), decl().bind("class"))),
+                      unless(isMarkedImplicit()))
+          .bind("ctor"),
+      &explicitImplicitChecker);
+
+  astMatcher.addMatcher(varDecl(hasType(autoNonAutoableType())).bind("node"),
+                        &noAutoTypeChecker);
+
+  astMatcher.addMatcher(constructorDecl(isExplicitMoveConstructor()).bind("node"),
+                        &noExplicitMoveConstructorChecker);
+
+  astMatcher.addMatcher(constructExpr(hasDeclaration(
+                                          constructorDecl(
+                                              isCompilerProvidedCopyConstructor(),
+                                              ofClass(hasRefCntMember())))).bind("node"),
+                        &refCountedCopyConstructorChecker);
+}
+
+// These enum variants determine whether an allocation has occured in the code.
+enum AllocationVariety {
+  AV_None,
+  AV_Global,
+  AV_Automatic,
+  AV_Temporary,
+  AV_Heap,
+};
+
+// XXX Currently the Decl* in the AutomaticTemporaryMap is unused, but it
+// probably will be used at some point in the future, in order to produce better
+// error messages.
+typedef DenseMap<const MaterializeTemporaryExpr *, const Decl *> AutomaticTemporaryMap;
+AutomaticTemporaryMap AutomaticTemporaries;
+
+void DiagnosticsMatcher::ScopeChecker::run(
+    const MatchFinder::MatchResult &Result) {
+  DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
+
+  // There are a variety of different reasons why something could be allocated
+  AllocationVariety Variety = AV_None;
+  SourceLocation Loc;
+  QualType T;
+
+  if (const ParmVarDecl *D = Result.Nodes.getNodeAs<ParmVarDecl>("parm_vardecl")) {
+    if (const Expr *Default = D->getDefaultArg()) {
+      if (const MaterializeTemporaryExpr *E = dyn_cast<MaterializeTemporaryExpr>(Default)) {
+        // We have just found a ParmVarDecl which has, as its default argument,
+        // a MaterializeTemporaryExpr. We mark that MaterializeTemporaryExpr as
+        // automatic, by adding it to the AutomaticTemporaryMap.
+        // Reporting on this type will occur when the MaterializeTemporaryExpr
+        // is matched against.
+        AutomaticTemporaries[E] = D;
+      }
+    }
+    return;
+  }
+
+  // Determine the type of allocation which we detected
+  if (const VarDecl *D = Result.Nodes.getNodeAs<VarDecl>("node")) {
+    if (D->hasGlobalStorage()) {
+      Variety = AV_Global;
+    } else {
+      Variety = AV_Automatic;
+    }
+    T = D->getType();
+    Loc = D->getLocStart();
+  } else if (const CXXNewExpr *E = Result.Nodes.getNodeAs<CXXNewExpr>("node")) {
+    // New allocates things on the heap.
+    // We don't consider placement new to do anything, as it doesn't actually
+    // allocate the storage, and thus gives us no useful information.
+    if (!isPlacementNew(E)) {
+      Variety = AV_Heap;
+      T = E->getAllocatedType();
+      Loc = E->getLocStart();
+    }
+  } else if (const MaterializeTemporaryExpr *E =
+                 Result.Nodes.getNodeAs<MaterializeTemporaryExpr>("node")) {
+    // Temporaries can actually have varying storage durations, due to temporary
+    // lifetime extension. We consider the allocation variety of this temporary
+    // to be the same as the allocation variety of its lifetime.
+
+    // XXX We maybe should mark these lifetimes as being due to a temporary
+    // which has had its lifetime extended, to improve the error messages.
+    switch (E->getStorageDuration()) {
+    case SD_FullExpression:
+      {
+        // Check if this temporary is allocated as a default argument!
+        // if it is, we want to pretend that it is automatic.
+        AutomaticTemporaryMap::iterator AutomaticTemporary = AutomaticTemporaries.find(E);
+        if (AutomaticTemporary != AutomaticTemporaries.end()) {
+          Variety = AV_Automatic;
+        } else {
+          Variety = AV_Temporary;
+        }
+      }
+      break;
+    case SD_Automatic:
+      Variety = AV_Automatic;
+      break;
+    case SD_Thread:
+    case SD_Static:
+      Variety = AV_Global;
+      break;
+    case SD_Dynamic:
+      assert(false && "I don't think that this ever should occur...");
+      Variety = AV_Heap;
+      break;
+    }
+    T = E->getType().getUnqualifiedType();
+    Loc = E->getLocStart();
+  } else if (const CallExpr *E = Result.Nodes.getNodeAs<CallExpr>("node")) {
+    T = E->getType()->getPointeeType();
+    if (!T.isNull()) {
+      // This will always allocate on the heap, as the heapAllocator() check
+      // was made in the matcher
+      Variety = AV_Heap;
+      Loc = E->getLocStart();
+    }
+  }
+
+  // Error messages for incorrect allocations.
+  unsigned StackID = Diag.getDiagnosticIDs()->getCustomDiagID(
+      DiagnosticIDs::Error, "variable of type %0 only valid on the stack");
+  unsigned GlobalID = Diag.getDiagnosticIDs()->getCustomDiagID(
+      DiagnosticIDs::Error, "variable of type %0 only valid as global");
+  unsigned HeapID = Diag.getDiagnosticIDs()->getCustomDiagID(
+      DiagnosticIDs::Error, "variable of type %0 only valid on the heap");
+  unsigned NonHeapID = Diag.getDiagnosticIDs()->getCustomDiagID(
+      DiagnosticIDs::Error, "variable of type %0 is not valid on the heap");
+  unsigned NonTemporaryID = Diag.getDiagnosticIDs()->getCustomDiagID(
+      DiagnosticIDs::Error, "variable of type %0 is not valid in a temporary");
+
+  unsigned StackNoteID = Diag.getDiagnosticIDs()->getCustomDiagID(
+      DiagnosticIDs::Note,
+      "value incorrectly allocated in an automatic variable");
+  unsigned GlobalNoteID = Diag.getDiagnosticIDs()->getCustomDiagID(
+      DiagnosticIDs::Note, "value incorrectly allocated in a global variable");
+  unsigned HeapNoteID = Diag.getDiagnosticIDs()->getCustomDiagID(
+      DiagnosticIDs::Note, "value incorrectly allocated on the heap");
+  unsigned TemporaryNoteID = Diag.getDiagnosticIDs()->getCustomDiagID(
+      DiagnosticIDs::Note, "value incorrectly allocated in a temporary");
+
+  // Report errors depending on the annotations on the input types.
+  switch (Variety) {
+  case AV_None:
+    return;
+
+  case AV_Global:
+    StackClass.reportErrorIfPresent(Diag, T, Loc, StackID, GlobalNoteID);
+    HeapClass.reportErrorIfPresent(Diag, T, Loc, HeapID, GlobalNoteID);
+    break;
+
+  case AV_Automatic:
+    GlobalClass.reportErrorIfPresent(Diag, T, Loc, GlobalID, StackNoteID);
+    HeapClass.reportErrorIfPresent(Diag, T, Loc, HeapID, StackNoteID);
+    break;
+
+  case AV_Temporary:
+    GlobalClass.reportErrorIfPresent(Diag, T, Loc, GlobalID, TemporaryNoteID);
+    HeapClass.reportErrorIfPresent(Diag, T, Loc, HeapID, TemporaryNoteID);
+    NonTemporaryClass.reportErrorIfPresent(Diag, T, Loc,
+                                           NonTemporaryID, TemporaryNoteID);
+    break;
+
+  case AV_Heap:
+    GlobalClass.reportErrorIfPresent(Diag, T, Loc, GlobalID, HeapNoteID);
+    StackClass.reportErrorIfPresent(Diag, T, Loc, StackID, HeapNoteID);
+    NonHeapClass.reportErrorIfPresent(Diag, T, Loc, NonHeapID, HeapNoteID);
+    break;
+  }
+}
+
+void DiagnosticsMatcher::ArithmeticArgChecker::run(
+    const MatchFinder::MatchResult &Result) {
+  DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
+  unsigned errorID = Diag.getDiagnosticIDs()->getCustomDiagID(
+      DiagnosticIDs::Error,
+      "cannot pass an arithmetic expression of built-in types to %0");
+  const Expr *expr = Result.Nodes.getNodeAs<Expr>("node");
+  if (const CallExpr *call = Result.Nodes.getNodeAs<CallExpr>("call")) {
+    Diag.Report(expr->getLocStart(), errorID) << call->getDirectCallee();
+  } else if (const CXXConstructExpr *ctr =
+                 Result.Nodes.getNodeAs<CXXConstructExpr>("call")) {
+    Diag.Report(expr->getLocStart(), errorID) << ctr->getConstructor();
+  }
+}
+
+void DiagnosticsMatcher::TrivialCtorDtorChecker::run(
+    const MatchFinder::MatchResult &Result) {
+  DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
+  unsigned errorID = Diag.getDiagnosticIDs()->getCustomDiagID(
+      DiagnosticIDs::Error,
+      "class %0 must have trivial constructors and destructors");
+  const CXXRecordDecl *node = Result.Nodes.getNodeAs<CXXRecordDecl>("node");
+
+  bool badCtor = !node->hasTrivialDefaultConstructor();
+  bool badDtor = !node->hasTrivialDestructor();
+  if (badCtor || badDtor)
+    Diag.Report(node->getLocStart(), errorID) << node;
+}
+
+void DiagnosticsMatcher::NaNExprChecker::run(
+    const MatchFinder::MatchResult &Result) {
+  if (!Result.Context->getLangOpts().CPlusPlus) {
+    // mozilla::IsNaN is not usable in C, so there is no point in issuing these
+    // warnings.
+    return;
+  }
+
+  DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
+  unsigned errorID = Diag.getDiagnosticIDs()->getCustomDiagID(
+      DiagnosticIDs::Error, "comparing a floating point value to itself for "
+                            "NaN checking can lead to incorrect results");
+  unsigned noteID = Diag.getDiagnosticIDs()->getCustomDiagID(
+      DiagnosticIDs::Note, "consider using mozilla::IsNaN instead");
+  const BinaryOperator *expr = Result.Nodes.getNodeAs<BinaryOperator>("node");
+  const DeclRefExpr *lhs = Result.Nodes.getNodeAs<DeclRefExpr>("lhs");
+  const DeclRefExpr *rhs = Result.Nodes.getNodeAs<DeclRefExpr>("rhs");
+  const ImplicitCastExpr *lhsExpr = dyn_cast<ImplicitCastExpr>(expr->getLHS());
+  const ImplicitCastExpr *rhsExpr = dyn_cast<ImplicitCastExpr>(expr->getRHS());
+  // The AST subtree that we are looking for will look like this:
+  // -BinaryOperator ==/!=
+  //  |-ImplicitCastExpr LValueToRValue
+  //  | |-DeclRefExpr
+  //  |-ImplicitCastExpr LValueToRValue
+  //    |-DeclRefExpr
+  // The check below ensures that we are dealing with the correct AST subtree
+  // shape, and
+  // also that both of the found DeclRefExpr's point to the same declaration.
+  if (lhs->getFoundDecl() == rhs->getFoundDecl() && lhsExpr && rhsExpr &&
+      std::distance(lhsExpr->child_begin(), lhsExpr->child_end()) == 1 &&
+      std::distance(rhsExpr->child_begin(), rhsExpr->child_end()) == 1 &&
+      *lhsExpr->child_begin() == lhs && *rhsExpr->child_begin() == rhs) {
+    Diag.Report(expr->getLocStart(), errorID);
+    Diag.Report(expr->getLocStart(), noteID);
+  }
+}
+
+void DiagnosticsMatcher::NoAddRefReleaseOnReturnChecker::run(
+    const MatchFinder::MatchResult &Result) {
+  DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
+  unsigned errorID = Diag.getDiagnosticIDs()->getCustomDiagID(
+      DiagnosticIDs::Error, "%1 cannot be called on the return value of %0");
+  const Stmt *node = Result.Nodes.getNodeAs<Stmt>("node");
+  const FunctionDecl *func = Result.Nodes.getNodeAs<FunctionDecl>("func");
+  const MemberExpr *member = Result.Nodes.getNodeAs<MemberExpr>("member");
+  const CXXMethodDecl *method =
+      dyn_cast<CXXMethodDecl>(member->getMemberDecl());
+
+  Diag.Report(node->getLocStart(), errorID) << func << method;
+}
+
+void DiagnosticsMatcher::RefCountedInsideLambdaChecker::run(
+    const MatchFinder::MatchResult &Result) {
+  DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
+  unsigned errorID = Diag.getDiagnosticIDs()->getCustomDiagID(
+      DiagnosticIDs::Error,
+      "Refcounted variable %0 of type %1 cannot be captured by a lambda");
+  unsigned noteID = Diag.getDiagnosticIDs()->getCustomDiagID(
+      DiagnosticIDs::Note, "Please consider using a smart pointer");
+  const LambdaExpr *Lambda = Result.Nodes.getNodeAs<LambdaExpr>("lambda");
+
+  for (const LambdaCapture Capture : Lambda->captures()) {
+    if (Capture.capturesVariable()) {
+      QualType Pointee = Capture.getCapturedVar()->getType()->getPointeeType();
+
+      if (!Pointee.isNull() && isClassRefCounted(Pointee)) {
+        Diag.Report(Capture.getLocation(), errorID)
+          << Capture.getCapturedVar() << Pointee;
+        Diag.Report(Capture.getLocation(), noteID);
+      }
+    }
+  }
+}
+
+void DiagnosticsMatcher::ExplicitOperatorBoolChecker::run(
+    const MatchFinder::MatchResult &Result) {
+  DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
+  unsigned errorID = Diag.getDiagnosticIDs()->getCustomDiagID(
+      DiagnosticIDs::Error, "bad implicit conversion operator for %0");
+  unsigned noteID = Diag.getDiagnosticIDs()->getCustomDiagID(
+      DiagnosticIDs::Note, "consider adding the explicit keyword to %0");
+  const CXXConversionDecl *method =
+      Result.Nodes.getNodeAs<CXXConversionDecl>("node");
+  const CXXRecordDecl *clazz = method->getParent();
+
+  if (!method->isExplicitSpecified() &&
+      !MozChecker::hasCustomAnnotation(method, "moz_implicit") &&
+      !IsInSystemHeader(method->getASTContext(), *method) &&
+      isInterestingDeclForImplicitConversion(method)) {
+    Diag.Report(method->getLocStart(), errorID) << clazz;
+    Diag.Report(method->getLocStart(), noteID) << "'operator bool'";
+  }
+}
+
+void DiagnosticsMatcher::NoDuplicateRefCntMemberChecker::run(
+    const MatchFinder::MatchResult &Result) {
+  DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
+  unsigned warningID = Diag.getDiagnosticIDs()->getCustomDiagID(
+      DiagnosticIDs::Error,
+      "Refcounted record %0 has multiple mRefCnt members");
+  unsigned note1ID = Diag.getDiagnosticIDs()->getCustomDiagID(
+      DiagnosticIDs::Note, "Superclass %0 also has an mRefCnt member");
+  unsigned note2ID = Diag.getDiagnosticIDs()->getCustomDiagID(
+      DiagnosticIDs::Note,
+      "Consider using the _INHERITED macros for AddRef and Release here");
+
+  const CXXRecordDecl *decl = Result.Nodes.getNodeAs<CXXRecordDecl>("decl");
+  const FieldDecl *refCntMember = getClassRefCntMember(decl);
+  assert(refCntMember &&
+         "The matcher checked to make sure we have a refCntMember");
+
+  // Check every superclass for whether it has a base with a refcnt member, and
+  // warn for those which do
+  for (CXXRecordDecl::base_class_const_iterator base = decl->bases_begin(),
+                                                e = decl->bases_end();
+       base != e; ++base) {
+    const FieldDecl *baseRefCntMember = getBaseRefCntMember(base->getType());
+    if (baseRefCntMember) {
+      Diag.Report(decl->getLocStart(), warningID) << decl;
+      Diag.Report(baseRefCntMember->getLocStart(), note1ID)
+          << baseRefCntMember->getParent();
+      Diag.Report(refCntMember->getLocStart(), note2ID);
+    }
+  }
+}
+
+void DiagnosticsMatcher::NeedsNoVTableTypeChecker::run(
+    const MatchFinder::MatchResult &Result) {
+  DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
+  unsigned errorID = Diag.getDiagnosticIDs()->getCustomDiagID(
+      DiagnosticIDs::Error,
+      "%0 cannot be instantiated because %1 has a VTable");
+  unsigned noteID = Diag.getDiagnosticIDs()->getCustomDiagID(
+      DiagnosticIDs::Note, "bad instantiation of %0 requested here");
+
+  const ClassTemplateSpecializationDecl *specialization =
+      Result.Nodes.getNodeAs<ClassTemplateSpecializationDecl>("node");
+
+  // Get the offending template argument
+  QualType offender;
+  const TemplateArgumentList &args =
+      specialization->getTemplateInstantiationArgs();
+  for (unsigned i = 0; i < args.size(); ++i) {
+    offender = args[i].getAsType();
+    if (typeHasVTable(offender)) {
+      break;
+    }
+  }
+
+  Diag.Report(specialization->getLocStart(), errorID) << specialization
+                                                      << offender;
+  Diag.Report(specialization->getPointOfInstantiation(), noteID)
+      << specialization;
+}
+
+void DiagnosticsMatcher::NonMemMovableChecker::run(
+    const MatchFinder::MatchResult &Result) {
+  DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
+  unsigned errorID = Diag.getDiagnosticIDs()->getCustomDiagID(
+      DiagnosticIDs::Error,
+      "Cannot instantiate %0 with non-memmovable template argument %1");
+  unsigned note1ID = Diag.getDiagnosticIDs()->getCustomDiagID(
+      DiagnosticIDs::Note, "instantiation of %0 requested here");
+
+  // Get the specialization
+  const ClassTemplateSpecializationDecl *specialization =
+      Result.Nodes.getNodeAs<ClassTemplateSpecializationDecl>("specialization");
+  SourceLocation requestLoc = specialization->getPointOfInstantiation();
+
+  // Report an error for every template argument which is non-memmovable
+  const TemplateArgumentList &args =
+      specialization->getTemplateInstantiationArgs();
+  for (unsigned i = 0; i < args.size(); ++i) {
+    QualType argType = args[i].getAsType();
+    if (NonMemMovable.hasEffectiveAnnotation(args[i].getAsType())) {
+      Diag.Report(specialization->getLocation(), errorID) << specialization
+                                                          << argType;
+      // XXX It would be really nice if we could get the instantiation stack
+      // information
+      // from Sema such that we could print a full template instantiation stack,
+      // however,
+      // it seems as though that information is thrown out by the time we get
+      // here so we
+      // can only report one level of template specialization (which in many
+      // cases won't
+      // be useful)
+      Diag.Report(requestLoc, note1ID) << specialization;
+      NonMemMovable.dumpAnnotationReason(Diag, argType, requestLoc);
+    }
+  }
+}
+
+void DiagnosticsMatcher::ExplicitImplicitChecker::run(
+    const MatchFinder::MatchResult &Result) {
+  DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
+  unsigned ErrorID = Diag.getDiagnosticIDs()->getCustomDiagID(
+      DiagnosticIDs::Error, "bad implicit conversion constructor for %0");
+  unsigned NoteID = Diag.getDiagnosticIDs()->getCustomDiagID(
+      DiagnosticIDs::Note,
+      "consider adding the explicit keyword to the constructor");
+
+  // We've already checked everything in the matcher, so we just have to report
+  // the error.
+
+  const CXXConstructorDecl *Ctor =
+      Result.Nodes.getNodeAs<CXXConstructorDecl>("ctor");
+  const CXXRecordDecl *Decl = Result.Nodes.getNodeAs<CXXRecordDecl>("class");
+
+  Diag.Report(Ctor->getLocation(), ErrorID) << Decl->getDeclName();
+  Diag.Report(Ctor->getLocation(), NoteID);
+}
+
+void DiagnosticsMatcher::NoAutoTypeChecker::run(
+    const MatchFinder::MatchResult &Result) {
+  DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
+  unsigned ErrorID = Diag.getDiagnosticIDs()->getCustomDiagID(
+      DiagnosticIDs::Error, "Cannot use auto to declare a variable of type %0");
+  unsigned NoteID = Diag.getDiagnosticIDs()->getCustomDiagID(
+      DiagnosticIDs::Note, "Please write out this type explicitly");
+
+  const VarDecl *D = Result.Nodes.getNodeAs<VarDecl>("node");
+
+  Diag.Report(D->getLocation(), ErrorID) << D->getType();
+  Diag.Report(D->getLocation(), NoteID);
+}
+
+void DiagnosticsMatcher::NoExplicitMoveConstructorChecker::run(
+    const MatchFinder::MatchResult &Result) {
+  DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
+  unsigned ErrorID = Diag.getDiagnosticIDs()->getCustomDiagID(
+      DiagnosticIDs::Error, "Move constructors may not be marked explicit");
+
+  // Everything we needed to know was checked in the matcher - we just report
+  // the error here
+  const CXXConstructorDecl *D =
+    Result.Nodes.getNodeAs<CXXConstructorDecl>("node");
+
+  Diag.Report(D->getLocation(), ErrorID);
+}
+
+void DiagnosticsMatcher::RefCountedCopyConstructorChecker::run(
+    const MatchFinder::MatchResult &Result) {
+  DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
+  unsigned ErrorID = Diag.getDiagnosticIDs()->getCustomDiagID(
+      DiagnosticIDs::Error, "Invalid use of compiler-provided copy constructor "
+                            "on refcounted type");
+  unsigned NoteID = Diag.getDiagnosticIDs()->getCustomDiagID(
+      DiagnosticIDs::Note, "The default copy constructor also copies the "
+                           "default mRefCnt property, leading to reference "
+                           "count imbalance issues. Please provide your own "
+                           "copy constructor which only copies the fields which "
+                           "need to be copied");
+
+  // Everything we needed to know was checked in the matcher - we just report
+  // the error here
+  const CXXConstructExpr *E =
+    Result.Nodes.getNodeAs<CXXConstructExpr>("node");
+
+  Diag.Report(E->getLocation(), ErrorID);
+  Diag.Report(E->getLocation(), NoteID);
+}
+
+class MozCheckAction : public PluginASTAction {
+public:
+  ASTConsumerPtr CreateASTConsumer(CompilerInstance &CI,
+                                   StringRef fileName) override {
+#if CLANG_VERSION_FULL >= 306
+    std::unique_ptr<MozChecker> checker(llvm::make_unique<MozChecker>(CI));
+    ASTConsumerPtr other(checker->getOtherConsumer());
+
+    std::vector<ASTConsumerPtr> consumers;
+    consumers.push_back(std::move(checker));
+    consumers.push_back(std::move(other));
+    return llvm::make_unique<MultiplexConsumer>(std::move(consumers));
+#else
+    MozChecker *checker = new MozChecker(CI);
+
+    ASTConsumer *consumers[] = {checker, checker->getOtherConsumer()};
+    return new MultiplexConsumer(consumers);
+#endif
+  }
+
+  bool ParseArgs(const CompilerInstance &CI,
+                 const std::vector<std::string> &args) override {
+    return true;
+  }
+};
+}
+
+static FrontendPluginRegistry::Add<MozCheckAction> X("moz-check",
+                                                     "check moz action");
diff --git a/src/third_party/mozjs-45/build/clang-plugin/moz.build b/src/third_party/mozjs-45/build/clang-plugin/moz.build
new file mode 100644
index 0000000..c800221
--- /dev/null
+++ b/src/third_party/mozjs-45/build/clang-plugin/moz.build
@@ -0,0 +1,23 @@
+# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+SharedLibrary('clang-plugin')
+
+SOURCES += [
+    'clang-plugin.cpp',
+]
+
+DISABLE_STL_WRAPPING = True
+NO_VISIBILITY_FLAGS = True
+
+# libc++ is required to build plugins against clang on OS X.
+if CONFIG['HOST_OS_ARCH'] == 'Darwin':
+    CXXFLAGS += ['-stdlib=libc++']
+    LDFLAGS += ['-lc++']
+
+DIRS += [
+    'tests',
+]
diff --git a/src/third_party/mozjs-45/build/clang-plugin/tests/Makefile.in b/src/third_party/mozjs-45/build/clang-plugin/tests/Makefile.in
new file mode 100644
index 0000000..1231197
--- /dev/null
+++ b/src/third_party/mozjs-45/build/clang-plugin/tests/Makefile.in
@@ -0,0 +1,15 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# Build without any warning flags, and with clang verify flag for a
+# syntax-only build (no codegen), without a limit on the number of errors.
+OS_CFLAGS := $(filter-out -W%,$(OS_CFLAGS)) -fsyntax-only -Xclang -verify -ferror-limit=0 -std=c11
+OS_CXXFLAGS := $(filter-out -W%,$(OS_CXXFLAGS)) -fsyntax-only -Xclang -verify -ferror-limit=0
+
+include $(topsrcdir)/config/rules.mk
+
+export:: $(OBJS)
+
+# We don't actually build anything.
+.PHONY: $(OBJS)
diff --git a/src/third_party/mozjs-45/build/clang-plugin/tests/TestBadImplicitConversionCtor.cpp b/src/third_party/mozjs-45/build/clang-plugin/tests/TestBadImplicitConversionCtor.cpp
new file mode 100644
index 0000000..ca24725
--- /dev/null
+++ b/src/third_party/mozjs-45/build/clang-plugin/tests/TestBadImplicitConversionCtor.cpp
@@ -0,0 +1,50 @@
+#define MOZ_IMPLICIT __attribute__((annotate("moz_implicit")))
+
+struct Foo {
+  Foo(int); // expected-error {{bad implicit conversion constructor for 'Foo'}} expected-note {{consider adding the explicit keyword to the constructor}}
+  Foo(int, char=0); // expected-error {{bad implicit conversion constructor for 'Foo'}} expected-note {{consider adding the explicit keyword to the constructor}}
+  Foo(...); // expected-error {{bad implicit conversion constructor for 'Foo'}} expected-note {{consider adding the explicit keyword to the constructor}}
+  template<class T>
+  Foo(float); // expected-error {{bad implicit conversion constructor for 'Foo'}} expected-note {{consider adding the explicit keyword to the constructor}}
+  Foo(int, unsigned);
+  Foo(Foo&);
+  Foo(const Foo&);
+  Foo(volatile Foo&);
+  Foo(const volatile Foo&);
+  Foo(Foo&&);
+  Foo(const Foo&&);
+  Foo(volatile Foo&&);
+  Foo(const volatile Foo&&);
+};
+
+struct Bar {
+  explicit Bar(int);
+  explicit Bar(int, char=0);
+  explicit Bar(...);
+};
+
+struct Baz {
+  MOZ_IMPLICIT Baz(int);
+  MOZ_IMPLICIT Baz(int, char=0);
+  MOZ_IMPLICIT Baz(...);
+};
+
+struct Barn {
+  Barn(int) = delete;
+  Barn(int, char=0) = delete;
+  Barn(...) = delete;
+};
+
+struct Abstract {
+  Abstract(int);
+  Abstract(int, char=0);
+  Abstract(...);
+  virtual void f() = 0;
+};
+
+template<class T>
+struct Template {
+  Template(int); // expected-error {{bad implicit conversion constructor for 'Template'}} expected-note {{consider adding the explicit keyword to the constructor}}
+  template<class U>
+  Template(float); // expected-error {{bad implicit conversion constructor for 'Template'}} expected-note {{consider adding the explicit keyword to the constructor}}
+};
diff --git a/src/third_party/mozjs-45/build/clang-plugin/tests/TestCustomHeap.cpp b/src/third_party/mozjs-45/build/clang-plugin/tests/TestCustomHeap.cpp
new file mode 100644
index 0000000..9514ff2
--- /dev/null
+++ b/src/third_party/mozjs-45/build/clang-plugin/tests/TestCustomHeap.cpp
@@ -0,0 +1,28 @@
+#define MOZ_NONHEAP_CLASS __attribute__((annotate("moz_nonheap_class")))
+#define MOZ_HEAP_ALLOCATOR \
+  _Pragma("GCC diagnostic push") \
+  _Pragma("GCC diagnostic ignored \"-Wgcc-compat\"") \
+  __attribute__((annotate("moz_heap_allocator"))) \
+  _Pragma("GCC diagnostic pop")
+
+#include <stdlib.h>
+#include <memory>
+
+struct MOZ_NONHEAP_CLASS X {
+};
+
+void *operator new(size_t x, int qual) MOZ_HEAP_ALLOCATOR {
+  return ::operator new(x);
+}
+
+template <typename T>
+T *customAlloc() MOZ_HEAP_ALLOCATOR {
+  T *arg =  static_cast<T*>(malloc(sizeof(T)));
+  return new (arg) T();
+}
+
+template <typename T>
+void misuseX(T q) {
+  X *foo = customAlloc<X>(); // expected-error {{variable of type 'X' is not valid on the heap}} expected-note {{value incorrectly allocated on the heap}}
+  X *foo2 = new (100) X(); // expected-error {{variable of type 'X' is not valid on the heap}} expected-note {{value incorrectly allocated on the heap}}
+}
diff --git a/src/third_party/mozjs-45/build/clang-plugin/tests/TestExplicitOperatorBool.cpp b/src/third_party/mozjs-45/build/clang-plugin/tests/TestExplicitOperatorBool.cpp
new file mode 100644
index 0000000..bc4b43a
--- /dev/null
+++ b/src/third_party/mozjs-45/build/clang-plugin/tests/TestExplicitOperatorBool.cpp
@@ -0,0 +1,11 @@
+#define MOZ_IMPLICIT __attribute__((annotate("moz_implicit")))
+
+struct Bad {
+  operator bool(); // expected-error {{bad implicit conversion operator for 'Bad'}} expected-note {{consider adding the explicit keyword to 'operator bool'}}
+};
+struct Good {
+  explicit operator bool();
+};
+struct Okay {
+  MOZ_IMPLICIT operator bool();
+};
diff --git a/src/third_party/mozjs-45/build/clang-plugin/tests/TestGlobalClass.cpp b/src/third_party/mozjs-45/build/clang-plugin/tests/TestGlobalClass.cpp
new file mode 100644
index 0000000..1825b97
--- /dev/null
+++ b/src/third_party/mozjs-45/build/clang-plugin/tests/TestGlobalClass.cpp
@@ -0,0 +1,52 @@
+#define MOZ_GLOBAL_CLASS __attribute__((annotate("moz_global_class")))
+#include <stddef.h>
+
+struct MOZ_GLOBAL_CLASS Global {
+  int i;
+  void *operator new(size_t x) throw() { return 0; }
+  void *operator new(size_t blah, char *buffer) { return buffer; }
+};
+
+template <class T>
+struct MOZ_GLOBAL_CLASS TemplateClass {
+  T i;
+};
+
+void gobble(void *) { }
+
+void misuseGlobalClass(int len) {
+  Global notValid; // expected-error {{variable of type 'Global' only valid as global}} expected-note {{value incorrectly allocated in an automatic variable}}
+  Global alsoNotValid[2]; // expected-error {{variable of type 'Global [2]' only valid as global}} expected-note {{'Global [2]' is a global type because it is an array of global type 'Global'}} expected-note {{value incorrectly allocated in an automatic variable}}
+  static Global valid;
+  static Global alsoValid[2];
+
+  gobble(&notValid);
+  gobble(&valid);
+  gobble(&alsoValid[0]);
+
+  gobble(new Global); // expected-error {{variable of type 'Global' only valid as global}} expected-note {{value incorrectly allocated on the heap}}
+  gobble(new Global[10]); // expected-error {{variable of type 'Global' only valid as global}} expected-note {{value incorrectly allocated on the heap}}
+  gobble(new TemplateClass<int>); // expected-error {{variable of type 'TemplateClass<int>' only valid as global}} expected-note {{value incorrectly allocated on the heap}}
+  gobble(len <= 5 ? &valid : new Global); // expected-error {{variable of type 'Global' only valid as global}} expected-note {{value incorrectly allocated on the heap}}
+
+  char buffer[sizeof(Global)];
+  gobble(new (buffer) Global);
+}
+
+Global valid;
+struct RandomClass {
+  Global nonstaticMember; // expected-note {{'RandomClass' is a global type because member 'nonstaticMember' is a global type 'Global'}}
+  static Global staticMember;
+};
+struct MOZ_GLOBAL_CLASS RandomGlobalClass {
+  Global nonstaticMember;
+  static Global staticMember;
+};
+
+struct BadInherit : Global {}; // expected-note {{'BadInherit' is a global type because it inherits from a global type 'Global'}}
+struct MOZ_GLOBAL_CLASS GoodInherit : Global {};
+
+void misuseGlobalClassEvenMore(int len) {
+  BadInherit moreInvalid; // expected-error {{variable of type 'BadInherit' only valid as global}} expected-note {{value incorrectly allocated in an automatic variable}}
+  RandomClass evenMoreInvalid; // expected-error {{variable of type 'RandomClass' only valid as global}} expected-note {{value incorrectly allocated in an automatic variable}}
+}
diff --git a/src/third_party/mozjs-45/build/clang-plugin/tests/TestHeapClass.cpp b/src/third_party/mozjs-45/build/clang-plugin/tests/TestHeapClass.cpp
new file mode 100644
index 0000000..317a258
--- /dev/null
+++ b/src/third_party/mozjs-45/build/clang-plugin/tests/TestHeapClass.cpp
@@ -0,0 +1,64 @@
+#define MOZ_HEAP_CLASS __attribute__((annotate("moz_heap_class")))
+#define MOZ_IMPLICIT __attribute__((annotate("moz_implicit")))
+
+#include <stddef.h>
+
+struct MOZ_HEAP_CLASS Heap {
+  int i;
+  Heap() {}
+  MOZ_IMPLICIT Heap(int i) {}
+  Heap(int i, int j) {}
+  void *operator new(size_t x) throw() { return 0; }
+  void *operator new(size_t blah, char *buffer) { return buffer; }
+};
+
+template <class T>
+struct MOZ_HEAP_CLASS TemplateClass {
+  T i;
+};
+
+void gobble(void *) { }
+
+void gobbleref(const Heap&) { }
+
+void misuseHeapClass(int len) {
+  Heap invalid; // expected-error {{variable of type 'Heap' only valid on the heap}} expected-note {{value incorrectly allocated in an automatic variable}}
+  Heap alsoInvalid[2]; // expected-error {{variable of type 'Heap [2]' only valid on the heap}} expected-note {{value incorrectly allocated in an automatic variable}} expected-note {{'Heap [2]' is a heap type because it is an array of heap type 'Heap'}}
+  static Heap invalidStatic; // expected-error {{variable of type 'Heap' only valid on the heap}} expected-note {{value incorrectly allocated in a global variable}}
+  static Heap alsoInvalidStatic[2]; // expected-error {{variable of type 'Heap [2]' only valid on the heap}} expected-note {{value incorrectly allocated in a global variable}} expected-note {{'Heap [2]' is a heap type because it is an array of heap type 'Heap'}}
+
+  gobble(&invalid);
+  gobble(&invalidStatic);
+  gobble(&alsoInvalid[0]);
+
+  gobbleref(Heap()); // expected-error {{variable of type 'Heap' only valid on the heap}} expected-note {{value incorrectly allocated in a temporary}}
+  gobbleref(Heap(10, 20)); // expected-error {{variable of type 'Heap' only valid on the heap}} expected-note {{value incorrectly allocated in a temporary}}
+  gobbleref(Heap(10)); // expected-error {{variable of type 'Heap' only valid on the heap}} expected-note {{value incorrectly allocated in a temporary}}
+  gobbleref(10); // expected-error {{variable of type 'Heap' only valid on the heap}} expected-note {{value incorrectly allocated in a temporary}}
+
+  gobble(new Heap);
+  gobble(new Heap[10]);
+  gobble(new TemplateClass<int>);
+  gobble(len <= 5 ? &invalid : new Heap);
+
+  char buffer[sizeof(Heap)];
+  gobble(new (buffer) Heap);
+}
+
+Heap invalidStatic; // expected-error {{variable of type 'Heap' only valid on the heap}} expected-note {{value incorrectly allocated in a global variable}}
+struct RandomClass {
+  Heap nonstaticMember; // expected-note {{'RandomClass' is a heap type because member 'nonstaticMember' is a heap type 'Heap'}}
+  static Heap staticMember; // expected-error {{variable of type 'Heap' only valid on the heap}} expected-note {{value incorrectly allocated in a global variable}}
+};
+struct MOZ_HEAP_CLASS RandomHeapClass {
+  Heap nonstaticMember;
+  static Heap staticMember; // expected-error {{variable of type 'Heap' only valid on the heap}} expected-note {{value incorrectly allocated in a global variable}}
+};
+
+struct BadInherit : Heap {}; // expected-note {{'BadInherit' is a heap type because it inherits from a heap type 'Heap'}}
+struct MOZ_HEAP_CLASS GoodInherit : Heap {};
+
+void useStuffWrongly() {
+  BadInherit i; // expected-error {{variable of type 'BadInherit' only valid on the heap}} expected-note {{value incorrectly allocated in an automatic variable}}
+  RandomClass r; // expected-error {{variable of type 'RandomClass' only valid on the heap}} expected-note {{value incorrectly allocated in an automatic variable}}
+}
diff --git a/src/third_party/mozjs-45/build/clang-plugin/tests/TestInheritTypeAnnotationsFromTemplateArgs.cpp b/src/third_party/mozjs-45/build/clang-plugin/tests/TestInheritTypeAnnotationsFromTemplateArgs.cpp
new file mode 100644
index 0000000..68a6e6d
--- /dev/null
+++ b/src/third_party/mozjs-45/build/clang-plugin/tests/TestInheritTypeAnnotationsFromTemplateArgs.cpp
@@ -0,0 +1,37 @@
+#define MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS                 \
+  __attribute__((annotate("moz_inherit_type_annotations_from_template_args")))
+#define MOZ_STACK_CLASS __attribute__((annotate("moz_stack_class")))
+#define MOZ_NON_MEMMOVABLE __attribute__((annotate("moz_non_memmovable")))
+#define MOZ_NEEDS_MEMMOVABLE_TYPE __attribute__((annotate("moz_needs_memmovable_type")))
+
+class Normal {};
+class MOZ_STACK_CLASS Stack {};
+class IndirectStack : Stack {}; // expected-note {{'IndirectStack' is a stack type because it inherits from a stack type 'Stack'}}
+class ContainsStack { Stack m; }; // expected-note {{'ContainsStack' is a stack type because member 'm' is a stack type 'Stack'}}
+class MOZ_NON_MEMMOVABLE Pointery {};
+class IndirectPointery : Pointery {}; // expected-note {{'IndirectPointery' is a non-memmove()able type because it inherits from a non-memmove()able type 'Pointery'}}
+class ContainsPointery { Pointery m; }; // expected-note {{'ContainsPointery' is a non-memmove()able type because member 'm' is a non-memmove()able type 'Pointery'}}
+
+template<class T>
+class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS Template {}; // expected-note-re 5 {{'Template<{{.*}}>' is a stack type because it has a template argument stack type '{{.*}}'}} expected-note-re 5 {{'Template<{{.*}}>' is a non-memmove()able type because it has a template argument non-memmove()able type '{{.*}}'}}
+class IndirectTemplate : Template<Stack> {}; // expected-note {{'IndirectTemplate' is a stack type because it inherits from a stack type 'Template<Stack>'}}
+class ContainsTemplate { Template<Stack> m; }; // expected-note {{'ContainsTemplate' is a stack type because member 'm' is a stack type 'Template<Stack>'}}
+
+static Template<Stack> a; // expected-error {{variable of type 'Template<Stack>' only valid on the stack}} expected-note {{value incorrectly allocated in a global variable}}
+static Template<IndirectStack> b; // expected-error {{variable of type 'Template<IndirectStack>' only valid on the stack}} expected-note {{value incorrectly allocated in a global variable}}
+static Template<ContainsStack> c; // expected-error {{variable of type 'Template<ContainsStack>' only valid on the stack}} expected-note {{value incorrectly allocated in a global variable}}
+static IndirectTemplate d; // expected-error {{variable of type 'IndirectTemplate' only valid on the stack}} expected-note {{value incorrectly allocated in a global variable}}
+static ContainsTemplate e; // expected-error {{variable of type 'ContainsTemplate' only valid on the stack}} expected-note {{value incorrectly allocated in a global variable}}
+static Template<Normal> f;
+
+template<class T>
+class MOZ_NEEDS_MEMMOVABLE_TYPE Mover { char mForceInstantiation[sizeof(T)]; }; // expected-error-re 5 {{Cannot instantiate 'Mover<{{.*}}>' with non-memmovable template argument '{{.*}}'}}
+class IndirectTemplatePointery : Template<Pointery> {}; // expected-note {{'IndirectTemplatePointery' is a non-memmove()able type because it inherits from a non-memmove()able type 'Template<Pointery>'}}
+class ContainsTemplatePointery { Template<Pointery> m; }; // expected-note {{'ContainsTemplatePointery' is a non-memmove()able type because member 'm' is a non-memmove()able type 'Template<Pointery>'}}
+
+static Mover<Template<Pointery>> n; // expected-note {{instantiation of 'Mover<Template<Pointery> >' requested here}}
+static Mover<Template<IndirectPointery>> o; // expected-note {{instantiation of 'Mover<Template<IndirectPointery> >' requested here}}
+static Mover<Template<ContainsPointery>> p; // expected-note {{instantiation of 'Mover<Template<ContainsPointery> >' requested here}}
+static Mover<IndirectTemplatePointery> q; // expected-note {{instantiation of 'Mover<IndirectTemplatePointery>' requested here}}
+static Mover<ContainsTemplatePointery> r; // expected-note {{instantiation of 'Mover<ContainsTemplatePointery>' requested here}}
+static Mover<Template<Normal>> s;
diff --git a/src/third_party/mozjs-45/build/clang-plugin/tests/TestMultipleAnnotations.cpp b/src/third_party/mozjs-45/build/clang-plugin/tests/TestMultipleAnnotations.cpp
new file mode 100644
index 0000000..37a43a5
--- /dev/null
+++ b/src/third_party/mozjs-45/build/clang-plugin/tests/TestMultipleAnnotations.cpp
@@ -0,0 +1,17 @@
+#define MOZ_MUST_USE __attribute__((annotate("moz_must_use")))
+#define MOZ_STACK_CLASS __attribute__((annotate("moz_stack_class")))
+
+class MOZ_MUST_USE MOZ_STACK_CLASS TestClass {};
+
+TestClass foo; // expected-error {{variable of type 'TestClass' only valid on the stack}} expected-note {{value incorrectly allocated in a global variable}}
+
+TestClass f()
+{
+  TestClass bar;
+  return bar;
+}
+
+void g()
+{
+  f(); // expected-error {{Unused value of must-use type 'TestClass'}}
+}
diff --git a/src/third_party/mozjs-45/build/clang-plugin/tests/TestMustOverride.cpp b/src/third_party/mozjs-45/build/clang-plugin/tests/TestMustOverride.cpp
new file mode 100644
index 0000000..8e053f6
--- /dev/null
+++ b/src/third_party/mozjs-45/build/clang-plugin/tests/TestMustOverride.cpp
@@ -0,0 +1,63 @@
+#define MOZ_MUST_OVERRIDE __attribute__((annotate("moz_must_override")))
+// Ignore warnings not related to static analysis here
+#pragma GCC diagnostic ignored "-Woverloaded-virtual"
+
+struct S {
+  virtual void f() MOZ_MUST_OVERRIDE; // expected-note {{function to override is here}}
+  virtual void g() MOZ_MUST_OVERRIDE;
+  virtual void h() MOZ_MUST_OVERRIDE; // expected-note {{function to override is here}}
+};
+struct C : S { // expected-error {{'C' must override 'f'}} expected-error {{'C' must override 'h'}}
+  virtual void g() MOZ_MUST_OVERRIDE; // expected-note {{function to override is here}}
+  virtual void h(int);
+  void q() MOZ_MUST_OVERRIDE; // expected-note {{function to override is here}}
+};
+struct D : C { // expected-error {{'D' must override 'g'}} expected-error {{'D' must override 'q'}}
+  virtual void f();
+};
+
+struct Base {
+  virtual void VirtMethod() MOZ_MUST_OVERRIDE; // expected-note {{function to override is here}}
+  void NonVirtMethod() MOZ_MUST_OVERRIDE; // expected-note {{function to override is here}}
+  static void StaticMethod() MOZ_MUST_OVERRIDE;
+};
+
+struct DoesNotPropagate : Base {
+  virtual void VirtMethod();
+  void NonVirtMethod();
+  static void StaticMethod();
+};
+
+struct Final : DoesNotPropagate { };
+
+struct Propagates : Base {
+  virtual void VirtMethod() MOZ_MUST_OVERRIDE; // expected-note {{function to override is here}}
+  void NonVirtMethod() MOZ_MUST_OVERRIDE; // expected-note {{function to override is here}}
+  static void StaticMethod() MOZ_MUST_OVERRIDE; // expected-note {{function to override is here}}
+};
+
+struct FailsFinal : Propagates { }; // expected-error {{'FailsFinal' must override 'VirtMethod'}} expected-error {{'FailsFinal' must override 'NonVirtMethod'}} expected-error {{'FailsFinal' must override 'StaticMethod'}}
+
+struct WrongOverload : Base { // expected-error {{'WrongOverload' must override 'VirtMethod'}} expected-error {{'WrongOverload' must override 'NonVirtMethod'}}
+  virtual void VirtMethod() const;
+  void NonVirtMethod(int param);
+  static void StaticMethod();
+};
+
+namespace A { namespace B { namespace C {
+  struct Param {};
+  struct Base {
+    void f(Param p) MOZ_MUST_OVERRIDE; // expected-note {{function to override is here}}
+  };
+}}}
+
+struct Param {};
+
+struct Derived : A::B::C::Base {
+  typedef A::B::C::Param Typedef;
+  void f(Typedef t);
+};
+
+struct BadDerived : A::B::C::Base { // expected-error {{'BadDerived' must override 'f'}}
+  void f(Param p);
+};
diff --git a/src/third_party/mozjs-45/build/clang-plugin/tests/TestMustUse.cpp b/src/third_party/mozjs-45/build/clang-plugin/tests/TestMustUse.cpp
new file mode 100644
index 0000000..03fcb06
--- /dev/null
+++ b/src/third_party/mozjs-45/build/clang-plugin/tests/TestMustUse.cpp
@@ -0,0 +1,177 @@
+#define MOZ_MUST_USE __attribute__((annotate("moz_must_use")))
+
+class MOZ_MUST_USE MustUse {};
+class MayUse {};
+
+MustUse producesMustUse();
+MustUse *producesMustUsePointer();
+MustUse &producesMustUseRef();
+
+MayUse producesMayUse();
+MayUse *producesMayUsePointer();
+MayUse &producesMayUseRef();
+
+void use(MustUse*);
+void use(MustUse&);
+void use(MustUse&&);
+void use(MayUse*);
+void use(MayUse&);
+void use(MayUse&&);
+void use(bool);
+
+void foo() {
+  MustUse u;
+
+  producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}}
+  producesMustUsePointer();
+  producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}}
+  producesMayUse();
+  producesMayUsePointer();
+  producesMayUseRef();
+  u = producesMustUse();
+  {
+    producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}}
+    producesMustUsePointer();
+    producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}}
+    producesMayUse();
+    producesMayUsePointer();
+    producesMayUseRef();
+    u = producesMustUse();
+  }
+  if (true) {
+    producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}}
+    producesMustUsePointer();
+    producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}}
+    producesMayUse();
+    producesMayUsePointer();
+    producesMayUseRef();
+    u = producesMustUse();
+  } else {
+    producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}}
+    producesMustUsePointer();
+    producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}}
+    producesMayUse();
+    producesMayUsePointer();
+    producesMayUseRef();
+    u = producesMustUse();
+  }
+
+  if(true) producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}}
+  else producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}}
+  if(true) producesMustUsePointer();
+  else producesMustUsePointer();
+  if(true) producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}}
+  else producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}}
+  if(true) producesMayUse();
+  else producesMayUse();
+  if(true) producesMayUsePointer();
+  else producesMayUsePointer();
+  if(true) producesMayUseRef();
+  else producesMayUseRef();
+  if(true) u = producesMustUse();
+  else u = producesMustUse();
+
+  while (true) producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}}
+  while (true) producesMustUsePointer();
+  while (true) producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}}
+  while (true) producesMayUse();
+  while (true) producesMayUsePointer();
+  while (true) producesMayUseRef();
+  while (true) u = producesMustUse();
+
+  do producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}}
+  while (true);
+  do producesMustUsePointer();
+  while (true);
+  do producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}}
+  while (true);
+  do producesMayUse();
+  while (true);
+  do producesMayUsePointer();
+  while (true);
+  do producesMayUseRef();
+  while (true);
+  do u = producesMustUse();
+  while (true);
+
+  for (;;) producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}}
+  for (;;) producesMustUsePointer();
+  for (;;) producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}}
+  for (;;) producesMayUse();
+  for (;;) producesMayUsePointer();
+  for (;;) producesMayUseRef();
+  for (;;) u = producesMustUse();
+
+  for (producesMustUse();;); // expected-error {{Unused value of must-use type 'MustUse'}}
+  for (producesMustUsePointer();;);
+  for (producesMustUseRef();;); // expected-error {{Unused value of must-use type 'MustUse'}}
+  for (producesMayUse();;);
+  for (producesMayUsePointer();;);
+  for (producesMayUseRef();;);
+  for (u = producesMustUse();;);
+
+  for (;;producesMustUse()); // expected-error {{Unused value of must-use type 'MustUse'}}
+  for (;;producesMustUsePointer());
+  for (;;producesMustUseRef()); // expected-error {{Unused value of must-use type 'MustUse'}}
+  for (;;producesMayUse());
+  for (;;producesMayUsePointer());
+  for (;;producesMayUseRef());
+  for (;;u = producesMustUse());
+
+  use((producesMustUse(), false)); // expected-error {{Unused value of must-use type 'MustUse'}}
+  use((producesMustUsePointer(), false));
+  use((producesMustUseRef(), false)); // expected-error {{Unused value of must-use type 'MustUse'}}
+  use((producesMayUse(), false));
+  use((producesMayUsePointer(), false));
+  use((producesMayUseRef(), false));
+  use((u = producesMustUse(), false));
+
+  switch (1) {
+  case 1:
+    producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}}
+    producesMustUsePointer();
+    producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}}
+    producesMayUse();
+    producesMayUsePointer();
+    producesMayUseRef();
+    u = producesMustUse();
+  case 2:
+    producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}}
+  case 3:
+    producesMustUsePointer();
+  case 4:
+    producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}}
+  case 5:
+    producesMayUse();
+  case 6:
+    producesMayUsePointer();
+  case 7:
+    producesMayUseRef();
+  case 8:
+    u = producesMustUse();
+  default:
+    producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}}
+    producesMustUsePointer();
+    producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}}
+    producesMayUse();
+    producesMayUsePointer();
+    producesMayUseRef();
+    u = producesMustUse();
+  }
+
+  use(producesMustUse());
+  use(producesMustUsePointer());
+  use(producesMustUseRef());
+  use(producesMayUse());
+  use(producesMayUsePointer());
+  use(producesMayUseRef());
+  use(u = producesMustUse());
+
+  MustUse a = producesMustUse();
+  MustUse *b = producesMustUsePointer();
+  MustUse &c = producesMustUseRef();
+  MayUse d = producesMayUse();
+  MayUse *e = producesMayUsePointer();
+  MayUse &f = producesMayUseRef();
+  MustUse g = u = producesMustUse();
+}
diff --git a/src/third_party/mozjs-45/build/clang-plugin/tests/TestNANTestingExpr.cpp b/src/third_party/mozjs-45/build/clang-plugin/tests/TestNANTestingExpr.cpp
new file mode 100644
index 0000000..943577d
--- /dev/null
+++ b/src/third_party/mozjs-45/build/clang-plugin/tests/TestNANTestingExpr.cpp
@@ -0,0 +1,16 @@
+void test(bool x);
+void foo() {
+  float f, f2;
+  typedef double mydouble;
+  mydouble d;
+  double d2;
+  test(f == f); // expected-error{{comparing a floating point value to itself for NaN checking can lead to incorrect results}} expected-note{{consider using mozilla::IsNaN instead}}
+  test(d == d); // expected-error{{comparing a floating point value to itself for NaN checking can lead to incorrect results}} expected-note{{consider using mozilla::IsNaN instead}}
+  test(f != f); // expected-error{{comparing a floating point value to itself for NaN checking can lead to incorrect results}} expected-note{{consider using mozilla::IsNaN instead}}
+  test(d != d); // expected-error{{comparing a floating point value to itself for NaN checking can lead to incorrect results}} expected-note{{consider using mozilla::IsNaN instead}}
+  test(f != d);
+  test(d == (d - f));
+  test(f == f2);
+  test(d == d2);
+  test(d + 1 == d);
+}
diff --git a/src/third_party/mozjs-45/build/clang-plugin/tests/TestNANTestingExprC.c b/src/third_party/mozjs-45/build/clang-plugin/tests/TestNANTestingExprC.c
new file mode 100644
index 0000000..ab2fead
--- /dev/null
+++ b/src/third_party/mozjs-45/build/clang-plugin/tests/TestNANTestingExprC.c
@@ -0,0 +1,17 @@
+/* expected-no-diagnostics */
+void test(int x);
+void foo() {
+  float f, f2;
+  typedef double mydouble;
+  mydouble d;
+  double d2;
+  test(f == f);
+  test(d == d);
+  test(f != f);
+  test(d != d);
+  test(f != d);
+  test(d == (d - f));
+  test(f == f2);
+  test(d == d2);
+  test(d + 1 == d);
+}
diff --git a/src/third_party/mozjs-45/build/clang-plugin/tests/TestNeedsNoVTableType.cpp b/src/third_party/mozjs-45/build/clang-plugin/tests/TestNeedsNoVTableType.cpp
new file mode 100644
index 0000000..531a1c8
--- /dev/null
+++ b/src/third_party/mozjs-45/build/clang-plugin/tests/TestNeedsNoVTableType.cpp
@@ -0,0 +1,94 @@
+#define MOZ_NEEDS_NO_VTABLE_TYPE __attribute__((annotate("moz_needs_no_vtable_type")))
+
+template <class T>
+struct MOZ_NEEDS_NO_VTABLE_TYPE PickyConsumer { // expected-error {{'PickyConsumer<B>' cannot be instantiated because 'B' has a VTable}} expected-error {{'PickyConsumer<E>' cannot be instantiated because 'E' has a VTable}} expected-error {{'PickyConsumer<F>' cannot be instantiated because 'F' has a VTable}} expected-error {{'PickyConsumer<G>' cannot be instantiated because 'G' has a VTable}}
+  T *m;
+};
+
+template <class T>
+struct MOZ_NEEDS_NO_VTABLE_TYPE PickyConsumer_A { // expected-error {{'PickyConsumer_A<B>' cannot be instantiated because 'B' has a VTable}} expected-error {{'PickyConsumer_A<E>' cannot be instantiated because 'E' has a VTable}} expected-error {{'PickyConsumer_A<F>' cannot be instantiated because 'F' has a VTable}} expected-error {{'PickyConsumer_A<G>' cannot be instantiated because 'G' has a VTable}}
+  T *m;
+};
+template <class T>
+struct PickyConsumerWrapper {
+  PickyConsumer_A<T> m; // expected-note {{bad instantiation of 'PickyConsumer_A<B>' requested here}} expected-note {{bad instantiation of 'PickyConsumer_A<E>' requested here}} expected-note {{bad instantiation of 'PickyConsumer_A<F>' requested here}} expected-note {{bad instantiation of 'PickyConsumer_A<G>' requested here}}
+};
+
+template <class T>
+struct MOZ_NEEDS_NO_VTABLE_TYPE PickyConsumer_B { // expected-error {{'PickyConsumer_B<B>' cannot be instantiated because 'B' has a VTable}} expected-error {{'PickyConsumer_B<E>' cannot be instantiated because 'E' has a VTable}} expected-error {{'PickyConsumer_B<F>' cannot be instantiated because 'F' has a VTable}} expected-error {{'PickyConsumer_B<G>' cannot be instantiated because 'G' has a VTable}}
+  T *m;
+};
+template <class T>
+struct PickyConsumerSubclass : PickyConsumer_B<T> {}; // expected-note {{bad instantiation of 'PickyConsumer_B<B>' requested here}} expected-note {{bad instantiation of 'PickyConsumer_B<E>' requested here}} expected-note {{bad instantiation of 'PickyConsumer_B<F>' requested here}} expected-note {{bad instantiation of 'PickyConsumer_B<G>' requested here}}
+
+template <class T>
+struct NonPickyConsumer {
+  T *m;
+};
+
+struct A {};
+struct B : virtual A {};
+struct C : A {};
+struct D {
+  void d();
+};
+struct E {
+  virtual void e();
+};
+struct F : E {
+  virtual void e() final;
+};
+struct G {
+  virtual void e() = 0;
+};
+
+void f() {
+  {
+    PickyConsumer<A> a1;
+    PickyConsumerWrapper<A> a2;
+    PickyConsumerSubclass<A> a3;
+    NonPickyConsumer<A> a4;
+  }
+
+  {
+    PickyConsumer<B> a1; // expected-note {{bad instantiation of 'PickyConsumer<B>' requested here}}
+    PickyConsumerWrapper<B> a2;
+    PickyConsumerSubclass<B> a3;
+    NonPickyConsumer<B> a4;
+  }
+
+  {
+    PickyConsumer<C> a1;
+    PickyConsumerWrapper<C> a2;
+    PickyConsumerSubclass<C> a3;
+    NonPickyConsumer<C> a4;
+  }
+
+  {
+    PickyConsumer<D> a1;
+    PickyConsumerWrapper<D> a2;
+    PickyConsumerSubclass<D> a3;
+    NonPickyConsumer<D> a4;
+  }
+
+  {
+    PickyConsumer<E> a1; // expected-note {{bad instantiation of 'PickyConsumer<E>' requested here}}
+    PickyConsumerWrapper<E> a2;
+    PickyConsumerSubclass<E> a3;
+    NonPickyConsumer<E> a4;
+  }
+
+  {
+    PickyConsumer<F> a1; // expected-note {{bad instantiation of 'PickyConsumer<F>' requested here}}
+    PickyConsumerWrapper<F> a2;
+    PickyConsumerSubclass<F> a3;
+    NonPickyConsumer<F> a4;
+  }
+
+  {
+    PickyConsumer<G> a1; // expected-note {{bad instantiation of 'PickyConsumer<G>' requested here}}
+    PickyConsumerWrapper<G> a2;
+    PickyConsumerSubclass<G> a3;
+    NonPickyConsumer<G> a4;
+  }
+}
diff --git a/src/third_party/mozjs-45/build/clang-plugin/tests/TestNoAddRefReleaseOnReturn.cpp b/src/third_party/mozjs-45/build/clang-plugin/tests/TestNoAddRefReleaseOnReturn.cpp
new file mode 100644
index 0000000..2e1f833
--- /dev/null
+++ b/src/third_party/mozjs-45/build/clang-plugin/tests/TestNoAddRefReleaseOnReturn.cpp
@@ -0,0 +1,110 @@
+#define MOZ_NO_ADDREF_RELEASE_ON_RETURN __attribute__((annotate("moz_no_addref_release_on_return")))
+
+struct Test {
+  void AddRef();
+  void Release();
+  void foo();
+};
+
+struct TestD : Test {};
+
+struct S {
+  Test* f() MOZ_NO_ADDREF_RELEASE_ON_RETURN;
+  Test& g() MOZ_NO_ADDREF_RELEASE_ON_RETURN;
+  Test  h() MOZ_NO_ADDREF_RELEASE_ON_RETURN;
+};
+
+struct SD {
+  TestD* f() MOZ_NO_ADDREF_RELEASE_ON_RETURN;
+  TestD& g() MOZ_NO_ADDREF_RELEASE_ON_RETURN;
+  TestD  h() MOZ_NO_ADDREF_RELEASE_ON_RETURN;
+};
+
+template<class T>
+struct X {
+  T* f() MOZ_NO_ADDREF_RELEASE_ON_RETURN;
+  T& g() MOZ_NO_ADDREF_RELEASE_ON_RETURN;
+  T  h() MOZ_NO_ADDREF_RELEASE_ON_RETURN;
+};
+
+template<class T>
+struct SP {
+  T* operator->() MOZ_NO_ADDREF_RELEASE_ON_RETURN;
+};
+
+Test* f() MOZ_NO_ADDREF_RELEASE_ON_RETURN;
+Test& g() MOZ_NO_ADDREF_RELEASE_ON_RETURN;
+Test  h() MOZ_NO_ADDREF_RELEASE_ON_RETURN;
+
+TestD* fd() MOZ_NO_ADDREF_RELEASE_ON_RETURN;
+TestD& gd() MOZ_NO_ADDREF_RELEASE_ON_RETURN;
+TestD  hd() MOZ_NO_ADDREF_RELEASE_ON_RETURN;
+
+void test() {
+  S s;
+  s.f()->AddRef(); // expected-error{{'AddRef' cannot be called on the return value of 'f'}}
+  s.f()->Release(); // expected-error{{'Release' cannot be called on the return value of 'f'}}
+  s.f()->foo();
+  s.g().AddRef(); // expected-error{{'AddRef' cannot be called on the return value of 'g'}}
+  s.g().Release(); // expected-error{{'Release' cannot be called on the return value of 'g'}}
+  s.g().foo();
+  s.h().AddRef(); // expected-error{{'AddRef' cannot be called on the return value of 'h'}}
+  s.h().Release(); // expected-error{{'Release' cannot be called on the return value of 'h'}}
+  s.h().foo();
+  SD sd;
+  sd.f()->AddRef(); // expected-error{{'AddRef' cannot be called on the return value of 'f'}}
+  sd.f()->Release(); // expected-error{{'Release' cannot be called on the return value of 'f'}}
+  sd.f()->foo();
+  sd.g().AddRef(); // expected-error{{'AddRef' cannot be called on the return value of 'g'}}
+  sd.g().Release(); // expected-error{{'Release' cannot be called on the return value of 'g'}}
+  sd.g().foo();
+  sd.h().AddRef(); // expected-error{{'AddRef' cannot be called on the return value of 'h'}}
+  sd.h().Release(); // expected-error{{'Release' cannot be called on the return value of 'h'}}
+  sd.h().foo();
+  X<Test> x;
+  x.f()->AddRef(); // expected-error{{'AddRef' cannot be called on the return value of 'f'}}
+  x.f()->Release(); // expected-error{{'Release' cannot be called on the return value of 'f'}}
+  x.f()->foo();
+  x.g().AddRef(); // expected-error{{'AddRef' cannot be called on the return value of 'g'}}
+  x.g().Release(); // expected-error{{'Release' cannot be called on the return value of 'g'}}
+  x.g().foo();
+  x.h().AddRef(); // expected-error{{'AddRef' cannot be called on the return value of 'h'}}
+  x.h().Release(); // expected-error{{'Release' cannot be called on the return value of 'h'}}
+  x.h().foo();
+  X<TestD> xd;
+  xd.f()->AddRef(); // expected-error{{'AddRef' cannot be called on the return value of 'f'}}
+  xd.f()->Release(); // expected-error{{'Release' cannot be called on the return value of 'f'}}
+  xd.f()->foo();
+  xd.g().AddRef(); // expected-error{{'AddRef' cannot be called on the return value of 'g'}}
+  xd.g().Release(); // expected-error{{'Release' cannot be called on the return value of 'g'}}
+  xd.g().foo();
+  xd.h().AddRef(); // expected-error{{'AddRef' cannot be called on the return value of 'h'}}
+  xd.h().Release(); // expected-error{{'Release' cannot be called on the return value of 'h'}}
+  xd.h().foo();
+  SP<Test> sp;
+  sp->AddRef(); // expected-error{{'AddRef' cannot be called on the return value of 'operator->'}}
+  sp->Release(); // expected-error{{'Release' cannot be called on the return value of 'operator->'}}
+  sp->foo();
+  SP<TestD> spd;
+  spd->AddRef(); // expected-error{{'AddRef' cannot be called on the return value of 'operator->'}}
+  spd->Release(); // expected-error{{'Release' cannot be called on the return value of 'operator->'}}
+  spd->foo();
+  f()->AddRef(); // expected-error{{'AddRef' cannot be called on the return value of 'f'}}
+  f()->Release(); // expected-error{{'Release' cannot be called on the return value of 'f'}}
+  f()->foo();
+  g().AddRef(); // expected-error{{'AddRef' cannot be called on the return value of 'g'}}
+  g().Release(); // expected-error{{'Release' cannot be called on the return value of 'g'}}
+  g().foo();
+  h().AddRef(); // expected-error{{'AddRef' cannot be called on the return value of 'h'}}
+  h().Release(); // expected-error{{'Release' cannot be called on the return value of 'h'}}
+  h().foo();
+  fd()->AddRef(); // expected-error{{'AddRef' cannot be called on the return value of 'fd'}}
+  fd()->Release(); // expected-error{{'Release' cannot be called on the return value of 'fd'}}
+  fd()->foo();
+  gd().AddRef(); // expected-error{{'AddRef' cannot be called on the return value of 'gd'}}
+  gd().Release(); // expected-error{{'Release' cannot be called on the return value of 'gd'}}
+  gd().foo();
+  hd().AddRef(); // expected-error{{'AddRef' cannot be called on the return value of 'hd'}}
+  hd().Release(); // expected-error{{'Release' cannot be called on the return value of 'hd'}}
+  hd().foo();
+}
diff --git a/src/third_party/mozjs-45/build/clang-plugin/tests/TestNoArithmeticExprInArgument.cpp b/src/third_party/mozjs-45/build/clang-plugin/tests/TestNoArithmeticExprInArgument.cpp
new file mode 100644
index 0000000..d147b17
--- /dev/null
+++ b/src/third_party/mozjs-45/build/clang-plugin/tests/TestNoArithmeticExprInArgument.cpp
@@ -0,0 +1,32 @@
+#define MOZ_NO_ARITHMETIC_EXPR_IN_ARGUMENT __attribute__((annotate("moz_no_arith_expr_in_arg")))
+
+struct X {
+  explicit X(int) MOZ_NO_ARITHMETIC_EXPR_IN_ARGUMENT;
+  void baz(int) MOZ_NO_ARITHMETIC_EXPR_IN_ARGUMENT;
+};
+
+int operator+(int, X);
+int operator+(X, int);
+int operator++(X);
+
+void badArithmeticsInArgs() {
+  int a = 1;
+  typedef int myint;
+  myint b = 2;
+  X goodObj1(a);
+  goodObj1.baz(b);
+  X badObj1(a + b); // expected-error{{cannot pass an arithmetic expression of built-in types to 'X'}}
+  X badObj2 = X(a ? 0 : ++a); // expected-error{{cannot pass an arithmetic expression of built-in types to 'X'}}
+  X badObj3(~a); // expected-error{{cannot pass an arithmetic expression of built-in types to 'X'}}
+  badObj1.baz(a - 1 - b); // expected-error{{cannot pass an arithmetic expression of built-in types to 'baz'}}
+  badObj1.baz(++a); // expected-error{{cannot pass an arithmetic expression of built-in types to 'baz'}}
+  badObj1.baz(a++); // expected-error{{cannot pass an arithmetic expression of built-in types to 'baz'}}
+  badObj1.baz(a || b);
+  badObj1.baz(a + goodObj1);
+  badObj1.baz(goodObj1 + a);
+  badObj1.baz(++goodObj1);
+  badObj1.baz(-1);
+  badObj1.baz(-1.0);
+  badObj1.baz(1 + 2);
+  badObj1.baz(1 << (sizeof(int)/2));
+}
diff --git a/src/third_party/mozjs-45/build/clang-plugin/tests/TestNoAutoType.cpp b/src/third_party/mozjs-45/build/clang-plugin/tests/TestNoAutoType.cpp
new file mode 100644
index 0000000..6c6e65f
--- /dev/null
+++ b/src/third_party/mozjs-45/build/clang-plugin/tests/TestNoAutoType.cpp
@@ -0,0 +1,41 @@
+#define MOZ_NON_AUTOABLE __attribute__((annotate("moz_non_autoable")))
+
+template<class T>
+struct MOZ_NON_AUTOABLE ExplicitTypeTemplate {};
+struct MOZ_NON_AUTOABLE ExplicitType {};
+struct NonExplicitType {};
+
+void f() {
+  {
+    ExplicitType a;
+    auto b = a; // expected-error {{Cannot use auto to declare a variable of type 'ExplicitType'}} expected-note {{Please write out this type explicitly}}
+    auto &br = a; // expected-error {{Cannot use auto to declare a variable of type 'ExplicitType &'}} expected-note {{Please write out this type explicitly}}
+    const auto &brc = a; // expected-error {{Cannot use auto to declare a variable of type 'const ExplicitType &'}} expected-note {{Please write out this type explicitly}}
+    auto *bp = &a; // expected-error {{Cannot use auto to declare a variable of type 'ExplicitType *'}} expected-note {{Please write out this type explicitly}}
+    const auto *bpc = &a; // expected-error {{Cannot use auto to declare a variable of type 'const ExplicitType *'}} expected-note {{Please write out this type explicitly}}
+  }
+
+  {
+    ExplicitTypeTemplate<int> a;
+    auto b = a; // expected-error {{Cannot use auto to declare a variable of type 'ExplicitTypeTemplate<int>'}} expected-note {{Please write out this type explicitly}}
+    auto &br = a; // expected-error {{Cannot use auto to declare a variable of type 'ExplicitTypeTemplate<int> &'}} expected-note {{Please write out this type explicitly}}
+    const auto &brc = a; // expected-error {{Cannot use auto to declare a variable of type 'const ExplicitTypeTemplate<int> &'}} expected-note {{Please write out this type explicitly}}
+    auto *bp = &a; // expected-error {{Cannot use auto to declare a variable of type 'ExplicitTypeTemplate<int> *'}} expected-note {{Please write out this type explicitly}}
+    const auto *bpc = &a; // expected-error {{Cannot use auto to declare a variable of type 'const ExplicitTypeTemplate<int> *'}} expected-note {{Please write out this type explicitly}}
+  }
+
+  {
+    NonExplicitType c;
+    auto d = c;
+    auto &dr = c;
+    const auto &drc = c;
+    auto *dp = &c;
+    const auto *dpc = &c;
+  }
+}
+
+ExplicitType A;
+auto B = A; // expected-error {{Cannot use auto to declare a variable of type 'ExplicitType'}} expected-note {{Please write out this type explicitly}}
+
+NonExplicitType C;
+auto D = C;
diff --git a/src/third_party/mozjs-45/build/clang-plugin/tests/TestNoDuplicateRefCntMember.cpp b/src/third_party/mozjs-45/build/clang-plugin/tests/TestNoDuplicateRefCntMember.cpp
new file mode 100644
index 0000000..dad78d6
--- /dev/null
+++ b/src/third_party/mozjs-45/build/clang-plugin/tests/TestNoDuplicateRefCntMember.cpp
@@ -0,0 +1,38 @@
+class C1 {};
+
+class RC1 {
+public:
+  virtual void AddRef();
+  virtual void Release();
+
+private:
+  int mRefCnt; // expected-note 2 {{Superclass 'RC1' also has an mRefCnt member}}
+};
+
+class RC2 : public RC1 { // expected-error {{Refcounted record 'RC2' has multiple mRefCnt members}}
+public:
+  virtual void AddRef();
+  virtual void Release();
+
+private:
+  int mRefCnt; // expected-note {{Consider using the _INHERITED macros for AddRef and Release here}}
+};
+
+class C2 : public RC1 {};
+
+class RC3 : public RC1 {};
+
+class RC4 : public RC3, public C2 {};
+
+class RC5 : public RC1 {};
+
+class RC6 : public C1, public RC5 { // expected-error {{Refcounted record 'RC6' has multiple mRefCnt members}}
+public:
+  virtual void AddRef();
+  virtual void Release();
+
+private:
+  int mRefCnt; // expected-note {{Consider using the _INHERITED macros for AddRef and Release here}}
+};
+
+class Predecl;
diff --git a/src/third_party/mozjs-45/build/clang-plugin/tests/TestNoExplicitMoveConstructor.cpp b/src/third_party/mozjs-45/build/clang-plugin/tests/TestNoExplicitMoveConstructor.cpp
new file mode 100644
index 0000000..5aea6b1
--- /dev/null
+++ b/src/third_party/mozjs-45/build/clang-plugin/tests/TestNoExplicitMoveConstructor.cpp
@@ -0,0 +1,25 @@
+class Foo {
+  Foo(Foo&& f);
+};
+
+class Bar {
+  explicit Bar(Bar&& f); // expected-error {{Move constructors may not be marked explicit}}
+};
+
+class Baz {
+  template<typename T>
+  explicit Baz(T&& f) {};
+};
+
+class Quxx {
+  Quxx();
+  Quxx(Quxx& q) = delete;
+  template<typename T>
+  explicit Quxx(T&& f) {};
+};
+
+void f() {
+  // Move a quxx into a quxx! (This speciailizes Quxx's constructor to look like
+  // a move constructor - to make sure it doesn't trigger)
+  Quxx(Quxx());
+}
diff --git a/src/third_party/mozjs-45/build/clang-plugin/tests/TestNoRefcountedInsideLambdas.cpp b/src/third_party/mozjs-45/build/clang-plugin/tests/TestNoRefcountedInsideLambdas.cpp
new file mode 100644
index 0000000..35aac9d
--- /dev/null
+++ b/src/third_party/mozjs-45/build/clang-plugin/tests/TestNoRefcountedInsideLambdas.cpp
@@ -0,0 +1,94 @@
+#define MOZ_STRONG_REF __attribute__((annotate("moz_strong_ref")))
+
+struct RefCountedBase {
+  void AddRef();
+  void Release();
+};
+
+template <class T>
+struct SmartPtr {
+  T* MOZ_STRONG_REF t;
+  T* operator->() const;
+};
+
+struct R : RefCountedBase {
+  void method();
+};
+
+void take(...);
+void foo() {
+  R* ptr;
+  SmartPtr<R> sp;
+  take([&](R* argptr) {
+    R* localptr;
+    ptr->method(); // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
+    argptr->method();
+    localptr->method();
+  });
+  take([&](SmartPtr<R> argsp) {
+    SmartPtr<R> localsp;
+    sp->method();
+    argsp->method();
+    localsp->method();
+  });
+  take([&](R* argptr) {
+    R* localptr;
+    take(ptr); // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
+    take(argptr);
+    take(localptr);
+  });
+  take([&](SmartPtr<R> argsp) {
+    SmartPtr<R> localsp;
+    take(sp);
+    take(argsp);
+    take(localsp);
+  });
+  take([=](R* argptr) {
+    R* localptr;
+    ptr->method(); // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
+    argptr->method();
+    localptr->method();
+  });
+  take([=](SmartPtr<R> argsp) {
+    SmartPtr<R> localsp;
+    sp->method();
+    argsp->method();
+    localsp->method();
+  });
+  take([=](R* argptr) {
+    R* localptr;
+    take(ptr); // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
+    take(argptr);
+    take(localptr);
+  });
+  take([=](SmartPtr<R> argsp) {
+    SmartPtr<R> localsp;
+    take(sp);
+    take(argsp);
+    take(localsp);
+  });
+  take([ptr](R* argptr) { // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
+    R* localptr;
+    ptr->method();
+    argptr->method();
+    localptr->method();
+  });
+  take([sp](SmartPtr<R> argsp) {
+    SmartPtr<R> localsp;
+    sp->method();
+    argsp->method();
+    localsp->method();
+  });
+  take([ptr](R* argptr) { // expected-error{{Refcounted variable 'ptr' of type 'R' cannot be captured by a lambda}} expected-note{{Please consider using a smart pointer}}
+    R* localptr;
+    take(ptr);
+    take(argptr);
+    take(localptr);
+  });
+  take([sp](SmartPtr<R> argsp) {
+    SmartPtr<R> localsp;
+    take(sp);
+    take(argsp);
+    take(localsp);
+  });
+}
diff --git a/src/third_party/mozjs-45/build/clang-plugin/tests/TestNonHeapClass.cpp b/src/third_party/mozjs-45/build/clang-plugin/tests/TestNonHeapClass.cpp
new file mode 100644
index 0000000..26fe640
--- /dev/null
+++ b/src/third_party/mozjs-45/build/clang-plugin/tests/TestNonHeapClass.cpp
@@ -0,0 +1,62 @@
+#define MOZ_NONHEAP_CLASS __attribute__((annotate("moz_nonheap_class")))
+#define MOZ_STACK_CLASS __attribute__((annotate("moz_stack_class")))
+#include <stddef.h>
+
+struct MOZ_NONHEAP_CLASS NonHeap {
+  int i;
+  void *operator new(size_t x) throw() { return 0; }
+  void *operator new(size_t blah, char *buffer) { return buffer; }
+};
+
+template <class T>
+struct MOZ_NONHEAP_CLASS TemplateClass {
+  T i;
+};
+
+void gobble(void *) { }
+
+void misuseNonHeapClass(int len) {
+  NonHeap valid;
+  NonHeap alsoValid[2];
+  static NonHeap validStatic;
+  static NonHeap alsoValidStatic[2];
+
+  gobble(&valid);
+  gobble(&validStatic);
+  gobble(&alsoValid[0]);
+
+  gobble(new NonHeap); // expected-error {{variable of type 'NonHeap' is not valid on the heap}} expected-note {{value incorrectly allocated on the heap}}
+  gobble(new NonHeap[10]); // expected-error {{variable of type 'NonHeap' is not valid on the heap}} expected-note {{value incorrectly allocated on the heap}}
+  gobble(new TemplateClass<int>); // expected-error {{variable of type 'TemplateClass<int>' is not valid on the heap}} expected-note {{value incorrectly allocated on the heap}}
+  gobble(len <= 5 ? &valid : new NonHeap); // expected-error {{variable of type 'NonHeap' is not valid on the heap}} expected-note {{value incorrectly allocated on the heap}}
+
+  char buffer[sizeof(NonHeap)];
+  gobble(new (buffer) NonHeap);
+}
+
+NonHeap validStatic;
+struct RandomClass {
+  NonHeap nonstaticMember; // expected-note {{'RandomClass' is a non-heap type because member 'nonstaticMember' is a non-heap type 'NonHeap'}}
+  static NonHeap staticMember;
+};
+struct MOZ_NONHEAP_CLASS RandomNonHeapClass {
+  NonHeap nonstaticMember;
+  static NonHeap staticMember;
+};
+
+struct BadInherit : NonHeap {}; // expected-note {{'BadInherit' is a non-heap type because it inherits from a non-heap type 'NonHeap'}}
+struct MOZ_NONHEAP_CLASS GoodInherit : NonHeap {};
+
+void useStuffWrongly() {
+  gobble(new BadInherit); // expected-error {{variable of type 'BadInherit' is not valid on the heap}} expected-note {{value incorrectly allocated on the heap}}
+  gobble(new RandomClass); // expected-error {{variable of type 'RandomClass' is not valid on the heap}} expected-note {{value incorrectly allocated on the heap}}
+}
+
+// Stack class overrides non-heap typees.
+struct MOZ_STACK_CLASS StackClass {};
+struct MOZ_NONHEAP_CLASS InferredStackClass : GoodInherit {
+  NonHeap nonstaticMember;
+  StackClass stackClass; // expected-note {{'InferredStackClass' is a stack type because member 'stackClass' is a stack type 'StackClass'}}
+};
+
+InferredStackClass global; // expected-error {{variable of type 'InferredStackClass' only valid on the stack}} expected-note {{value incorrectly allocated in a global variable}}
diff --git a/src/third_party/mozjs-45/build/clang-plugin/tests/TestNonMemMovable.cpp b/src/third_party/mozjs-45/build/clang-plugin/tests/TestNonMemMovable.cpp
new file mode 100644
index 0000000..3665fad
--- /dev/null
+++ b/src/third_party/mozjs-45/build/clang-plugin/tests/TestNonMemMovable.cpp
@@ -0,0 +1,812 @@
+#define MOZ_NON_MEMMOVABLE __attribute__((annotate("moz_non_memmovable")))
+#define MOZ_NEEDS_MEMMOVABLE_TYPE __attribute__((annotate("moz_needs_memmovable_type")))
+
+/*
+  These are a bunch of structs with variable levels of memmovability.
+  They will be used as template parameters to the various NeedyTemplates
+*/
+struct MOZ_NON_MEMMOVABLE NonMovable {};
+struct Movable {};
+
+// Subclasses
+struct S_NonMovable : NonMovable {}; // expected-note 48 {{'S_NonMovable' is a non-memmove()able type because it inherits from a non-memmove()able type 'NonMovable'}}
+struct S_Movable : Movable {};
+
+// Members
+struct W_NonMovable {
+  NonMovable m; // expected-note 32 {{'W_NonMovable' is a non-memmove()able type because member 'm' is a non-memmove()able type 'NonMovable'}}
+};
+struct W_Movable {
+  Movable m;
+};
+
+// Wrapped Subclasses
+struct WS_NonMovable {
+  S_NonMovable m; // expected-note 32 {{'WS_NonMovable' is a non-memmove()able type because member 'm' is a non-memmove()able type 'S_NonMovable'}}
+};
+struct WS_Movable {
+  S_Movable m;
+};
+
+// Combinations of the above
+struct SW_NonMovable : W_NonMovable {}; // expected-note 16 {{'SW_NonMovable' is a non-memmove()able type because it inherits from a non-memmove()able type 'W_NonMovable'}}
+struct SW_Movable : W_Movable {};
+
+struct SWS_NonMovable : WS_NonMovable {}; // expected-note 16 {{'SWS_NonMovable' is a non-memmove()able type because it inherits from a non-memmove()able type 'WS_NonMovable'}}
+struct SWS_Movable : WS_Movable {};
+
+// Basic templated wrapper
+template <class T>
+struct Template_Inline {
+  T m; // expected-note-re 56 {{'Template_Inline<{{.*}}>' is a non-memmove()able type because member 'm' is a non-memmove()able type '{{.*}}'}}
+};
+
+template <class T>
+struct Template_Ref {
+  T* m;
+};
+
+template <class T>
+struct Template_Unused {};
+
+template <class T>
+struct MOZ_NON_MEMMOVABLE Template_NonMovable {};
+
+/*
+  These tests take the following form:
+  DECLARATIONS => Declarations of the templates which are either marked with MOZ_NEEDS_MEMMOVABLE_TYPE
+                  or which instantiate a MOZ_NEEDS_MEMMOVABLE_TYPE through some mechanism.
+  BAD N        => Instantiations of the wrapper template with each of the non-memmovable types.
+                  The prefix S_ means subclass, W_ means wrapped. Each of these rows should produce an error
+                  on the NeedyTemplate in question, and a note at the instantiation location of that template.
+                  Unfortunately, on every case more complicated than bad1, the instantiation location is
+                  within another template. Thus, the notes are expected on the template in question which
+                  actually instantiates the MOZ_NEEDS_MEMMOVABLE_TYPE template.
+  GOOD N       => Instantiations of the wrapper template with each of the memmovable types.
+                  This is meant as a sanity check to ensure that we don't reject valid instantiations of
+                  templates.
+
+
+  Note 1: Each set uses it's own types to ensure that they don't re-use each-other's template specializations.
+  If they did, then some of the error messages would not be emitted (as error messages are emitted for template
+  specializations, rather than for variable declarations)
+
+  Note 2: Every instance of NeedyTemplate contains a member of type T. This is to ensure that T is actually
+  instantiated (if T is a template) by clang. If T isn't instantiated, then we can't actually tell if it is
+  NON_MEMMOVABLE. (This is OK in practice, as you cannot memmove a type which you don't know the size of).
+
+  Note 3: There are a set of tests for specializations of NeedyTemplate at the bottom. For each set of tests,
+  these tests contribute two expected errors to the templates.
+*/
+
+//
+// 1 - Unwrapped MOZ_NEEDS_MEMMOVABLE_TYPE
+//
+
+template <class T>
+struct MOZ_NEEDS_MEMMOVABLE_TYPE NeedyTemplate1 {T m;}; // expected-error-re 26 {{Cannot instantiate 'NeedyTemplate1<{{.*}}>' with non-memmovable template argument '{{.*}}'}}
+
+void bad1() {
+  NeedyTemplate1<NonMovable> a1; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
+  NeedyTemplate1<S_NonMovable> a2; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
+  NeedyTemplate1<W_NonMovable> a3; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
+  NeedyTemplate1<WS_NonMovable> a4; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
+  NeedyTemplate1<SW_NonMovable> a5; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
+  NeedyTemplate1<SWS_NonMovable> a6; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
+
+  NeedyTemplate1<Template_Inline<NonMovable> > b1; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
+  NeedyTemplate1<Template_Inline<S_NonMovable> > b2; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
+  NeedyTemplate1<Template_Inline<W_NonMovable> > b3; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
+  NeedyTemplate1<Template_Inline<WS_NonMovable> > b4; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
+  NeedyTemplate1<Template_Inline<SW_NonMovable> > b5; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
+  NeedyTemplate1<Template_Inline<SWS_NonMovable> > b6; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
+
+  NeedyTemplate1<Template_NonMovable<NonMovable> > c1; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
+  NeedyTemplate1<Template_NonMovable<S_NonMovable> > c2; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
+  NeedyTemplate1<Template_NonMovable<W_NonMovable> > c3; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
+  NeedyTemplate1<Template_NonMovable<WS_NonMovable> > c4; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
+  NeedyTemplate1<Template_NonMovable<SW_NonMovable> > c5; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
+  NeedyTemplate1<Template_NonMovable<SWS_NonMovable> > c6; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
+  NeedyTemplate1<Template_NonMovable<Movable> > c7; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
+  NeedyTemplate1<Template_NonMovable<S_Movable> > c8; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
+  NeedyTemplate1<Template_NonMovable<W_Movable> > c9; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
+  NeedyTemplate1<Template_NonMovable<WS_Movable> > c10; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
+  NeedyTemplate1<Template_NonMovable<SW_Movable> > c11; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
+  NeedyTemplate1<Template_NonMovable<SWS_Movable> > c12; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
+}
+
+void good1() {
+  NeedyTemplate1<Movable> a1;
+  NeedyTemplate1<S_Movable> a2;
+  NeedyTemplate1<W_Movable> a3;
+  NeedyTemplate1<WS_Movable> a4;
+  NeedyTemplate1<SW_Movable> a5;
+  NeedyTemplate1<SWS_Movable> a6;
+
+  NeedyTemplate1<Template_Inline<Movable> > b1;
+  NeedyTemplate1<Template_Inline<S_Movable> > b2;
+  NeedyTemplate1<Template_Inline<W_Movable> > b3;
+  NeedyTemplate1<Template_Inline<WS_Movable> > b4;
+  NeedyTemplate1<Template_Inline<SW_Movable> > b5;
+  NeedyTemplate1<Template_Inline<SWS_Movable> > b6;
+
+  NeedyTemplate1<Template_Unused<Movable> > c1;
+  NeedyTemplate1<Template_Unused<S_Movable> > c2;
+  NeedyTemplate1<Template_Unused<W_Movable> > c3;
+  NeedyTemplate1<Template_Unused<WS_Movable> > c4;
+  NeedyTemplate1<Template_Unused<SW_Movable> > c5;
+  NeedyTemplate1<Template_Unused<SWS_Movable> > c6;
+  NeedyTemplate1<Template_Unused<NonMovable> > c7;
+  NeedyTemplate1<Template_Unused<S_NonMovable> > c8;
+  NeedyTemplate1<Template_Unused<W_NonMovable> > c9;
+  NeedyTemplate1<Template_Unused<WS_NonMovable> > c10;
+  NeedyTemplate1<Template_Unused<SW_NonMovable> > c11;
+  NeedyTemplate1<Template_Unused<SWS_NonMovable> > c12;
+
+  NeedyTemplate1<Template_Ref<Movable> > d1;
+  NeedyTemplate1<Template_Ref<S_Movable> > d2;
+  NeedyTemplate1<Template_Ref<W_Movable> > d3;
+  NeedyTemplate1<Template_Ref<WS_Movable> > d4;
+  NeedyTemplate1<Template_Ref<SW_Movable> > d5;
+  NeedyTemplate1<Template_Ref<SWS_Movable> > d6;
+  NeedyTemplate1<Template_Ref<NonMovable> > d7;
+  NeedyTemplate1<Template_Ref<S_NonMovable> > d8;
+  NeedyTemplate1<Template_Ref<W_NonMovable> > d9;
+  NeedyTemplate1<Template_Ref<WS_NonMovable> > d10;
+  NeedyTemplate1<Template_Ref<SW_NonMovable> > d11;
+  NeedyTemplate1<Template_Ref<SWS_NonMovable> > d12;
+}
+
+//
+// 2 - Subclassed MOZ_NEEDS_MEMMOVABLE_TYPE
+//
+
+template <class T>
+struct MOZ_NEEDS_MEMMOVABLE_TYPE NeedyTemplate2 {T m;}; // expected-error-re 26 {{Cannot instantiate 'NeedyTemplate2<{{.*}}>' with non-memmovable template argument '{{.*}}'}}
+template <class T>
+struct S_NeedyTemplate2 : NeedyTemplate2<T> {}; // expected-note-re 26 {{instantiation of 'NeedyTemplate2<{{.*}}>' requested here}}
+
+void bad2() {
+  S_NeedyTemplate2<NonMovable> a1;
+  S_NeedyTemplate2<S_NonMovable> a2;
+  S_NeedyTemplate2<W_NonMovable> a3;
+  S_NeedyTemplate2<WS_NonMovable> a4;
+  S_NeedyTemplate2<SW_NonMovable> a5;
+  S_NeedyTemplate2<SWS_NonMovable> a6;
+
+  S_NeedyTemplate2<Template_Inline<NonMovable> > b1;
+  S_NeedyTemplate2<Template_Inline<S_NonMovable> > b2;
+  S_NeedyTemplate2<Template_Inline<W_NonMovable> > b3;
+  S_NeedyTemplate2<Template_Inline<WS_NonMovable> > b4;
+  S_NeedyTemplate2<Template_Inline<SW_NonMovable> > b5;
+  S_NeedyTemplate2<Template_Inline<SWS_NonMovable> > b6;
+
+  S_NeedyTemplate2<Template_NonMovable<NonMovable> > c1;
+  S_NeedyTemplate2<Template_NonMovable<S_NonMovable> > c2;
+  S_NeedyTemplate2<Template_NonMovable<W_NonMovable> > c3;
+  S_NeedyTemplate2<Template_NonMovable<WS_NonMovable> > c4;
+  S_NeedyTemplate2<Template_NonMovable<SW_NonMovable> > c5;
+  S_NeedyTemplate2<Template_NonMovable<SWS_NonMovable> > c6;
+  S_NeedyTemplate2<Template_NonMovable<Movable> > c7;
+  S_NeedyTemplate2<Template_NonMovable<S_Movable> > c8;
+  S_NeedyTemplate2<Template_NonMovable<W_Movable> > c9;
+  S_NeedyTemplate2<Template_NonMovable<WS_Movable> > c10;
+  S_NeedyTemplate2<Template_NonMovable<SW_Movable> > c11;
+  S_NeedyTemplate2<Template_NonMovable<SWS_Movable> > c12;
+}
+
+void good2() {
+  S_NeedyTemplate2<Movable> a1;
+  S_NeedyTemplate2<S_Movable> a2;
+  S_NeedyTemplate2<W_Movable> a3;
+  S_NeedyTemplate2<WS_Movable> a4;
+  S_NeedyTemplate2<SW_Movable> a5;
+  S_NeedyTemplate2<SWS_Movable> a6;
+
+  S_NeedyTemplate2<Template_Inline<Movable> > b1;
+  S_NeedyTemplate2<Template_Inline<S_Movable> > b2;
+  S_NeedyTemplate2<Template_Inline<W_Movable> > b3;
+  S_NeedyTemplate2<Template_Inline<WS_Movable> > b4;
+  S_NeedyTemplate2<Template_Inline<SW_Movable> > b5;
+  S_NeedyTemplate2<Template_Inline<SWS_Movable> > b6;
+
+  S_NeedyTemplate2<Template_Unused<Movable> > c1;
+  S_NeedyTemplate2<Template_Unused<S_Movable> > c2;
+  S_NeedyTemplate2<Template_Unused<W_Movable> > c3;
+  S_NeedyTemplate2<Template_Unused<WS_Movable> > c4;
+  S_NeedyTemplate2<Template_Unused<SW_Movable> > c5;
+  S_NeedyTemplate2<Template_Unused<SWS_Movable> > c6;
+  S_NeedyTemplate2<Template_Unused<NonMovable> > c7;
+  S_NeedyTemplate2<Template_Unused<S_NonMovable> > c8;
+  S_NeedyTemplate2<Template_Unused<W_NonMovable> > c9;
+  S_NeedyTemplate2<Template_Unused<WS_NonMovable> > c10;
+  S_NeedyTemplate2<Template_Unused<SW_NonMovable> > c11;
+  S_NeedyTemplate2<Template_Unused<SWS_NonMovable> > c12;
+
+  S_NeedyTemplate2<Template_Ref<Movable> > d1;
+  S_NeedyTemplate2<Template_Ref<S_Movable> > d2;
+  S_NeedyTemplate2<Template_Ref<W_Movable> > d3;
+  S_NeedyTemplate2<Template_Ref<WS_Movable> > d4;
+  S_NeedyTemplate2<Template_Ref<SW_Movable> > d5;
+  S_NeedyTemplate2<Template_Ref<SWS_Movable> > d6;
+  S_NeedyTemplate2<Template_Ref<NonMovable> > d7;
+  S_NeedyTemplate2<Template_Ref<S_NonMovable> > d8;
+  S_NeedyTemplate2<Template_Ref<W_NonMovable> > d9;
+  S_NeedyTemplate2<Template_Ref<WS_NonMovable> > d10;
+  S_NeedyTemplate2<Template_Ref<SW_NonMovable> > d11;
+  S_NeedyTemplate2<Template_Ref<SWS_NonMovable> > d12;
+}
+
+//
+// 3 - Wrapped MOZ_NEEDS_MEMMOVABLE_TYPE
+//
+
+template <class T>
+struct MOZ_NEEDS_MEMMOVABLE_TYPE NeedyTemplate3 {T m;}; // expected-error-re 26 {{Cannot instantiate 'NeedyTemplate3<{{.*}}>' with non-memmovable template argument '{{.*}}'}}
+template <class T>
+struct W_NeedyTemplate3 {
+  NeedyTemplate3<T> m; // expected-note-re 26 {{instantiation of 'NeedyTemplate3<{{.*}}>' requested here}}
+};
+void bad3() {
+  W_NeedyTemplate3<NonMovable> a1;
+  W_NeedyTemplate3<S_NonMovable> a2;
+  W_NeedyTemplate3<W_NonMovable> a3;
+  W_NeedyTemplate3<WS_NonMovable> a4;
+  W_NeedyTemplate3<SW_NonMovable> a5;
+  W_NeedyTemplate3<SWS_NonMovable> a6;
+
+  W_NeedyTemplate3<Template_Inline<NonMovable> > b1;
+  W_NeedyTemplate3<Template_Inline<S_NonMovable> > b2;
+  W_NeedyTemplate3<Template_Inline<W_NonMovable> > b3;
+  W_NeedyTemplate3<Template_Inline<WS_NonMovable> > b4;
+  W_NeedyTemplate3<Template_Inline<SW_NonMovable> > b5;
+  W_NeedyTemplate3<Template_Inline<SWS_NonMovable> > b6;
+
+  W_NeedyTemplate3<Template_NonMovable<NonMovable> > c1;
+  W_NeedyTemplate3<Template_NonMovable<S_NonMovable> > c2;
+  W_NeedyTemplate3<Template_NonMovable<W_NonMovable> > c3;
+  W_NeedyTemplate3<Template_NonMovable<WS_NonMovable> > c4;
+  W_NeedyTemplate3<Template_NonMovable<SW_NonMovable> > c5;
+  W_NeedyTemplate3<Template_NonMovable<SWS_NonMovable> > c6;
+  W_NeedyTemplate3<Template_NonMovable<Movable> > c7;
+  W_NeedyTemplate3<Template_NonMovable<S_Movable> > c8;
+  W_NeedyTemplate3<Template_NonMovable<W_Movable> > c9;
+  W_NeedyTemplate3<Template_NonMovable<WS_Movable> > c10;
+  W_NeedyTemplate3<Template_NonMovable<SW_Movable> > c11;
+  W_NeedyTemplate3<Template_NonMovable<SWS_Movable> > c12;
+}
+
+void good3() {
+  W_NeedyTemplate3<Movable> a1;
+  W_NeedyTemplate3<S_Movable> a2;
+  W_NeedyTemplate3<W_Movable> a3;
+  W_NeedyTemplate3<WS_Movable> a4;
+  W_NeedyTemplate3<SW_Movable> a5;
+  W_NeedyTemplate3<SWS_Movable> a6;
+
+  W_NeedyTemplate3<Template_Inline<Movable> > b1;
+  W_NeedyTemplate3<Template_Inline<S_Movable> > b2;
+  W_NeedyTemplate3<Template_Inline<W_Movable> > b3;
+  W_NeedyTemplate3<Template_Inline<WS_Movable> > b4;
+  W_NeedyTemplate3<Template_Inline<SW_Movable> > b5;
+  W_NeedyTemplate3<Template_Inline<SWS_Movable> > b6;
+
+  W_NeedyTemplate3<Template_Unused<Movable> > c1;
+  W_NeedyTemplate3<Template_Unused<S_Movable> > c2;
+  W_NeedyTemplate3<Template_Unused<W_Movable> > c3;
+  W_NeedyTemplate3<Template_Unused<WS_Movable> > c4;
+  W_NeedyTemplate3<Template_Unused<SW_Movable> > c5;
+  W_NeedyTemplate3<Template_Unused<SWS_Movable> > c6;
+  W_NeedyTemplate3<Template_Unused<NonMovable> > c7;
+  W_NeedyTemplate3<Template_Unused<S_NonMovable> > c8;
+  W_NeedyTemplate3<Template_Unused<W_NonMovable> > c9;
+  W_NeedyTemplate3<Template_Unused<WS_NonMovable> > c10;
+  W_NeedyTemplate3<Template_Unused<SW_NonMovable> > c11;
+  W_NeedyTemplate3<Template_Unused<SWS_NonMovable> > c12;
+
+  W_NeedyTemplate3<Template_Ref<Movable> > d1;
+  W_NeedyTemplate3<Template_Ref<S_Movable> > d2;
+  W_NeedyTemplate3<Template_Ref<W_Movable> > d3;
+  W_NeedyTemplate3<Template_Ref<WS_Movable> > d4;
+  W_NeedyTemplate3<Template_Ref<SW_Movable> > d5;
+  W_NeedyTemplate3<Template_Ref<SWS_Movable> > d6;
+  W_NeedyTemplate3<Template_Ref<NonMovable> > d7;
+  W_NeedyTemplate3<Template_Ref<S_NonMovable> > d8;
+  W_NeedyTemplate3<Template_Ref<W_NonMovable> > d9;
+  W_NeedyTemplate3<Template_Ref<WS_NonMovable> > d10;
+  W_NeedyTemplate3<Template_Ref<SW_NonMovable> > d11;
+  W_NeedyTemplate3<Template_Ref<SWS_NonMovable> > d12;
+}
+
+//
+// 4 - Wrapped Subclassed MOZ_NEEDS_MEMMOVABLE_TYPE
+//
+
+template <class T>
+struct MOZ_NEEDS_MEMMOVABLE_TYPE NeedyTemplate4 {T m;}; // expected-error-re 26 {{Cannot instantiate 'NeedyTemplate4<{{.*}}>' with non-memmovable template argument '{{.*}}'}}
+template <class T>
+struct S_NeedyTemplate4 : NeedyTemplate4<T> {}; // expected-note-re 26 {{instantiation of 'NeedyTemplate4<{{.*}}>' requested here}}
+template <class T>
+struct WS_NeedyTemplate4 {
+  S_NeedyTemplate4<T> m;
+};
+void bad4() {
+  WS_NeedyTemplate4<NonMovable> a1;
+  WS_NeedyTemplate4<S_NonMovable> a2;
+  WS_NeedyTemplate4<W_NonMovable> a3;
+  WS_NeedyTemplate4<WS_NonMovable> a4;
+  WS_NeedyTemplate4<SW_NonMovable> a5;
+  WS_NeedyTemplate4<SWS_NonMovable> a6;
+
+  WS_NeedyTemplate4<Template_Inline<NonMovable> > b1;
+  WS_NeedyTemplate4<Template_Inline<S_NonMovable> > b2;
+  WS_NeedyTemplate4<Template_Inline<W_NonMovable> > b3;
+  WS_NeedyTemplate4<Template_Inline<WS_NonMovable> > b4;
+  WS_NeedyTemplate4<Template_Inline<SW_NonMovable> > b5;
+  WS_NeedyTemplate4<Template_Inline<SWS_NonMovable> > b6;
+
+  WS_NeedyTemplate4<Template_NonMovable<NonMovable> > c1;
+  WS_NeedyTemplate4<Template_NonMovable<S_NonMovable> > c2;
+  WS_NeedyTemplate4<Template_NonMovable<W_NonMovable> > c3;
+  WS_NeedyTemplate4<Template_NonMovable<WS_NonMovable> > c4;
+  WS_NeedyTemplate4<Template_NonMovable<SW_NonMovable> > c5;
+  WS_NeedyTemplate4<Template_NonMovable<SWS_NonMovable> > c6;
+  WS_NeedyTemplate4<Template_NonMovable<Movable> > c7;
+  WS_NeedyTemplate4<Template_NonMovable<S_Movable> > c8;
+  WS_NeedyTemplate4<Template_NonMovable<W_Movable> > c9;
+  WS_NeedyTemplate4<Template_NonMovable<WS_Movable> > c10;
+  WS_NeedyTemplate4<Template_NonMovable<SW_Movable> > c11;
+  WS_NeedyTemplate4<Template_NonMovable<SWS_Movable> > c12;
+}
+
+void good4() {
+  WS_NeedyTemplate4<Movable> a1;
+  WS_NeedyTemplate4<S_Movable> a2;
+  WS_NeedyTemplate4<W_Movable> a3;
+  WS_NeedyTemplate4<WS_Movable> a4;
+  WS_NeedyTemplate4<SW_Movable> a5;
+  WS_NeedyTemplate4<SWS_Movable> a6;
+
+  WS_NeedyTemplate4<Template_Inline<Movable> > b1;
+  WS_NeedyTemplate4<Template_Inline<S_Movable> > b2;
+  WS_NeedyTemplate4<Template_Inline<W_Movable> > b3;
+  WS_NeedyTemplate4<Template_Inline<WS_Movable> > b4;
+  WS_NeedyTemplate4<Template_Inline<SW_Movable> > b5;
+  WS_NeedyTemplate4<Template_Inline<SWS_Movable> > b6;
+
+  WS_NeedyTemplate4<Template_Unused<Movable> > c1;
+  WS_NeedyTemplate4<Template_Unused<S_Movable> > c2;
+  WS_NeedyTemplate4<Template_Unused<W_Movable> > c3;
+  WS_NeedyTemplate4<Template_Unused<WS_Movable> > c4;
+  WS_NeedyTemplate4<Template_Unused<SW_Movable> > c5;
+  WS_NeedyTemplate4<Template_Unused<SWS_Movable> > c6;
+  WS_NeedyTemplate4<Template_Unused<NonMovable> > c7;
+  WS_NeedyTemplate4<Template_Unused<S_NonMovable> > c8;
+  WS_NeedyTemplate4<Template_Unused<W_NonMovable> > c9;
+  WS_NeedyTemplate4<Template_Unused<WS_NonMovable> > c10;
+  WS_NeedyTemplate4<Template_Unused<SW_NonMovable> > c11;
+  WS_NeedyTemplate4<Template_Unused<SWS_NonMovable> > c12;
+
+  WS_NeedyTemplate4<Template_Ref<Movable> > d1;
+  WS_NeedyTemplate4<Template_Ref<S_Movable> > d2;
+  WS_NeedyTemplate4<Template_Ref<W_Movable> > d3;
+  WS_NeedyTemplate4<Template_Ref<WS_Movable> > d4;
+  WS_NeedyTemplate4<Template_Ref<SW_Movable> > d5;
+  WS_NeedyTemplate4<Template_Ref<SWS_Movable> > d6;
+  WS_NeedyTemplate4<Template_Ref<NonMovable> > d7;
+  WS_NeedyTemplate4<Template_Ref<S_NonMovable> > d8;
+  WS_NeedyTemplate4<Template_Ref<W_NonMovable> > d9;
+  WS_NeedyTemplate4<Template_Ref<WS_NonMovable> > d10;
+  WS_NeedyTemplate4<Template_Ref<SW_NonMovable> > d11;
+  WS_NeedyTemplate4<Template_Ref<SWS_NonMovable> > d12;
+}
+
+//
+// 5 - Subclassed Wrapped MOZ_NEEDS_MEMMOVABLE_TYPE
+//
+
+template <class T>
+struct MOZ_NEEDS_MEMMOVABLE_TYPE NeedyTemplate5 {T m;}; // expected-error-re 26 {{Cannot instantiate 'NeedyTemplate5<{{.*}}>' with non-memmovable template argument '{{.*}}'}}
+template <class T>
+struct W_NeedyTemplate5 {
+  NeedyTemplate5<T> m; // expected-note-re 26 {{instantiation of 'NeedyTemplate5<{{.*}}>' requested here}}
+};
+template <class T>
+struct SW_NeedyTemplate5 : W_NeedyTemplate5<T> {};
+void bad5() {
+  SW_NeedyTemplate5<NonMovable> a1;
+  SW_NeedyTemplate5<S_NonMovable> a2;
+  SW_NeedyTemplate5<W_NonMovable> a3;
+  SW_NeedyTemplate5<WS_NonMovable> a4;
+  SW_NeedyTemplate5<SW_NonMovable> a5;
+  SW_NeedyTemplate5<SWS_NonMovable> a6;
+
+  SW_NeedyTemplate5<Template_Inline<NonMovable> > b1;
+  SW_NeedyTemplate5<Template_Inline<S_NonMovable> > b2;
+  SW_NeedyTemplate5<Template_Inline<W_NonMovable> > b3;
+  SW_NeedyTemplate5<Template_Inline<WS_NonMovable> > b4;
+  SW_NeedyTemplate5<Template_Inline<SW_NonMovable> > b5;
+  SW_NeedyTemplate5<Template_Inline<SWS_NonMovable> > b6;
+
+  SW_NeedyTemplate5<Template_NonMovable<NonMovable> > c1;
+  SW_NeedyTemplate5<Template_NonMovable<S_NonMovable> > c2;
+  SW_NeedyTemplate5<Template_NonMovable<W_NonMovable> > c3;
+  SW_NeedyTemplate5<Template_NonMovable<WS_NonMovable> > c4;
+  SW_NeedyTemplate5<Template_NonMovable<SW_NonMovable> > c5;
+  SW_NeedyTemplate5<Template_NonMovable<SWS_NonMovable> > c6;
+  SW_NeedyTemplate5<Template_NonMovable<Movable> > c7;
+  SW_NeedyTemplate5<Template_NonMovable<S_Movable> > c8;
+  SW_NeedyTemplate5<Template_NonMovable<W_Movable> > c9;
+  SW_NeedyTemplate5<Template_NonMovable<WS_Movable> > c10;
+  SW_NeedyTemplate5<Template_NonMovable<SW_Movable> > c11;
+  SW_NeedyTemplate5<Template_NonMovable<SWS_Movable> > c12;
+}
+
+void good5() {
+  SW_NeedyTemplate5<Movable> a1;
+  SW_NeedyTemplate5<S_Movable> a2;
+  SW_NeedyTemplate5<W_Movable> a3;
+  SW_NeedyTemplate5<WS_Movable> a4;
+  SW_NeedyTemplate5<SW_Movable> a5;
+  SW_NeedyTemplate5<SWS_Movable> a6;
+
+  SW_NeedyTemplate5<Template_Inline<Movable> > b1;
+  SW_NeedyTemplate5<Template_Inline<S_Movable> > b2;
+  SW_NeedyTemplate5<Template_Inline<W_Movable> > b3;
+  SW_NeedyTemplate5<Template_Inline<WS_Movable> > b4;
+  SW_NeedyTemplate5<Template_Inline<SW_Movable> > b5;
+  SW_NeedyTemplate5<Template_Inline<SWS_Movable> > b6;
+
+  SW_NeedyTemplate5<Template_Unused<Movable> > c1;
+  SW_NeedyTemplate5<Template_Unused<S_Movable> > c2;
+  SW_NeedyTemplate5<Template_Unused<W_Movable> > c3;
+  SW_NeedyTemplate5<Template_Unused<WS_Movable> > c4;
+  SW_NeedyTemplate5<Template_Unused<SW_Movable> > c5;
+  SW_NeedyTemplate5<Template_Unused<SWS_Movable> > c6;
+  SW_NeedyTemplate5<Template_Unused<NonMovable> > c7;
+  SW_NeedyTemplate5<Template_Unused<S_NonMovable> > c8;
+  SW_NeedyTemplate5<Template_Unused<W_NonMovable> > c9;
+  SW_NeedyTemplate5<Template_Unused<WS_NonMovable> > c10;
+  SW_NeedyTemplate5<Template_Unused<SW_NonMovable> > c11;
+  SW_NeedyTemplate5<Template_Unused<SWS_NonMovable> > c12;
+
+  SW_NeedyTemplate5<Template_Ref<Movable> > d1;
+  SW_NeedyTemplate5<Template_Ref<S_Movable> > d2;
+  SW_NeedyTemplate5<Template_Ref<W_Movable> > d3;
+  SW_NeedyTemplate5<Template_Ref<WS_Movable> > d4;
+  SW_NeedyTemplate5<Template_Ref<SW_Movable> > d5;
+  SW_NeedyTemplate5<Template_Ref<SWS_Movable> > d6;
+  SW_NeedyTemplate5<Template_Ref<NonMovable> > d7;
+  SW_NeedyTemplate5<Template_Ref<S_NonMovable> > d8;
+  SW_NeedyTemplate5<Template_Ref<W_NonMovable> > d9;
+  SW_NeedyTemplate5<Template_Ref<WS_NonMovable> > d10;
+  SW_NeedyTemplate5<Template_Ref<SW_NonMovable> > d11;
+  SW_NeedyTemplate5<Template_Ref<SWS_NonMovable> > d12;
+}
+
+//
+// 6 - MOZ_NEEDS_MEMMOVABLE_TYPE instantiated with default template argument
+//
+// Note: This has an extra error, because it also includes a test with the default template argument.
+//
+
+template <class T>
+struct MOZ_NEEDS_MEMMOVABLE_TYPE NeedyTemplate6 {T m;}; // expected-error-re 27 {{Cannot instantiate 'NeedyTemplate6<{{.*}}>' with non-memmovable template argument '{{.*}}'}}
+template <class T>
+struct W_NeedyTemplate6 {
+  NeedyTemplate6<T> m; // expected-note-re 27 {{instantiation of 'NeedyTemplate6<{{.*}}>' requested here}}
+};
+template <class T>
+struct SW_NeedyTemplate6 : W_NeedyTemplate6<T> {};
+// We create a different NonMovable type here, as NeedyTemplate6 will already be instantiated with NonMovable
+struct MOZ_NON_MEMMOVABLE NonMovable2 {};
+template <class T = NonMovable2>
+struct Defaulted_SW_NeedyTemplate6 {
+  SW_NeedyTemplate6<T> m;
+};
+void bad6() {
+  Defaulted_SW_NeedyTemplate6<NonMovable> a1;
+  Defaulted_SW_NeedyTemplate6<S_NonMovable> a2;
+  Defaulted_SW_NeedyTemplate6<W_NonMovable> a3;
+  Defaulted_SW_NeedyTemplate6<WS_NonMovable> a4;
+  Defaulted_SW_NeedyTemplate6<SW_NonMovable> a5;
+  Defaulted_SW_NeedyTemplate6<SWS_NonMovable> a6;
+
+  Defaulted_SW_NeedyTemplate6<Template_Inline<NonMovable> > b1;
+  Defaulted_SW_NeedyTemplate6<Template_Inline<S_NonMovable> > b2;
+  Defaulted_SW_NeedyTemplate6<Template_Inline<W_NonMovable> > b3;
+  Defaulted_SW_NeedyTemplate6<Template_Inline<WS_NonMovable> > b4;
+  Defaulted_SW_NeedyTemplate6<Template_Inline<SW_NonMovable> > b5;
+  Defaulted_SW_NeedyTemplate6<Template_Inline<SWS_NonMovable> > b6;
+
+  Defaulted_SW_NeedyTemplate6<Template_NonMovable<NonMovable> > c1;
+  Defaulted_SW_NeedyTemplate6<Template_NonMovable<S_NonMovable> > c2;
+  Defaulted_SW_NeedyTemplate6<Template_NonMovable<W_NonMovable> > c3;
+  Defaulted_SW_NeedyTemplate6<Template_NonMovable<WS_NonMovable> > c4;
+  Defaulted_SW_NeedyTemplate6<Template_NonMovable<SW_NonMovable> > c5;
+  Defaulted_SW_NeedyTemplate6<Template_NonMovable<SWS_NonMovable> > c6;
+  Defaulted_SW_NeedyTemplate6<Template_NonMovable<Movable> > c7;
+  Defaulted_SW_NeedyTemplate6<Template_NonMovable<S_Movable> > c8;
+  Defaulted_SW_NeedyTemplate6<Template_NonMovable<W_Movable> > c9;
+  Defaulted_SW_NeedyTemplate6<Template_NonMovable<WS_Movable> > c10;
+  Defaulted_SW_NeedyTemplate6<Template_NonMovable<SW_Movable> > c11;
+  Defaulted_SW_NeedyTemplate6<Template_NonMovable<SWS_Movable> > c12;
+
+  Defaulted_SW_NeedyTemplate6<> c13;
+}
+
+void good6() {
+  Defaulted_SW_NeedyTemplate6<Movable> a1;
+  Defaulted_SW_NeedyTemplate6<S_Movable> a2;
+  Defaulted_SW_NeedyTemplate6<W_Movable> a3;
+  Defaulted_SW_NeedyTemplate6<WS_Movable> a4;
+  Defaulted_SW_NeedyTemplate6<SW_Movable> a5;
+  Defaulted_SW_NeedyTemplate6<SWS_Movable> a6;
+
+  Defaulted_SW_NeedyTemplate6<Template_Inline<Movable> > b1;
+  Defaulted_SW_NeedyTemplate6<Template_Inline<S_Movable> > b2;
+  Defaulted_SW_NeedyTemplate6<Template_Inline<W_Movable> > b3;
+  Defaulted_SW_NeedyTemplate6<Template_Inline<WS_Movable> > b4;
+  Defaulted_SW_NeedyTemplate6<Template_Inline<SW_Movable> > b5;
+  Defaulted_SW_NeedyTemplate6<Template_Inline<SWS_Movable> > b6;
+
+  Defaulted_SW_NeedyTemplate6<Template_Unused<Movable> > c1;
+  Defaulted_SW_NeedyTemplate6<Template_Unused<S_Movable> > c2;
+  Defaulted_SW_NeedyTemplate6<Template_Unused<W_Movable> > c3;
+  Defaulted_SW_NeedyTemplate6<Template_Unused<WS_Movable> > c4;
+  Defaulted_SW_NeedyTemplate6<Template_Unused<SW_Movable> > c5;
+  Defaulted_SW_NeedyTemplate6<Template_Unused<SWS_Movable> > c6;
+  Defaulted_SW_NeedyTemplate6<Template_Unused<NonMovable> > c7;
+  Defaulted_SW_NeedyTemplate6<Template_Unused<S_NonMovable> > c8;
+  Defaulted_SW_NeedyTemplate6<Template_Unused<W_NonMovable> > c9;
+  Defaulted_SW_NeedyTemplate6<Template_Unused<WS_NonMovable> > c10;
+  Defaulted_SW_NeedyTemplate6<Template_Unused<SW_NonMovable> > c11;
+  Defaulted_SW_NeedyTemplate6<Template_Unused<SWS_NonMovable> > c12;
+
+  Defaulted_SW_NeedyTemplate6<Template_Ref<Movable> > d1;
+  Defaulted_SW_NeedyTemplate6<Template_Ref<S_Movable> > d2;
+  Defaulted_SW_NeedyTemplate6<Template_Ref<W_Movable> > d3;
+  Defaulted_SW_NeedyTemplate6<Template_Ref<WS_Movable> > d4;
+  Defaulted_SW_NeedyTemplate6<Template_Ref<SW_Movable> > d5;
+  Defaulted_SW_NeedyTemplate6<Template_Ref<SWS_Movable> > d6;
+  Defaulted_SW_NeedyTemplate6<Template_Ref<NonMovable> > d7;
+  Defaulted_SW_NeedyTemplate6<Template_Ref<S_NonMovable> > d8;
+  Defaulted_SW_NeedyTemplate6<Template_Ref<W_NonMovable> > d9;
+  Defaulted_SW_NeedyTemplate6<Template_Ref<WS_NonMovable> > d10;
+  Defaulted_SW_NeedyTemplate6<Template_Ref<SW_NonMovable> > d11;
+  Defaulted_SW_NeedyTemplate6<Template_Ref<SWS_NonMovable> > d12;
+}
+
+//
+// 7 - MOZ_NEEDS_MEMMOVABLE_TYPE instantiated as default template argument
+//
+
+template <class T>
+struct MOZ_NEEDS_MEMMOVABLE_TYPE NeedyTemplate7 {T m;}; // expected-error-re 26 {{Cannot instantiate 'NeedyTemplate7<{{.*}}>' with non-memmovable template argument '{{.*}}'}}
+template <class T, class Q = NeedyTemplate7<T> >
+struct Defaulted_Templated_NeedyTemplate7 {Q m;}; // expected-note-re 26 {{instantiation of 'NeedyTemplate7<{{.*}}>' requested here}}
+void bad7() {
+  Defaulted_Templated_NeedyTemplate7<NonMovable> a1;
+  Defaulted_Templated_NeedyTemplate7<S_NonMovable> a2;
+  Defaulted_Templated_NeedyTemplate7<W_NonMovable> a3;
+  Defaulted_Templated_NeedyTemplate7<WS_NonMovable> a4;
+  Defaulted_Templated_NeedyTemplate7<SW_NonMovable> a5;
+  Defaulted_Templated_NeedyTemplate7<SWS_NonMovable> a6;
+
+  Defaulted_Templated_NeedyTemplate7<Template_Inline<NonMovable> > b1;
+  Defaulted_Templated_NeedyTemplate7<Template_Inline<S_NonMovable> > b2;
+  Defaulted_Templated_NeedyTemplate7<Template_Inline<W_NonMovable> > b3;
+  Defaulted_Templated_NeedyTemplate7<Template_Inline<WS_NonMovable> > b4;
+  Defaulted_Templated_NeedyTemplate7<Template_Inline<SW_NonMovable> > b5;
+  Defaulted_Templated_NeedyTemplate7<Template_Inline<SWS_NonMovable> > b6;
+
+  Defaulted_Templated_NeedyTemplate7<Template_NonMovable<NonMovable> > c1;
+  Defaulted_Templated_NeedyTemplate7<Template_NonMovable<S_NonMovable> > c2;
+  Defaulted_Templated_NeedyTemplate7<Template_NonMovable<W_NonMovable> > c3;
+  Defaulted_Templated_NeedyTemplate7<Template_NonMovable<WS_NonMovable> > c4;
+  Defaulted_Templated_NeedyTemplate7<Template_NonMovable<SW_NonMovable> > c5;
+  Defaulted_Templated_NeedyTemplate7<Template_NonMovable<SWS_NonMovable> > c6;
+  Defaulted_Templated_NeedyTemplate7<Template_NonMovable<Movable> > c7;
+  Defaulted_Templated_NeedyTemplate7<Template_NonMovable<S_Movable> > c8;
+  Defaulted_Templated_NeedyTemplate7<Template_NonMovable<W_Movable> > c9;
+  Defaulted_Templated_NeedyTemplate7<Template_NonMovable<WS_Movable> > c10;
+  Defaulted_Templated_NeedyTemplate7<Template_NonMovable<SW_Movable> > c11;
+  Defaulted_Templated_NeedyTemplate7<Template_NonMovable<SWS_Movable> > c12;
+}
+
+void good7() {
+  Defaulted_Templated_NeedyTemplate7<Movable> a1;
+  Defaulted_Templated_NeedyTemplate7<S_Movable> a2;
+  Defaulted_Templated_NeedyTemplate7<W_Movable> a3;
+  Defaulted_Templated_NeedyTemplate7<WS_Movable> a4;
+  Defaulted_Templated_NeedyTemplate7<SW_Movable> a5;
+  Defaulted_Templated_NeedyTemplate7<SWS_Movable> a6;
+
+  Defaulted_Templated_NeedyTemplate7<Template_Inline<Movable> > b1;
+  Defaulted_Templated_NeedyTemplate7<Template_Inline<S_Movable> > b2;
+  Defaulted_Templated_NeedyTemplate7<Template_Inline<W_Movable> > b3;
+  Defaulted_Templated_NeedyTemplate7<Template_Inline<WS_Movable> > b4;
+  Defaulted_Templated_NeedyTemplate7<Template_Inline<SW_Movable> > b5;
+  Defaulted_Templated_NeedyTemplate7<Template_Inline<SWS_Movable> > b6;
+
+  Defaulted_Templated_NeedyTemplate7<Template_Unused<Movable> > c1;
+  Defaulted_Templated_NeedyTemplate7<Template_Unused<S_Movable> > c2;
+  Defaulted_Templated_NeedyTemplate7<Template_Unused<W_Movable> > c3;
+  Defaulted_Templated_NeedyTemplate7<Template_Unused<WS_Movable> > c4;
+  Defaulted_Templated_NeedyTemplate7<Template_Unused<SW_Movable> > c5;
+  Defaulted_Templated_NeedyTemplate7<Template_Unused<SWS_Movable> > c6;
+  Defaulted_Templated_NeedyTemplate7<Template_Unused<NonMovable> > c7;
+  Defaulted_Templated_NeedyTemplate7<Template_Unused<S_NonMovable> > c8;
+  Defaulted_Templated_NeedyTemplate7<Template_Unused<W_NonMovable> > c9;
+  Defaulted_Templated_NeedyTemplate7<Template_Unused<WS_NonMovable> > c10;
+  Defaulted_Templated_NeedyTemplate7<Template_Unused<SW_NonMovable> > c11;
+  Defaulted_Templated_NeedyTemplate7<Template_Unused<SWS_NonMovable> > c12;
+
+  Defaulted_Templated_NeedyTemplate7<Template_Ref<Movable> > d1;
+  Defaulted_Templated_NeedyTemplate7<Template_Ref<S_Movable> > d2;
+  Defaulted_Templated_NeedyTemplate7<Template_Ref<W_Movable> > d3;
+  Defaulted_Templated_NeedyTemplate7<Template_Ref<WS_Movable> > d4;
+  Defaulted_Templated_NeedyTemplate7<Template_Ref<SW_Movable> > d5;
+  Defaulted_Templated_NeedyTemplate7<Template_Ref<SWS_Movable> > d6;
+  Defaulted_Templated_NeedyTemplate7<Template_Ref<NonMovable> > d7;
+  Defaulted_Templated_NeedyTemplate7<Template_Ref<S_NonMovable> > d8;
+  Defaulted_Templated_NeedyTemplate7<Template_Ref<W_NonMovable> > d9;
+  Defaulted_Templated_NeedyTemplate7<Template_Ref<WS_NonMovable> > d10;
+  Defaulted_Templated_NeedyTemplate7<Template_Ref<SW_NonMovable> > d11;
+  Defaulted_Templated_NeedyTemplate7<Template_Ref<SWS_NonMovable> > d12;
+}
+
+//
+// 8 - Wrapped MOZ_NEEDS_MEMMOVABLE_TYPE instantiated as default template argument
+//
+
+template <class T>
+struct MOZ_NEEDS_MEMMOVABLE_TYPE NeedyTemplate8 {T m;}; // expected-error-re 26 {{Cannot instantiate 'NeedyTemplate8<{{.*}}>' with non-memmovable template argument '{{.*}}'}}
+template <class T, class Q = NeedyTemplate8<T> >
+struct Defaulted_Templated_NeedyTemplate8 {Q m;}; // expected-note-re 26 {{instantiation of 'NeedyTemplate8<{{.*}}>' requested here}}
+template <class T>
+struct W_Defaulted_Templated_NeedyTemplate8 {
+  Defaulted_Templated_NeedyTemplate8<T> m;
+};
+void bad8() {
+  W_Defaulted_Templated_NeedyTemplate8<NonMovable> a1;
+  W_Defaulted_Templated_NeedyTemplate8<S_NonMovable> a2;
+  W_Defaulted_Templated_NeedyTemplate8<W_NonMovable> a3;
+  W_Defaulted_Templated_NeedyTemplate8<WS_NonMovable> a4;
+  W_Defaulted_Templated_NeedyTemplate8<SW_NonMovable> a5;
+  W_Defaulted_Templated_NeedyTemplate8<SWS_NonMovable> a6;
+
+  W_Defaulted_Templated_NeedyTemplate8<Template_Inline<NonMovable> > b1;
+  W_Defaulted_Templated_NeedyTemplate8<Template_Inline<S_NonMovable> > b2;
+  W_Defaulted_Templated_NeedyTemplate8<Template_Inline<W_NonMovable> > b3;
+  W_Defaulted_Templated_NeedyTemplate8<Template_Inline<WS_NonMovable> > b4;
+  W_Defaulted_Templated_NeedyTemplate8<Template_Inline<SW_NonMovable> > b5;
+  W_Defaulted_Templated_NeedyTemplate8<Template_Inline<SWS_NonMovable> > b6;
+
+  W_Defaulted_Templated_NeedyTemplate8<Template_NonMovable<NonMovable> > c1;
+  W_Defaulted_Templated_NeedyTemplate8<Template_NonMovable<S_NonMovable> > c2;
+  W_Defaulted_Templated_NeedyTemplate8<Template_NonMovable<W_NonMovable> > c3;
+  W_Defaulted_Templated_NeedyTemplate8<Template_NonMovable<WS_NonMovable> > c4;
+  W_Defaulted_Templated_NeedyTemplate8<Template_NonMovable<SW_NonMovable> > c5;
+  W_Defaulted_Templated_NeedyTemplate8<Template_NonMovable<SWS_NonMovable> > c6;
+  W_Defaulted_Templated_NeedyTemplate8<Template_NonMovable<Movable> > c7;
+  W_Defaulted_Templated_NeedyTemplate8<Template_NonMovable<S_Movable> > c8;
+  W_Defaulted_Templated_NeedyTemplate8<Template_NonMovable<W_Movable> > c9;
+  W_Defaulted_Templated_NeedyTemplate8<Template_NonMovable<WS_Movable> > c10;
+  W_Defaulted_Templated_NeedyTemplate8<Template_NonMovable<SW_Movable> > c11;
+  W_Defaulted_Templated_NeedyTemplate8<Template_NonMovable<SWS_Movable> > c12;
+}
+
+void good8() {
+  W_Defaulted_Templated_NeedyTemplate8<Movable> a1;
+  W_Defaulted_Templated_NeedyTemplate8<S_Movable> a2;
+  W_Defaulted_Templated_NeedyTemplate8<W_Movable> a3;
+  W_Defaulted_Templated_NeedyTemplate8<WS_Movable> a4;
+  W_Defaulted_Templated_NeedyTemplate8<SW_Movable> a5;
+  W_Defaulted_Templated_NeedyTemplate8<SWS_Movable> a6;
+
+  W_Defaulted_Templated_NeedyTemplate8<Template_Inline<Movable> > b1;
+  W_Defaulted_Templated_NeedyTemplate8<Template_Inline<S_Movable> > b2;
+  W_Defaulted_Templated_NeedyTemplate8<Template_Inline<W_Movable> > b3;
+  W_Defaulted_Templated_NeedyTemplate8<Template_Inline<WS_Movable> > b4;
+  W_Defaulted_Templated_NeedyTemplate8<Template_Inline<SW_Movable> > b5;
+  W_Defaulted_Templated_NeedyTemplate8<Template_Inline<SWS_Movable> > b6;
+
+  W_Defaulted_Templated_NeedyTemplate8<Template_Unused<Movable> > c1;
+  W_Defaulted_Templated_NeedyTemplate8<Template_Unused<S_Movable> > c2;
+  W_Defaulted_Templated_NeedyTemplate8<Template_Unused<W_Movable> > c3;
+  W_Defaulted_Templated_NeedyTemplate8<Template_Unused<WS_Movable> > c4;
+  W_Defaulted_Templated_NeedyTemplate8<Template_Unused<SW_Movable> > c5;
+  W_Defaulted_Templated_NeedyTemplate8<Template_Unused<SWS_Movable> > c6;
+  W_Defaulted_Templated_NeedyTemplate8<Template_Unused<NonMovable> > c7;
+  W_Defaulted_Templated_NeedyTemplate8<Template_Unused<S_NonMovable> > c8;
+  W_Defaulted_Templated_NeedyTemplate8<Template_Unused<W_NonMovable> > c9;
+  W_Defaulted_Templated_NeedyTemplate8<Template_Unused<WS_NonMovable> > c10;
+  W_Defaulted_Templated_NeedyTemplate8<Template_Unused<SW_NonMovable> > c11;
+  W_Defaulted_Templated_NeedyTemplate8<Template_Unused<SWS_NonMovable> > c12;
+
+  W_Defaulted_Templated_NeedyTemplate8<Template_Ref<Movable> > d1;
+  W_Defaulted_Templated_NeedyTemplate8<Template_Ref<S_Movable> > d2;
+  W_Defaulted_Templated_NeedyTemplate8<Template_Ref<W_Movable> > d3;
+  W_Defaulted_Templated_NeedyTemplate8<Template_Ref<WS_Movable> > d4;
+  W_Defaulted_Templated_NeedyTemplate8<Template_Ref<SW_Movable> > d5;
+  W_Defaulted_Templated_NeedyTemplate8<Template_Ref<SWS_Movable> > d6;
+  W_Defaulted_Templated_NeedyTemplate8<Template_Ref<NonMovable> > d7;
+  W_Defaulted_Templated_NeedyTemplate8<Template_Ref<S_NonMovable> > d8;
+  W_Defaulted_Templated_NeedyTemplate8<Template_Ref<W_NonMovable> > d9;
+  W_Defaulted_Templated_NeedyTemplate8<Template_Ref<WS_NonMovable> > d10;
+  W_Defaulted_Templated_NeedyTemplate8<Template_Ref<SW_NonMovable> > d11;
+  W_Defaulted_Templated_NeedyTemplate8<Template_Ref<SWS_NonMovable> > d12;
+}
+
+/*
+  SpecializedNonMovable is a non-movable class which has an explicit specialization of NeedyTemplate
+  for it. Instantiations of NeedyTemplateN<SpecializedNonMovable> should be legal as the explicit
+  specialization isn't annotated with MOZ_NEEDS_MEMMOVABLE_TYPE.
+
+  However, as it is MOZ_NON_MEMMOVABLE, derived classes and members shouldn't be able to be used to
+  instantiate NeedyTemplate.
+*/
+
+struct MOZ_NON_MEMMOVABLE SpecializedNonMovable {};
+struct S_SpecializedNonMovable : SpecializedNonMovable {}; // expected-note 8 {{'S_SpecializedNonMovable' is a non-memmove()able type because it inherits from a non-memmove()able type 'SpecializedNonMovable'}}
+
+// Specialize all of the NeedyTemplates with SpecializedNonMovable.
+template <>
+struct NeedyTemplate1<SpecializedNonMovable> {};
+template <>
+struct NeedyTemplate2<SpecializedNonMovable> {};
+template <>
+struct NeedyTemplate3<SpecializedNonMovable> {};
+template <>
+struct NeedyTemplate4<SpecializedNonMovable> {};
+template <>
+struct NeedyTemplate5<SpecializedNonMovable> {};
+template <>
+struct NeedyTemplate6<SpecializedNonMovable> {};
+template <>
+struct NeedyTemplate7<SpecializedNonMovable> {};
+template <>
+struct NeedyTemplate8<SpecializedNonMovable> {};
+
+void specialization() {
+  /*
+    SpecializedNonMovable has a specialization for every variant of NeedyTemplate,
+    so these templates are valid, even though SpecializedNonMovable isn't
+    memmovable
+  */
+  NeedyTemplate1<SpecializedNonMovable> a1;
+  S_NeedyTemplate2<SpecializedNonMovable> a2;
+  W_NeedyTemplate3<SpecializedNonMovable> a3;
+  WS_NeedyTemplate4<SpecializedNonMovable> a4;
+  SW_NeedyTemplate5<SpecializedNonMovable> a5;
+  Defaulted_SW_NeedyTemplate6<SpecializedNonMovable> a6;
+  Defaulted_Templated_NeedyTemplate7<SpecializedNonMovable> a7;
+  W_Defaulted_Templated_NeedyTemplate8<SpecializedNonMovable> a8;
+
+  /*
+    These entries contain an element which is SpecializedNonMovable, and are non-movable
+    as there is no valid specialization, and their member is non-memmovable
+  */
+  NeedyTemplate1<Template_Inline<SpecializedNonMovable> > b1;  // expected-note {{instantiation of 'NeedyTemplate1<Template_Inline<SpecializedNonMovable> >' requested here}}
+  S_NeedyTemplate2<Template_Inline<SpecializedNonMovable> > b2;
+  W_NeedyTemplate3<Template_Inline<SpecializedNonMovable> > b3;
+  WS_NeedyTemplate4<Template_Inline<SpecializedNonMovable> > b4;
+  SW_NeedyTemplate5<Template_Inline<SpecializedNonMovable> > b5;
+  Defaulted_SW_NeedyTemplate6<Template_Inline<SpecializedNonMovable> > b6;
+  Defaulted_Templated_NeedyTemplate7<Template_Inline<SpecializedNonMovable> > b7;
+  W_Defaulted_Templated_NeedyTemplate8<Template_Inline<SpecializedNonMovable> > b8;
+
+  /*
+    The subclass of SpecializedNonMovable, is also non-memmovable,
+    as there is no valid specialization.
+  */
+  NeedyTemplate1<S_SpecializedNonMovable> c1; // expected-note {{instantiation of 'NeedyTemplate1<S_SpecializedNonMovable>' requested here}}
+  S_NeedyTemplate2<S_SpecializedNonMovable> c2;
+  W_NeedyTemplate3<S_SpecializedNonMovable> c3;
+  WS_NeedyTemplate4<S_SpecializedNonMovable> c4;
+  SW_NeedyTemplate5<S_SpecializedNonMovable> c5;
+  Defaulted_SW_NeedyTemplate6<S_SpecializedNonMovable> c6;
+  Defaulted_Templated_NeedyTemplate7<S_SpecializedNonMovable> c7;
+  W_Defaulted_Templated_NeedyTemplate8<S_SpecializedNonMovable> c8;
+}
diff --git a/src/third_party/mozjs-45/build/clang-plugin/tests/TestNonMemMovableStd.cpp b/src/third_party/mozjs-45/build/clang-plugin/tests/TestNonMemMovableStd.cpp
new file mode 100644
index 0000000..9fce524
--- /dev/null
+++ b/src/third_party/mozjs-45/build/clang-plugin/tests/TestNonMemMovableStd.cpp
@@ -0,0 +1,21 @@
+#define MOZ_NEEDS_MEMMOVABLE_TYPE __attribute__((annotate("moz_needs_memmovable_type")))
+
+template<class T>
+class MOZ_NEEDS_MEMMOVABLE_TYPE Mover { T mForceInst; }; // expected-error-re 4 {{Cannot instantiate 'Mover<{{.*}}>' with non-memmovable template argument '{{.*}}'}}
+
+namespace std {
+// In theory defining things in std:: like this invokes undefined
+// behavior, but in practice it's good enough for this test case.
+template<class C> class basic_string { };
+typedef basic_string<char> string;
+template<class T, class U> class pair { T mT; U mU; }; // expected-note {{std::pair<bool, std::basic_string<char> >' is a non-memmove()able type because member 'mU' is a non-memmove()able type 'std::basic_string<char>'}}
+class arbitrary_name { };
+}
+
+class HasString { std::string m; }; // expected-note {{'HasString' is a non-memmove()able type because member 'm' is a non-memmove()able type 'std::string' (aka 'basic_string<char>')}}
+
+static Mover<std::string> bad; // expected-note {{instantiation of 'Mover<std::basic_string<char> >' requested here}}
+static Mover<HasString> bad_mem; // expected-note {{instantiation of 'Mover<HasString>' requested here}}
+static Mover<std::arbitrary_name> assumed_bad; // expected-note {{instantiation of 'Mover<std::arbitrary_name>' requested here}}
+static Mover<std::pair<bool, int>> good;
+static Mover<std::pair<bool, std::string>> not_good; // expected-note {{instantiation of 'Mover<std::pair<bool, std::basic_string<char> > >' requested here}}
diff --git a/src/third_party/mozjs-45/build/clang-plugin/tests/TestNonTemporaryClass.cpp b/src/third_party/mozjs-45/build/clang-plugin/tests/TestNonTemporaryClass.cpp
new file mode 100644
index 0000000..08b5e9a
--- /dev/null
+++ b/src/third_party/mozjs-45/build/clang-plugin/tests/TestNonTemporaryClass.cpp
@@ -0,0 +1,70 @@
+#define MOZ_NON_TEMPORARY_CLASS __attribute__((annotate("moz_non_temporary_class")))
+#define MOZ_IMPLICIT __attribute__((annotate("moz_implicit")))
+
+#include <stddef.h>
+
+struct MOZ_NON_TEMPORARY_CLASS NonTemporary {
+  int i;
+  NonTemporary() {}
+  MOZ_IMPLICIT NonTemporary(int i) {}
+  NonTemporary(int i, int j) {}
+  void *operator new(size_t x) throw() { return 0; }
+  void *operator new(size_t blah, char *buffer) { return buffer; }
+};
+
+template <class T>
+struct MOZ_NON_TEMPORARY_CLASS TemplateClass {
+  T i;
+};
+
+void gobble(void *) { }
+
+void gobbleref(const NonTemporary&) { }
+
+template <class T>
+void gobbleanyref(const T&) { }
+
+void misuseNonTemporaryClass(int len) {
+  NonTemporary invalid;
+  NonTemporary alsoInvalid[2];
+  static NonTemporary invalidStatic;
+  static NonTemporary alsoInvalidStatic[2];
+
+  gobble(&invalid);
+  gobble(&invalidStatic);
+  gobble(&alsoInvalid[0]);
+
+  gobbleref(NonTemporary()); // expected-error {{variable of type 'NonTemporary' is not valid in a temporary}} expected-note {{value incorrectly allocated in a temporary}}
+  gobbleref(NonTemporary(10, 20)); // expected-error {{variable of type 'NonTemporary' is not valid in a temporary}} expected-note {{value incorrectly allocated in a temporary}}
+  gobbleref(NonTemporary(10)); // expected-error {{variable of type 'NonTemporary' is not valid in a temporary}} expected-note {{value incorrectly allocated in a temporary}}
+  gobbleref(10); // expected-error {{variable of type 'NonTemporary' is not valid in a temporary}} expected-note {{value incorrectly allocated in a temporary}}
+  gobbleanyref(TemplateClass<int>()); // expected-error {{variable of type 'TemplateClass<int>' is not valid in a temporary}} expected-note {{value incorrectly allocated in a temporary}}
+
+  gobble(new NonTemporary);
+  gobble(new NonTemporary[10]);
+  gobble(new TemplateClass<int>);
+  gobble(len <= 5 ? &invalid : new NonTemporary);
+
+  char buffer[sizeof(NonTemporary)];
+  gobble(new (buffer) NonTemporary);
+}
+
+void defaultArg(const NonTemporary& arg = NonTemporary()) {
+}
+
+NonTemporary invalidStatic;
+struct RandomClass {
+  NonTemporary nonstaticMember; // expected-note {{'RandomClass' is a non-temporary type because member 'nonstaticMember' is a non-temporary type 'NonTemporary'}}
+  static NonTemporary staticMember;
+};
+struct MOZ_NON_TEMPORARY_CLASS RandomNonTemporaryClass {
+  NonTemporary nonstaticMember;
+  static NonTemporary staticMember;
+};
+
+struct BadInherit : NonTemporary {}; // expected-note {{'BadInherit' is a non-temporary type because it inherits from a non-temporary type 'NonTemporary'}}
+
+void useStuffWrongly() {
+  gobbleanyref(BadInherit()); // expected-error {{variable of type 'BadInherit' is not valid in a temporary}} expected-note {{value incorrectly allocated in a temporary}}
+  gobbleanyref(RandomClass()); // expected-error {{variable of type 'RandomClass' is not valid in a temporary}} expected-note {{value incorrectly allocated in a temporary}}
+}
diff --git a/src/third_party/mozjs-45/build/clang-plugin/tests/TestRefCountedCopyConstructor.cpp b/src/third_party/mozjs-45/build/clang-plugin/tests/TestRefCountedCopyConstructor.cpp
new file mode 100644
index 0000000..d3bd730
--- /dev/null
+++ b/src/third_party/mozjs-45/build/clang-plugin/tests/TestRefCountedCopyConstructor.cpp
@@ -0,0 +1,25 @@
+// Implicit copy construct which is unused
+class RC1 {
+  void AddRef();
+  void Release();
+  int mRefCnt;
+};
+
+// Explicit copy constructor which is used
+class RC2 {
+public:
+  RC2();
+  RC2(const RC2&);
+private:
+  void AddRef();
+  void Release();
+  int mRefCnt;
+};
+
+void f() {
+  RC1* r1 = new RC1();
+  RC1* r1p = new RC1(*r1); // expected-error {{Invalid use of compiler-provided copy constructor on refcounted type}} expected-note {{The default copy constructor also copies the default mRefCnt property, leading to reference count imbalance issues. Please provide your own copy constructor which only copies the fields which need to be copied}}
+
+  RC2* r2 = new RC2();
+  RC2* r2p = new RC2(*r2);
+}
diff --git a/src/third_party/mozjs-45/build/clang-plugin/tests/TestStackClass.cpp b/src/third_party/mozjs-45/build/clang-plugin/tests/TestStackClass.cpp
new file mode 100644
index 0000000..41afa39
--- /dev/null
+++ b/src/third_party/mozjs-45/build/clang-plugin/tests/TestStackClass.cpp
@@ -0,0 +1,50 @@
+#define MOZ_STACK_CLASS __attribute__((annotate("moz_stack_class")))
+#include <stddef.h>
+
+struct MOZ_STACK_CLASS Stack {
+  int i;
+  void *operator new(size_t x) throw() { return 0; }
+  void *operator new(size_t blah, char *buffer) { return buffer; }
+};
+
+template <class T>
+struct MOZ_STACK_CLASS TemplateClass {
+  T i;
+};
+
+void gobble(void *) { }
+
+void misuseStackClass(int len) {
+  Stack valid;
+  Stack alsoValid[2];
+  static Stack notValid; // expected-error {{variable of type 'Stack' only valid on the stack}} expected-note {{value incorrectly allocated in a global variable}}
+  static Stack alsoNotValid[2]; // expected-error {{variable of type 'Stack [2]' only valid on the stack}} expected-note {{'Stack [2]' is a stack type because it is an array of stack type 'Stack'}} expected-note {{value incorrectly allocated in a global variable}}
+
+  gobble(&valid);
+  gobble(&notValid);
+  gobble(&alsoValid[0]);
+
+  gobble(new Stack); // expected-error {{variable of type 'Stack' only valid on the stack}} expected-note {{value incorrectly allocated on the heap}}
+  gobble(new Stack[10]); // expected-error {{variable of type 'Stack' only valid on the stack}} expected-note {{value incorrectly allocated on the heap}}
+  gobble(new TemplateClass<int>); // expected-error {{variable of type 'TemplateClass<int>' only valid on the stack}} expected-note {{value incorrectly allocated on the heap}}
+  gobble(len <= 5 ? &valid : new Stack); // expected-error {{variable of type 'Stack' only valid on the stack}} expected-note {{value incorrectly allocated on the heap}}
+
+  char buffer[sizeof(Stack)];
+  gobble(new (buffer) Stack);
+}
+
+Stack notValid; // expected-error {{variable of type 'Stack' only valid on the stack}} expected-note {{value incorrectly allocated in a global variable}}
+struct RandomClass {
+  Stack nonstaticMember; // expected-note {{'RandomClass' is a stack type because member 'nonstaticMember' is a stack type 'Stack'}}
+  static Stack staticMember; // expected-error {{variable of type 'Stack' only valid on the stack}} expected-note {{value incorrectly allocated in a global variable}}
+};
+struct MOZ_STACK_CLASS RandomStackClass {
+  Stack nonstaticMember;
+  static Stack staticMember; // expected-error {{variable of type 'Stack' only valid on the stack}} expected-note {{value incorrectly allocated in a global variable}}
+};
+
+struct BadInherit : Stack {}; // expected-note {{'BadInherit' is a stack type because it inherits from a stack type 'Stack'}}
+struct MOZ_STACK_CLASS GoodInherit : Stack {};
+
+BadInherit moreInvalid; // expected-error {{variable of type 'BadInherit' only valid on the stack}} expected-note {{value incorrectly allocated in a global variable}}
+RandomClass evenMoreInvalid; // expected-error {{variable of type 'RandomClass' only valid on the stack}} expected-note {{value incorrectly allocated in a global variable}}
diff --git a/src/third_party/mozjs-45/build/clang-plugin/tests/TestTrivialCtorDtor.cpp b/src/third_party/mozjs-45/build/clang-plugin/tests/TestTrivialCtorDtor.cpp
new file mode 100644
index 0000000..81604c1
--- /dev/null
+++ b/src/third_party/mozjs-45/build/clang-plugin/tests/TestTrivialCtorDtor.cpp
@@ -0,0 +1,58 @@
+#define MOZ_TRIVIAL_CTOR_DTOR __attribute__((annotate("moz_trivial_ctor_dtor")))
+
+struct MOZ_TRIVIAL_CTOR_DTOR EmptyClass{};
+
+template <class T>
+struct MOZ_TRIVIAL_CTOR_DTOR TemplateEmptyClass{};
+
+struct MOZ_TRIVIAL_CTOR_DTOR BadUserDefinedCtor { // expected-error {{class 'BadUserDefinedCtor' must have trivial constructors and destructors}}
+  BadUserDefinedCtor() {}
+};
+
+struct MOZ_TRIVIAL_CTOR_DTOR BadUserDefinedDtor { // expected-error {{class 'BadUserDefinedDtor' must have trivial constructors and destructors}}
+  ~BadUserDefinedDtor() {}
+};
+
+struct MOZ_TRIVIAL_CTOR_DTOR BadVirtualDtor { // expected-error {{class 'BadVirtualDtor' must have trivial constructors and destructors}}
+  virtual ~BadVirtualDtor() {}
+};
+
+struct MOZ_TRIVIAL_CTOR_DTOR BadVirtualMember { // expected-error {{class 'BadVirtualMember' must have trivial constructors and destructors}}
+  virtual void f();
+};
+
+void foo();
+struct MOZ_TRIVIAL_CTOR_DTOR BadNonEmptyCtorDtor { // expected-error {{class 'BadNonEmptyCtorDtor' must have trivial constructors and destructors}}
+  BadNonEmptyCtorDtor() { foo(); }
+  ~BadNonEmptyCtorDtor() { foo(); }
+};
+
+struct NonTrivialCtor {
+  NonTrivialCtor() { foo(); }
+};
+
+struct NonTrivialDtor {
+  ~NonTrivialDtor() { foo(); }
+};
+
+struct VirtualMember {
+  virtual void f();
+};
+
+struct MOZ_TRIVIAL_CTOR_DTOR BadNonTrivialCtorInBase : NonTrivialCtor { // expected-error {{class 'BadNonTrivialCtorInBase' must have trivial constructors and destructors}}
+};
+
+struct MOZ_TRIVIAL_CTOR_DTOR BadNonTrivialDtorInBase : NonTrivialDtor { // expected-error {{class 'BadNonTrivialDtorInBase' must have trivial constructors and destructors}}
+};
+
+struct MOZ_TRIVIAL_CTOR_DTOR BadNonTrivialCtorInMember { // expected-error {{class 'BadNonTrivialCtorInMember' must have trivial constructors and destructors}}
+  NonTrivialCtor m;
+};
+
+struct MOZ_TRIVIAL_CTOR_DTOR BadNonTrivialDtorInMember { // expected-error {{class 'BadNonTrivialDtorInMember' must have trivial constructors and destructors}}
+  NonTrivialDtor m;
+};
+
+struct MOZ_TRIVIAL_CTOR_DTOR BadVirtualMemberInMember { // expected-error {{class 'BadVirtualMemberInMember' must have trivial constructors and destructors}}
+  VirtualMember m;
+};
diff --git a/src/third_party/mozjs-45/build/clang-plugin/tests/moz.build b/src/third_party/mozjs-45/build/clang-plugin/tests/moz.build
new file mode 100644
index 0000000..b5e5d3d
--- /dev/null
+++ b/src/third_party/mozjs-45/build/clang-plugin/tests/moz.build
@@ -0,0 +1,36 @@
+# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+SOURCES += [
+    'TestBadImplicitConversionCtor.cpp',
+    'TestCustomHeap.cpp',
+    'TestExplicitOperatorBool.cpp',
+    'TestGlobalClass.cpp',
+    'TestHeapClass.cpp',
+    'TestInheritTypeAnnotationsFromTemplateArgs.cpp',
+    'TestMultipleAnnotations.cpp',
+    'TestMustOverride.cpp',
+    'TestMustUse.cpp',
+    'TestNANTestingExpr.cpp',
+    'TestNANTestingExprC.c',
+    'TestNeedsNoVTableType.cpp',
+    'TestNoAddRefReleaseOnReturn.cpp',
+    'TestNoArithmeticExprInArgument.cpp',
+    'TestNoAutoType.cpp',
+    'TestNoDuplicateRefCntMember.cpp',
+    'TestNoExplicitMoveConstructor.cpp',
+    'TestNonHeapClass.cpp',
+    'TestNonMemMovable.cpp',
+    'TestNonMemMovableStd.cpp',
+    'TestNonTemporaryClass.cpp',
+    'TestNoRefcountedInsideLambdas.cpp',
+    'TestRefCountedCopyConstructor.cpp',
+    'TestStackClass.cpp',
+    'TestTrivialCtorDtor.cpp',
+]
+
+DISABLE_STL_WRAPPING = True
+NO_VISIBILITY_FLAGS = True
diff --git a/src/third_party/mozjs-45/build/compare-mozconfig/compare-mozconfigs-wrapper.py b/src/third_party/mozjs-45/build/compare-mozconfig/compare-mozconfigs-wrapper.py
new file mode 100644
index 0000000..b0b8560
--- /dev/null
+++ b/src/third_party/mozjs-45/build/compare-mozconfig/compare-mozconfigs-wrapper.py
@@ -0,0 +1,63 @@
+#!/usr/bin/python
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+from __future__ import unicode_literals
+
+import subprocess
+import sys
+from os import path
+from buildconfig import substs
+
+import logging
+log = logging.getLogger(__name__)
+
+def determine_platform():
+    platform_mapping = {'WINNT': {'x86_64': 'win64',
+                                  'i686': 'win32'},
+                        'Darwin': {'x86_64': 'macosx-universal',
+                                   'i386':'macosx-universal'},
+                        'Linux': {'x86_64': 'linux64',
+                                  'i686': 'linux32'}}
+
+    os_type = substs['OS_TARGET']
+    cpu_type = substs['TARGET_CPU']
+    return platform_mapping.get(os_type, {}).get(cpu_type, None)
+
+def main():
+    """ A wrapper script that calls compare-mozconfig.py
+    based on the platform that the machine is building for"""
+    platform = determine_platform()
+
+    if platform is not None:
+        python_exe = substs['PYTHON']
+        topsrcdir = substs['top_srcdir']
+
+        # construct paths and args for compare-mozconfig
+        browser_dir = path.join(topsrcdir, 'browser')
+        script_path = path.join(topsrcdir, 'build/compare-mozconfig/compare-mozconfigs.py')
+        whitelist_path = path.join(browser_dir, 'config/mozconfigs/whitelist')
+        beta_mozconfig_path = path.join(browser_dir, 'config/mozconfigs', platform, 'beta')
+        release_mozconfig_path = path.join(browser_dir, 'config/mozconfigs', platform, 'release')
+        nightly_mozconfig_path = path.join(browser_dir, 'config/mozconfigs', platform, 'nightly')
+
+        log.info("Comparing beta against nightly mozconfigs")
+        ret_code = subprocess.call([python_exe, script_path, '--whitelist',
+                                    whitelist_path, '--no-download',
+                                    platform + ',' + beta_mozconfig_path +
+                                    ',' + nightly_mozconfig_path])
+
+        if ret_code > 0:
+            return ret_code
+
+        log.info("Comparing release against nightly mozconfigs")
+        ret_code = subprocess.call([python_exe, script_path, '--whitelist',
+                                    whitelist_path, '--no-download',
+                                    platform + ',' + release_mozconfig_path +
+                                    ',' + nightly_mozconfig_path])
+
+        return ret_code
+
+if __name__ == '__main__':
+    sys.exit(main())
diff --git a/src/third_party/mozjs-45/build/compare-mozconfig/compare-mozconfigs.py b/src/third_party/mozjs-45/build/compare-mozconfig/compare-mozconfigs.py
new file mode 100644
index 0000000..876e336
--- /dev/null
+++ b/src/third_party/mozjs-45/build/compare-mozconfig/compare-mozconfigs.py
@@ -0,0 +1,170 @@
+#!/usr/bin/python
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# originally from http://hg.mozilla.org/build/tools/file/4ab9c1a4e05b/scripts/release/compare-mozconfigs.py
+
+from __future__ import unicode_literals
+
+import logging
+import os
+import site
+import sys
+import urllib2
+import difflib
+
+FAILURE_CODE = 1
+SUCCESS_CODE = 0
+
+log = logging.getLogger(__name__)
+
+class ConfigError(Exception):
+    pass
+
+def make_hg_url(hgHost, repoPath, protocol='https', revision=None,
+                filename=None):
+    """construct a valid hg url from a base hg url (hg.mozilla.org),
+    repoPath, revision and possible filename"""
+    base = '%s://%s' % (protocol, hgHost)
+    repo = '/'.join(p.strip('/') for p in [base, repoPath])
+    if not filename:
+        if not revision:
+            return repo
+        else:
+            return '/'.join([p.strip('/') for p in [repo, 'rev', revision]])
+    else:
+        assert revision
+        return '/'.join([p.strip('/') for p in [repo, 'raw-file', revision,
+                         filename]])
+
+def readConfig(configfile, keys=[], required=[]):
+    c = {}
+    execfile(configfile, c)
+    for k in keys:
+        c = c[k]
+    items = c.keys()
+    err = False
+    for key in required:
+        if key not in items:
+            err = True
+            log.error("Required item `%s' missing from %s" % (key, c))
+    if err:
+        raise ConfigError("Missing at least one item in config, see above")
+    return c
+
+def verify_mozconfigs(mozconfig_pair, nightly_mozconfig_pair, platform,
+                      mozconfigWhitelist={}):
+    """Compares mozconfig to nightly_mozconfig and compare to an optional
+    whitelist of known differences. mozconfig_pair and nightly_mozconfig_pair
+    are pairs containing the mozconfig's identifier and the list of lines in
+    the mozconfig."""
+
+    # unpack the pairs to get the names, the names are just for
+    # identifying the mozconfigs when logging the error messages
+    mozconfig_name, mozconfig_lines = mozconfig_pair
+    nightly_mozconfig_name, nightly_mozconfig_lines = nightly_mozconfig_pair
+
+    missing_args = mozconfig_lines == [] or nightly_mozconfig_lines == []
+    if missing_args:
+        log.info("Missing mozconfigs to compare for %s" % platform)
+        return False
+
+    success = True
+
+    diff_instance = difflib.Differ()
+    diff_result = diff_instance.compare(mozconfig_lines, nightly_mozconfig_lines)
+    diff_list = list(diff_result)
+
+    for line in diff_list:
+        clean_line = line[1:].strip()
+        if (line[0] == '-' or line[0] == '+') and len(clean_line) > 1:
+            # skip comment lines
+            if clean_line.startswith('#'):
+                continue
+            # compare to whitelist
+            message = ""
+            if line[0] == '-':
+                # handle lines that move around in diff
+                if '+' + line[1:] in diff_list:
+                    continue
+                if platform in mozconfigWhitelist.get('release', {}):
+                    if clean_line in \
+                            mozconfigWhitelist['release'][platform]:
+                        continue
+            elif line[0] == '+':
+                if '-' + line[1:] in diff_list:
+                    continue
+                if platform in mozconfigWhitelist.get('nightly', {}):
+                    if clean_line in \
+                            mozconfigWhitelist['nightly'][platform]:
+                        continue
+                    else:
+                        log.warning("%s not in %s %s!" % (
+                            clean_line, platform,
+                            mozconfigWhitelist['nightly'][platform]))
+            else:
+                log.error("Skipping line %s!" % line)
+                continue
+            message = "found in %s but not in %s: %s"
+            if line[0] == '-':
+                log.error(message % (mozconfig_name,
+                                     nightly_mozconfig_name, clean_line))
+            else:
+                log.error(message % (nightly_mozconfig_name,
+                                     mozconfig_name, clean_line))
+            success = False
+    return success
+
+def get_mozconfig(path, options):
+    """Consumes a path and returns a list of lines from
+    the mozconfig file. If download is required, the path
+    specified should be relative to the root of the hg
+    repository e.g browser/config/mozconfigs/linux32/nightly"""
+    if options.no_download:
+        return open(path, 'r').readlines()
+    else:
+        url = make_hg_url(options.hghost, options.branch, 'http',
+                    options.revision, path)
+        return urllib2.urlopen(url).readlines()
+
+if __name__ == '__main__':
+    from optparse import OptionParser
+    parser = OptionParser()
+
+    parser.add_option('--branch', dest='branch')
+    parser.add_option('--revision', dest='revision')
+    parser.add_option('--hghost', dest='hghost', default='hg.mozilla.org')
+    parser.add_option('--whitelist', dest='whitelist')
+    parser.add_option('--no-download', action='store_true', dest='no_download',
+                      default=False)
+    options, args = parser.parse_args()
+
+    logging.basicConfig(level=logging.INFO)
+
+    missing_args = options.branch is None or options.revision is None
+    if not options.no_download and missing_args:
+        logging.error('Not enough arguments to download mozconfigs')
+        sys.exit(FAILURE_CODE)
+
+    mozconfig_whitelist = readConfig(options.whitelist, ['whitelist'])
+
+    for arg in args:
+        platform, mozconfig_path, nightly_mozconfig_path = arg.split(',')
+
+        mozconfig_lines = get_mozconfig(mozconfig_path, options)
+        nightly_mozconfig_lines = get_mozconfig(nightly_mozconfig_path, options)
+
+        mozconfig_pair = (mozconfig_path, mozconfig_lines)
+        nightly_mozconfig_pair = (nightly_mozconfig_path,
+                                  nightly_mozconfig_lines)
+
+        passed = verify_mozconfigs(mozconfig_pair, nightly_mozconfig_pair,
+                                   platform, mozconfig_whitelist)
+
+        if passed:
+            logging.info('Mozconfig check passed!')
+        else:
+            logging.error('Mozconfig check failed!')
+            sys.exit(FAILURE_CODE)
+    sys.exit(SUCCESS_CODE)
diff --git a/src/third_party/mozjs-45/build/defines.sh b/src/third_party/mozjs-45/build/defines.sh
new file mode 100644
index 0000000..cf98c3d
--- /dev/null
+++ b/src/third_party/mozjs-45/build/defines.sh
@@ -0,0 +1,3 @@
+# Define indicating that this build is prior to one of the early betas. To be
+# unset mid-way through the beta cycle.
+EARLY_BETA_OR_EARLIER=
diff --git a/src/third_party/mozjs-45/build/docs/androideclipse.rst b/src/third_party/mozjs-45/build/docs/androideclipse.rst
new file mode 100644
index 0000000..a8c0481
--- /dev/null
+++ b/src/third_party/mozjs-45/build/docs/androideclipse.rst
@@ -0,0 +1,90 @@
+.. _build_androideclipse:
+
+========================
+Android Eclipse Projects
+========================
+
+The build system contains alpha support for generating Android Eclipse
+project files to aid with development.
+
+To generate Android Eclipse project files, you'll need to have a fully
+built and packaged tree::
+
+   mach build && mach package
+
+(This is because Eclipse itself packages an APK containing
+``omni.ja``, and ``omni.ja`` is only assembled during packaging.)
+
+Then, simply generate the Android Eclipse build backend::
+
+   mach build-backend -b AndroidEclipse
+
+If all goes well, the path to the generated projects should be
+printed (currently, ``$OBJDIR/android_eclipse``).
+
+To use the generated Android Eclipse project files, you'll need to
+have a recent version of Eclipse (see `Tested Versions`_) with the
+`Eclipse ADT plugin
+<http://developer.android.com/tools/sdk/eclipse-adt.html>`_
+installed. You can then import all the projects into Eclipse using
+*File > Import ... > General > Existing Projects into Workspace*.
+
+Updating Project Files
+======================
+
+As you pull and update the source tree, your Android Eclipse files may
+fall out of sync with the build configuration. The tree should still
+build fine from within Eclipse, but source files may be missing and in
+rare circumstances Eclipse's index may not have the proper build
+configuration.
+
+To account for this, you'll want to periodically regenerate the
+Android Eclipse project files. You can do this by running ``mach build
+&& mach package && mach build-backend -b AndroidEclipse`` from the
+command line. It's a good idea to refresh and clean build all projects
+in Eclipse after doing this.
+
+In future, we'd like to include an Android Eclipse run configuration
+or build target that integrates updating the project files.
+
+Currently, regeneration rewrites the original project files. **If
+you've made any customizations to the projects, they will likely get
+overwritten.** We would like to improve this user experience in the
+future.
+
+Troubleshooting
+===============
+
+If Eclipse's builder gets confused, you should always refresh and
+clean build all projects. If Eclipse's builder is continually
+confused, you can see a log of what is happening at
+``$OBJDIR/android_eclipse/build.log``.
+
+If you run into memory problems executing ``dex``, you should
+`Increase Eclipse's memory limits <http://stackoverflow.com/a/11093228>`_.
+
+The produced Android Eclipse project files are unfortunately not
+portable. Please don't move them around.
+
+Structure of Android Eclipse projects
+=====================================
+
+The Android Eclipse backend generates several projects spanning Fennec
+itself and its tests. You'll mostly interact with the *Fennec* project
+itself.
+
+In future, we'd like to expand this documentation to include some of
+the technical details of how the Eclipse integration works, and how to
+add additional Android Eclipse projects using the ``moz.build``
+system.
+
+Tested Versions
+===============
+
+===============    ====================================    =================
+OS                 Version                                 Working as of
+===============    ====================================    =================
+Mac OS X           Luna (Build id: 20130919-0819)          February 2014
+Mac OS X           Kepler (Build id: 20131219-0014)        February 2014
+Mac OS X 10.8.5    Kepler (Build id: 20130919-0819)        February 2014
+===============    ====================================    =================
diff --git a/src/third_party/mozjs-45/build/docs/build-overview.rst b/src/third_party/mozjs-45/build/docs/build-overview.rst
new file mode 100644
index 0000000..a81531b
--- /dev/null
+++ b/src/third_party/mozjs-45/build/docs/build-overview.rst
@@ -0,0 +1,117 @@
+.. _build_overview:
+
+=====================
+Build System Overview
+=====================
+
+This document provides an overview on how the build system works. It is
+targeted at people wanting to learn about internals of the build system.
+It is not meant for persons who casually interact with the build system.
+That being said, knowledge empowers, so consider reading on.
+
+The build system is composed of many different components working in
+harmony to build the source tree. We begin with a graphic overview.
+
+.. graphviz::
+
+   digraph build_components {
+      rankdir="LR";
+      "configure" -> "config.status" -> "build backend" -> "build output"
+   }
+
+Phase 1: Configuration
+======================
+
+Phase 1 centers around the ``configure`` script, which is a bash shell script.
+The file is generated from a file called ``configure.in`` which is written in M4
+and processed using Autoconf 2.13 to create the final configure script.
+You don't have to worry about how you obtain a ``configure`` file: the build
+system does this for you.
+
+The primary job of ``configure`` is to determine characteristics of the system
+and compiler, apply options passed into it, and validate everything looks OK to
+build. The primary output of the ``configure`` script is an executable file
+in the object directory called ``config.status``. ``configure`` also produces
+some additional files (like ``autoconf.mk``). However, the most important file
+in terms of architecture is ``config.status``.
+
+The existence of a ``config.status`` file may be familiar to those who have worked
+with Autoconf before. However, Mozilla's ``config.status`` is different from almost
+any other ``config.status`` you've ever seen: it's written in Python! Instead of
+having our ``configure`` script produce a shell script, we have it generating
+Python.
+
+Now is as good a time as any to mention that Python is prevalent in our build
+system. If we need to write code for the build system, we do it in Python.
+That's just how we roll. For more, see :ref:`python`.
+
+``config.status`` contains 2 parts: data structures representing the output of
+``configure`` and a command-line interface for preparing/configuring/generating
+an appropriate build backend. (A build backend is merely a tool used to build
+the tree - like GNU Make or Tup). These data structures essentially describe
+the current state of the system and what the existing build configuration looks
+like. For example, it defines which compiler to use, how to invoke it, which
+application features are enabled, etc. You are encouraged to open up
+``config.status`` to have a look for yourself!
+
+Once we have emitted a ``config.status`` file, we pass into the realm of
+phase 2.
+
+Phase 2: Build Backend Preparation and the Build Definition
+===========================================================
+
+Once ``configure`` has determined what the current build configuration is,
+we need to apply this to the source tree so we can actually build.
+
+What essentially happens is the automatically-produced ``config.status`` Python
+script is executed as soon as ``configure`` has generated it. ``config.status``
+is charged with the task of tell a tool how to build the tree. To do this,
+``config.status`` must first scan the build system definition.
+
+The build system definition consists of various ``moz.build`` files in the tree.
+There is roughly one ``moz.build`` file per directory or per set of related directories.
+Each ``moz.build`` files defines how its part of the build config works. For
+example it says *I want these C++ files compiled* or *look for additional
+information in these directories.* config.status starts with the ``moz.build``
+file from the root directory and then descends into referenced ``moz.build``
+files by following ``DIRS`` variables or similar.
+
+As the ``moz.build`` files are read, data structures describing the overall
+build system definition are emitted. These data structures are then fed into a
+build backend, which then performs actions, such as writing out files to
+be read by a build tool. e.g. a ``make`` backend will write a
+``Makefile``.
+
+When ``config.status`` runs, you'll see the following output::
+
+   Reticulating splines...
+   Finished reading 1096 moz.build files into 1276 descriptors in 2.40s
+   Backend executed in 2.39s
+   2188 total backend files. 0 created; 1 updated; 2187 unchanged
+   Total wall time: 5.03s; CPU time: 3.79s; Efficiency: 75%
+
+What this is saying is that a total of *1096* ``moz.build`` files were read.
+Altogether, *1276* data structures describing the build configuration were
+derived from them.  It took *2.40s* wall time to just read these files and
+produce the data structures.  The *1276* data structures were fed into the
+build backend which then determined it had to manage *2188* files derived
+from those data structures. Most of them already existed and didn't need
+changed. However, *1* was updated as a result of the new configuration.
+The whole process took *5.03s*. Although, only *3.79s* was in
+CPU time. That likely means we spent roughly *25%* of the time waiting on
+I/O.
+
+For more on how ``moz.build`` files work, see :ref:`mozbuild-files`.
+
+Phase 3: Invokation of the Build Backend
+========================================
+
+When most people think of the build system, they think of phase 3. This is
+where we take all the code in the tree and produce Firefox or whatever
+application you are creating. Phase 3 effectively takes whatever was
+generated by phase 2 and runs it. Since the dawn of Mozilla, this has been
+make consuming Makefiles. However, with the transition to moz.build files,
+you may soon see non-Make build backends, such as Tup or Visual Studio.
+
+When building the tree, most of the time is spent in phase 3. This is when
+header files are installed, C++ files are compiled, files are preprocessed, etc.
diff --git a/src/third_party/mozjs-45/build/docs/build-targets.rst b/src/third_party/mozjs-45/build/docs/build-targets.rst
new file mode 100644
index 0000000..dacd46c
--- /dev/null
+++ b/src/third_party/mozjs-45/build/docs/build-targets.rst
@@ -0,0 +1,62 @@
+.. _build_targets:
+
+=============
+Build Targets
+=============
+
+When you build with ``mach build``, there are some special targets that can be
+built. This page attempts to document them.
+
+Partial Tree Targets
+====================
+
+The targets in this section only build part of the tree. Please note that
+partial tree builds can be unreliable. Use at your own risk.
+
+export
+   Build the *export* tier. The *export* tier builds everything that is
+   required for C/C++ compilation. It stages all header files, processes
+   IDLs, etc.
+
+compile
+   Build the *compile* tier. The *compile* tier compiles all C/C++ files.
+
+libs
+   Build the *libs* tier. The *libs* tier performs linking and performs
+   most build steps which aren't related to compilation.
+
+tools
+   Build the *tools* tier. The *tools* tier mostly deals with supplementary
+   tools and compiled tests. It will link tools against libXUL, including
+   compiled test binaries.
+
+binaries:
+   Recompiles and relinks C/C++ files. Only works after a complete normal
+   build, but allows for much faster rebuilds of C/C++ code. For performance
+   reasons, however, it skips nss, nspr, icu and ffi. This is targeted to
+   improve local developer workflow when touching C/C++ code.
+
+install-manifests
+   Process install manifests. Install manifests handle the installation of
+   files into the object directory.
+
+   Unless ``NO_REMOVE=1`` is defined in the environment, files not accounted
+   in the install manifests will be deleted from the object directory.
+
+install-tests
+   Processes the tests install manifest.
+
+Common Actions
+==============
+
+The targets in this section correspond to common build-related actions. Many
+of the actions in this section are effectively frontends to shell scripts.
+These actions will likely all be replaced by mach commands someday.
+
+buildsymbols
+   Create a symbols archive for the current build.
+
+   This must be performed after a successful build.
+
+check
+   Run build system tests.
diff --git a/src/third_party/mozjs-45/build/docs/cppeclipse.rst b/src/third_party/mozjs-45/build/docs/cppeclipse.rst
new file mode 100644
index 0000000..4492add
--- /dev/null
+++ b/src/third_party/mozjs-45/build/docs/cppeclipse.rst
@@ -0,0 +1,54 @@
+.. _build_cppeclipse:
+
+=====================
+Cpp Eclipse Projects
+=====================
+
+For additional information on using Eclipse CDT see
+`the MDN page
+<https://developer.mozilla.org/en-US/docs/Eclipse_CDT>`_.
+
+The build system contains alpha support for generating C++ Eclipse
+project files to aid with development.
+
+Please report bugs to bugzilla and make them depend on bug 973770.
+
+To generate a C++ Eclipse project files, you'll need to have a fully
+built tree::
+
+   mach build
+
+Then, simply generate the Android Eclipse build backend::
+
+   mach build-backend -b CppEclipse
+
+If all goes well, the path to the generated workspace should be
+printed (currently, ``$OBJDIR/android_eclipse``).
+
+To use the generated Android Eclipse project files, you'll need to
+have a Eclipse CDT 8.3 (We plan to follow the latest Eclipse release)
+`Eclipse CDT plugin
+<https://www.eclipse.org/cdt/>`_
+installed. You can then import all the projects into Eclipse using
+*File > Import ... > General > Existing Projects into Workspace*
+-only- if you have not ran the background indexer.
+
+Updating Project Files
+======================
+
+As you pull and update the source tree, your C++ Eclipse files may
+fall out of sync with the build configuration. The tree should still
+build fine from within Eclipse, but source files may be missing and in
+rare circumstances Eclipse's index may not have the proper build
+configuration.
+
+To account for this, you'll want to periodically regenerate the
+Android Eclipse project files. You can do this by running ``mach build
+&& mach build-backend -b CppEclipse`` from the
+command line.
+
+Currently, regeneration rewrites the original project files. **If
+you've made any customizations to the projects, they will likely get
+overwritten.** We would like to improve this user experience in the
+future.
+
diff --git a/src/third_party/mozjs-45/build/docs/defining-binaries.rst b/src/third_party/mozjs-45/build/docs/defining-binaries.rst
new file mode 100644
index 0000000..97dadbb
--- /dev/null
+++ b/src/third_party/mozjs-45/build/docs/defining-binaries.rst
@@ -0,0 +1,351 @@
+.. _defining_binaries:
+
+======================================
+Defining Binaries for the Build System
+======================================
+
+One part of what the build system does is compile C/C++ and link the resulting
+objects to produce executables and/or libraries. This document describes the
+basics of defining what is going to be built and how. All the following
+describes constructs to use in moz.build files.
+
+
+Source files
+============
+
+Source files to be used in a given directory are registered in the ``SOURCES``
+and ``UNIFIED_SOURCES`` variables. ``UNIFIED_SOURCES`` have a special behavior
+in that they are aggregated by batches of 16, requiring, for example, that there
+are no conflicting variables in those source files.
+
+``SOURCES`` and ``UNIFIED_SOURCES`` are lists which must be appended to, and
+each append requires the given list to be alphanumerically ordered.
+
+.. code-block:: python
+
+   UNIFIED_SOURCES += [
+       'FirstSource.cpp',
+       'SecondSource.cpp',
+       'ThirdSource.cpp',
+   ]
+
+   SOURCES += [
+       'OtherSource.cpp',
+   ]
+
+``SOURCES`` and ``UNIFIED_SOURCES`` can contain a mix of different file types,
+for C, C++, and Objective C.
+
+
+Static Libraries
+================
+
+To build a static library, other than defining the source files (see above), one
+just needs to define a library name with the ``Library`` template.
+
+.. code-block:: python
+
+   Library('foo')
+
+The library file name will be ``libfoo.a`` on UNIX systems and ``foo.lib`` on
+Windows.
+
+If the static library needs to aggregate other static libraries, a list of
+``Library`` names can be added to the ``USE_LIBS`` variable. Like ``SOURCES``, it
+requires the appended list to be alphanumerically ordered.
+
+.. code-block:: python
+
+   USE_LIBS += ['bar', 'baz']
+
+If there are multiple directories containing the same ``Library`` name, it is
+possible to disambiguate by prefixing with the path to the wanted one (relative
+or absolute):
+
+.. code-block:: python
+
+   USE_LIBS += [
+       '/path/from/topsrcdir/to/bar',
+       '../relative/baz',
+   ]
+
+Note that the leaf name in those paths is the ``Library`` name, not an actual
+file name.
+
+Note that currently, the build system may not create an actual library for
+static libraries. It is an implementation detail that shouldn't need to be
+worried about.
+
+As a special rule, ``USE_LIBS`` is allowed to contain references to shared
+libraries. In such cases, programs and shared libraries linking this static
+library will inherit those shared library dependencies.
+
+
+Intermediate (Static) Libraries
+===============================
+
+In many cases in the tree, static libraries are built with the only purpose
+of being linked into another, bigger one (like libxul). Instead of adding all
+required libraries to ``USE_LIBS`` for the bigger one, it is possible to tell
+the build system that the library built in the current directory is meant to
+be linked to that bigger library, with the ``FINAL_LIBRARY`` variable.
+
+.. code-block:: python
+
+   FINAL_LIBRARY = 'xul'
+
+The ``FINAL_LIBRARY`` value must match a unique ``Library`` name somewhere
+in the tree.
+
+As a special rule, those intermediate libraries don't need a ``Library`` name
+for themselves.
+
+
+Shared Libraries
+================
+
+Sometimes, we want shared libraries, a.k.a. dynamic libraries. Such libraries
+are defined similarly to static libraries, using the ``SharedLibrary`` template
+instead of ``Library``.
+
+.. code-block:: python
+
+   SharedLibrary('foo')
+
+When this template is used, no static library is built. See further below to
+build both types of libraries.
+
+With a ``SharedLibrary`` name of ``foo``, the library file name will be
+``libfoo.dylib`` on OSX, ``libfoo.so`` on ELF systems (Linux, etc.), and
+``foo.dll`` on Windows. On Windows, there is also an import library named
+``foo.lib``, used on the linker command line. ``libfoo.dylib`` and
+``libfoo.so`` are considered the import library name for, resp. OSX and ELF
+systems.
+
+On OSX, one may want to create a special kind of dynamic library: frameworks.
+This is done with the ``Framework`` template.
+
+.. code-block:: python
+
+   Framework('foo')
+
+With a ``Framework`` name of ``foo``, the framework file name will be ``foo``.
+This template however affects the behavior on all platforms, so it needs to
+be set only on OSX.
+
+
+Executables
+===========
+
+Executables, a.k.a. programs, are, in the simplest form, defined with the
+``Program`` template.
+
+.. code-block:: python
+
+   Program('foobar')
+
+On UNIX systems, the executable file name will be ``foobar``, while on Windows,
+it will be ``foobar.exe``.
+
+Like static and shared libraries, the build system can be instructed to link
+libraries to the executable with ``USE_LIBS``, listing various ``Library``
+names.
+
+In some cases, we want to create an executable per source file in the current
+directory, in which case we can use the ``SimplePrograms`` template
+
+.. code-block:: python
+
+   SimplePrograms([
+       'FirstProgram',
+       'SecondProgram',
+   ])
+
+Contrary to ``Program``, which requires corresponding ``SOURCES``, when using
+``SimplePrograms``, the corresponding ``SOURCES`` are implied. If the
+corresponding ``sources`` have an extension different from ``.cpp``, it is
+possible to specify the proper extension:
+
+.. code-block:: python
+
+   SimplePrograms([
+       'ThirdProgram',
+       'FourthProgram',
+   ], ext='.c')
+
+Please note this construct was added for compatibility with what already lives
+in the mozilla tree ; it is recommended not to add new simple programs with
+sources with a different extension than ``.cpp``.
+
+Similar to ``SimplePrograms``, is the ``CppUnitTests`` template, which defines,
+with the same rules, C++ unit tests programs. Like ``SimplePrograms``, it takes
+an ``ext`` argument to specify the extension for the corresponding ``SOURCES``,
+if it's different from ``.cpp``.
+
+
+Linking with system libraries
+=============================
+
+Programs and libraries usually need to link with system libraries, such as a
+widget toolkit, etc. Those required dependencies can be given with the
+``OS_LIBS`` variable.
+
+.. code-block:: python
+
+   OS_LIBS += [
+       'foo',
+       'bar',
+   ]
+
+This expands to ``foo.lib bar.lib`` when building with MSVC, and
+``-lfoo -lbar`` otherwise.
+
+For convenience with ``pkg-config``, ``OS_LIBS`` can also take linker flags
+such as ``-L/some/path`` and ``-llib``, such that it is possible to directly
+assign ``LIBS`` variables from ``CONFIG``, such as:
+
+.. code-block:: python
+
+   OS_LIBS += CONFIG['MOZ_PANGO_LIBS']
+
+(assuming ``CONFIG['MOZ_PANGO_LIBS']`` is a list, not a string)
+
+Like ``USE_LIBS``, this variable applies to static and shared libraries, as
+well as programs.
+
+
+Libraries from third party build system
+=======================================
+
+Some libraries in the tree are not built by the moz.build-governed build
+system, and there is no ``Library`` corresponding to them.
+
+However, ``USE_LIBS`` allows to reference such libraries by giving a full
+path (like when disambiguating identical ``Library`` names). The same naming
+rules apply as other uses of ``USE_LIBS``, so only the library name without
+prefix and suffix shall be given.
+
+.. code-block:: python
+
+   USE_LIBS += [
+       '/path/from/topsrcdir/to/third-party/bar',
+       '../relative/third-party/baz',
+   ]
+
+Note that ``/path/from/topsrcdir/to/third-party`` and
+``../relative/third-party/baz`` must lead under a subconfigured directory (a
+directory with an AC_OUTPUT_SUBDIRS in configure.in), or ``security/nss``.
+
+
+Building both static and shared libraries
+=========================================
+
+When both types of libraries are required, one needs to set both
+``FORCE_SHARED_LIB`` and ``FORCE_STATIC_LIB`` boolean variables.
+
+.. code-block:: python
+
+   FORCE_SHARED_LIB = True
+   FORCE_STATIC_LIB = True
+
+But because static libraries and Windows import libraries have the same file
+names, either the static or the shared library name needs to be different
+than the name given to the ``Library`` template.
+
+The ``STATIC_LIBRARY_NAME`` and ``SHARED_LIBRARY_NAME`` variables can be used
+to change either the static or the shared library name.
+
+.. code-block:: python
+
+  Library('foo')
+  STATIC_LIBRARY_NAME = 'foo_s'
+
+With the above, on Windows, ``foo_s.lib`` will be the static library,
+``foo.dll`` the shared library, and ``foo.lib`` the import library.
+
+In some cases, for convenience, it is possible to set both
+``STATIC_LIBRARY_NAME`` and ``SHARED_LIBRARY_NAME``. For example:
+
+.. code-block:: python
+
+  Library('mylib')
+  STATIC_LIBRARY_NAME = 'mylib_s'
+  SHARED_LIBRARY_NAME = CONFIG['SHARED_NAME']
+
+This allows to use ``mylib`` in the ``USE_LIBS`` of another library or
+executable.
+
+When refering to a ``Library`` name building both types of libraries in
+``USE_LIBS``, the shared library is chosen to be linked. But sometimes,
+it is wanted to link the static version, in which case the ``Library`` name
+needs to be prefixed with ``static:`` in ``USE_LIBS``
+
+::
+
+   a/moz.build:
+      Library('mylib')
+      FORCE_SHARED_LIB = True
+      FORCE_STATIC_LIB = True
+      STATIC_LIBRARY_NAME = 'mylib_s'
+   b/moz.build:
+      Program('myprog')
+      USE_LIBS += [
+          'static:mylib',
+      ]
+
+
+Miscellaneous
+=============
+
+The ``SDK_LIBRARY`` boolean variable defines whether the library in the current
+directory is going to be installed in the SDK.
+
+The ``SONAME`` variable declares a "shared object name" for the library. It
+defaults to the ``Library`` name or the ``SHARED_LIBRARY_NAME`` if set. When
+linking to a library with a ``SONAME``, the resulting library or program will
+have a dependency on the library with the name corresponding to the ``SONAME``
+instead of the ``Library`` name. This only impacts ELF systems.
+
+::
+
+   a/moz.build:
+      Library('mylib')
+   b/moz.build:
+      Library('otherlib')
+      SONAME = 'foo'
+   c/moz.build:
+      Program('myprog')
+      USE_LIBS += [
+          'mylib',
+          'otherlib',
+      ]
+
+On e.g. Linux, the above ``myprog`` will have DT_NEEDED markers for
+``libmylib.so`` and ``libfoo.so`` instead of ``libmylib.so`` and
+``libotherlib.so`` if there weren't a ``SONAME``. This means the runtime
+requirement for ``myprog`` is ``libfoo.so`` instead of ``libotherlib.so``.
+
+
+Gecko-related binaries
+======================
+
+Some programs or libraries are totally independent of Gecko, and can use the
+above mentioned templates. Others are Gecko-related in some way, and may
+need XPCOM linkage, mozglue. These things are tedious. A set of additional
+templates exists to ease defining such programs and libraries. They are
+essentially the same as the above mentioned templates, prefixed with "Gecko":
+
+  - ``GeckoProgram``
+  - ``GeckoSimplePrograms``
+  - ``GeckoCppUnitTests``
+  - ``GeckoSharedLibrary``
+  - ``GeckoFramework``
+
+There is also ``XPCOMBinaryComponent`` for XPCOM components, which is a
+special kind of library.
+
+All the Gecko-prefixed templates take the same arguments as their
+non-Gecko-prefixed counterparts, and can take a few more arguments
+for non-standard cases. See the definition of ``GeckoBinary`` in
+build/gecko_templates.mozbuild for more details, but most usecases
+should not require these additional arguments.
diff --git a/src/third_party/mozjs-45/build/docs/environment-variables.rst b/src/third_party/mozjs-45/build/docs/environment-variables.rst
new file mode 100644
index 0000000..c463391
--- /dev/null
+++ b/src/third_party/mozjs-45/build/docs/environment-variables.rst
@@ -0,0 +1,31 @@
+.. _environment_variables:
+
+================================================
+Environment Variables Impacting the Build System
+================================================
+
+Various environment variables have an impact on the behavior of the
+build system. This document attempts to document them.
+
+AUTOCLOBBER
+   If defines, the build system will automatically clobber as needed.
+   The default behavior is to print a message and error out when a
+   clobber is needed.
+
+   This variable is typically defined in a :ref:`mozconfig <mozconfig>`
+   file via ``mk_add_options``.
+
+REBUILD_CHECK
+   If defined, the build system will print information about why
+   certain files were rebuilt.
+
+   This feature is disabled by default because it makes the build slower.
+
+MACH_NO_TERMINAL_FOOTER
+   If defined, the terminal footer displayed when building with mach in
+   a TTY is disabled.
+
+MACH_NO_WRITE_TIMES
+   If defined, mach commands will not prefix output lines with the
+   elapsed time since program start. This option is equivalent to
+   passing ``--log-no-times`` to mach.
diff --git a/src/third_party/mozjs-45/build/docs/files-metadata.rst b/src/third_party/mozjs-45/build/docs/files-metadata.rst
new file mode 100644
index 0000000..5af4d96
--- /dev/null
+++ b/src/third_party/mozjs-45/build/docs/files-metadata.rst
@@ -0,0 +1,178 @@
+.. _mozbuild_files_metadata:
+
+==============
+Files Metadata
+==============
+
+:ref:`mozbuild-files` provide a mechanism for attaching metadata to
+files. Essentially, you define some flags to set on a file or file
+pattern. Later, some tool or process queries for metadata attached to a
+file of interest and it does something intelligent with that data.
+
+Defining Metadata
+=================
+
+Files metadata is defined by using the
+:ref:`Files Sub-Context <mozbuild_subcontext_Files>` in ``moz.build``
+files. e.g.::
+
+    with Files('**/Makefile.in'):
+        BUG_COMPONENT = ('Core', 'Build Config')
+
+This working example says, *for all Makefile.in files in every directory
+underneath this one - including this directory - set the Bugzilla
+component to Core :: Build Config*.
+
+For more info, read the
+:ref:`docs on Files <mozbuild_subcontext_Files>`.
+
+How Metadata is Read
+====================
+
+``Files`` metadata is extracted in :ref:`mozbuild_fs_reading_mode`.
+
+Reading starts by specifying a set of files whose metadata you are
+interested in. For each file, the filesystem is walked to the root
+of the source directory. Any ``moz.build`` encountered during this
+walking are marked as relevant to the file.
+
+Let's say you have the following filesystem content::
+
+   /moz.build
+   /root_file
+   /dir1/moz.build
+   /dir1/foo
+   /dir1/subdir1/foo
+   /dir2/foo
+
+For ``/root_file``, the relevant ``moz.build`` files are just
+``/moz.build``.
+
+For ``/dir1/foo`` and ``/dir1/subdir1/foo``, the relevant files are
+``/moz.build`` and ``/dir1/moz.build``.
+
+For ``/dir2``, the relevant file is just ``/moz.build``.
+
+Once the list of relevant ``moz.build`` files is obtained, each
+``moz.build`` file is evaluated. Root ``moz.build`` file first,
+leaf-most files last. This follows the rules of
+:ref:`mozbuild_fs_reading_mode`, with the set of evaluated ``moz.build``
+files being controlled by filesystem content, not ``DIRS`` variables.
+
+The file whose metadata is being resolved maps to a set of ``moz.build``
+files which in turn evaluates to a list of contexts. For file metadata,
+we only care about one of these contexts:
+:ref:`Files <mozbuild_subcontext_Files>`.
+
+We start with an empty ``Files`` instance to represent the file. As
+we encounter a *files sub-context*, we see if it is appropriate to
+this file. If it is, we apply its values. This process is repeated
+until all *files sub-contexts* have been applied or skipped. The final
+state of the ``Files`` instance is used to represent the metadata for
+this particular file.
+
+It may help to visualize this. Say we have 2 ``moz.build`` files::
+
+    # /moz.build
+    with Files('*.cpp'):
+        BUG_COMPONENT = ('Core', 'XPCOM')
+
+    with Files('**/*.js'):
+        BUG_COMPONENT = ('Firefox', 'General')
+
+    # /foo/moz.build
+    with Files('*.js'):
+        BUG_COMPONENT = ('Another', 'Component')
+
+Querying for metadata for the file ``/foo/test.js`` will reveal 3
+relevant ``Files`` sub-contexts. They are evaluated as follows:
+
+1. ``/moz.build - Files('*.cpp')``. Does ``/*.cpp`` match
+   ``/foo/test.js``? **No**. Ignore this context.
+2. ``/moz.build - Files('**/*.js')``. Does ``/**/*.js`` match
+   ``/foo/test.js``? **Yes**. Apply ``BUG_COMPONENT = ('Firefox', 'General')``
+   to us.
+3. ``/foo/moz.build - Files('*.js')``. Does ``/foo/*.js`` match
+   ``/foo/test.js``? **Yes**. Apply
+   ``BUG_COMPONENT = ('Another', 'Component')``.
+
+At the end of execution, we have
+``BUG_COMPONENT = ('Another', 'Component')`` as the metadata for
+``/foo/test.js``.
+
+One way to look at file metadata is as a stack of data structures.
+Each ``Files`` sub-context relevant to a given file is applied on top
+of the previous state, starting from an empty state. The final state
+wins.
+
+.. _mozbuild_files_metadata_finalizing:
+
+Finalizing Values
+=================
+
+The default behavior of ``Files`` sub-context evaluation is to apply new
+values on top of old. In most circumstances, this results in desired
+behavior. However, there are circumstances where this may not be
+desired. There is thus a mechanism to *finalize* or *freeze* values.
+
+Finalizing values is useful for scenarios where you want to prevent
+wildcard matches from overwriting previously-set values. This is useful
+for one-off files.
+
+Let's take ``Makefile.in`` files as an example. The build system module
+policy dictates that ``Makefile.in`` files are part of the ``Build
+Config`` module and should be reviewed by peers of that module. However,
+there exist ``Makefile.in`` files in many directories in the source
+tree. Without finalization, a ``*`` or ``**`` wildcard matching rule
+would match ``Makefile.in`` files and overwrite their metadata.
+
+Finalizing of values is performed by setting the ``FINAL`` variable
+on ``Files`` sub-contexts. See the
+:ref:`Files documentation <mozbuild_subcontext_Files>` for more.
+
+Here is an example with ``Makefile.in`` files, showing how it is
+possible to finalize the ``BUG_COMPONENT`` value.::
+
+    # /moz.build
+    with Files('**/Makefile.in'):
+        BUG_COMPONENT = ('Core', 'Build Config')
+        FINAL = True
+
+    # /foo/moz.build
+    with Files('**'):
+        BUG_COMPONENT = ('Another', 'Component')
+
+If we query for metadata of ``/foo/Makefile.in``, both ``Files``
+sub-contexts match the file pattern. However, since ``BUG_COMPONENT`` is
+marked as finalized by ``/moz.build``, the assignment from
+``/foo/moz.build`` is ignored. The final value for ``BUG_COMPONENT``
+is ``('Core', 'Build Config')``.
+
+Here is another example::
+
+    with Files('*.cpp'):
+        BUG_COMPONENT = ('One-Off', 'For C++')
+        FINAL = True
+
+    with Files('**'):
+        BUG_COMPONENT = ('Regular', 'Component')
+
+For every files except ``foo.cpp``, the bug component will be resolved
+as ``Regular :: Component``. However, ``foo.cpp`` has its value of
+``One-Off :: For C++`` preserved because it is finalized.
+
+.. important::
+
+   ``FINAL`` only applied to variables defined in a context.
+
+   If you want to mark one variable as finalized but want to leave
+   another mutable, you'll need to use 2 ``Files`` contexts.
+
+Guidelines for Defining Metadata
+================================
+
+In general, values defined towards the root of the source tree are
+generic and become more specific towards the leaves. For example,
+the ``BUG_COMPONENT`` for ``/browser`` might be ``Firefox :: General``
+whereas ``/browser/components/preferences`` would list
+``Firefox :: Preferences``.
diff --git a/src/third_party/mozjs-45/build/docs/glossary.rst b/src/third_party/mozjs-45/build/docs/glossary.rst
new file mode 100644
index 0000000..f846eff
--- /dev/null
+++ b/src/third_party/mozjs-45/build/docs/glossary.rst
@@ -0,0 +1,48 @@
+========
+Glossary
+========
+
+.. glossary::
+   :sorted:
+
+   object directory
+       A directory holding the output of the build system. The build
+       system attempts to isolate all file modifications to this
+       directory. By convention, object directories are commonly
+       directories under the source directory prefixed with **obj-**.
+       e.g. **obj-firefox**.
+
+   mozconfig
+       A shell script used to configure the build system.
+
+   configure
+       A generated shell script which detects the current system
+       environment, applies a requested set of build configuration
+       options, and writes out metadata to be consumed by the build
+       system.
+
+   config.status
+       An executable file produced by **configure** that takes the
+       generated build config and writes out files used to build the
+       tree. Traditionally, config.status writes out a bunch of
+       Makefiles.
+
+   install manifest
+       A file containing metadata describing file installation rules.
+       A large part of the build system consists of copying files
+       around to appropriate places. We write out special files
+       describing the set of required operations so we can process the
+       actions effeciently. These files are install manifests.
+
+   clobber build
+      A build performed with an initially empty object directory. All
+      build actions must be performed.
+
+   incremental build
+      A build performed with the result of a previous build in an
+      object directory. The build should not have to work as hard because
+      it will be able to reuse the work from previous builds.
+
+   mozinfo
+      An API for accessing a common and limited subset of the build and
+      run-time configuration. See :ref:`mozinfo`.
diff --git a/src/third_party/mozjs-45/build/docs/index.rst b/src/third_party/mozjs-45/build/docs/index.rst
new file mode 100644
index 0000000..eef0094
--- /dev/null
+++ b/src/third_party/mozjs-45/build/docs/index.rst
@@ -0,0 +1,47 @@
+============
+Build System
+============
+
+Important Concepts
+==================
+.. toctree::
+   :maxdepth: 1
+
+   glossary
+   build-overview
+   supported-configurations
+   Mozconfig Files <mozconfigs>
+   mozbuild-files
+   mozbuild-symbols
+   files-metadata
+   Profile Guided Optimization <pgo>
+   slow
+   environment-variables
+   build-targets
+   python
+   test_manifests
+   mozinfo
+   preprocessor
+   jar-manifests
+   defining-binaries
+
+integrated development environment (IDE)
+========================================
+.. toctree::
+   :maxdepth: 1
+
+   androideclipse
+   cppeclipse
+   visualstudio
+
+mozbuild
+========
+
+mozbuild is a Python package containing a lot of the code for the
+Mozilla build system.
+
+.. toctree::
+   :maxdepth: 1
+
+   mozbuild/index
+   mozbuild/dumbmake
diff --git a/src/third_party/mozjs-45/build/docs/jar-manifests.rst b/src/third_party/mozjs-45/build/docs/jar-manifests.rst
new file mode 100644
index 0000000..5ee656a
--- /dev/null
+++ b/src/third_party/mozjs-45/build/docs/jar-manifests.rst
@@ -0,0 +1,104 @@
+.. _jar_manifests:
+
+=============
+JAR Manifests
+=============
+
+JAR Manifests are plaintext files in the tree that are used to package chrome
+files into the correct JARs, and create
+`Chrome Registration <https://developer.mozilla.org/en-US/docs/Chrome_Registration>`_
+manifests. JAR Manifests are commonly named ``jar.mn``. They are
+declared in ``moz.build`` files using the ``JAR_MANIFESTS`` variable.
+
+``jar.mn`` files are automatically processed by the build system when building a
+source directory that contains one. The ``jar``.mn is run through the
+:ref:`preprocessor` before being passed to the manifest processor. In order to
+have ``@variables@`` expanded (such as ``@AB_CD@``) throughout the file, add
+the line ``#filter substitution`` at the top of your ``jar.mn`` file.
+
+The format of a jar.mn is fairly simple; it consists of a heading specifying
+which JAR file is being packaged, followed by indented lines listing files and
+chrome registration instructions.
+
+To see a simple ``jar.mn`` file at work, see ``toolkit/profile/jar.mn``. A much
+more complex ``jar.mn`` is at ``toolkit/locales/jar.mn``.
+
+Shipping Chrome Files
+=====================
+
+To ship chrome files in a JAR, an indented line indicates a file to be packaged::
+
+   <jarfile>.jar:
+     path/in/jar/file_name.xul     (source/tree/location/file_name.xul)
+
+The JAR location may be preceded with a base path between square brackets::
+   [base/path] <jarfile>.jar:
+     path/in/jar/file_name.xul     (source/tree/location/file_name.xul)
+
+In this case, the jar will be directly located under the given ``base/bath``,
+while without a base path, it will be under a ``chrome`` directory.
+
+If the JAR manifest and packaged file live in the same directory, the path and
+parenthesis can be omitted. In other words, the following two lines are
+equivalent::
+
+   path/in/jar/same_place.xhtml     (same_place.xhtml)
+   path/in/jar/same_place.xhtml
+
+The source tree location may also be an *absolute* path (taken from the
+top of the source tree::
+
+   path/in/jar/file_name.xul     (/path/in/sourcetree/file_name.xul)
+
+An asterisk marker (``*``) at the beginning of the line indicates that the
+file should be processed by the :ref:`preprocessor` before being packaged::
+
+   * path/in/jar/preprocessed.xul  (source/tree/location/file_name.xul)
+
+A plus marker (``+``) at the beginning of the line indicates that the file
+should replace an existing file, even if the source file's timestamp isn't
+newer than the existing file::
+
+   + path/in/jar/file_name.xul     (source/tree/location/my_file_name.xul)
+
+Preprocessed files always replace existing files, to ensure that changes in
+``#expand`` or ``#include`` directives are picked up, so ``+`` and ``*`` are
+equivalent.
+
+There is a special source-directory format for localized files (note the
+percent sign in the source file location): this format reads ``localized.dtd``
+from the ``en-US`` directory if building an English version, and reads the
+file from the alternate localization source tree
+``/l10n/<locale>/path/localized.dtd`` if building a localized version::
+
+   locale/path/localized.dtd     (%localized/path/localized.dtd)
+
+The source tree location can also use wildcards, in which case the path in
+jar is expected to be a base directory. Paths before the wildcard are not
+made part of the destination path::
+
+     path/in/jar/                (source/tree/location/*.xul)
+
+The above will install all xul files under ``source/tree/location`` as
+``path/in/jar/*.xul``.
+
+Register Chrome
+===============
+
+`Chrome Registration <https://developer.mozilla.org/en-US/docs/Chrome_Registration>`_
+instructions are marked with a percent sign (``%``) at the beginning of the
+line, and must be part of the definition of a JAR file. Any additional percents
+signs are replaced with an appropriate relative URL of the JAR file being
+packaged::
+
+   % content global %path/in/jar/
+   % overlay chrome://blah/content/blah.xul chrome://foo/content/overlay.xul
+
+There are two possible locations for a manifest file. If the chrome is being
+built into a standalone application, the ``jar.mn`` processor creates a
+``<jarfilename>.manifest`` next to the JAR file itself. This is the default
+behavior.
+
+If the build specifies ``USE_EXTENSION_MANIFEST = 1``, the ``jar.mn`` processor
+creates a single ``chrome.manifest`` file suitable for registering chrome as
+an extension.
diff --git a/src/third_party/mozjs-45/build/docs/mozbuild-files.rst b/src/third_party/mozjs-45/build/docs/mozbuild-files.rst
new file mode 100644
index 0000000..3550c51
--- /dev/null
+++ b/src/third_party/mozjs-45/build/docs/mozbuild-files.rst
@@ -0,0 +1,176 @@
+.. _mozbuild-files:
+
+===============
+moz.build Files
+===============
+
+``moz.build`` files are the mechanism by which tree metadata (notably
+the build configuration) is defined.
+
+Directories in the tree contain ``moz.build`` files which declare
+functionality for their respective part of the tree. This includes
+things such as the list of C++ files to compile, where to find tests,
+etc.
+
+``moz.build`` files are actually Python scripts. However, their
+execution is governed by special rules. This is explained below.
+
+moz.build Python Sandbox
+========================
+
+As mentioned above, ``moz.build`` files are Python scripts. However,
+they are executed in a special Python *sandbox* that significantly
+changes and limits the execution environment. The environment is so
+different, it's doubtful most ``moz.build`` files would execute without
+error if executed by a vanilla Python interpreter (e.g. ``python
+moz.build``.
+
+The following properties make execution of ``moz.build`` files special:
+
+1. The execution environment exposes a limited subset of Python.
+2. There is a special set of global symbols and an enforced naming
+   convention of symbols.
+3. Some symbols are inherited from previously-executed ``moz.build``
+   files.
+
+The limited subset of Python is actually an extremely limited subset.
+Only a few symbols from ``__builtins__`` are exposed. These include
+``True``, ``False``, and ``None``. Global functions like ``import``,
+``print``, and ``open`` aren't available. Without these, ``moz.build``
+files can do very little. *This is by design*.
+
+The execution sandbox treats all ``UPPERCASE`` variables specially. Any
+``UPPERCASE`` variable must be known to the sandbox before the script
+executes. Any attempt to read or write to an unknown ``UPPERCASE``
+variable will result in an exception being raised. Furthermore, the
+types of all ``UPPERCASE`` variables is strictly enforced. Attempts to
+assign an incompatible type to an ``UPPERCASE`` variable will result in
+an exception being raised.
+
+The strictness of behavior with ``UPPERCASE`` variables is a very
+intentional design decision. By ensuring strict behavior, any operation
+involving an ``UPPERCASE`` variable is guaranteed to have well-defined
+side-effects. Previously, when the build configuration was defined in
+``Makefiles``, assignments to variables that did nothing would go
+unnoticed. ``moz.build`` files fix this problem by eliminating the
+potential for false promises.
+
+After a ``moz.build`` file has completed execution, only the
+``UPPERCASE`` variables are used to retrieve state.
+
+The set of variables and functions available to the Python sandbox is
+defined by the :py:mod:`mozbuild.frontend.context` module. The
+data structures in this module are consumed by the
+:py:class:`mozbuild.frontend.reader.MozbuildSandbox` class to construct
+the sandbox. There are tests to ensure that the set of symbols exposed
+to an empty sandbox are all defined in the ``context`` module.
+This module also contains documentation for each symbol, so nothing can
+sneak into the sandbox without being explicitly defined and documented.
+
+Reading and Traversing moz.build Files
+======================================
+
+The process for reading ``moz.build`` files roughly consists of:
+
+1. Start at the root ``moz.build`` (``<topsrcdir>/moz.build``).
+2. Evaluate the ``moz.build`` file in a new sandbox.
+3. Emit the main *context* and any *sub-contexts* from the executed
+   sandbox.
+4. Extract a set of ``moz.build`` files to execute next.
+5. For each additional ``moz.build`` file, goto #2 and repeat until all
+   referenced files have executed.
+
+From the perspective of the consumer, the output of reading is a stream
+of :py:class:`mozbuild.frontend.reader.context.Context` instances. Each
+``Context`` defines a particular aspect of data. Consumers iterate over
+these objects and do something with the data inside. Each object is
+essentially a dictionary of all the ``UPPERCASE`` variables populated
+during its execution.
+
+.. note::
+
+   Historically, there was only one ``context`` per ``moz.build`` file.
+   As the number of things tracked by ``moz.build`` files grew and more
+   and more complex processing was desired, it was necessary to split these
+   contexts into multiple logical parts. It is now common to emit
+   multiple contexts per ``moz.build`` file.
+
+Build System Reading Mode
+-------------------------
+
+The traditional mode of evaluation of ``moz.build`` files is what's
+called *build system traversal mode.* In this mode, the ``CONFIG``
+variable in each ``moz.build`` sandbox is populated from data coming
+from ``config.status``, which is produced by ``configure``.
+
+During evaluation, ``moz.build`` files often make decisions conditional
+on the state of the build configuration. e.g. *only compile foo.cpp if
+feature X is enabled*.
+
+In this mode, traversal of ``moz.build`` files is governed by variables
+like ``DIRS`` and ``TEST_DIRS``. For example, to execute a child
+directory, ``foo``, you would add ``DIRS += ['foo']`` to a ``moz.build``
+file and ``foo/moz.build`` would be evaluated.
+
+.. _mozbuild_fs_reading_mode:
+
+Filesystem Reading Mode
+-----------------------
+
+There is an alternative reading mode that doesn't involve the build
+system and doesn't use ``DIRS`` variables to control traversal into
+child directories. This mode is called *filesystem reading mode*.
+
+In this reading mode, the ``CONFIG`` variable is a dummy, mostly empty
+object. Accessing all but a few special variables will return an empty
+value. This means that nearly all ``if CONFIG['FOO']:`` branches will
+not be taken.
+
+Instead of using content from within the evaluated ``moz.build``
+file to drive traversal into subsequent ``moz.build`` files, the set
+of files to evaluate is controlled by the thing doing the reading.
+
+A single ``moz.build`` file is not guaranteed to be executable in
+isolation. Instead, we must evaluate all *parent* ``moz.build`` files
+first. For example, in order to evaluate ``/foo/moz.build``, one must
+execute ``/moz.build`` and have its state influence the execution of
+``/foo/moz.build``.
+
+Filesystem reading mode is utilized to power the
+:ref:`mozbuild_files_metadata` feature.
+
+Technical Details
+-----------------
+
+The code for reading ``moz.build`` files lives in
+:py:mod:`mozbuild.frontend.reader`. The Python sandboxes evaluation results
+(:py:class:`mozbuild.frontend.context.Context`) are passed into
+:py:mod:`mozbuild.frontend.emitter`, which converts them to classes defined
+in :py:mod:`mozbuild.frontend.data`. Each class in this module defines a
+domain-specific component of tree metdata. e.g. there will be separate
+classes that represent a JavaScript file vs a compiled C++ file or test
+manifests. This means downstream consumers of this data can filter on class
+types to only consume what they are interested in.
+
+There is no well-defined mapping between ``moz.build`` file instances
+and the number of :py:mod:`mozbuild.frontend.data` classes derived from
+each. Depending on the content of the ``moz.build`` file, there may be 1
+object derived or 100.
+
+The purpose of the ``emitter`` layer between low-level sandbox execution
+and metadata representation is to facilitate a unified normalization and
+verification step. There are multiple downstream consumers of the
+``moz.build``-derived data and many will perform the same actions. This
+logic can be complicated, so we have a component dedicated to it.
+
+:py:class:`mozbuild.frontend.reader.BuildReader`` and
+:py:class:`mozbuild.frontend.reader.TreeMetadataEmitter`` have a
+stream-based API courtesy of generators. When you hook them up properly,
+the :py:mod:`mozbuild.frontend.data` classes are emitted before all
+``moz.build`` files have been read. This means that downstream errors
+are raised soon after sandbox execution.
+
+Lots of the code for evaluating Python sandboxes is applicable to
+non-Mozilla systems. In theory, it could be extracted into a standalone
+and generic package. However, until there is a need, there will
+likely be some tightly coupled bits.
diff --git a/src/third_party/mozjs-45/build/docs/mozbuild-symbols.rst b/src/third_party/mozjs-45/build/docs/mozbuild-symbols.rst
new file mode 100644
index 0000000..4e9a885
--- /dev/null
+++ b/src/third_party/mozjs-45/build/docs/mozbuild-symbols.rst
@@ -0,0 +1,7 @@
+.. _mozbuild_symbols:
+
+========================
+mozbuild Sandbox Symbols
+========================
+
+.. mozbuildsymbols:: mozbuild.frontend.context
diff --git a/src/third_party/mozjs-45/build/docs/mozbuild/dumbmake.rst b/src/third_party/mozjs-45/build/docs/mozbuild/dumbmake.rst
new file mode 100644
index 0000000..7840695
--- /dev/null
+++ b/src/third_party/mozjs-45/build/docs/mozbuild/dumbmake.rst
@@ -0,0 +1,38 @@
+dumbmake
+========
+
+*dumbmake* is a simple dependency tracker for make.
+
+It turns lists of make targets into longer lists of make targets that
+include dependencies.  For example:
+
+    netwerk, package
+
+might be turned into
+
+    netwerk, netwerk/build, toolkit/library, package
+
+The dependency list is read from the plain text file
+`topsrcdir/build/dumbmake-dependencies`.  The format best described by
+example:
+
+    build_this
+        when_this_changes
+
+Interpret this to mean that `build_this` is a dependency of
+`when_this_changes`.  More formally, a line (CHILD) indented more than
+the preceding line (PARENT) means that CHILD should trigger building
+PARENT.  That is, building CHILD will trigger building first CHILD and
+then PARENT.
+
+This structure is recursive:
+
+    build_this_when_either_change
+        build_this_only_when
+            this_changes
+
+This means that `build_this_when_either_change` is a dependency of
+`build_this_only_when` and `this_changes`, and `build_this_only_when`
+is a dependency of `this_changes`.  Building `this_changes` will build
+first `this_changes`, then `build_this_only_when`, and finally
+`build_this_when_either_change`.
diff --git a/src/third_party/mozjs-45/build/docs/mozbuild/index.rst b/src/third_party/mozjs-45/build/docs/mozbuild/index.rst
new file mode 100644
index 0000000..86f3894
--- /dev/null
+++ b/src/third_party/mozjs-45/build/docs/mozbuild/index.rst
@@ -0,0 +1,41 @@
+========
+mozbuild
+========
+
+mozbuild is a Python package providing functionality used by Mozilla's
+build system.
+
+Modules Overview
+================
+
+* mozbuild.backend -- Functionality for producing and interacting with build
+  backends. A build backend is an entity that consumes build system metadata
+  (from mozbuild.frontend) and does something useful with it (typically writing
+  out files that can be used by a build tool to build the tree).
+* mozbuild.compilation -- Functionality related to compiling. This
+  includes managing compiler warnings.
+* mozbuild.frontend -- Functionality for reading build frontend files
+  (what defines the build system) and converting them to data structures
+  which are fed into build backends to produce backend configurations.
+* mozpack -- Functionality related to packaging builds.
+
+Overview
+========
+
+The build system consists of frontend files that define what to do. They
+say things like "compile X" "copy Y."
+
+The mozbuild.frontend package contains code for reading these frontend
+files and converting them to static data structures. The set of produced
+static data structures for the tree constitute the current build
+configuration.
+
+There exist entities called build backends. From a high level, build
+backends consume the build configuration and do something with it. They
+typically produce tool-specific files such as make files which can be used
+to build the tree.
+
+Piecing it all together, we have frontend files that are parsed into data
+structures. These data structures are fed into a build backend. The output
+from build backends is used by builders to build the tree.
+
diff --git a/src/third_party/mozjs-45/build/docs/mozconfigs.rst b/src/third_party/mozjs-45/build/docs/mozconfigs.rst
new file mode 100644
index 0000000..1befca9
--- /dev/null
+++ b/src/third_party/mozjs-45/build/docs/mozconfigs.rst
@@ -0,0 +1,70 @@
+.. _mozconfig:
+
+===============
+mozconfig Files
+===============
+
+mozconfig files are used to configure how a build works.
+
+mozconfig files are actually shell scripts. They are executed in a
+special context with specific variables and functions exposed to them.
+
+API
+===
+
+Functions
+---------
+
+The following special functions are available to a mozconfig script.
+
+ac_add_options
+^^^^^^^^^^^^^^
+
+This function is used to declare extra options/arguments to pass into
+configure.
+
+e.g.::
+
+    ac_add_options --disable-tests
+    ac_add_options --enable-optimize
+
+mk_add_options
+^^^^^^^^^^^^^^
+
+This function is used to inject statements into client.mk for execution.
+It is typically used to define variables, notably the object directory.
+
+e.g.::
+
+    mk_add_options AUTOCLOBBER=1
+
+ac_add_options
+^^^^^^^^^^^^^^
+
+This is a variant of ac_add_options() which only adds configure options
+for a specified application. This is only used when building multiple
+applications through client.mk. This function is typically not needed.
+
+Special mk_add_options Variables
+--------------------------------
+
+For historical reasons, the method for communicating certain
+well-defined variables is via mk_add_options(). In this section, we
+document what those special variables are.
+
+MOZ_OBJDIR
+^^^^^^^^^^
+
+This variable is used to define the :term:`object directory` for the current
+build.
+
+Finding the active mozconfig
+============================
+
+Multiple mozconfig files can exist to provide different configuration
+options for different tasks. The rules for finding the active mozconfig
+are defined in the
+:py:func:`mozbuild.mozconfig.MozconfigLoader.find_mozconfig` method:
+
+.. autoclass:: mozbuild.mozconfig.MozconfigLoader
+   :members: find_mozconfig
diff --git a/src/third_party/mozjs-45/build/docs/mozinfo.rst b/src/third_party/mozjs-45/build/docs/mozinfo.rst
new file mode 100644
index 0000000..1d09fd5
--- /dev/null
+++ b/src/third_party/mozjs-45/build/docs/mozinfo.rst
@@ -0,0 +1,162 @@
+.. _mozinfo:
+
+=======
+mozinfo
+=======
+
+``mozinfo`` is a solution for representing a subset of build
+configuration and run-time data.
+
+``mozinfo`` data is typically accessed through a ``mozinfo.json`` file
+which is written to the :term:`object directory` during build
+configuration. The code for writing this file lives in
+:py:mod:`mozbuild.mozinfo`.
+
+``mozinfo.json`` is an object/dictionary of simple string values.
+
+The attributes in ``mozinfo.json`` are used for many purposes. One use
+is to filter tests for applicability to the current build. For more on
+this, see :ref:`test_manifests`.
+
+.. _mozinfo_attributes:
+
+mozinfo.json Attributes
+=================================
+
+``mozinfo`` currently records the following attributes.
+
+appname
+   The application being built.
+
+   Value comes from ``MOZ_APP_NAME`` from ``config.status``.
+
+   Optional.
+
+asan
+   Whether address sanitization is enabled.
+
+   Values are ``true`` and ``false``.
+
+   Always defined.
+
+bin_suffix
+   The file suffix for binaries produced with this build.
+
+   Values may be an empty string, as not all platforms have a binary
+   suffix.
+
+   Always defined.
+
+bits
+   The number of bits in the CPU this build targets.
+
+   Values are typically ``32`` or ``64``.
+
+   Universal Mac builds do not have this key defined.
+
+   Unkown processor architectures (see ``processor`` below) may not have
+   this key defined.
+
+   Optional.
+
+buildapp
+   The path to the XUL application being built.
+
+   For desktop Firefox, this is ``browser``. For Fennec, it's
+   ``mobile/android``. For B2G, it's ``b2g``.
+
+crashreporter
+   Whether the crash reporter is enabled for this build.
+
+   Values are ``true`` and ``false``.
+
+   Always defined.
+
+datareporting
+   Whether data reporting (MOZ_DATA_REPORTING) is enabled for this build.
+
+   Values are ``true`` and ``false``.
+
+   Always defined.
+
+debug
+   Whether this is a debug build.
+
+   Values are ``true`` and ``false``.
+
+   Always defined.
+
+healthreport
+   Whether the Health Report feature is enabled.
+
+   Values are ``true`` and ``false``.
+
+   Always defined.
+
+mozconfig
+   The path of the :ref:`mozconfig file <mozconfig>` used to produce this build.
+
+   Optional.
+
+os
+   The operating system the build is produced for. Values for tier-1
+   supported platforms are ``linux``, ``win``, ``mac``, ``b2g``, and
+   ``android``. For other platforms, the value is the lowercase version
+   of the ``OS_TARGET`` variable from ``config.status``.
+
+   Always defined.
+
+processor
+   Information about the processor architecture this build targets.
+
+   Values come from ``TARGET_CPU``, however some massaging may be
+   performed.
+
+   If the build is a universal build on Mac (it targets both 32-bit and
+   64-bit), the value is ``universal-x86-x86_64``.
+
+   If the value starts with ``arm``, the value is ``arm``.
+
+   If the value starts with a string of the form ``i[3-9]86]``, the
+   value is ``x86``.
+
+   Always defined.
+
+release_build
+   Whether this is a release build.
+
+   Values are ``true`` and ``false``.
+
+   Always defined.
+
+tests_enabled
+   Whether tests are enabled for this build.
+
+   Values are ``true`` and ``false``.
+
+   Always defined.
+
+toolkit
+   The widget toolkit in case. The value comes from the
+   ``MOZ_WIDGET_TOOLKIT`` ``config.status`` variable.
+
+   Always defined.
+
+topsrcdir
+   The path to the source directory the build came from.
+
+   Always defined.
+
+wave
+   Whether Wave audio support is enabled.
+
+   Values are ``true`` and ``false``.
+
+   Always defined.
+
+webm
+   Whether WebM support is enabled.
+
+   Values are ``true`` and ``false``.
+
+   Always defined.
diff --git a/src/third_party/mozjs-45/build/docs/pgo.rst b/src/third_party/mozjs-45/build/docs/pgo.rst
new file mode 100644
index 0000000..51d03c6
--- /dev/null
+++ b/src/third_party/mozjs-45/build/docs/pgo.rst
@@ -0,0 +1,40 @@
+.. _pgo:
+
+===========================
+Profile Guided Optimization
+===========================
+
+:abbr:`PGO (Profile Guided Optimization)` is the process of adding
+probes to a compiled binary, running said binary, then using the
+run-time information to *recompile* the binary to (hopefully) make it
+faster.
+
+How PGO Builds Work
+===================
+
+The supported interface for invoking a PGO build is to evaluate the
+*build* target of client.mk with *MOZ_PGO* defined. e.g.::
+
+    $ make -f client.mk MOZ_PGO=1
+
+This is equivalent to::
+
+    $ make -f client.mk profiledbuild
+
+Which is roughly equivalent to:
+
+#. Perform a build with *MOZ_PROFILE_GENERATE=1* and *MOZ_PGO_INSTRUMENTED=1*
+#. Package with *MOZ_PGO_INSTRUMENTED=1*
+#. Performing a run of the instrumented binaries
+#. $ make maybe_clobber_profiledbuild
+#. Perform a build with *MOZ_PROFILE_USE=1*
+
+Differences between toolchains
+==============================
+
+There are some implementation differences depending on the compiler
+toolchain being used.
+
+The *maybe_clobber_profiledbuild* step gets its name because of a
+difference. On Windows, this step merely moves some *.pgc* files around.
+Using GCC or Clang, it is equivalent to a *make clean*.
diff --git a/src/third_party/mozjs-45/build/docs/preprocessor.rst b/src/third_party/mozjs-45/build/docs/preprocessor.rst
new file mode 100644
index 0000000..ab2d8ec
--- /dev/null
+++ b/src/third_party/mozjs-45/build/docs/preprocessor.rst
@@ -0,0 +1,244 @@
+.. _preprocessor:
+
+=================
+Text Preprocessor
+=================
+
+The build system contains a text preprocessor similar to the C preprocessor,
+meant for processing files which have no built-in preprocessor such as XUL
+and JavaScript documents. It is implemented at ``python/mozbuild/mozbuild/preprocessor.py`` and
+is typically invoked via :ref:`jar_manifests`.
+
+While used to preprocess CSS files, the directives are changed to begin with
+``%`` instead of ``#`` to avoid conflict of the id selectors.
+
+Directives
+==========
+
+Variable Definition
+-------------------
+
+define
+^^^^^^
+
+::
+
+   #define variable
+   #define variable value
+
+Defines a preprocessor variable.
+
+Note that, unlike the C preprocessor, instances of this variable later in the
+source are not automatically replaced (see #filter). If value is not supplied,
+it defaults to ``1``.
+
+Note that whitespace is significant, so ``"#define foo one"`` and
+``"#define foo one "`` is different (in the second case, ``foo`` is defined to
+be a four-character string).
+
+undef
+^^^^^
+
+::
+
+   #undef variable
+
+Undefines a preprocessor variable.
+
+Conditionals
+------------
+
+if
+^^
+
+::
+
+   #if variable
+   #if !variable
+   #if variable==string
+   #if variable!=string
+
+Disables output if the conditional is false. This can be nested to arbitrary
+depths. Note that in the equality checks, the variable must come first, and
+the comparison operator must not be surrounded by any whitespace.
+
+else
+^^^^
+
+::
+
+   #else
+
+Reverses the state of the previous conditional block; for example, if the
+last ``#if`` was true (output was enabled), an ``#else`` makes it off
+(output gets disabled).
+
+.. warning:: An ``#else`` is relative to the last conditional block only,
+   unlike the C preprocessor.
+
+   It does not matter whether any blocks before it were true. This behavior
+   changed on trunk (Gecko 1.9) on 2006-12-07; see Bug 277122 for details.
+
+::
+
+   #if 1
+     always included
+   #elif 1
+     never included
+   #else
+     always included
+   #endif
+
+endif
+^^^^^
+
+::
+
+   #endif
+
+Ends the conditional block.
+
+ifdef / ifndef
+^^^^^^^^^^^^^^
+
+::
+
+   #ifdef variable
+   #ifndef variable
+
+An ``#if`` conditional that is true only if the preprocessor variable
+variable is defined (in the case of ``ifdef``) or not defined (``ifndef``).
+
+elif / elifdef / elifndef
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+::
+
+   #elif variable
+   #elif !variable
+   #elif variable == string
+   #elif variable != string
+   #elifdef variable
+   #elifndef variable
+
+A shorthand to mean an ``#else`` combined with the relevant conditional.
+The following two blocks are equivalent::
+
+   #ifdef foo
+     block 1
+   #elifdef bar
+     block 2
+   #endif
+
+::
+
+   #ifdef foo
+     block 1
+   #else
+   #ifdef bar
+     block 2
+   #endif
+   #endif
+
+.. warning:: An ``#elif``, ``#elifdef``, or ``#elifndef`` is relative to
+   the last conditional block only (as well as the condition it implies),
+   unlike the C preprocessor. It does not matter whether any blocks before
+   it were true. This behavior changed on trunk (Gecko 1.9) on 2006-12-07.
+   See Bug 277122 for details.
+
+File Inclusion
+--------------
+
+include
+^^^^^^^
+
+::
+
+   #include filename
+
+The file specified by filename is processed as if the contents was placed
+at this position. This also means that preprocessor conditionals can even
+be started in one file and ended in another (but is highly discouraged).
+There is no limit on depth of inclusion, or repeated inclusion of the same
+file, or self inclusion; thus, care should be taken to avoid infinite loops.
+
+includesubst
+^^^^^^^^^^^^
+
+::
+
+   #includesubst @variable@filename
+
+Same as a ``#include`` except that all instances of variable in the included
+file is also expanded as in ``#filter`` substitution
+
+expand
+^^^^^^
+
+::
+
+   #expand string
+
+All variables wrapped in ``__`` are replaced with their value, for this line
+only. If the variable is not defined, it expands to an empty string. For
+example, if ``foo`` has the value ``bar``, and ``baz`` is not defined, then::
+
+   #expand This <__foo__> <__baz__> gets expanded
+
+Is expanded to::
+
+   This <bar> <> gets expanded
+
+filter / unfilter
+^^^^^^^^^^^^^^^^^
+
+::
+
+   #filter filter1 filter2 ... filterN
+   #unfilter filter1 filter2 ... filterN
+
+``#filter`` turns on the given filter.
+
+Filters are run in alphabetical order on a per-line basis.
+
+``#unfilter`` turns off the given filter. Available filters are:
+
+emptyLines
+   strips blank lines from the output
+slashslash
+   strips everything from the first two consecutive slash (``/``)
+   characters until the end of the line
+spaces
+   collapses consecutive sequences of spaces into a single space,
+   and strips leading and trailing spaces
+substitution
+   all variables wrapped in @ are replaced with their value. If the
+   variable is not defined, it is a fatal error. Similar to ``#expand``
+   and ``#filter``
+attemptSubstitution
+   all variables wrapped in ``@`` are replaced with their value, or an
+   empty string if the variable is not defined. Similar to ``#expand``.
+
+literal
+^^^^^^^
+
+::
+
+   #literal string
+
+Output the string (i.e. the rest of the line) literally, with no other fixups.
+This is useful to output lines starting with ``#``, or to temporarily
+disable filters.
+
+Other
+-----
+
+#error
+^^^^^^
+
+::
+
+   #error string
+
+Cause a fatal error at this point, with the error message being the
+given string.
diff --git a/src/third_party/mozjs-45/build/docs/python.rst b/src/third_party/mozjs-45/build/docs/python.rst
new file mode 100644
index 0000000..0985417
--- /dev/null
+++ b/src/third_party/mozjs-45/build/docs/python.rst
@@ -0,0 +1,178 @@
+.. _python:
+
+===========================
+Python and the Build System
+===========================
+
+The Python programming language is used significantly in the build
+system. If we need to write code for the build system or for a tool
+related to the build system, Python is typically the first choice.
+
+Python Requirements
+===================
+
+The tree requires Python 2.7.3 or greater but not Python 3 to build.
+All Python packages not in the Python distribution are included in the
+source tree. So all you should need is a vanilla Python install and you
+should be good to go.
+
+Only CPython (the Python distribution available from www.python.org) is
+supported.
+
+We require Python 2.7.3 (and not say 2.7.2) to build because Python
+2.7.3 contains numerous bug fixes, especially around the area of Unicode
+handling. These bug fixes are extremely annoying and have to be worked
+around. The build maintainers were tired of doing this, so the minimum
+version requirement was upped (bug 870420).
+
+We intend to eventually support Python 3. This will come by way of dual
+2.7/3.x compatibility because a single flag day conversion to 3.x will
+be too cumbersome given the amount of Python that would need converted.
+We will not know which 3.x minor release we are targeting until this
+effort is underway. This is tracked in bug 636155.
+
+Compiled Python Packages
+========================
+
+There are some features of the build that rely on compiled Python packages
+(packages containing C source). These features are currently all
+optional because not every system contains the Python development
+headers required to build these extensions.
+
+We recommend you have the Python development headers installed (``mach
+bootstrap`` should do this for you) so you can take advantage of these
+features.
+
+Issues with OS X System Python
+==============================
+
+The Python that ships with OS X has historically been littered with
+subtle bugs and suboptimalities. Furthermore, OS X up through 10.8 don't
+ship with Python 2.7.3 (10.8 ships with 2.7.2).
+
+OS X 10.8 and below users will be required to install a new Python
+distribution. This may not be necessary for OS X 10.9+. However, we
+still recommend installing a separate Python because of the history with
+OS X's system Python issues.
+
+We recommend installing Python through Homebrew or MacPorts. If you run
+``mach bootstrap``, this should be done for you.
+
+Virtualenvs
+===========
+
+The build system relies heavily on
+`virtualenvs <http://www.virtualenv.org/en/latest/>`_. Virtualenvs are
+standalone and isolated Python environments. The problem a virtualenv
+solves is that of dependencies across multiple Python components. If two
+components on a system relied on different versions of a package, there
+could be a conflict. Instead of managing multiple versions of a package
+simultaneously, Python and virtualenvs take the route that it is easier
+to just keep them separate so there is no potential for conflicts.
+
+Very early in the build process, a virtualenv is created inside the
+:term:`object directory`. The virtualenv is configured such that it can
+find all the Python packages in the source tree. The code for this lives
+in :py:mod:`mozbuild.virtualenv`.
+
+Deficiencies
+------------
+
+There are numerous deficiencies with the way virtualenvs are handled in
+the build system.
+
+* mach reinvents the virtualenv.
+
+  There is code in ``build/mach_bootstrap.py`` that configures ``sys.path``
+  much the same way the virtualenv does. There are various bugs tracking
+  this. However, no clear solution has yet been devised. It's not a huge
+  problem and thus not a huge priority.
+
+* They aren't preserved across copies and packaging.
+
+  If you attempt to copy an entire tree from one machine to another or
+  from one directory to another, chances are the virtualenv will fall
+  apart. It would be nice if we could preserve it somehow. Instead of
+  actually solving portable virtualenvs, all we really need to solve is
+  encapsulating the logic for populating the virtualenv along with all
+  dependent files in the appropriate place.
+
+* .pyc files written to source directory.
+
+  We rely heavily on ``.pth`` files in our virtualenv. A ``.pth`` file
+  is a special file that contains a list of paths. Python will take the
+  set of listed paths encountered in ``.pth`` files and add them to
+  ``sys.path``.
+
+  When Python compiles a ``.py`` file to bytecode, it writes out a
+  ``.pyc`` file so it doesn't have to perform this compilation again.
+  It puts these ``.pyc`` files alongside the ``.pyc`` file. Python
+  provides very little control for determing where these ``.pyc`` files
+  go, even in Python 3 (which offers customer importers).
+
+  With ``.pth`` files pointing back to directories in the source tree
+  and not the object directory, ``.pyc`` files are created in the source
+  tree. This is bad because when Python imports a module, it first looks
+  for a ``.pyc`` file before the ``.py`` file. If there is a ``.pyc``
+  file but no ``.py`` file, it will happily import the module. This
+  wreaks havoc during file moves, refactoring, etc.
+
+  There are various proposals for fixing this. See bug 795995.
+
+Installing Python Manually
+==========================
+
+We highly recommend you use your system's package manager or a
+well-supported 3rd party package manager to install Python for you. If
+these are not available to you, we recommend the following tools for
+installing Python:
+
+* `buildout.python <https://github.com/collective/buildout.python>`_
+* `pyenv <https://github.com/yyuu/pyenv>`_
+* An official installer from http://www.python.org.
+
+If all else fails, consider compiling Python from source manually. But this
+should be viewed as the least desirable option.
+
+Common Issues with Python
+=========================
+
+Upgrading your Python distribution breaks the virtualenv
+--------------------------------------------------------
+
+If you upgrade the Python distribution (e.g. install Python 2.7.5
+from 2.7.3, chances are parts of the virtualenv will break.
+This commonly manifests as a cryptic ``Cannot import XXX`` exception.
+More often than not, the module being imported contains binary/compiled
+components.
+
+If you upgrade or reinstall your Python distribution, we recommend
+clobbering your build.
+
+Packages installed at the system level conflict with build system's
+-------------------------------------------------------------------
+
+It is common for people to install Python packages using ``sudo`` (e.g.
+``sudo pip install psutil``) or with the system's package manager
+(e.g. ``apt-get install python-mysql``.
+
+A problem with this is that packages installed at the system level may
+conflict with the package provided by the source tree. As of bug 907902
+and changeset f18eae7c3b27 (September 16, 2013), this should no longer
+be an issue since the virtualenv created as part of the build doesn't
+add the system's ``site-packages`` directory to ``sys.path``. However,
+poorly installed packages may still find a way to creep into the mix and
+interfere with our virtualenv.
+
+As a general principle, we recommend against using your system's package
+manager or using ``sudo`` to install Python packages. Instead, create
+virtualenvs and isolated Python environments for all of your Python
+projects.
+
+Python on $PATH is not appropriate
+----------------------------------
+
+Tools like ``mach`` will look for Python by performing ``/usr/bin/env
+python`` or equivalent. Please be sure the appropriate Python 2.7.3+
+path is on $PATH. On OS X, this likely means you'll need to modify your
+shell's init script to put something ahead of ``/usr/bin``.
diff --git a/src/third_party/mozjs-45/build/docs/slow.rst b/src/third_party/mozjs-45/build/docs/slow.rst
new file mode 100644
index 0000000..546fe26
--- /dev/null
+++ b/src/third_party/mozjs-45/build/docs/slow.rst
@@ -0,0 +1,179 @@
+.. _slow:
+
+============================
+Why the Build System is Slow
+============================
+
+A common complaint about the build system is that it's slow. There are
+many reasons contributing to its slowness. We will attempt to document
+them here.
+
+First, it is important to distinguish between a :term:`clobber build`
+and an :term:`incremental build`. The reasons for why each are slow can
+be different.
+
+The build does a lot of work
+============================
+
+It may not be obvious, but the main reason the build system is slow is
+because it does a lot of work! The source tree consists of a few
+thousand C++ files. On a modern machine, we spend over 120 minutes of CPU
+core time compiling files! So, if you are looking for the root cause of
+slow clobber builds, look at the sheer volume of C++ files in the tree.
+
+You don't have enough CPU cores and MHz
+=======================================
+
+The build should be CPU bound. If the build system maintainers are
+optimizing the build system perfectly, every CPU core in your machine
+should be 100% saturated during a build. While this isn't currently the
+case (keep reading below), generally speaking, the more CPU cores you
+have in your machine and the more total MHz in your machine, the better.
+
+**We highly recommend building with no fewer than 4 physical CPU
+cores.** Please note the *physical* in this sentence. Hyperthreaded
+cores (an Intel Core i7 will report 8 CPU cores but only 4 are physical
+for example) only yield at most a 1.25x speedup per core.
+
+We also recommend using the most modern CPU model possible. Haswell
+chips deliver much more performance per CPU cycle than say Sandy Bridge
+CPUs.
+
+This cause impacts both clobber and incremental builds.
+
+You are building with a slow I/O layer
+======================================
+
+The build system can be I/O bound if your I/O layer is slow. Linking
+libxul on some platforms and build architectures can perform gigabytes
+of I/O.
+
+To minimize the impact of slow I/O on build performance, **we highly
+recommend building with an SSD.** Power users with enough memory may opt
+to build from a RAM disk. Mechanical disks should be avoided if at all
+possible.
+
+Some may dispute the importance of an SSD on build times. It is true
+that the beneficial impact of an SSD can be mitigated if your system has
+lots of memory and the build files stay in the page cache. However,
+operating system memory management is complicated. You don't really have
+control over what or when something is evicted from the page cache.
+Therefore, unless your machine is a dedicated build machine or you have
+more memory than is needed by everything running on your machine,
+chances are you'll run into page cache eviction and you I/O layer will
+impact build performance. That being said, an SSD certainly doesn't
+hurt build times. And, anyone who has used a machine with an SSD will
+tell you how great of an investment it is for performance all around the
+operating system. On top of that, some automated tests are I/O bound
+(like those touching SQLite databases), so an SSD will make tests
+faster.
+
+This cause impacts both clobber and incremental builds.
+
+You don't have enough memory
+============================
+
+The build system allocates a lot of memory, especially when building
+many things in parallel. If you don't have enough free system memory,
+the build will cause swap activity, slowing down your system and the
+build. Even if you never get to the point of swapping, the build system
+performs a lot of I/O and having all accessed files in memory and the
+page cache can significantly reduce the influence of the I/O layer on
+the build system.
+
+**We recommend building with no less than 8 GB of system memory.** As
+always, the more memory you have, the better. For a bare bones machine
+doing nothing more than building the source tree, anything more than 16
+GB is likely entering the point of diminishing returns.
+
+This cause impacts both clobber and incremental builds.
+
+You are building on Windows
+===========================
+
+New processes on Windows are about a magnitude slower to spawn than on
+UNIX-y systems such as Linux. This is because Windows has optimized new
+threads while the \*NIX platforms typically optimize new processes.
+Anyway, the build system spawns thousands of new processes during a
+build. Parts of the build that rely on rapid spawning of new processes
+are slow on Windows as a result. This is most pronounced when running
+*configure*. The configure file is a giant shell script and shell
+scripts rely heavily on new processes. This is why configure on Windows
+can run over a minute slower on Windows.
+
+Another reason Windows builds are slower is because Windows lacks proper
+symlink support. On systems that support symlinks, we can generate a
+file into a staging area then symlink it into the final directory very
+quickly. On Windows, we have to perform a full file copy. This incurs
+much more I/O. And if done poorly, can muck with file modification
+times, messing up build dependencies. As of the summer of 2013, the
+impact of symlinks is being mitigated through the use
+of an :term:`install manifest`.
+
+These issues impact both clobber and incremental builds.
+
+Recursive make traversal is slow
+================================
+
+The build system has traditionally been built by employing recursive
+make. Recursive make involves make iterating through directories / make
+files sequentially and executing each in turn. This is inefficient for
+directories containing few targets/tasks because make could be *starved*
+for work when processing these directories. Any time make is starved,
+the build isn't using all available CPU cycles and the build is slower
+as a result.
+
+Work has started in bug 907365 to fix this issue by changing the way
+make traverses all the make files.
+
+The impact of slow recursive make traversal is mostly felt on
+incremental builds. Traditionally, most of the wall time during a
+no-op build is spent in make traversal.
+
+make is inefficient
+===================
+
+Compared to modern build backends like Tup or Ninja, make is slow and
+inefficient. We can only make make so fast. At some point, we'll hit a
+performance plateau and will need to use a different tool to make builds
+faster.
+
+Please note that clobber and incremental builds are different. A clobber
+build with make will likely be as fast as a clobber build with e.g. Tup.
+However, Tup should vastly outperform make when it comes to incremental
+builds. Therefore, this issue is mostly seen when performing incremental
+builds.
+
+C++ header dependency hell
+==========================
+
+Modifying a *.h* file can have significant impact on the build system.
+If you modify a *.h* that is used by 1000 C++ files, all of those 1000
+C++ files will be recompiled.
+
+Our code base has traditionally been sloppy managing the impact of
+changed headers on build performance. Bug 785103 tracks improving the
+situation.
+
+This issue mostly impacts the times of an :term:`incremental build`.
+
+A search/indexing service on your machine is running
+====================================================
+
+Many operating systems have a background service that automatically
+indexes filesystem content to make searching faster. On Windows, you
+have the Windows Search Service. On OS X, you have Finder.
+
+These background services sometimes take a keen interest in the files
+being produced as part of the build. Since the build system produces
+hundreds of megabytes or even a few gigabytes of file data, you can
+imagine how much work this is to index! If this work is being performed
+while the build is running, your build will be slower.
+
+OS X's Finder is notorious for indexing when the build is running. And,
+it has a tendency to suck up a whole CPU core. This can make builds
+several minutes slower. If you build with ``mach`` and have the optional
+``psutil`` package built (it requires Python development headers - see
+:ref:`python` for more) and Finder is running during a build, mach will
+print a warning at the end of the build, complete with instructions on
+how to fix it.
diff --git a/src/third_party/mozjs-45/build/docs/supported-configurations.rst b/src/third_party/mozjs-45/build/docs/supported-configurations.rst
new file mode 100644
index 0000000..cc2c1ea
--- /dev/null
+++ b/src/third_party/mozjs-45/build/docs/supported-configurations.rst
@@ -0,0 +1,55 @@
+.. _build_supported_configurations:
+
+========================
+Supported Configurations
+========================
+
+This page attempts to document supported build configurations.
+
+Windows
+=======
+
+We support building on Windows XP and newer operating systems using
+Visual Studio 2010 and newer.
+
+The following are not fully supported by Mozilla (but may work):
+
+* Building without the latest *MozillaBuild* Windows development
+  environment
+* Building with Mingw or any other non-Visual Studio toolchain.
+
+OS X
+====
+
+We support building on OS X 10.6 and newer with the OS X 10.6 SDK.
+
+The tree should build with the following OS X releases and SDK versions:
+
+* 10.6 Snow Leopard
+* 10.7 Lion
+* 10.8 Mountain Lion
+* 10.9 Mavericks
+
+The tree requires building with Clang 3.3 and newer. This corresponds to
+version of 4.2 of Apple's Clang that ships with Xcode. This corresponds
+to Xcode 4.6 and newer. Xcode 4.6 only runs on OS X 10.7.4 and newer.
+So, OS X 10.6 users will need to install a non-Apple toolchain. Running
+``mach bootstrap`` should install an appropriate toolchain from Homebrew
+or MacPorts automatically.
+
+The tree should build with GCC 4.4 and newer on OS X. However, this
+build configuration isn't as widely used (and differs from what Mozilla
+uses to produce OS X builds), so it's recommended to stick with Clang.
+
+Linux
+=====
+
+Linux 2.6 and later kernels are supported.
+
+Most distributions are supported as long as the proper package
+dependencies are in place. Running ``mach bootstrap`` should install
+packages for popular Linux distributions. ``configure`` will typically
+detect missing dependencies and inform you how to disable features to
+work around unsatisfied dependencies.
+
+Clang 3.3 or GCC 4.4 is required to build the tree.
diff --git a/src/third_party/mozjs-45/build/docs/test_manifests.rst b/src/third_party/mozjs-45/build/docs/test_manifests.rst
new file mode 100644
index 0000000..1655a90
--- /dev/null
+++ b/src/third_party/mozjs-45/build/docs/test_manifests.rst
@@ -0,0 +1,198 @@
+.. _test_manifests:
+
+==============
+Test Manifests
+==============
+
+Many test suites have their test metadata defined in files called
+**test manifests**.
+
+Test manifests are divided into two flavors: :ref:`manifestparser_manifests`
+and :ref:`reftest_manifests`.
+
+Naming Convention
+=================
+
+The build system does not enforce file naming for test manifest files.
+However, the following convention is used.
+
+mochitest.ini
+   For the *plain* flavor of mochitests.
+
+chrome.ini
+   For the *chrome* flavor of mochitests.
+
+browser.ini
+   For the *browser chrome* flavor of mochitests.
+
+a11y.ini
+   For the *a11y* flavor of mochitests.
+
+xpcshell.ini
+   For *xpcshell* tests.
+
+webapprt.ini
+   For the *chrome* flavor of webapp runtime mochitests.
+
+.. _manifestparser_manifests:
+
+ManifestParser Manifests
+==========================
+
+ManifestParser manifests are essentially ini files that conform to a basic
+set of assumptions.
+
+The `reference documentation <http://mozbase.readthedocs.org/en/latest/manifestparser.html>`_
+for manifestparser manifests describes the basic format of test manifests.
+
+In summary, manifests are ini files with section names describing test files::
+
+    [test_foo.js]
+    [test_bar.js]
+
+Keys under sections can hold metadata about each test::
+
+    [test_foo.js]
+    skip-if = os == "win"
+    [test_foo.js]
+    skip-if = os == "linux" && debug
+    [test_baz.js]
+    fail-if = os == "mac" || os == "android"
+
+There is a special **DEFAULT** section whose keys/metadata apply to all
+sections/tests::
+
+    [DEFAULT]
+    property = value
+
+    [test_foo.js]
+
+In the above example, **test_foo.js** inherits the metadata **property = value**
+from the **DEFAULT** section.
+
+Recognized Metadata
+-------------------
+
+Test manifests can define some common keys/metadata to influence behavior.
+Those keys are as follows:
+
+head
+   List of files that will be executed before the test file. (Used in
+   xpcshell tests.)
+
+tail
+   List of files that will be executed after the test file. (Used in
+   xpcshell tests.)
+
+support-files
+   List of additional files required to run tests. This is typically
+   defined in the **DEFAULT** section.
+
+   Unlike other file lists, *support-files* supports a globbing mechanism
+   to facilitate pulling in many files with minimal typing. This globbing
+   mechanism is activated if an entry in this value contains a ``*``
+   character. A single ``*`` will wildcard match all files in a directory.
+   A double ``**`` will descend into child directories. For example,
+   ``data/*`` will match ``data/foo`` but not ``data/subdir/bar`` where
+   ``data/**`` will match ``data/foo`` and ``data/subdir/bar``.
+
+   Support files starting with ``/`` are placed in a root directory, rather
+   than a location determined by the manifest location. For mochitests,
+   this allows for the placement of files at the server root. The source
+   file is selected from the base name (e.g., ``foo`` for ``/path/foo``).
+   Files starting with ``/`` cannot be selected using globbing.
+
+generated-files
+   List of files that are generated as part of the build and don't exist in
+   the source tree.
+
+   The build system assumes that each manifest file, test file, and file
+   listed in **head**, **tail**, and **support-files** is static and
+   provided by the source tree (and not automatically generated as part
+   of the build). This variable tells the build system not to make this
+   assumption.
+
+   This variable will likely go away sometime once all generated files are
+   accounted for in the build config.
+
+   If a generated file is not listed in this key, a clobber build will
+   likely fail.
+
+dupe-manifest
+   Record that this manifest duplicates another manifest.
+
+   The common scenario is two manifest files will include a shared
+   manifest file via the ``[include:file]`` special section. The build
+   system enforces that each test file is only provided by a single
+   manifest. Having this key present bypasses that check.
+
+   The value of this key is ignored.
+
+
+skip-if
+   Skip this test if the specified condition is true.
+   See :ref:`manifest_filter_language`.
+
+fail-if
+   Expect test failure if the specified condition is true.
+   See :ref:`manifest_filter_language`.
+
+run-sequentially
+   If present, the test should not be run in parallel with other tests.
+
+   Some test harnesses support parallel test execution on separate processes
+   and/or threads (behavior varies by test harness). If this key is present,
+   the test harness should not attempt to run this test in parallel with any
+   other test.
+
+   By convention, the value of this key is a string describing why the test
+   can't be run in parallel.
+
+.. _manifest_filter_language:
+
+Manifest Filter Language
+------------------------
+
+Some manifest keys accept a special filter syntax as their values. These
+values are essentially boolean expressions that are evaluated at test
+execution time.
+
+The expressions can reference a well-defined set of variables, such as
+``os`` and ``debug``. These variables are populated from the
+``mozinfo.json`` file. For the full list of available variables, see
+the :ref:`mozinfo documentation <mozinfo_attributes>`.
+
+See
+`the source <https://hg.mozilla.org/mozilla-central/file/default/testing/mozbase/manifestparser/manifestparser/manifestparser.py>`_ for the full documentation of the
+expression syntax until it is documented here.
+
+.. todo::
+
+   Document manifest filter language.
+
+.. _manifest_file_installation:
+
+File Installation
+-----------------
+
+Files referenced by manifests are automatically installed into the object
+directory into paths defined in
+:py:func:`mozbuild.frontend.emitter.TreeMetadataEmitter._process_test_manifest`.
+
+Relative paths resolving to parent directory (e.g.
+``support-files = ../foo.txt`` have special behavior.
+
+For ``support-files``, the file will be installed to the default destination
+for that manifest. Only the file's base name is used to construct the final
+path: directories are irrelevant.  Files starting with ``/`` are an exception,
+these are installed relative to the root of the destination; the base name is
+instead used to select the file..
+
+For all other entry types, the file installation is skipped.
+
+.. _reftest_manifests:
+
+Reftest Manifests
+=================
+
+See `MDN <https://developer.mozilla.org/en-US/docs/Creating_reftest-based_unit_tests>`_.
diff --git a/src/third_party/mozjs-45/build/docs/visualstudio.rst b/src/third_party/mozjs-45/build/docs/visualstudio.rst
new file mode 100644
index 0000000..3fbf28e
--- /dev/null
+++ b/src/third_party/mozjs-45/build/docs/visualstudio.rst
@@ -0,0 +1,100 @@
+.. _build_visualstudio:
+
+======================
+Visual Studio Projects
+======================
+
+The build system contains alpha support for generating Visual Studio
+project files to aid with development.
+
+To generate Visual Studio project files, you'll need to have a configured tree::
+
+   mach configure
+
+(If you have built recently, your tree is already configured.)
+
+Then, simply generate the Visual Studio build backend::
+
+   mach build-backend -b VisualStudio
+
+If all goes well, the path to the generated Solution (``.sln``) file should be
+printed. You should be able to open that solution with Visual Studio 2010 or
+newer.
+
+Currently, output is hard-coded to the Visual Studio 2010 format. If you open
+the solution in a newer Visual Studio release, you will be prompted to upgrade
+projects. Simply click through the wizard to do that.
+
+Structure of Solution
+=====================
+
+The Visual Studio solution consists of hundreds of projects spanning thousands
+of files. To help with organization, the solution is divided into the following
+trees/folders:
+
+Build Targets
+   This folder contains common build targets. The *full* project is used to
+   perform a full build. The *binaries* project is used to build just binaries.
+   The *visual-studio* project can be built to regenerate the Visual Studio
+   project files.
+
+   Performing the *clean* action on any of these targets will clean the
+   *entire* build output.
+
+Binaries
+   This folder contains common binaries that can be executed from within
+   Visual Studio. If you are building the Firefox desktop application,
+   the *firefox* project will launch firefox.exe. You probably want one of
+   these set to your startup project.
+
+Libraries
+   This folder contains entries for each static library that is produced as
+   part of the build. These roughly correspond to each directory in the tree
+   containing C/C++. e.g. code from ``dom/base`` will be contained in the
+   ``dom_base`` project.
+
+   These projects don't do anything when built. If you build a project here,
+   the *binaries* build target project is built.
+
+Updating Project Files
+======================
+
+As you pull and update the source tree, your Visual Studio files may fall out
+of sync with the build configuration. The tree should still build fine from
+within Visual Studio. But source files may be missing and IntelliSense may not
+have the proper build configuration.
+
+To account for this, you'll want to periodically regenerate the Visual Studio
+project files. You can do this within Visual Studio by building the
+``Build Targets :: visual-studio`` project or by running
+``mach build-backend -b VisualStudio`` from the command line.
+
+Currently, regeneration rewrites the original project files. **If you've made
+any customizations to the solution or projects, they will likely get
+overwritten.** We would like to improve this user experience in the
+future.
+
+Moving Project Files Around
+===========================
+
+The produced Visual Studio solution and project files should be portable.
+If you want to move them to a non-default directory, they should continue
+to work from wherever they are. If they don't, please file a bug.
+
+Invoking mach through Visual Studio
+===================================
+
+It's possible to build the tree via Visual Studio. There is some light magic
+involved here.
+
+Alongside the Visual Studio project files is a batch script named ``mach.bat``.
+This batch script sets the environment variables present in your *MozillaBuild*
+development environment at the time of Visual Studio project generation
+and invokes *mach* inside an msys shell with the arguments specified to the
+batch script. This script essentially allows you to invoke mach commands
+inside the MozillaBuild environment without having to load MozillaBuild.
+
+While projects currently only utilize the ``mach build`` command, the batch
+script does not limit it's use: any mach command can be invoked. Developers
+may abuse this fact to add custom projects and commands that invoke other
+mach commands.
diff --git a/src/third_party/mozjs-45/build/dumbmake-dependencies b/src/third_party/mozjs-45/build/dumbmake-dependencies
new file mode 100644
index 0000000..d99f567
--- /dev/null
+++ b/src/third_party/mozjs-45/build/dumbmake-dependencies
@@ -0,0 +1,71 @@
+toolkit/library
+  dom
+    ipc
+    security/sandbox
+  ipc
+  netwerk/build
+    netwerk
+  storage/build
+    storage
+  xpcom
+    chrome
+  extensions
+  docshell/build
+    docshell
+    uriloader
+  modules
+  widget
+  gfx
+  toolkit/components/build
+    toolkit/components
+  security/manager
+    security/certverifier
+      security/build
+  accessible
+  dom
+  content
+  layout
+  editor
+  parser
+  js/src
+    mfbt
+  js/xpconnect
+    js/xpconnect/loader
+  view
+  caps
+  xpfe/appshell
+  xpfe/components
+  js
+  toolkit
+  rdf/build
+  embedding
+  hal
+  image/build
+    image
+  intl/build
+    intl
+  media
+  profile
+  services
+  startupcache
+  devtools/server
+  devtools/shared
+browser/app
+  browser/base
+  browser/components
+  devtools/client
+  browser/locales
+  browser/modules
+  browser/themes
+  toolkit
+  toolkit/components
+  toolkit/components/jsdownloads
+  toolkit/content
+  toolkit/crashreporter
+  toolkit/forgetaboutsite
+  toolkit/identity
+  toolkit/modules
+  toolkit/mozapps/extensions
+  toolkit/profile
+  toolkit/themes
+  toolkit/webapps
diff --git a/src/third_party/mozjs-45/build/gabi++/Android.mk b/src/third_party/mozjs-45/build/gabi++/Android.mk
new file mode 100644
index 0000000..1d2f735
--- /dev/null
+++ b/src/third_party/mozjs-45/build/gabi++/Android.mk
@@ -0,0 +1,55 @@
+LOCAL_PATH:= $(call my-dir)
+
+libgabi++_cflags := \
+	-I$(LOCAL_PATH)/include 
+
+libgabi++_common_src_files := \
+	src/array_type_info.cc \
+	src/class_type_info.cc \
+        src/delete.cc \
+	src/dynamic_cast.cc \
+	src/enum_type_info.cc \
+	src/function_type_info.cc \
+        src/new.cc \
+	src/pbase_type_info.cc \
+	src/pointer_type_info.cc \
+	src/pointer_to_member_type_info.cc \
+	src/si_class_type_info.cc \
+	src/type_info.cc \
+	src/vmi_class_type_info.cc
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_CPP_EXTENSION := .cc
+
+LOCAL_SRC_FILES:= $(libgabi++_common_src_files)
+
+LOCAL_MODULE:= libgabi++
+
+LOCAL_CFLAGS := $(libgabi++_cflags)
+
+LOCAL_RTTI_FLAG := -frtti
+
+LOCAL_SYSTEM_SHARED_LIBRARIES := libc
+
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_CPP_EXTENSION := .cc
+
+LOCAL_SRC_FILES:= $(libgabi++_common_src_files)
+
+LOCAL_MODULE:= libgabi++
+
+LOCAL_CFLAGS := $(libgabi++_cflags)
+
+LOCAL_RTTI_FLAG := -frtti
+
+LOCAL_SYSTEM_SHARED_LIBRARIES := libc
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/src/third_party/mozjs-45/build/gabi++/README.mozilla b/src/third_party/mozjs-45/build/gabi++/README.mozilla
new file mode 100644
index 0000000..f679480
--- /dev/null
+++ b/src/third_party/mozjs-45/build/gabi++/README.mozilla
@@ -0,0 +1 @@
+This copy of libgabi++ is from Android 5.0 source code on https://android.googlesource.com/platform/abi/cpp/.  Tag is android-5.0.0_r1.
diff --git a/src/third_party/mozjs-45/build/gabi++/include/cxxabi.h b/src/third_party/mozjs-45/build/gabi++/include/cxxabi.h
new file mode 100644
index 0000000..516e6a8
--- /dev/null
+++ b/src/third_party/mozjs-45/build/gabi++/include/cxxabi.h
@@ -0,0 +1,183 @@
+// Copyright (C) 2011 The Android Open Source Project
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the project nor the names of its contributors
+//    may be used to endorse or promote products derived from this software
+//    without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+//
+
+#ifndef __GABIXX_CXXABI_H__
+#define __GABIXX_CXXABI_H__
+
+#include <typeinfo>
+
+namespace __cxxabiv1
+{
+  extern "C" void __cxa_pure_virtual();
+
+  // Derived types of type_info below are based on 2.9.5 of C++ ABI.
+
+  // Typeinfo for fundamental types.
+  class __fundamental_type_info : public std::type_info
+  {
+  public:
+    ~__fundamental_type_info();
+  };
+
+  // Typeinfo for array types.
+  class __array_type_info : public std::type_info
+  {
+  public:
+    ~__array_type_info();
+  };
+
+  // Typeinfo for function types.
+  class __function_type_info : public std::type_info
+  {
+  public:
+    ~__function_type_info();
+  };
+
+  // Typeinfo for enum types.
+  class __enum_type_info : public std::type_info
+  {
+  public:
+    ~__enum_type_info();
+  };
+
+  // Typeinfo for classes with no bases.
+  class __class_type_info : public std::type_info
+  {
+  public:
+    ~__class_type_info();
+
+    enum class_type_info_code
+      {
+        CLASS_TYPE_INFO_CODE,
+        SI_CLASS_TYPE_INFO_CODE,
+        VMI_CLASS_TYPE_INFO_CODE
+      };
+
+    virtual class_type_info_code
+    code() const { return CLASS_TYPE_INFO_CODE; }
+  };
+
+  // Typeinfo for classes containing only a single, public, non-virtual base at
+  // offset zero.
+  class __si_class_type_info : public __class_type_info
+  {
+  public:
+    ~__si_class_type_info();
+    const __class_type_info *__base_type;
+
+    virtual __class_type_info::class_type_info_code
+    code() const { return SI_CLASS_TYPE_INFO_CODE; }
+  };
+
+  struct __base_class_type_info
+  {
+  public:
+    const __class_type_info *__base_type;
+
+    // All but the lower __offset_shift bits of __offset_flags are a signed
+    // offset. For a non-virtual base, this is the offset in the object of the
+    // base subobject. For a virtual base, this is the offset in the virtual
+    // table of the virtual base offset for the virtual base referenced
+    // (negative).
+    long __offset_flags;
+
+    enum __offset_flags_masks
+      {
+        __virtual_mask = 0x1,
+        __public_mask = 0x2,
+        __offset_shift = 8
+      };
+
+    bool inline
+    is_virtual() const { return (__offset_flags & __virtual_mask) != 0; }
+
+    bool inline
+    is_public() const { return (__offset_flags & __public_mask) != 0; }
+
+    // FIXME: Right-shift of signed integer is implementation dependent.
+    long inline
+    offset() const { return __offset_flags >> __offset_shift; }
+
+    long inline
+    flags() const { return __offset_flags & ((1L << __offset_shift) - 1); }
+  };
+
+  // Typeinfo for classes with bases that do not satisfy the
+  // __si_class_type_info constraints.
+  class __vmi_class_type_info : public __class_type_info
+  {
+  public:
+    ~__vmi_class_type_info();
+    unsigned int __flags;
+    unsigned int __base_count;
+    __base_class_type_info __base_info[1];
+
+    enum __flags_masks
+      {
+        __non_diamond_repeat_mask = 0x1,
+        __diamond_shaped_mask = 0x2
+      };
+
+    virtual __class_type_info::class_type_info_code
+    code() const { return VMI_CLASS_TYPE_INFO_CODE; }
+  };
+
+  class __pbase_type_info : public std::type_info
+  {
+  public:
+    ~__pbase_type_info();
+    unsigned int __flags;
+    const std::type_info *__pointee;
+
+    enum __masks
+      {
+        __const_mask = 0x1,
+        __volatile_mask = 0x2,
+        __restrict_mask = 0x4,
+        __incomplete_mask = 0x8,
+        __incomplete_class_mask = 0x10
+      };
+  };
+
+  class __pointer_type_info : public __pbase_type_info
+  {
+  public:
+    ~__pointer_type_info();
+  };
+
+  class __pointer_to_member_type_info : public __pbase_type_info
+  {
+  public:
+    ~__pointer_to_member_type_info();
+  };
+}
+
+namespace abi = __cxxabiv1;
+
+#endif /* defined(__GABIXX_CXXABI_H__) */
+
diff --git a/src/third_party/mozjs-45/build/gabi++/include/new b/src/third_party/mozjs-45/build/gabi++/include/new
new file mode 100644
index 0000000..92dd960
--- /dev/null
+++ b/src/third_party/mozjs-45/build/gabi++/include/new
@@ -0,0 +1,56 @@
+// Copyright (C) 2011 The Android Open Source Project
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the project nor the names of its contributors
+//    may be used to endorse or promote products derived from this software
+//    without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+//
+// new: Dynamic storage management.
+
+#ifndef __GABIXX_NEW__
+#define __GABIXX_NEW__
+
+#include <cstddef>
+
+namespace std
+{
+  struct nothrow_t {};
+  extern const nothrow_t nothrow;
+  typedef void (*new_handler)();
+}
+
+// FIXME: Need to handle exceptions.
+void* operator new(std::size_t size) throw(/*std::bad_alloc*/);
+void* operator new(std::size_t size, const std::nothrow_t&) throw();
+void  operator delete(void* ptr) throw();
+void  operator delete(void*, const std::nothrow_t&) throw();
+void* operator new[](std::size_t size) throw(/*std::bad_alloc*/);
+void* operator new[](std::size_t size, const std::nothrow_t&) throw();
+void  operator delete[](void* ptr) throw();
+void  operator delete[](void* const, std::nothrow_t&) throw();
+void* operator new(std::size_t size, void* ptr) throw();
+void* operator new[](std::size_t size, void* ptr) throw();
+void  operator delete(void* ptr, void*) throw();
+void  operator delete[](void* ptr, void*) throw();
+
+#endif // __GABIXX_NEW__
diff --git a/src/third_party/mozjs-45/build/gabi++/include/typeinfo b/src/third_party/mozjs-45/build/gabi++/include/typeinfo
new file mode 100644
index 0000000..ab87f7e
--- /dev/null
+++ b/src/third_party/mozjs-45/build/gabi++/include/typeinfo
@@ -0,0 +1,76 @@
+// Copyright (C) 2011 The Android Open Source Project
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the project nor the names of its contributors
+//    may be used to endorse or promote products derived from this software
+//    without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+//
+// typeinfo: RTTI support header.
+//
+// References:
+// Itanium C++ ABI at http://www.codesourcery.com/public/cxx-abi/abi.html.
+// IHI0041A C++ Application Binary Interface for the ARM architecture.
+// Linux Standard Base C++ Specification for S390X 4.1.
+//
+
+#ifndef __GABIXX_TYPEINFO__
+#define __GABIXX_TYPEINFO__
+
+namespace std
+{
+  // Defintion of type_info based on example in C++ ABI section 2.9.3
+  class type_info
+  {
+  public:
+    virtual
+    ~type_info();
+
+    // Whether two type_infos corresponds to the same types.
+    bool
+    operator==(const type_info &ti) const;
+
+    // Whether two type_infos corresponds to the different types.
+    bool
+    operator!=(const type_info &ti) const;
+
+    bool
+    before(const type_info &ti) const;
+
+    // Return name of type.
+    const char*
+    name() const { return __type_name; }
+
+  private:
+    // Assignment of type_info is not allowed.
+    type_info (const type_info& rhs);
+
+    type_info&
+    operator=(const type_info& rhs);
+
+    // Mangled name of type.
+    const char *__type_name;
+  };
+
+} // namespace std
+
+#endif // _GABIXX_TYPEINFO_
diff --git a/src/third_party/mozjs-45/build/gabi++/moz.build b/src/third_party/mozjs-45/build/gabi++/moz.build
new file mode 100644
index 0000000..2e586c3
--- /dev/null
+++ b/src/third_party/mozjs-45/build/gabi++/moz.build
@@ -0,0 +1,36 @@
+# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+Library('gabi++')
+
+SOURCES += [
+    'src/array_type_info.cc',
+    'src/class_type_info.cc',
+    'src/delete.cc',
+    'src/dynamic_cast.cc',
+    'src/enum_type_info.cc',
+    'src/function_type_info.cc',
+    'src/fundamental_type_info.cc',
+    'src/new.cc',
+    'src/pbase_type_info.cc',
+    'src/pointer_to_member_type_info.cc',
+    'src/pointer_type_info.cc',
+    'src/si_class_type_info.cc',
+    'src/type_info.cc',
+    'src/vmi_class_type_info.cc',
+]
+
+LOCAL_INCLUDES += [
+    'include'
+]
+
+DISABLE_STL_WRAPPING = True
+NO_VISIBILITY_FLAGS = True
+
+CXXFLAGS += [
+    '-fexceptions',
+    '-frtti'
+]
diff --git a/src/third_party/mozjs-45/build/gabi++/src/array_type_info.cc b/src/third_party/mozjs-45/build/gabi++/src/array_type_info.cc
new file mode 100644
index 0000000..006f50d
--- /dev/null
+++ b/src/third_party/mozjs-45/build/gabi++/src/array_type_info.cc
@@ -0,0 +1,37 @@
+// Copyright (C) 2011 The Android Open Source Project
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the project nor the names of its contributors
+//    may be used to endorse or promote products derived from this software
+//    without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+//
+// fundamental_type_info.cc: Methods for __fundamental_type_info.
+
+#include <cxxabi.h>
+
+namespace __cxxabiv1
+{
+  __fundamental_type_info::~__fundamental_type_info()
+  {
+  }
+} // namespace __cxxabiv1
diff --git a/src/third_party/mozjs-45/build/gabi++/src/class_type_info.cc b/src/third_party/mozjs-45/build/gabi++/src/class_type_info.cc
new file mode 100644
index 0000000..4544542
--- /dev/null
+++ b/src/third_party/mozjs-45/build/gabi++/src/class_type_info.cc
@@ -0,0 +1,37 @@
+// Copyright (C) 2011 The Android Open Source Project
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the project nor the names of its contributors
+//    may be used to endorse or promote products derived from this software
+//    without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+//
+// class_type_info.cc: Methods for __class_type_info.
+
+#include <cxxabi.h>
+
+namespace __cxxabiv1
+{
+  __class_type_info::~__class_type_info()
+  {
+  }
+} // namespace __cxxabiv1
diff --git a/src/third_party/mozjs-45/build/gabi++/src/delete.cc b/src/third_party/mozjs-45/build/gabi++/src/delete.cc
new file mode 100644
index 0000000..f13fc49
--- /dev/null
+++ b/src/third_party/mozjs-45/build/gabi++/src/delete.cc
@@ -0,0 +1,38 @@
+// Copyright (C) 2011 The Android Open Source Project
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the project nor the names of its contributors
+//    may be used to endorse or promote products derived from this software
+//    without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+//
+// delete.cc: delete operator
+
+#include <stdlib.h>
+#include <new>
+
+void
+operator delete(void* ptr) throw()
+{
+  if (ptr)
+    free(ptr);
+}
diff --git a/src/third_party/mozjs-45/build/gabi++/src/dynamic_cast.cc b/src/third_party/mozjs-45/build/gabi++/src/dynamic_cast.cc
new file mode 100644
index 0000000..2dacac8
--- /dev/null
+++ b/src/third_party/mozjs-45/build/gabi++/src/dynamic_cast.cc
@@ -0,0 +1,356 @@
+// Copyright (C) 2011 The Android Open Source Project
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the project nor the names of its contributors
+//    may be used to endorse or promote products derived from this software
+//    without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+//
+// dynamic_cast.cc: RTTI support.
+//
+// References:
+// Itanium C++ ABI at http://www.codesourcery.com/public/cxx-abi/abi.html
+// IHI0041A C++ Application Binary Interface for the ARM architecture.
+//
+
+#include <cxxabi.h>
+
+#include <cstddef>
+#include <cassert>
+
+namespace
+{
+  // Adjust a pointer by an offset.
+
+  const void*
+  adjust_pointer(const void* p, std::ptrdiff_t off)
+  {
+    // FIXME: should we align pointer after adjustment?
+    const char *cp = reinterpret_cast<const char*>(p) + off;
+    return reinterpret_cast<const void*>(cp);
+  }
+
+  // Return the vtable pointer of a polymorphic object pointed by p.
+
+  inline const void*
+  get_vtable(const void* p)
+  {
+    return *reinterpret_cast<void*const*>(p);
+  }
+
+  // Return a pointer to a __class_type_info in a vtable.
+
+  inline const abi::__class_type_info*
+  get_class_type_info(const void* vtable)
+  {
+    const void* type_info_ptr = adjust_pointer(vtable, -sizeof(void*));
+    return *reinterpret_cast<abi::__class_type_info*const*>(type_info_ptr);
+  }
+
+  // Return offset to object in a vtable.
+
+  inline std::ptrdiff_t
+  get_offset_to_top(const void* vtable)
+  {
+    const void* type_info_ptr_address = adjust_pointer(vtable, -sizeof(void*));
+    const void* offset_to_top_address =
+      adjust_pointer(type_info_ptr_address, -sizeof(std::ptrdiff_t));
+    return *reinterpret_cast<const std::ptrdiff_t*>(offset_to_top_address);
+  }
+
+  // Return the virtual pointer to the most derived object of referred by a
+  // pointer p.
+
+  const void*
+  get_most_derived_object(const void* p)
+  {
+    const void* vtable = get_vtable(p);
+    std::ptrdiff_t offset_to_top = get_offset_to_top(vtable);
+    return adjust_pointer(p, offset_to_top);
+  }
+
+  // We assume that -1 cannot be a valid pointer to object.
+  const void * const ambiguous_object =
+    reinterpret_cast<const void*>(-1);
+
+  // Return a pointer to the subobject described by base_info.
+
+  const void*
+  get_subobject(const void* object,
+                const void* vtable,
+                const abi::__base_class_type_info* base_info)
+  {
+    long offset = base_info->offset();
+    if (base_info->is_virtual())
+      {
+        const std::ptrdiff_t* virtual_base_offset_address =
+          static_cast<const std::ptrdiff_t*> (adjust_pointer(vtable, offset));
+        offset = *virtual_base_offset_address;
+      }
+    return adjust_pointer(object, offset);
+  }
+
+  // Helper of __dyanmic_cast to walk the type tree of an object.
+
+  const void *
+  walk_object(const void *object,
+              const abi::__class_type_info *type,
+              const void *match_object,
+              const abi::__class_type_info *match_type)
+  {
+    if (*type == *match_type)
+      return (match_object == NULL || object == match_object) ? object : NULL;
+
+    switch(type->code())
+      {
+      case abi::__class_type_info::CLASS_TYPE_INFO_CODE:
+        // This isn't not the class you're looking for.
+        return NULL;
+
+      case abi::__class_type_info::SI_CLASS_TYPE_INFO_CODE:
+        // derived type has a single public base at offset 0.
+        {
+          const abi::__si_class_type_info* ti =
+            static_cast<const abi::__si_class_type_info*>(type);
+          return walk_object(object, ti->__base_type, match_object,
+                             match_type);
+        }
+
+      case abi::__class_type_info::VMI_CLASS_TYPE_INFO_CODE:
+        {
+          const void* vtable = get_vtable(object);
+          const abi::__vmi_class_type_info* ti =
+            static_cast<const abi::__vmi_class_type_info*>(type);
+
+          // Look at all direct bases.
+          const void* result = NULL;
+          for (unsigned i = 0; i < ti->__base_count; ++i)
+            {
+              if (!ti->__base_info[i].is_public())
+                continue;
+
+              const void *subobject =
+                get_subobject(object, vtable, &ti->__base_info[i]);
+              const void* walk_subobject_result =
+                walk_object(subobject, ti->__base_info[i].__base_type,
+                            match_object, match_type);
+
+              if (walk_subobject_result == ambiguous_object)
+                return ambiguous_object;
+              else if (walk_subobject_result != NULL)
+                {
+                  if (result == NULL)
+                    {
+                      result = walk_subobject_result;
+                    }
+                  else if (result != walk_subobject_result)
+                    return ambiguous_object;
+                }
+            }
+          return result;
+        }
+
+      default:
+        assert(0);
+      }
+    return NULL;
+  }
+
+  // Bookkeeping structure for derived-to-base cast in the general case.
+  struct cast_context
+  {
+  public:
+    const void* object;
+    const abi::__class_type_info *src_type;
+    const abi::__class_type_info *dst_type;
+    std::ptrdiff_t src2dst_offset;
+
+    const void* dst_object;
+    const void* result;
+
+    cast_context(const void* obj, const abi::__class_type_info *src,
+                 const abi::__class_type_info *dst, std::ptrdiff_t offset)
+      : object(obj), src_type(src), dst_type(dst), src2dst_offset(offset),
+        dst_object(NULL), result(NULL)
+    { }
+  };
+
+  // based-to-derive cast in the general case.
+
+  void
+  base_to_derived_cast(const void *object,
+                       const abi::__class_type_info *type,
+                       cast_context* context)
+  {
+    const void* saved_dst_object = context->dst_object;
+    bool is_dst_type = *type == *context->dst_type;
+    if (is_dst_type)
+      context->dst_object = object;
+
+    if (object == context->object
+        && context->dst_object != NULL
+        && *type == *context->src_type)
+      {
+        if (context->result == NULL)
+          context->result = context->dst_object;
+        else if (context->result != context->dst_object)
+          context->result = ambiguous_object;
+        context->dst_object = saved_dst_object;
+        return;
+      }
+
+    switch(type->code())
+      {
+      case abi::__class_type_info::CLASS_TYPE_INFO_CODE:
+        // This isn't not the class you're looking for.
+        break;
+
+      case abi::__class_type_info::SI_CLASS_TYPE_INFO_CODE:
+        // derived type has a single public base at offset 0.
+        {
+          const abi::__si_class_type_info* ti =
+            static_cast<const abi::__si_class_type_info*>(type);
+          base_to_derived_cast(object, ti->__base_type, context);
+          break;
+        }
+
+      case abi::__class_type_info::VMI_CLASS_TYPE_INFO_CODE:
+        {
+          const void* vtable = get_vtable(object);
+          const abi::__vmi_class_type_info* ti =
+            static_cast<const abi::__vmi_class_type_info*>(type);
+
+          // Look at all direct bases.
+          for (unsigned i = 0; i < ti->__base_count; ++i)
+            {
+              if (!ti->__base_info[i].is_public())
+                continue;
+
+              const void *subobject =
+                get_subobject(object, vtable, &ti->__base_info[i]);
+              base_to_derived_cast(subobject, ti->__base_info[i].__base_type,
+                                   context);
+
+              // FIXME: Use flags in base_info to optimize search.
+              if (context->result == ambiguous_object)
+                break;
+            }
+          break;
+        }
+
+      default:
+        assert(0);
+      }
+     context->dst_object = saved_dst_object;
+  }
+} // namespace
+
+namespace __cxxabiv1
+{
+#define DYNAMIC_CAST_NO_HINT -1
+#define DYNAMIC_CAST_NOT_PUBLIC_BASE -2
+#define DYNAMIC_CAST_MULTIPLE_PUBLIC_NONVIRTUAL_BASE -3
+
+  /* v: source address to be adjusted; nonnull, and since the
+   *    source object is polymorphic, *(void**)v is a virtual pointer.
+   * src: static type of the source object.
+   * dst: destination type (the "T" in "dynamic_cast<T>(v)").
+   * src2dst_offset: a static hint about the location of the
+   *    source subobject with respect to the complete object;
+   *    special negative values are:
+   *       -1: no hint
+   *       -2: src is not a public base of dst
+   *       -3: src is a multiple public base type but never a
+   *           virtual base type
+   *    otherwise, the src type is a unique public nonvirtual
+   *    base type of dst at offset src2dst_offset from the
+   *    origin of dst.
+   */
+  extern "C" void*
+  __dynamic_cast (const void *v,
+                  const abi::__class_type_info *src,
+                  const abi::__class_type_info *dst,
+                  std::ptrdiff_t src2dst_offset)
+  {
+    const void* most_derived_object = get_most_derived_object(v);
+    const void* vtable = get_vtable(most_derived_object);
+    const abi::__class_type_info* most_derived_class_type_info =
+      get_class_type_info(vtable);
+
+    // If T is not a public base type of the most derived class referred
+    // by v, the cast always fails.
+    void* t_object =
+      const_cast<void*>(walk_object(most_derived_object,
+                                    most_derived_class_type_info, NULL, dst));
+    if (t_object == NULL)
+      return NULL;
+
+    // C++ ABI 2.9.7 The dynamic_cast Algorithm:
+    //
+    // If, in the most derived object pointed (referred) to by v, v points
+    // (refers) to a public base class subobject of a T object [note: this can
+    // be checked at compile time], and if only one object of type T is derived
+    // from the subobject pointed (referred) to by v, the result is a pointer
+    // (an lvalue referring) to that T object.
+
+    // We knew that src is not a public base, so base-to-derived cast
+    // is not possible.  This works even if there are multiple subobjects
+    // of type T in the most derived object.
+    if (src2dst_offset != DYNAMIC_CAST_NOT_PUBLIC_BASE)
+      {
+        // If it is known that v points to a public base class subobject
+        // of a T object, simply adjust the pointer by the offset.
+        if (t_object != ambiguous_object && src2dst_offset >= 0)
+          return const_cast<void*>(adjust_pointer(v, -src2dst_offset));
+
+        // If there is only one T type subobject, we only need to look at
+        // there.  Otherwise, look for the subobject referred by v in the
+        // most derived object.
+        cast_context context(v, src, dst, src2dst_offset);
+        if (t_object != ambiguous_object)
+          base_to_derived_cast(t_object, dst, &context);
+        else
+          base_to_derived_cast(most_derived_object,
+                               most_derived_class_type_info, &context);
+
+        if (context.result != NULL && context.result != ambiguous_object)
+          return const_cast<void*>(context.result);
+      }
+
+    // C++ ABI 2.9.7 The dynamic_cast Algorithm:
+    //
+    // Otherwise, if v points (refers) to a public base class subobject of the
+    // most derived object, and the type of the most derived object has an
+    // unambiguous public base class of type T, the result is a pointer (an
+    // lvalue referring) to the T subobject of the most derived object.
+    // Otherwise, the run-time check fails.
+
+    // Check to see if T is a unambiguous public base class.
+    if (t_object == ambiguous_object)
+      return NULL;
+
+    // See if v refers to a public base class subobject.
+    const void* v_object =
+      walk_object(most_derived_object, most_derived_class_type_info, v, src);
+    return v_object == v ? t_object : NULL;
+  }
+} // namespace __cxxabiv1
diff --git a/src/third_party/mozjs-45/build/gabi++/src/enum_type_info.cc b/src/third_party/mozjs-45/build/gabi++/src/enum_type_info.cc
new file mode 100644
index 0000000..3a0f809
--- /dev/null
+++ b/src/third_party/mozjs-45/build/gabi++/src/enum_type_info.cc
@@ -0,0 +1,37 @@
+// Copyright (C) 2011 The Android Open Source Project
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the project nor the names of its contributors
+//    may be used to endorse or promote products derived from this software
+//    without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+//
+// enum_type_info.cc: Methods for __enum_type_info.
+
+#include <cxxabi.h>
+
+namespace __cxxabiv1
+{
+  __enum_type_info::~__enum_type_info()
+  {
+  }
+} // namespace __cxxabiv1
diff --git a/src/third_party/mozjs-45/build/gabi++/src/function_type_info.cc b/src/third_party/mozjs-45/build/gabi++/src/function_type_info.cc
new file mode 100644
index 0000000..138dd07
--- /dev/null
+++ b/src/third_party/mozjs-45/build/gabi++/src/function_type_info.cc
@@ -0,0 +1,37 @@
+// Copyright (C) 2011 The Android Open Source Project
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the project nor the names of its contributors
+//    may be used to endorse or promote products derived from this software
+//    without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+//
+// function_type_info.cc: Methods for __function_type_info.
+
+#include <cxxabi.h>
+
+namespace __cxxabiv1
+{
+  __function_type_info::~__function_type_info()
+  {
+  }
+} // namespace __cxxabiv1
diff --git a/src/third_party/mozjs-45/build/gabi++/src/fundamental_type_info.cc b/src/third_party/mozjs-45/build/gabi++/src/fundamental_type_info.cc
new file mode 100644
index 0000000..d84af0a
--- /dev/null
+++ b/src/third_party/mozjs-45/build/gabi++/src/fundamental_type_info.cc
@@ -0,0 +1,37 @@
+// Copyright (C) 2011 The Android Open Source Project
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the project nor the names of its contributors
+//    may be used to endorse or promote products derived from this software
+//    without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+//
+// array_type_info.cc: Methods for __array_type_info.
+
+#include <cxxabi.h>
+
+namespace __cxxabiv1
+{
+  __array_type_info::~__array_type_info()
+  {
+  }
+} // namespace __cxxabiv1
diff --git a/src/third_party/mozjs-45/build/gabi++/src/new.cc b/src/third_party/mozjs-45/build/gabi++/src/new.cc
new file mode 100644
index 0000000..77f54a4
--- /dev/null
+++ b/src/third_party/mozjs-45/build/gabi++/src/new.cc
@@ -0,0 +1,42 @@
+// Copyright (C) 2011 The Android Open Source Project
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the project nor the names of its contributors
+//    may be used to endorse or promote products derived from this software
+//    without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+//
+
+#include <stdlib.h>
+#include <new>
+
+// FIXME: need to handle exceptions
+void*
+operator new(std::size_t size) throw (/*std::bad_alloc*/)
+{
+  void* ptr = malloc(size);
+#if 0
+  if (ptr == NULL)
+    throw std::bad_alloc();
+#endif
+  return ptr;
+}
diff --git a/src/third_party/mozjs-45/build/gabi++/src/pbase_type_info.cc b/src/third_party/mozjs-45/build/gabi++/src/pbase_type_info.cc
new file mode 100644
index 0000000..d7b1901
--- /dev/null
+++ b/src/third_party/mozjs-45/build/gabi++/src/pbase_type_info.cc
@@ -0,0 +1,37 @@
+// Copyright (C) 2011 The Android Open Source Project
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the project nor the names of its contributors
+//    may be used to endorse or promote products derived from this software
+//    without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+//
+// pbase_type_info.cc: Methods for __pbase_type_info.
+
+#include <cxxabi.h>
+
+namespace __cxxabiv1
+{
+  __pbase_type_info::~__pbase_type_info()
+  {
+  }
+} // namespace __cxxabiv1
diff --git a/src/third_party/mozjs-45/build/gabi++/src/pointer_to_member_type_info.cc b/src/third_party/mozjs-45/build/gabi++/src/pointer_to_member_type_info.cc
new file mode 100644
index 0000000..e2892ab
--- /dev/null
+++ b/src/third_party/mozjs-45/build/gabi++/src/pointer_to_member_type_info.cc
@@ -0,0 +1,37 @@
+// Copyright (C) 2011 The Android Open Source Project
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the project nor the names of its contributors
+//    may be used to endorse or promote products derived from this software
+//    without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+//
+// pointer_to_member_type_info.cc: Methods for __pointer_to_member_type_info.
+
+#include <cxxabi.h>
+
+namespace __cxxabiv1
+{
+  __pointer_to_member_type_info::~__pointer_to_member_type_info()
+  {
+  }
+} // namespace __cxxabiv1
diff --git a/src/third_party/mozjs-45/build/gabi++/src/pointer_type_info.cc b/src/third_party/mozjs-45/build/gabi++/src/pointer_type_info.cc
new file mode 100644
index 0000000..31a84f4
--- /dev/null
+++ b/src/third_party/mozjs-45/build/gabi++/src/pointer_type_info.cc
@@ -0,0 +1,37 @@
+// Copyright (C) 2011 The Android Open Source Project
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the project nor the names of its contributors
+//    may be used to endorse or promote products derived from this software
+//    without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+//
+// pointer_type_info.cc: Methods for __pointer_type_info.
+
+#include <cxxabi.h>
+
+namespace __cxxabiv1
+{
+  __pointer_type_info::~__pointer_type_info()
+  {
+  }
+} // namespace __cxxabiv1
diff --git a/src/third_party/mozjs-45/build/gabi++/src/si_class_type_info.cc b/src/third_party/mozjs-45/build/gabi++/src/si_class_type_info.cc
new file mode 100644
index 0000000..d6a631f
--- /dev/null
+++ b/src/third_party/mozjs-45/build/gabi++/src/si_class_type_info.cc
@@ -0,0 +1,37 @@
+// Copyright (C) 2011 The Android Open Source Project
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the project nor the names of its contributors
+//    may be used to endorse or promote products derived from this software
+//    without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+//
+// si_class_type_info.cc: Methods for __si_class_type_info.
+
+#include <cxxabi.h>
+
+namespace __cxxabiv1
+{
+  __si_class_type_info::~__si_class_type_info()
+  {
+  }
+} // namespace __cxxabiv1
diff --git a/src/third_party/mozjs-45/build/gabi++/src/type_info.cc b/src/third_party/mozjs-45/build/gabi++/src/type_info.cc
new file mode 100644
index 0000000..69b9f3a
--- /dev/null
+++ b/src/third_party/mozjs-45/build/gabi++/src/type_info.cc
@@ -0,0 +1,75 @@
+// Copyright (C) 2011 The Android Open Source Project
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the project nor the names of its contributors
+//    may be used to endorse or promote products derived from this software
+//    without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+//
+// type_info.cc: Methods for std::type_info.
+//
+
+#include <cxxabi.h>
+#ifdef __ARM_EABI__
+// ARM EABI requires string comprison for mangled type names for type_info
+// equality.
+#include <string.h>
+#endif
+
+#include <typeinfo>
+
+namespace std
+{
+  type_info::~type_info()
+  {
+  }
+
+  bool
+  type_info::operator==(const type_info& rhs) const
+  {
+#ifdef __ARM_EABI__
+    // IHI0041A CPPABI 3.2.5.6.  Because of weak linkage and share libraries,
+    // we perform string comparison.
+    return strcmp(this->__type_name, rhs.__type_name) == 0;
+#else
+    return this == &rhs;
+#endif
+  }
+
+  bool
+  type_info::operator!=(const type_info& rhs) const
+  {
+    return !this->operator==(rhs);
+  }
+
+  bool
+  type_info::before(const type_info& rhs) const
+  {
+#ifdef __ARM_EABI__
+    // IHI0041A CPPABI 3.2.5.6.  Because of weak linkage and share libraries,
+    // we perform string comparison.
+    return strcmp(this->__type_name, rhs.__type_name) < 0;
+#else
+    return this < &rhs;
+#endif
+  }
+} // end namespace std
diff --git a/src/third_party/mozjs-45/build/gabi++/src/vmi_class_type_info.cc b/src/third_party/mozjs-45/build/gabi++/src/vmi_class_type_info.cc
new file mode 100644
index 0000000..b6a4bf6
--- /dev/null
+++ b/src/third_party/mozjs-45/build/gabi++/src/vmi_class_type_info.cc
@@ -0,0 +1,37 @@
+// Copyright (C) 2011 The Android Open Source Project
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the project nor the names of its contributors
+//    may be used to endorse or promote products derived from this software
+//    without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+//
+// vmi_class_type_info.cc: Methods for __vmi_class_type_info.
+
+#include <cxxabi.h>
+
+namespace __cxxabiv1
+{
+  __vmi_class_type_info::~__vmi_class_type_info()
+  {
+  }
+} // namespace __cxxabiv1
diff --git a/src/third_party/mozjs-45/build/gabi++/use_rtti.mk b/src/third_party/mozjs-45/build/gabi++/use_rtti.mk
new file mode 100644
index 0000000..372816c
--- /dev/null
+++ b/src/third_party/mozjs-45/build/gabi++/use_rtti.mk
@@ -0,0 +1,8 @@
+# To use RTTI, "include abi/cpp/use_rtti.mk" in your target.
+
+LOCAL_C_INCLUDES := \
+	abi/cpp/include \
+	$(LOCAL_C_INCLUDES)
+
+LOCAL_RTTI_FLAG := -frtti
+LOCAL_SHARED_LIBRARIES += libgabi++
diff --git a/src/third_party/mozjs-45/build/gecko_templates.mozbuild b/src/third_party/mozjs-45/build/gecko_templates.mozbuild
new file mode 100644
index 0000000..57a4f54
--- /dev/null
+++ b/src/third_party/mozjs-45/build/gecko_templates.mozbuild
@@ -0,0 +1,170 @@
+# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+@template
+def GeckoBinary(linkage='dependent', msvcrt='dynamic', mozglue=None):
+    '''Template for Gecko-related binaries.
+
+    This template is meant to be used in other templates.
+
+    `linkage` indicates the wanted xpcom linkage type. Valid values are
+    'dependent', 'standalone' or None. 'dependent' is the default. It is
+    used for e.g. XPCOM components and executables with direct dependencies
+    on libxul. Most executables should use the 'standalone' linkage, which
+    uses the standalone XPCOM glue to load libxul. None means no XPCOM glue
+    or libxul linkage at all.
+
+    `msvcrt` indicates which Microsoft Visual Studio CRT, for Windows build,
+    ought to be linked: 'static' or 'dynamic'.
+
+    `mozglue` indicates whether to link against the mozglue library, and if
+    so, what linkage to apply. Valid values are None (mozglue not linked),
+    'program' (mozglue linked to an executable program), or 'library' (mozglue
+    linked to a shared library).
+    '''
+    if msvcrt == 'dynamic' or CONFIG['OS_ARCH'] != 'WINNT' or CONFIG['MOZ_ASAN']:
+        xpcomglue = 'xpcomglue'
+    elif msvcrt == 'static':
+        USE_STATIC_LIBS = True
+        xpcomglue = 'xpcomglue_staticruntime'
+        if not CONFIG['GNU_CC']:
+            mozglue = None
+            if linkage == 'dependent':
+                USE_LIBS += [
+                    'mozalloc_staticruntime',
+                ]
+    else:
+        error('msvcrt must be "dynamic" or "static"')
+
+    if linkage == 'dependent':
+        USE_LIBS += [
+            'nspr',
+            '%s_s' % xpcomglue,
+            'xul',
+        ]
+    elif linkage == 'standalone':
+        DEFINES['XPCOM_GLUE'] = True
+
+        USE_LIBS += [
+            xpcomglue,
+        ]
+    elif linkage != None:
+        error('`linkage` must be "dependent", "standalone" or None')
+
+    if mozglue:
+        if CONFIG['MOZ_CRT']:
+            if msvcrt == 'dynamic':
+                USE_LIBS += ['mozcrt']
+            elif msvcrt == 'static':
+                USE_LIBS += ['mozglue']
+            else:
+                error('`msvcrt` must be "dynamic" or "static"')
+        else:
+            LDFLAGS += CONFIG['MOZ_GLUE_WRAP_LDFLAGS']
+            if mozglue == 'program':
+                USE_LIBS += ['mozglue']
+                if CONFIG['MOZ_GLUE_IN_PROGRAM']:
+                    if CONFIG['GNU_CC']:
+                        LDFLAGS += ['-rdynamic']
+                    if CONFIG['MOZ_MEMORY']:
+                        USE_LIBS += ['memory']
+                    if CONFIG['MOZ_LINKER']:
+                        OS_LIBS += CONFIG['MOZ_ZLIB_LIBS']
+            elif mozglue == 'library':
+                if not CONFIG['MOZ_GLUE_IN_PROGRAM']:
+                    USE_LIBS += ['mozglue']
+            else:
+                error('`mozglue` must be "program" or "library"')
+
+    if not CONFIG['JS_STANDALONE']:
+        USE_LIBS += [
+            'fallible',
+        ]
+
+
+@template
+def GeckoProgram(name, linkage='standalone', **kwargs):
+    '''Template for program executables related to Gecko.
+
+    `name` identifies the executable base name.
+
+    See the documentation for `GeckoBinary` for other possible arguments,
+    with the notable difference that the default for `linkage` is 'standalone'.
+    '''
+    Program(name)
+
+    kwargs.setdefault('mozglue', 'program')
+
+    GeckoBinary(linkage=linkage, **kwargs)
+
+
+@template
+def GeckoSimplePrograms(names, **kwargs):
+    '''Template for simple program executables related to Gecko.
+
+    `names` identifies the executable base names for each executable.
+
+    See the documentation for `GeckoBinary` for other possible arguments.
+    '''
+    SimplePrograms(names)
+
+    kwargs.setdefault('mozglue', 'program')
+
+    GeckoBinary(**kwargs)
+
+
+@template
+def GeckoCppUnitTests(names, **kwargs):
+    '''Template for C++ unit tests related to Gecko.
+
+    `names` identifies the executable base names for each executable.
+
+    See the documentation for `GeckoBinary` for other possible arguments.
+    '''
+    CppUnitTests(names)
+
+    kwargs.setdefault('mozglue', 'program')
+
+    GeckoBinary(**kwargs)
+
+
+@template
+def GeckoSharedLibrary(name, **kwargs):
+    '''Template for shared libraries related to Gecko.
+
+    `name` identifies the library base name.
+    See the documentation for `GeckoBinary` for other possible arguments.
+    '''
+    SharedLibrary(name)
+
+    kwargs.setdefault('mozglue', 'library')
+
+    GeckoBinary(**kwargs)
+
+
+@template
+def GeckoFramework(name, **kwargs):
+    '''Template for OSX frameworks related to Gecko.
+
+    `name` identifies the library base name.
+    See the documentation for `GeckoBinary` for other possible arguments.
+    '''
+    Framework(name)
+
+    kwargs.setdefault('mozglue', 'library')
+
+    GeckoBinary(**kwargs)
+
+
+@template
+def XPCOMBinaryComponent(name):
+    '''Template defining an XPCOM binary component for Gecko.
+
+    `name` is the name of the component.
+    '''
+    GeckoSharedLibrary(name)
+
+    IS_COMPONENT = True
diff --git a/src/third_party/mozjs-45/build/gen_test_packages_manifest.py b/src/third_party/mozjs-45/build/gen_test_packages_manifest.py
new file mode 100644
index 0000000..d762e58
--- /dev/null
+++ b/src/third_party/mozjs-45/build/gen_test_packages_manifest.py
@@ -0,0 +1,80 @@
+#!/usr/bin/python
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+import json
+
+from argparse import ArgumentParser
+
+ALL_HARNESSES = [
+    'common', # Harnesses without a specific package will look here.
+    'mochitest',
+    'reftest',
+    'webapprt',
+    'xpcshell',
+    'cppunittest',
+    'jittest',
+    'mozbase',
+    'web-platform',
+    'talos',
+]
+
+PACKAGE_SPECIFIED_HARNESSES = [
+    'cppunittest',
+    'mochitest',
+    'reftest',
+    'xpcshell',
+    'web-platform',
+    'talos',
+]
+
+
+def parse_args():
+    parser = ArgumentParser(description='Generate a test_packages.json file to tell automation which harnesses require which test packages.')
+    parser.add_argument("--common", required=True,
+                        action="store", dest="tests_common",
+                        help="Name of the \"common\" archive, a package to be used by all harnesses.")
+    parser.add_argument("--jsshell", required=True,
+                        action="store", dest="jsshell",
+                        help="Name of the jsshell zip.")
+    parser.add_argument("--use-short-names", action="store_true",
+                        help="Use short names for packages (target.$name.tests.zip "
+                             "instead of $(PACKAGE_BASENAME).$name.tests.zip)")
+    for harness in PACKAGE_SPECIFIED_HARNESSES:
+        parser.add_argument("--%s" % harness, required=True,
+                            action="store", dest=harness,
+                            help="Name of the %s zip." % harness)
+    parser.add_argument("--dest-file", required=True,
+                        action="store", dest="destfile",
+                        help="Path to the output file to be written.")
+    return parser.parse_args()
+
+def generate_package_data(args):
+    # Generate a dictionary mapping test harness names (exactly as they're known to
+    # mozharness and testsuite-targets.mk, ideally) to the set of archive names that
+    # harness depends on to run.
+    # mozharness will use this file to determine what test zips to download,
+    # which will be an optimization once parts of the main zip are split to harness
+    # specific zips.
+    tests_common = args.tests_common
+    if args.use_short_names:
+        tests_common = 'target.common.tests.zip'
+
+    jsshell = args.jsshell
+
+    harness_requirements = dict([(k, [tests_common]) for k in ALL_HARNESSES])
+    harness_requirements['jittest'].append(jsshell)
+    for harness in PACKAGE_SPECIFIED_HARNESSES:
+        pkg_name = getattr(args, harness)
+        if args.use_short_names:
+            pkg_name = 'target.%s.tests.zip' % harness
+        harness_requirements[harness].append(pkg_name)
+    return harness_requirements
+
+if __name__ == '__main__':
+    args = parse_args()
+    packages_data = generate_package_data(args)
+    with open(args.destfile, 'w') as of:
+        json.dump(packages_data, of, indent=4)
diff --git a/src/third_party/mozjs-45/build/genrc.sh b/src/third_party/mozjs-45/build/genrc.sh
new file mode 100755
index 0000000..c0c6194
--- /dev/null
+++ b/src/third_party/mozjs-45/build/genrc.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+DATATYPE="$1"
+INFILE="$2"
+
+echo "${DATATYPE} RCDATA"
+sed 's/"/""/g' ${INFILE} | awk 'BEGIN { printf("BEGIN\n") } { printf("\"%s\\r\\n\",\n", $0) } END { printf("\"\\0\"\nEND\n") }'
+
+exit 0
diff --git a/src/third_party/mozjs-45/build/gyp.mozbuild b/src/third_party/mozjs-45/build/gyp.mozbuild
new file mode 100644
index 0000000..2ae5ac0
--- /dev/null
+++ b/src/third_party/mozjs-45/build/gyp.mozbuild
@@ -0,0 +1,135 @@
+# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+gyp_vars = {
+    'lsan': 0,
+    'asan': 0,
+    'build_with_mozilla': 1,
+    'build_with_chromium': 0,
+    'use_official_google_api_keys': 0,
+    'have_clock_monotonic': 1 if CONFIG['HAVE_CLOCK_MONOTONIC'] else 0,
+    'have_ethtool_cmd_speed_hi': 1 if CONFIG['MOZ_WEBRTC_HAVE_ETHTOOL_SPEED_HI'] else 0,
+    'include_alsa_audio': 1 if CONFIG['MOZ_ALSA'] else 0,
+    'include_pulse_audio': 1 if CONFIG['MOZ_PULSEAUDIO'] else 0,
+    # basic stuff for everything
+    'include_internal_video_render': 0,
+    'clang_use_chrome_plugins': 0,
+    'enable_protobuf': 0,
+    'include_tests': 0,
+    'enable_android_opensl': 1,
+    'enable_android_opensl_output': 0,
+    # use_system_lib* still seems to be in use in trunk/build
+    'use_system_libjpeg': 0,
+    'use_system_libvpx': 0,
+    'build_json': 0,
+    'build_libjpeg': 0,
+    'build_libyuv': 0,
+    'build_libvpx': 0,
+    'build_ssl': 0,
+    'build_json': 0,
+    'build_icu': 0,
+    'build_opus': 0,
+    'libyuv_dir': '/media/libyuv',
+    'yuv_disable_avx2': 0 if CONFIG['HAVE_X86_AVX2'] else 1,
+    # don't use openssl
+    'use_openssl': 0,
+
+    'use_x11': 1 if CONFIG['MOZ_X11'] else 0,
+    'use_glib': 1 if CONFIG['GLIB_LIBS'] else 0,
+
+     # turn off mandatory use of NEON and instead use NEON detection
+    'arm_neon': 0,
+    'arm_neon_optional': 1,
+
+    'moz_widget_toolkit_gonk': 0,
+    'moz_webrtc_omx': 0,
+    'moz_webrtc_mediacodec': 0,
+
+    # Turn off multi monitor screen share
+    'multi_monitor_screenshare%' : 0,
+
+    # (for vp8) chromium sets to 0 also
+    'use_temporal_layers': 0,
+
+    # Creates AEC internal sample dump files in current directory
+    'aec_debug_dump': 1,
+
+    # Enable and force use of hardware AEC
+    'hardware_aec_ns': 1 if CONFIG['MOZ_WEBRTC_HARDWARE_AEC_NS'] else 0,
+
+    # codec enable/disables:
+    'include_g711': 1,
+    'include_opus': 1,
+    'include_g722': 1,
+    'include_ilbc': 0,
+    # We turn on ISAC because the AGC uses parts of it, and depend on the
+    # linker to throw away uneeded bits.
+    'include_isac': 1,
+    'include_pcm16b': 1,
+}
+
+os = CONFIG['OS_TARGET']
+
+if os == 'WINNT':
+    gyp_vars.update(
+        MSVS_VERSION=CONFIG['_MSVS_VERSION'],
+        MSVS_OS_BITS=64 if CONFIG['HAVE_64BIT_BUILD'] else 32,
+    )
+elif os == 'Android':
+    if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
+        gyp_vars['build_with_gonk'] = 1
+        gyp_vars['moz_widget_toolkit_gonk'] = 1
+        gyp_vars['opus_complexity'] = 1
+        if int(CONFIG['ANDROID_VERSION']) >= 18:
+          gyp_vars['moz_webrtc_omx'] = 1
+    else:
+        gyp_vars.update(
+            gtest_target_type='executable',
+            moz_webrtc_mediacodec=1,
+            android_toolchain=CONFIG['ANDROID_TOOLCHAIN'],
+        )
+
+flavors = {
+    'WINNT': 'win',
+    'Android': 'linux' if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' else 'android',
+    'Linux': 'linux',
+    'Darwin': 'mac' if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa' else 'ios',
+    'SunOS': 'solaris',
+    'GNU/kFreeBSD': 'freebsd',
+    'DragonFly': 'dragonfly',
+    'FreeBSD': 'freebsd',
+    'NetBSD': 'netbsd',
+    'OpenBSD': 'openbsd',
+}
+gyp_vars['OS'] = flavors.get(os)
+
+arches = {
+    'x86_64': 'x64',
+    'x86': 'ia32',
+}
+
+gyp_vars['target_arch'] = arches.get(CONFIG['CPU_ARCH'], CONFIG['CPU_ARCH'])
+
+if CONFIG['ARM_ARCH']:
+    if int(CONFIG['ARM_ARCH']) < 7:
+        gyp_vars['armv7'] = 0
+        gyp_vars['arm_neon_optional'] = 0
+    elif os == 'Android':
+        gyp_vars['armv7'] = 1
+    else:
+        # CPU detection for ARM works on Android only.  armv7 always uses CPU
+        # detection, so we have to set armv7=0 for non-Android target
+        gyp_vars['armv7'] = 0
+    # For libyuv
+    gyp_vars['arm_version'] = int(CONFIG['ARM_ARCH'])
+
+# Don't try to compile ssse3/sse4.1 code if toolchain doesn't support
+if CONFIG['INTEL_ARCHITECTURE']:
+    if not CONFIG['HAVE_TOOLCHAIN_SUPPORT_MSSSE3'] or not CONFIG['HAVE_TOOLCHAIN_SUPPORT_MSSE4_1']:
+        gyp_vars['yuv_disable_asm'] = 1
+
+if CONFIG['MACOS_SDK_DIR']:
+    gyp_vars['mac_sdk_path'] = CONFIG['MACOS_SDK_DIR']
diff --git a/src/third_party/mozjs-45/build/mach_bootstrap.py b/src/third_party/mozjs-45/build/mach_bootstrap.py
new file mode 100644
index 0000000..4f7365b
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mach_bootstrap.py
@@ -0,0 +1,383 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+from __future__ import print_function, unicode_literals
+
+import errno
+import os
+import platform
+import sys
+import time
+import __builtin__
+
+from types import ModuleType
+
+
+STATE_DIR_FIRST_RUN = '''
+mach and the build system store shared state in a common directory on the
+filesystem. The following directory will be created:
+
+  {userdir}
+
+If you would like to use a different directory, hit CTRL+c and set the
+MOZBUILD_STATE_PATH environment variable to the directory you would like to
+use and re-run mach. For this change to take effect forever, you'll likely
+want to export this environment variable from your shell's init scripts.
+'''.lstrip()
+
+NO_MERCURIAL_SETUP = '''
+*** MERCURIAL NOT CONFIGURED ***
+
+mach has detected that you have never run `{mach} mercurial-setup`.
+
+Running this command will ensure your Mercurial version control tool is up
+to date and optimally configured for a better, more productive experience
+when working on Mozilla projects.
+
+Please run `{mach} mercurial-setup` now.
+
+Note: `{mach} mercurial-setup` does not make any changes without prompting
+you first.
+'''.strip()
+
+MERCURIAL_SETUP_FATAL_INTERVAL = 31 * 24 * 60 * 60
+
+
+# TODO Bug 794506 Integrate with the in-tree virtualenv configuration.
+SEARCH_PATHS = [
+    'python/mach',
+    'python/mozboot',
+    'python/mozbuild',
+    'python/mozversioncontrol',
+    'python/blessings',
+    'python/compare-locales',
+    'python/configobj',
+    'python/jsmin',
+    'python/psutil',
+    'python/which',
+    'python/pystache',
+    'python/pyyaml/lib',
+    'python/requests',
+    'python/slugid',
+    'build',
+    'config',
+    'dom/bindings',
+    'dom/bindings/parser',
+    'layout/tools/reftest',
+    'other-licenses/ply',
+    'testing',
+    'testing/firefox-ui/harness',
+    'testing/firefox-ui/tests',
+    'testing/luciddream',
+    'testing/marionette/client',
+    'testing/marionette/client/marionette/runner/mixins/browsermob-proxy-py',
+    'testing/marionette/transport',
+    'testing/marionette/driver',
+    'testing/mozbase/mozcrash',
+    'testing/mozbase/mozdebug',
+    'testing/mozbase/mozdevice',
+    'testing/mozbase/mozfile',
+    'testing/mozbase/mozhttpd',
+    'testing/mozbase/mozinfo',
+    'testing/mozbase/mozinstall',
+    'testing/mozbase/mozleak',
+    'testing/mozbase/mozlog',
+    'testing/mozbase/moznetwork',
+    'testing/mozbase/mozprocess',
+    'testing/mozbase/mozprofile',
+    'testing/mozbase/mozrunner',
+    'testing/mozbase/mozsystemmonitor',
+    'testing/mozbase/mozscreenshot',
+    'testing/mozbase/moztest',
+    'testing/mozbase/mozversion',
+    'testing/mozbase/manifestparser',
+    'testing/puppeteer/firefox',
+    'testing/taskcluster',
+    'testing/tools/autotry',
+    'testing/web-platform',
+    'testing/web-platform/harness',
+    'testing/web-platform/tests/tools/wptserve',
+    'testing/xpcshell',
+    'xpcom/idl-parser',
+]
+
+# Individual files providing mach commands.
+MACH_MODULES = [
+    'addon-sdk/mach_commands.py',
+    'build/valgrind/mach_commands.py',
+    'dom/bindings/mach_commands.py',
+    'layout/tools/reftest/mach_commands.py',
+    'python/mach_commands.py',
+    'python/mach/mach/commands/commandinfo.py',
+    'python/compare-locales/mach_commands.py',
+    'python/mozboot/mozboot/mach_commands.py',
+    'python/mozbuild/mozbuild/mach_commands.py',
+    'python/mozbuild/mozbuild/backend/mach_commands.py',
+    'python/mozbuild/mozbuild/compilation/codecomplete.py',
+    'python/mozbuild/mozbuild/frontend/mach_commands.py',
+    'services/common/tests/mach_commands.py',
+    'testing/firefox-ui/mach_commands.py',
+    'testing/luciddream/mach_commands.py',
+    'testing/mach_commands.py',
+    'testing/marionette/mach_commands.py',
+    'testing/mochitest/mach_commands.py',
+    'testing/mozharness/mach_commands.py',
+    'testing/talos/mach_commands.py',
+    'testing/taskcluster/mach_commands.py',
+    'testing/web-platform/mach_commands.py',
+    'testing/xpcshell/mach_commands.py',
+    'tools/docs/mach_commands.py',
+    'tools/mercurial/mach_commands.py',
+    'tools/mach_commands.py',
+    'tools/power/mach_commands.py',
+    'mobile/android/mach_commands.py',
+]
+
+
+CATEGORIES = {
+    'build': {
+        'short': 'Build Commands',
+        'long': 'Interact with the build system',
+        'priority': 80,
+    },
+    'post-build': {
+        'short': 'Post-build Commands',
+        'long': 'Common actions performed after completing a build.',
+        'priority': 70,
+    },
+    'testing': {
+        'short': 'Testing',
+        'long': 'Run tests.',
+        'priority': 60,
+    },
+    'ci': {
+        'short': 'CI',
+        'long': 'Taskcluster commands',
+        'priority': 59
+    },
+    'devenv': {
+        'short': 'Development Environment',
+        'long': 'Set up and configure your development environment.',
+        'priority': 50,
+    },
+    'build-dev': {
+        'short': 'Low-level Build System Interaction',
+        'long': 'Interact with specific parts of the build system.',
+        'priority': 20,
+    },
+    'misc': {
+        'short': 'Potpourri',
+        'long': 'Potent potables and assorted snacks.',
+        'priority': 10,
+    },
+    'disabled': {
+        'short': 'Disabled',
+        'long': 'The disabled commands are hidden by default. Use -v to display them. These commands are unavailable for your current context, run "mach <command>" to see why.',
+        'priority': 0,
+    }
+}
+
+
+def get_state_dir():
+    """Obtain the path to a directory to hold state.
+
+    Returns a tuple of the path and a bool indicating whether the value came
+    from an environment variable.
+    """
+    state_user_dir = os.path.expanduser('~/.mozbuild')
+    state_env_dir = os.environ.get('MOZBUILD_STATE_PATH', None)
+
+    if state_env_dir:
+        return state_env_dir, True
+    else:
+        return state_user_dir, False
+
+
+def bootstrap(topsrcdir, mozilla_dir=None):
+    if mozilla_dir is None:
+        mozilla_dir = topsrcdir
+
+    # Ensure we are running Python 2.7+. We put this check here so we generate a
+    # user-friendly error message rather than a cryptic stack trace on module
+    # import.
+    if sys.version_info[0] != 2 or sys.version_info[1] < 7:
+        print('Python 2.7 or above (but not Python 3) is required to run mach.')
+        print('You are running Python', platform.python_version())
+        sys.exit(1)
+
+    # Global build system and mach state is stored in a central directory. By
+    # default, this is ~/.mozbuild. However, it can be defined via an
+    # environment variable. We detect first run (by lack of this directory
+    # existing) and notify the user that it will be created. The logic for
+    # creation is much simpler for the "advanced" environment variable use
+    # case. For default behavior, we educate users and give them an opportunity
+    # to react. We always exit after creating the directory because users don't
+    # like surprises.
+    try:
+        import mach.main
+    except ImportError:
+        sys.path[0:0] = [os.path.join(mozilla_dir, path) for path in SEARCH_PATHS]
+        import mach.main
+
+    def pre_dispatch_handler(context, handler, args):
+        """Perform global checks before command dispatch.
+
+        Currently, our goal is to ensure developers periodically run
+        `mach mercurial-setup` (when applicable) to ensure their Mercurial
+        tools are up to date.
+        """
+        # Don't do anything when...
+
+        # The user is performing a maintenance command.
+        if handler.name in ('bootstrap', 'doctor', 'mach-commands', 'mercurial-setup'):
+            return
+
+        # We are running in automation.
+        if 'MOZ_AUTOMATION' in os.environ or 'TASK_ID' in os.environ:
+            return
+
+        # We are a curmudgeon who has found this undocumented variable.
+        if 'I_PREFER_A_SUBOPTIMAL_MERCURIAL_EXPERIENCE' in os.environ:
+            return
+
+        # The environment is likely a machine invocation.
+        if sys.stdin.closed or not sys.stdin.isatty():
+            return
+
+        # Mercurial isn't managing this source checkout.
+        if not os.path.exists(os.path.join(topsrcdir, '.hg')):
+            return
+
+        state_dir = get_state_dir()[0]
+        last_check_path = os.path.join(state_dir, 'mercurial',
+                                       'setup.lastcheck')
+
+        mtime = None
+        try:
+            mtime = os.path.getmtime(last_check_path)
+        except OSError as e:
+            if e.errno != errno.ENOENT:
+                raise
+
+        # No last run file means mercurial-setup has never completed.
+        if mtime is None:
+            print(NO_MERCURIAL_SETUP.format(mach=sys.argv[0]), file=sys.stderr)
+            sys.exit(2)
+
+    def populate_context(context, key=None):
+        if key is None:
+            return
+        if key == 'state_dir':
+            state_dir, is_environ = get_state_dir()
+            if is_environ:
+                if not os.path.exists(state_dir):
+                    print('Creating global state directory from environment variable: %s'
+                        % state_dir)
+                    os.makedirs(state_dir, mode=0o770)
+                    print('Please re-run mach.')
+                    sys.exit(1)
+            else:
+                if not os.path.exists(state_dir):
+                    print(STATE_DIR_FIRST_RUN.format(userdir=state_dir))
+                    try:
+                        for i in range(20, -1, -1):
+                            time.sleep(1)
+                            sys.stdout.write('%d ' % i)
+                            sys.stdout.flush()
+                    except KeyboardInterrupt:
+                        sys.exit(1)
+
+                    print('\nCreating default state directory: %s' % state_dir)
+                    os.mkdir(state_dir)
+                    print('Please re-run mach.')
+                    sys.exit(1)
+
+            return state_dir
+
+        if key == 'topdir':
+            return topsrcdir
+
+        if key == 'pre_dispatch_handler':
+            return pre_dispatch_handler
+
+        raise AttributeError(key)
+
+    mach = mach.main.Mach(os.getcwd())
+    mach.populate_context_handler = populate_context
+
+    for category, meta in CATEGORIES.items():
+        mach.define_category(category, meta['short'], meta['long'],
+            meta['priority'])
+
+    for path in MACH_MODULES:
+        mach.load_commands_from_file(os.path.join(mozilla_dir, path))
+
+    return mach
+
+
+# Hook import such that .pyc/.pyo files without a corresponding .py file in
+# the source directory are essentially ignored. See further below for details
+# and caveats.
+# Objdirs outside the source directory are ignored because in most cases, if
+# a .pyc/.pyo file exists there, a .py file will be next to it anyways.
+class ImportHook(object):
+    def __init__(self, original_import):
+        self._original_import = original_import
+        # Assume the source directory is the parent directory of the one
+        # containing this file.
+        self._source_dir = os.path.normcase(os.path.abspath(
+            os.path.dirname(os.path.dirname(__file__)))) + os.sep
+        self._modules = set()
+
+    def __call__(self, name, globals=None, locals=None, fromlist=None,
+                 level=-1):
+        # name might be a relative import. Instead of figuring out what that
+        # resolves to, which is complex, just rely on the real import.
+        # Since we don't know the full module name, we can't check sys.modules,
+        # so we need to keep track of which modules we've already seen to avoid
+        # to stat() them again when they are imported multiple times.
+        module = self._original_import(name, globals, locals, fromlist, level)
+
+        # Some tests replace modules in sys.modules with non-module instances.
+        if not isinstance(module, ModuleType):
+            return module
+
+        resolved_name = module.__name__
+        if resolved_name in self._modules:
+            return module
+        self._modules.add(resolved_name)
+
+        # Builtin modules don't have a __file__ attribute.
+        if not hasattr(module, '__file__'):
+            return module
+
+        # Note: module.__file__ is not always absolute.
+        path = os.path.normcase(os.path.abspath(module.__file__))
+        # Note: we could avoid normcase and abspath above for non pyc/pyo
+        # files, but those are actually rare, so it doesn't really matter.
+        if not path.endswith(('.pyc', '.pyo')):
+            return module
+
+        # Ignore modules outside our source directory
+        if not path.startswith(self._source_dir):
+            return module
+
+        # If there is no .py corresponding to the .pyc/.pyo module we're
+        # loading, remove the .pyc/.pyo file, and reload the module.
+        # Since we already loaded the .pyc/.pyo module, if it had side
+        # effects, they will have happened already, and loading the module
+        # with the same name, from another directory may have the same side
+        # effects (or different ones). We assume it's not a problem for the
+        # python modules under our source directory (either because it
+        # doesn't happen or because it doesn't matter).
+        if not os.path.exists(module.__file__[:-1]):
+            os.remove(module.__file__)
+            del sys.modules[module.__name__]
+            module = self(name, globals, locals, fromlist, level)
+
+        return module
+
+
+# Install our hook
+__builtin__.__import__ = ImportHook(__builtin__.__import__)
diff --git a/src/third_party/mozjs-45/build/macosx/cross-mozconfig.common b/src/third_party/mozjs-45/build/macosx/cross-mozconfig.common
new file mode 100644
index 0000000..6247ca1
--- /dev/null
+++ b/src/third_party/mozjs-45/build/macosx/cross-mozconfig.common
@@ -0,0 +1,52 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+MOZ_AUTOMATION_L10N_CHECK=0
+
+if [ "x$IS_NIGHTLY" = "xyes" ]; then
+  # Some nightlies (eg: Mulet) don't want these set.
+  MOZ_AUTOMATION_UPDATE_PACKAGING=${MOZ_AUTOMATION_UPDATE_PACKAGING-1}
+  MOZ_AUTOMATION_SDK=${MOZ_AUTOMATION_SDK-1}
+fi
+. "$topsrcdir/build/mozconfig.common"
+
+# ld needs libLTO.so from llvm
+mk_add_options "export LD_LIBRARY_PATH=$topsrcdir/clang/lib"
+
+CROSS_CCTOOLS_PATH=$topsrcdir/cctools
+CROSS_SYSROOT=$topsrcdir/MacOSX10.7.sdk
+CROSS_PRIVATE_FRAMEWORKS=$CROSS_SYSROOT/System/Library/PrivateFrameworks
+FLAGS="-target x86_64-apple-darwin10 -mlinker-version=136 -B $CROSS_CCTOOLS_PATH/bin -isysroot $CROSS_SYSROOT"
+
+export CC="$topsrcdir/clang/bin/clang $FLAGS"
+export CXX="$topsrcdir/clang/bin/clang++ $FLAGS"
+export CPP="$topsrcdir/clang/bin/clang $FLAGS -E"
+export LLVMCONFIG=$topsrcdir/clang/bin/llvm-config
+export LDFLAGS="-Wl,-syslibroot,$CROSS_SYSROOT -Wl,-dead_strip"
+export TOOLCHAIN_PREFIX=$CROSS_CCTOOLS_PATH/bin/x86_64-apple-darwin10-
+#TODO: bug 1184202 - would be nice if these could be detected with TOOLCHAIN_PREFIX automatically
+export AR=${TOOLCHAIN_PREFIX}ar
+export RANLIB=${TOOLCHAIN_PREFIX}ranlib
+export STRIP=${TOOLCHAIN_PREFIX}strip
+export OTOOL=${TOOLCHAIN_PREFIX}otool
+export DSYMUTIL=$topsrcdir/clang/bin/llvm-dsymutil
+export GENISOIMAGE=$topsrcdir/genisoimage/genisoimage
+export DMG_TOOL=$topsrcdir/dmg/dmg
+
+export HOST_CC="$topsrcdir/clang/bin/clang"
+export HOST_CXX="$topsrcdir/clang/bin/clang++"
+export HOST_CPP="$topsrcdir/clang/bin/clang -E"
+export HOST_CFLAGS="-g"
+export HOST_CXXFLAGS="-g"
+export HOST_LDFLAGS="-g"
+
+ac_add_options --target=x86_64-apple-darwin
+ac_add_options --with-macos-private-frameworks=$CROSS_PRIVATE_FRAMEWORKS
+
+# Enable static analysis checks by default on OSX cross builds.
+ac_add_options --enable-clang-plugin
+
+. "$topsrcdir/build/mozconfig.cache"
+
+export SOCORRO_SYMBOL_UPLOAD_TOKEN_FILE=/builds/crash-stats-api.token
diff --git a/src/third_party/mozjs-45/build/macosx/local-mozconfig.common b/src/third_party/mozjs-45/build/macosx/local-mozconfig.common
new file mode 100644
index 0000000..39e162d
--- /dev/null
+++ b/src/third_party/mozjs-45/build/macosx/local-mozconfig.common
@@ -0,0 +1,39 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+MOZ_AUTOMATION_L10N_CHECK=0
+
+if [ "x$IS_NIGHTLY" = "xyes" ]; then
+  # Some nightlies (eg: Mulet) don't want these set.
+  MOZ_AUTOMATION_UPLOAD_SYMBOLS=${MOZ_AUTOMATION_UPLOAD_SYMBOLS-1}
+  MOZ_AUTOMATION_UPDATE_PACKAGING=${MOZ_AUTOMATION_UPDATE_PACKAGING-1}
+  MOZ_AUTOMATION_SDK=${MOZ_AUTOMATION_SDK-1}
+fi
+. "$topsrcdir/build/mozconfig.common"
+
+if [ -d "$topsrcdir/clang" ]; then
+    # mozilla-central based build
+    export CC=$topsrcdir/clang/bin/clang
+    export CXX=$topsrcdir/clang/bin/clang++
+    export LLVMCONFIG=$topsrcdir/clang/bin/llvm-config
+    export DSYMUTIL=$topsrcdir/clang/bin/llvm-dsymutil
+elif [ -d "$topsrcdir/../clang" ]; then
+    # comm-central based build
+    export CC=$topsrcdir/../clang/bin/clang
+    export CXX=$topsrcdir/../clang/bin/clang++
+    export LLVMCONFIG=$topsrcdir/../clang/bin/llvm-config
+    export DSYMUTIL=$topsrcdir/../clang/bin/llvm-dsymutil
+fi
+
+# If not set use the system default clang
+if [ -z "$CC" ]; then
+    export CC=clang
+fi
+
+# If not set use the system default clang++
+if [ -z "$CXX" ]; then
+    export CXX=clang++
+fi
+
+export SOCORRO_SYMBOL_UPLOAD_TOKEN_FILE=/builds/crash-stats-api.token
diff --git a/src/third_party/mozjs-45/build/macosx/mozconfig.common b/src/third_party/mozjs-45/build/macosx/mozconfig.common
new file mode 100644
index 0000000..27634b7
--- /dev/null
+++ b/src/third_party/mozjs-45/build/macosx/mozconfig.common
@@ -0,0 +1,5 @@
+if test `uname -s` = Linux; then
+  . $topsrcdir/build/macosx/cross-mozconfig.common
+else
+  . $topsrcdir/build/macosx/local-mozconfig.common
+fi
diff --git a/src/third_party/mozjs-45/build/macosx/mozconfig.rust b/src/third_party/mozjs-45/build/macosx/mozconfig.rust
new file mode 100644
index 0000000..92d9a60
--- /dev/null
+++ b/src/third_party/mozjs-45/build/macosx/mozconfig.rust
@@ -0,0 +1,6 @@
+# Options to enable rust in automation builds.
+
+if test `uname -s` != Linux; then
+RUSTC="$topsrcdir/rustc/bin/rustc"
+ac_add_options --enable-rust
+fi
diff --git a/src/third_party/mozjs-45/build/macosx/permissions/chown_revert.c b/src/third_party/mozjs-45/build/macosx/permissions/chown_revert.c
new file mode 100644
index 0000000..2cf3e37
--- /dev/null
+++ b/src/third_party/mozjs-45/build/macosx/permissions/chown_revert.c
@@ -0,0 +1,20 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include <unistd.h>
+#include <stdio.h>
+
+int main(int argc, char **argv)
+{
+  if (argc != 2)
+    return 1;
+
+  uid_t realuser = getuid();
+  char uidstring[20];
+  snprintf(uidstring, 19, "%i", realuser);
+  uidstring[19] = '\0';
+
+  return execl("/usr/sbin/chown",
+               "/usr/sbin/chown", "-R", "-h", uidstring, argv[1], (char*) 0);
+}
diff --git a/src/third_party/mozjs-45/build/macosx/permissions/chown_root.c b/src/third_party/mozjs-45/build/macosx/permissions/chown_root.c
new file mode 100644
index 0000000..c9b13a5
--- /dev/null
+++ b/src/third_party/mozjs-45/build/macosx/permissions/chown_root.c
@@ -0,0 +1,14 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include <unistd.h>
+
+int main(int argc, char **argv)
+{
+  if (argc != 2)
+    return 1;
+
+  return execl("/usr/sbin/chown",
+               "/usr/sbin/chown", "-R", "-h", "root:admin", argv[1], (char*) 0);
+}
diff --git a/src/third_party/mozjs-45/build/macosx/universal/flight.mk b/src/third_party/mozjs-45/build/macosx/universal/flight.mk
new file mode 100644
index 0000000..71672d4
--- /dev/null
+++ b/src/third_party/mozjs-45/build/macosx/universal/flight.mk
@@ -0,0 +1,31 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# BE CAREFUL!  This makefile handles a postflight_all rule for a
+# multi-project build, so DON'T rely on anything that might differ between
+# the two OBJDIRs.
+
+ifndef OBJDIR
+OBJDIR_ARCH_1 = $(MOZ_OBJDIR)/$(firstword $(MOZ_BUILD_PROJECTS))
+OBJDIR_ARCH_2 = $(MOZ_OBJDIR)/$(word 2,$(MOZ_BUILD_PROJECTS))
+DIST_ARCH_1 = $(OBJDIR_ARCH_1)/dist
+DIST_ARCH_2 = $(OBJDIR_ARCH_2)/dist
+DIST_UNI = $(DIST_ARCH_1)/universal
+OBJDIR = $(OBJDIR_ARCH_1)
+endif
+
+topsrcdir = $(TOPSRCDIR)
+DEPTH = $(OBJDIR)
+include $(OBJDIR)/config/autoconf.mk
+
+DIST = $(OBJDIR)/dist
+
+postflight_all:
+	mkdir -p $(DIST_UNI)/$(MOZ_PKG_APPNAME)
+	rm -f $(DIST_ARCH_2)/universal
+	ln -s $(abspath $(DIST_UNI)) $(DIST_ARCH_2)/universal
+# Stage a package for buildsymbols to be happy. Doing so in OBJDIR_ARCH_1
+# actually does a universal staging with both OBJDIR_ARCH_1 and OBJDIR_ARCH_2.
+	$(MAKE) -C $(OBJDIR_ARCH_1)/$(MOZ_BUILD_APP)/installer \
+	   PKG_SKIP_STRIP=1 stage-package
diff --git a/src/third_party/mozjs-45/build/macosx/universal/mozconfig b/src/third_party/mozjs-45/build/macosx/universal/mozconfig
new file mode 100644
index 0000000..32ab66f
--- /dev/null
+++ b/src/third_party/mozjs-45/build/macosx/universal/mozconfig
@@ -0,0 +1,11 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# i386/x86-64 Universal Build mozconfig
+
+# As used here, arguments in $MOZ_BUILD_PROJECTS are suitable as arguments
+# to gcc's -arch parameter.
+mk_add_options MOZ_BUILD_PROJECTS="x86_64 i386"
+
+. $topsrcdir/build/macosx/universal/mozconfig.common
diff --git a/src/third_party/mozjs-45/build/macosx/universal/mozconfig.common b/src/third_party/mozjs-45/build/macosx/universal/mozconfig.common
new file mode 100644
index 0000000..518274b
--- /dev/null
+++ b/src/third_party/mozjs-45/build/macosx/universal/mozconfig.common
@@ -0,0 +1,54 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+mk_add_options MOZ_UNIFY_BDATE=1
+
+mk_add_options MOZ_POSTFLIGHT_ALL+=build/macosx/universal/flight.mk
+
+DARWIN_VERSION=`uname -r`
+ac_add_app_options i386 --target=i386-apple-darwin$DARWIN_VERSION
+ac_add_app_options x86_64 --target=x86_64-apple-darwin$DARWIN_VERSION
+ac_add_app_options i386 --with-unify-dist=../x86_64/dist
+ac_add_app_options x86_64 --with-unify-dist=../i386/dist
+
+ac_add_options --with-macos-sdk=/Developer/SDKs/MacOSX10.7.sdk
+
+. $topsrcdir/build/macosx/mozconfig.common
+
+# $MOZ_BUILD_APP is only defined when sourced by configure.  That's not a
+# problem, because the variables it affects only need to be set for
+# configure.
+if test -n "$MOZ_BUILD_APP" ; then
+if test "$MOZ_BUILD_APP" = "i386" -o "$MOZ_BUILD_APP" = "x86_64"; then
+  TARGET_CPU=$MOZ_BUILD_APP
+
+  # $HOST_CXX is presently unused.  $HOST_CC will only be used during a cross
+  # compile.
+  HOST_CC=$CC
+  HOST_CXX=$CXX
+
+  NATIVE_CPU=`$topsrcdir/build/autoconf/config.guess | cut -f1 -d-`
+
+  # It's not strictly necessary to specify -arch during native builds, but it
+  # makes the merged about:buildconfig easier to follow, and it reduces
+  # conditionalized differences between builds.
+  CC="$CC -arch $TARGET_CPU"
+  CXX="$CXX -arch $TARGET_CPU"
+
+  # These must be set for cross builds, and don't hurt straight builds.
+  RANLIB=ranlib
+  AR=ar
+  AS=$CC
+  LD=ld
+  STRIP="strip"
+  OTOOL="otool"
+
+  # Each per-CPU build should be entirely oblivious to the fact that a
+  # universal binary will be produced.  The exception is packager.mk, which
+  # needs to know to look for universal bits when building the .dmg.
+  UNIVERSAL_BINARY=1
+
+  export CC CXX HOST_CC HOST_CXX RANLIB AR AS LD STRIP OTOOL
+fi
+fi
diff --git a/src/third_party/mozjs-45/build/macosx/universal/unify b/src/third_party/mozjs-45/build/macosx/universal/unify
new file mode 100755
index 0000000..38dd354
--- /dev/null
+++ b/src/third_party/mozjs-45/build/macosx/universal/unify
@@ -0,0 +1,1525 @@
+#!/usr/bin/perl
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+use strict;
+use warnings;
+
+=pod
+
+=head1 NAME
+
+B<unify> - Mac OS X universal binary packager
+
+=head1 SYNOPSIS
+
+B<unify>
+I<ppc-path>
+I<x86-path>
+I<universal-path>
+[B<--dry-run>]
+[B<--only-one> I<action>]
+[B<--verbosity> I<level>]
+[B<--unify-with-sort> I<regex>]
+
+=head1 DESCRIPTION
+
+I<unify> merges any two architecture-specific files or directory trees
+into a single file or tree suitable for use on either architecture as a
+"fat" or "universal binary."
+
+Architecture-specific Mach-O files will be merged into fat Mach-O files
+using L<lipo(1)>.  Non-Mach-O files in the architecture-specific trees
+are compared to ensure that they are equivalent before copying.  Symbolic
+links are permitted in the architecture-specific trees and will cause
+identical links to be created in the merged tree, provided that the source
+links have identical targets.  Directories are processed recursively.
+
+If the architecture-specific source trees contain zip archives (including
+jar files) that are not identical according to a byte-for-byte check, they
+are still assumed to be equivalent if both archives contain exactly the
+same members with identical checksums and sizes.
+
+Behavior when one architecture-specific tree contains files that the other
+does not is controlled by the B<--only-one> option.
+
+If Mach-O files cannot be merged using L<lipo(1)>, zip archives are not
+equivalent, regular files are not identical, or any other error occurs,
+B<unify> will fail with an exit status of 1.  Diagnostic messages are
+typically printed to stderr; this behavior can be controlled with the
+B<--verbosity> option.
+
+=head1 OPTIONS
+
+=over 5
+
+=item I<ppc-path>
+
+=item I<x86-path>
+
+The paths to directory trees containing PowerPC and x86 builds,
+respectively.  I<ppc-path> and I<x86-path> are permitted to contain files
+that are already "fat," and only the appropriate architecture's images will
+be used.
+
+I<ppc-path> and I<x86-path> are also permitted to both be files, in which
+case B<unify> operates solely on those files, and produces an appropriate
+merged file at I<target-path>.
+
+=item I<target-path>
+
+The path to the merged file or directory tree.  This path will be created,
+and it must not exist prior to running B<unify>.
+
+=item B<--dry-run>
+
+When specified, the commands that would be executed are printed, without
+actually executing them.  Note that B<--dry-run> and the equivalent
+B<--verbosity> level during "wet" runs may print equivalent commands when
+no commands are in fact executed: certain operations are handled internally
+within B<unify>, and an approximation of a command that performs a similar
+task is printed.
+
+=item B<--only-one> I<action>
+
+Controls handling of files that are only present in one of the two source
+trees.  I<action> may be:
+  skip - These files are skipped.
+  copy - These files are copied from the tree in which they exist.
+  fail - When this condition occurs, it is treated as an error.
+
+The default I<action> is copy.
+
+=item B<--verbosity> I<level>
+
+Adjusts the level of loudness of B<unify>.  The possible values for
+I<level> are:
+  0 - B<unify> never prints anything.
+      (Other programs that B<unify> calls may still print messages.)
+  1 - Fatal error messages are printed to stderr.
+  2 - Nonfatal warnings are printed to stderr.
+  3 - Commands are printed to stdout as they are executed.
+
+The default I<level> is 2.
+
+=item B<--unify-with-sort> I<regex>
+
+Allows merging files matching I<regex> that differ only by the ordering
+of the lines contained within them. The unified file will have its contents
+sorted. This option may be given multiple times to specify multiple
+regexes for matching files.
+
+=back
+
+=head1 EXAMPLES
+
+=over 5
+
+=item Create a universal .app bundle from two architecture-specific .app
+bundles:
+
+unify --only-one copy ppc/dist/firefox/Firefox.app
+  x86/dist/firefox/Firefox.app universal/Firefox.app
+  --verbosity 3
+
+=item Merge two identical architecture-specific trees:
+
+unify --only-one fail /usr/local /nfs/x86/usr/local
+  /tmp/usrlocal.fat
+
+=back
+
+=head1 REQUIREMENTS
+
+The only esoteric requirement of B<unify> is that the L<lipo(1)> command
+be available.  It is present on Mac OS X systems at least as early as
+10.3.9, and probably earlier.  Mac OS X 10.4 ("Tiger") or later are
+recommended.
+
+=head1 LICENSE
+
+MPL 2.
+
+=head1 AUTHOR
+
+The software was initially written by Mark Mentovai; copyright 2006
+Google Inc.
+
+=head1 SEE ALSO
+
+L<cmp(1)>, L<ditto(1)>, L<lipo(1)>
+
+=cut
+
+use Archive::Zip(':ERROR_CODES');
+use Errno;
+use Fcntl;
+use File::Compare;
+use File::Copy;
+use Getopt::Long;
+
+my (%gConfig, $gDryRun, $gOnlyOne, $gVerbosity, @gSortMatches);
+
+sub argumentEscape(@);
+sub command(@);
+sub compareZipArchives($$);
+sub complain($$@);
+sub copyIfIdentical($$$);
+sub slurp($);
+sub get_sorted($);
+sub compare_sorted($$);
+sub copyIfIdenticalWhenSorted($$$);
+sub createUniqueFile($$);
+sub makeUniversal($$$);
+sub makeUniversalDirectory($$$);
+sub makeUniversalInternal($$$$);
+sub makeUniversalFile($$$);
+sub usage();
+sub readZipCRCs($);
+
+{
+  package FileAttrCache;
+
+  sub new($$);
+
+  sub isFat($);
+  sub isMachO($);
+  sub isZip($);
+  sub lIsDir($);
+  sub lIsExecutable($);
+  sub lIsRegularFile($);
+  sub lIsSymLink($);
+  sub lstat($);
+  sub lstatMode($);
+  sub lstatType($);
+  sub magic($);
+  sub magic2($);
+  sub path($);
+  sub stat($);
+  sub statSize($);
+}
+
+%gConfig = (
+  'cmd_lipo' => 'lipo',
+  'cmd_rm'   => 'rm',
+);
+
+$gDryRun = 0;
+$gOnlyOne = 'copy';
+$gVerbosity = 2;
+@gSortMatches = ();
+
+Getopt::Long::Configure('pass_through');
+GetOptions('dry-run'           => \$gDryRun,
+           'only-one=s'        => \$gOnlyOne,
+           'verbosity=i'       => \$gVerbosity,
+           'unify-with-sort=s' => \@gSortMatches,
+           'config=s'          => \%gConfig); # "hidden" option not in usage()
+
+if (scalar(@ARGV) != 3 || $gVerbosity < 0 || $gVerbosity > 3 ||
+    ($gOnlyOne ne 'skip' && $gOnlyOne ne 'copy' && $gOnlyOne ne 'fail')) {
+  usage();
+  exit(1);
+}
+
+if (!makeUniversal($ARGV[0],$ARGV[1],$ARGV[2])) {
+  # makeUniversal or something it called will have printed an error.
+  exit(1);
+}
+
+exit(0);
+
+# argumentEscape(@arguments)
+#
+# Takes a list of @arguments and makes them shell-safe.
+sub argumentEscape(@) {
+  my (@arguments);
+  @arguments = @_;
+
+  my ($argument, @argumentsOut);
+  foreach $argument (@arguments) {
+    $argument =~ s%([^A-Za-z0-9_\-/.=+,])%\\$1%g;
+    push(@argumentsOut, $argument);
+  }
+
+  return @argumentsOut;
+}
+
+# command(@arguments)
+#
+# Runs the specified command by calling system(@arguments).  If $gDryRun
+# is true, the command is printed but not executed, and 0 is returned.
+# if $gVerbosity is greater than 1, the command is printed before being
+# executed.  When the command is executed, the system() return value will
+# be returned.  stdout and stderr are left connected for command output.
+sub command(@) {
+  my (@arguments);
+  @arguments = @_;
+  if ($gVerbosity >= 3 || $gDryRun) {
+    print(join(' ', argumentEscape(@arguments))."\n");
+  }
+  if ($gDryRun) {
+    return 0;
+  }
+  return system(@arguments);
+}
+
+# compareZipArchives($zip1, $zip2)
+#
+# Given two pathnames to zip archives, determines whether or not they are
+# functionally identical.  Returns true if they are, false if they differ in
+# some substantial way, and undef if an error occurs.  If the zip files
+# differ, diagnostic messages are printed indicating how they differ.
+#
+# Zip files will differ if any of the members are different as defined by
+# readZipCRCs, which consider CRCs, sizes, and file types as stored in the
+# file header.  Timestamps are not considered.  Zip files also differ if one
+# file contains members that the other one does not.  $gOnlyOne has no
+# effect on this behavior.
+sub compareZipArchives($$) {
+  my ($zip1, $zip2);
+  ($zip1, $zip2) = @_;
+
+  my ($CRCHash1, $CRCHash2);
+  if (!defined($CRCHash1 = readZipCRCs($zip1))) {
+    # readZipCRCs printed an error.
+    return undef;
+  }
+  if (!defined($CRCHash2 = readZipCRCs($zip2))) {
+    # readZipCRCs printed an error.
+    return undef;
+  }
+
+  my (@diffCRCs, @onlyInZip1);
+  @diffCRCs = ();
+  @onlyInZip1 = ();
+
+  my ($memberName);
+  foreach $memberName (keys(%$CRCHash1)) {
+    if (!exists($$CRCHash2{$memberName})) {
+      # The member is present in $zip1 but not $zip2.
+      push(@onlyInZip1, $memberName);
+    }
+    elsif ($$CRCHash1{$memberName} ne $$CRCHash2{$memberName}) {
+      # The member is present in both archives but its CRC or some other
+      # other critical attribute isn't identical.
+      push(@diffCRCs, $memberName);
+    }
+    delete($$CRCHash2{$memberName});
+  }
+
+  # If any members remain in %CRCHash2, it's because they're not present
+  # in $zip1.
+  my (@onlyInZip2);
+  @onlyInZip2 = keys(%$CRCHash2);
+
+  if (scalar(@onlyInZip1) + scalar(@onlyInZip2) + scalar(@diffCRCs)) {
+    complain(1, 'compareZipArchives: zip archives differ:',
+             $zip1,
+             $zip2);
+    if (scalar(@onlyInZip1)) {
+      complain(1, 'compareZipArchives: members only in former:',
+               @onlyInZip1);
+    }
+    if (scalar(@onlyInZip2)) {
+      complain(1, 'compareZipArchives: members only in latter:',
+               @onlyInZip2);
+    }
+    if (scalar(@diffCRCs)) {
+      complain(1, 'compareZipArchives: members differ:',
+               @diffCRCs);
+    }
+    return 0;
+  }
+
+  return 1;
+}
+
+# complain($severity, $message, @list)
+#
+# Prints $message to stderr if $gVerbosity allows it for severity level
+# $severity.  @list is a list of words that will be shell-escaped and printed
+# after $message, one per line, intended to be used, for example, to list
+# arguments to a call that failed.
+#
+# Expected severity levels are 1 for hard errors and 2 for non-fatal warnings.
+#
+# Always returns false as a convenience, so callers can return complain's
+# return value when it is used to signal errors.
+sub complain($$@) {
+  my ($severity, $message, @list);
+  ($severity, $message, @list) = @_;
+
+  if ($gVerbosity >= $severity) {
+    print STDERR ($0.': '.$message."\n");
+
+    my ($item);
+    while ($item = shift(@list)) {
+      print STDERR ('  '.(argumentEscape($item))[0].
+                    (scalar(@list)?',':'')."\n");
+    }
+  }
+
+  return 0;
+}
+
+# copyIfIdentical($source1, $source2, $target)
+#
+# $source1 and $source2 are FileAttrCache objects that are compared, and if
+# identical, copied to path string $target.  The comparison is initially
+# done as a byte-for-byte comparison, but if the files differ and appear to
+# be zip archives, compareZipArchives is called to determine whether
+# files that are not byte-for-byte identical are equivalent archives.
+#
+# Returns true on success, false for files that are not identical or
+# equivalent archives, and undef if an error occurs.
+#
+# One of $source1 and $source2 is permitted to be undef.  In this event,
+# whichever source is defined is copied directly to $target without performing
+# any comparisons.  This enables the $gOnlyOne = 'copy' mode, which is
+# driven by makeUniversalDirectory and makeUniversalInternal.
+sub copyIfIdentical($$$) {
+  my ($source1, $source2, $target);
+  ($source1, $source2, $target) = @_;
+
+  if (!defined($source1)) {
+    # If there's only one source file, make it the first file.  Order
+    # isn't important here, and this makes it possible to use
+    # defined($source2) as the switch, and to always copy from $source1.
+    $source1 = $source2;
+    $source2 = undef;
+  }
+
+  if (defined($source2)) {
+    # Only do the comparisons if there are two source files.  If there's
+    # only one source file, skip the comparisons and go straight to the
+    # copy operation.
+    if ($gVerbosity >= 3 || $gDryRun) {
+      print('cmp -s '.
+            join(' ',argumentEscape($source1->path(), $source2->path()))."\n");
+    }
+    my ($comparison);
+    if (!defined($comparison = compare($source1->path(), $source2->path())) ||
+        $comparison == -1) {
+      return complain(1, 'copyIfIdentical: compare: '.$!.' while comparing:',
+                      $source1->path(),
+                      $source2->path());
+    }
+    elsif ($comparison != 0) {
+      my ($zip1, $zip2);
+      if (defined($zip1 = $source1->isZip()) &&
+          defined($zip2 = $source2->isZip()) &&
+          $zip1 && $zip2) {
+        my ($zipComparison);
+        if (!defined($zipComparison = compareZipArchives($source1->path(),
+                                                         $source2->path)) ||
+            !$zipComparison) {
+          # An error occurred or the zip files aren't sufficiently identical.
+          # compareZipArchives will have printed an error message.
+          return 0;
+        }
+        # The zip files were compared successfully, and they both contain
+        # all of the same members, and all of their members' CRCs are
+        # identical.  For the purposes of this script, the zip files can be
+        # treated as identical, so reset $comparison.
+        $comparison = 0;
+      }
+    }
+    if ($comparison != 0) {
+      return complain(1, 'copyIfIdentical: files differ:',
+                      $source1->path(),
+                      $source2->path());
+    }
+  }
+
+  if ($gVerbosity >= 3 || $gDryRun) {
+    print('cp '.
+          join(' ',argumentEscape($source1->path(), $target))."\n");
+  }
+
+  if (!$gDryRun) {
+    my ($isExecutable);
+
+    # Set the execute bits (as allowed by the umask) on the new file if any
+    # execute bit is set on either old file.
+    $isExecutable = $source1->lIsExecutable() ||
+                    (defined($source2) && $source2->lIsExecutable());
+
+    if (!createUniqueFile($target, $isExecutable ? 0777 : 0666)) {
+      # createUniqueFile printed an error.
+      return 0;
+    }
+
+    if (!copy($source1->path(), $target)) {
+      complain(1, 'copyIfIdentical: copy: '.$!.' while copying',
+               $source1->path(),
+               $target);
+      unlink($target);
+      return 0;
+    }
+  }
+
+  return 1;
+}
+
+# slurp($file)
+#
+# Read the contents of $file into an array and return it.
+# Returns undef on error.
+sub slurp($) {
+  my $file = $_[0];
+  open FILE, $file or return undef;
+  my @lines = <FILE>;
+  close FILE;
+  return @lines;
+}
+
+# get_sorted($file)
+# Get the sorted lines of a file as a list, normalizing a newline on the last line if necessary.
+sub get_sorted($) {
+  my ($file) = @_;
+  my @lines = slurp($file);
+  my $lastline = $lines[-1];
+  if (!($lastline =~ /\n/)) {
+    $lines[-1] = $lastline . "\n";
+  }
+  return sort(@lines);
+}
+
+# compare_sorted($file1, $file2)
+#
+# Read the contents of both files into arrays, sort the arrays,
+# and then compare the two arrays for equality.
+#
+# Returns 0 if the sorted array contents are equal, or 1 if not.
+# Returns undef on error.
+sub compare_sorted($$) {
+  my ($file1, $file2) = @_;
+  my @lines1 = get_sorted($file1);
+  my @lines2 = get_sorted($file2);
+
+  return undef if !@lines1 || !@lines2;
+  return 1 unless scalar @lines1 == scalar @lines2;
+
+  for (my $i = 0; $i < scalar @lines1; $i++) {
+    return 1 if $lines1[$i] ne $lines2[$i];
+  }
+  return 0;
+}
+
+# copyIfIdenticalWhenSorted($source1, $source2, $target)
+#
+# $source1 and $source2 are FileAttrCache objects that are compared, and if
+# identical, copied to path string $target.  The comparison is done by
+# sorting the individual lines within the two files and comparing the results.
+#
+# Returns true on success, false for files that are not equivalent,
+# and undef if an error occurs.
+sub copyIfIdenticalWhenSorted($$$) {
+  my ($source1, $source2, $target);
+  ($source1, $source2, $target) = @_;
+
+  if ($gVerbosity >= 3 || $gDryRun) {
+    print('cmp -s '.
+          join(' ',argumentEscape($source1->path(), $source2->path()))."\n");
+  }
+  my ($comparison);
+  if (!defined($comparison = compare_sorted($source1->path(),
+                                            $source2->path())) ||
+      $comparison == -1) {
+    return complain(1, 'copyIfIdenticalWhenSorted: compare: '.$!
+                    .' while comparing:',
+                      $source1->path(),
+                      $source2->path());
+  }
+  if ($comparison != 0) {
+    return complain(1, 'copyIfIdenticalWhenSorted: files differ:',
+                    $source1->path(),
+                    $source2->path());
+  }
+
+  if ($gVerbosity >= 3 || $gDryRun) {
+    print('cp '.
+          join(' ',argumentEscape($source1->path(), $target))."\n");
+  }
+
+  if (!$gDryRun) {
+    my ($isExecutable);
+
+    # Set the execute bits (as allowed by the umask) on the new file if any
+    # execute bit is set on either old file.
+    $isExecutable = $source1->lIsExecutable() ||
+                    (defined($source2) && $source2->lIsExecutable());
+
+    if (!createUniqueFile($target, $isExecutable ? 0777 : 0666)) {
+      # createUniqueFile printed an error.
+      return 0;
+    }
+
+    if (!copy($source1->path(), $target)) {
+      complain(1, 'copyIfIdenticalWhenSorted: copy: '.$!
+               .' while copying',
+               $source1->path(),
+               $target);
+      unlink($target);
+      return 0;
+    }
+  }
+
+  return 1;
+}
+
+# createUniqueFile($path, $mode)
+#
+# Creates a new plain empty file at pathname $path, provided it does not
+# yet exist.  $mode is used as the file mode.  The actual file's mode will
+# be modified by the effective umask.  Returns false if the file could
+# not be created, setting $! to the error.  An error message is printed
+# in the event of failure.
+sub createUniqueFile($$) {
+  my ($path, $mode);
+  ($path, $mode) = @_;
+
+  my ($fh);
+  if (!sysopen($fh, $path, O_WRONLY | O_CREAT | O_EXCL, $mode)) {
+    return complain(1, 'createUniqueFile: open: '.$!.' for:',
+                    $path);
+  }
+  close($fh);
+
+  return 1;
+}
+
+# makeUniversal($pathPPC, $pathX86, $pathTarget)
+#
+# The top-level call.  $pathPPC, $pathX86, and $pathTarget are strings
+# identifying the ppc and x86 files or directories to merge and the location
+# to merge them to.  Returns false on failure and true on success.
+sub makeUniversal($$$) {
+  my ($pathTarget, $pathPPC, $pathX86);
+  ($pathPPC, $pathX86, $pathTarget) = @_;
+
+  my ($filePPC, $fileX86);
+  $filePPC = FileAttrCache->new($pathPPC);
+  $fileX86 = FileAttrCache->new($pathX86);
+
+  return makeUniversalInternal(1, $filePPC, $fileX86, $pathTarget);
+}
+
+# makeUniversalDirectory($dirPPC, $dirX86, $dirTarget)
+#
+# This is part of the heart of recursion.  $dirPPC and $dirX86 are
+# FileAttrCache objects designating the source ppc and x86 directories to
+# merge into a universal directory at $dirTarget, a string.  For each file
+# in $dirPPC and $dirX86, makeUniversalInternal is called.
+# makeUniversalInternal will call back into makeUniversalDirectory for
+# directories, thus completing the recursion.  If a failure is encountered
+# in ths function or in makeUniversalInternal or anything that it calls,
+# false is returned, otherwise, true is returned.
+#
+# If there are files present in one source directory but not both, the
+# value of $gOnlyOne controls the behavior.  If $gOnlyOne is 'copy', the
+# single source file is copied into $pathTarget.  If it is 'skip', it is
+# skipped.  If it is 'fail', such files will trigger makeUniversalDirectory
+# to fail.
+#
+# If either source directory is undef, it is treated as having no files.
+# This facilitates deep recursion when entire directories are only present
+# in one source when $gOnlyOne = 'copy'.
+sub makeUniversalDirectory($$$) {
+  my ($dirPPC, $dirX86, $dirTarget);
+  ($dirPPC, $dirX86, $dirTarget) = @_;
+
+  my ($dh, @filesPPC, @filesX86);
+
+  @filesPPC = ();
+  if (defined($dirPPC)) {
+    if (!opendir($dh, $dirPPC->path())) {
+      return complain(1, 'makeUniversalDirectory: opendir ppc: '.$!.' for:',
+                      $dirPPC->path());
+    }
+    @filesPPC = readdir($dh);
+    closedir($dh);
+  }
+
+  @filesX86 = ();
+  if (defined($dirX86)) {
+    if (!opendir($dh, $dirX86->path())) {
+      return complain(1, 'makeUniversalDirectory: opendir x86: '.$!.' for:',
+                      $dirX86->path());
+     }
+    @filesX86 = readdir($dh);
+    closedir($dh);
+  }
+
+  my (%common, $file, %onlyPPC, %onlyX86);
+
+  %onlyPPC = ();
+  foreach $file (@filesPPC) {
+    if ($file eq '.' || $file eq '..') {
+      next;
+    }
+    $onlyPPC{$file}=1;
+  }
+
+  %common = ();
+  %onlyX86 = ();
+  foreach $file (@filesX86) {
+    if ($file eq '.' || $file eq '..') {
+      next;
+    }
+    if ($onlyPPC{$file}) {
+      delete $onlyPPC{$file};
+      $common{$file}=1;
+    }
+    else {
+      $onlyX86{$file}=1;
+    }
+  }
+
+  # First, handle files common to both.
+  foreach $file (sort(keys(%common))) {
+    if (!makeUniversalInternal(0,
+                               FileAttrCache->new($dirPPC->path().'/'.$file),
+                               FileAttrCache->new($dirX86->path().'/'.$file),
+                               $dirTarget.'/'.$file)) {
+      # makeUniversalInternal will have printed an error.
+      return 0;
+    }
+  }
+
+  # Handle files found only in a single directory here.  There are three
+  # options, dictated by $gOnlyOne: fail if files are only present in
+  # one directory, skip any files only present in one directory, or copy
+  # these files straight over to the target directory.  In any event,
+  # a message will be printed indicating that the file trees don't match
+  # exactly.
+  if (keys(%onlyPPC)) {
+    complain(($gOnlyOne eq 'fail' ? 1 : 2),
+             ($gOnlyOne ne 'fail' ? 'warning: ' : '').
+             'makeUniversalDirectory: only in ppc '.
+             (argumentEscape($dirPPC->path()))[0].':',
+             argumentEscape(keys(%onlyPPC)));
+  }
+
+  if (keys(%onlyX86)) {
+    complain(($gOnlyOne eq 'fail' ? 1 : 2),
+             ($gOnlyOne ne 'fail' ? 'warning: ' : '').
+             'makeUniversalDirectory: only in x86 '.
+             (argumentEscape($dirX86->path()))[0].':',
+             argumentEscape(keys(%onlyX86)));
+  }
+
+  if ($gOnlyOne eq 'fail' && (keys(%onlyPPC) || keys(%onlyX86))) {
+    # Error message(s) printed above.
+    return 0;
+  }
+
+  if ($gOnlyOne eq 'copy') {
+    foreach $file (sort(keys(%onlyPPC))) {
+      if (!makeUniversalInternal(0,
+                                 FileAttrCache->new($dirPPC->path().'/'.$file),
+                                 undef,
+                                 $dirTarget.'/'.$file)) {
+        # makeUniversalInternal will have printed an error.
+        return 0;
+      }
+    }
+
+    foreach $file (sort(keys(%onlyX86))) {
+      if (!makeUniversalInternal(0,
+                                 undef,
+                                 FileAttrCache->new($dirX86->path().'/'.$file),
+                                 $dirTarget.'/'.$file)) {
+        # makeUniversalInternal will have printed an error.
+        return 0;
+      }
+    }
+  }
+
+  return 1;
+}
+
+# makeUniversalFile($sourcePPC, $sourceX86, $targetPath)
+#
+# Creates a universal file at pathname $targetPath based on a ppc image at
+# $sourcePPC and an x86 image at $sourceX86.  $sourcePPC and $sourceX86 are
+# both FileAttrCache objects.  Returns true on success and false on failure.
+# On failure, diagnostics will be printed to stderr.
+#
+# The source files may be either thin Mach-O images of the appropriate
+# architecture, or fat Mach-O files that contain images of the appropriate
+# architecture.
+#
+# This function wraps the lipo utility, see lipo(1).
+sub makeUniversalFile($$$) {
+  my ($sourcePPC, $sourceX86, $targetPath, @tempThinFiles, $thinPPC, $thinX86);
+  ($sourcePPC, $sourceX86, $targetPath) = @_;
+  $thinPPC = $sourcePPC;
+  $thinX86 = $sourceX86;
+
+  @tempThinFiles = ();
+
+  # The source files might already be fat.  They should be thinned out to only
+  # contain a single architecture.
+ 
+  my ($isFatPPC, $isFatX86);
+
+  if(!defined($isFatPPC = $sourcePPC->isFat())) {
+    # isFat printed its own error
+    return 0;
+  }
+  elsif($isFatPPC) {
+    $thinPPC = FileAttrCache->new($targetPath.'.ppc');
+    push(@tempThinFiles, $thinPPC->path());
+    if (command($gConfig{'cmd_lipo'}, '-thin', 'ppc',
+                $sourcePPC->path(), '-output', $thinPPC->path()) != 0) {
+      unlink(@tempThinFiles);
+      return complain(1, 'lipo thin ppc failed for:',
+                      $sourcePPC->path(),
+                      $thinPPC->path());
+    }
+  }
+
+  if(!defined($isFatX86 = $sourceX86->isFat())) {
+    # isFat printed its own error
+    unlink(@tempThinFiles);
+    return 0;
+  }
+  elsif($isFatX86) {
+    $thinX86 = FileAttrCache->new($targetPath.'.x86');
+    push(@tempThinFiles, $thinX86->path());
+    if (command($gConfig{'cmd_lipo'}, '-thin', 'i386',
+                $sourceX86->path(), '-output', $thinX86->path()) != 0) {
+      unlink(@tempThinFiles);
+      return complain(1, 'lipo thin x86 failed for:',
+                      $sourceX86->path(),
+                      $thinX86->path());
+    }
+  }
+
+  # The image for each architecture in the fat file will be aligned on
+  # a specific boundary, default 4096 bytes, see lipo(1) -segalign.
+  # Since there's no tail-padding, the fat file will consume the least
+  # space on disk if the image that comes last exceeds the segment size
+  # by the smallest amount.
+  #
+  # This saves an average of 1kB per fat file over the naive approach of
+  # always putting one architecture first: average savings is 2kB per
+  # file, but the naive approach would have gotten it right half of the
+  # time.
+
+  my ($sizePPC, $sizeX86, $thinPPCForStat, $thinX86ForStat);
+
+  if (!$gDryRun) {
+    $thinPPCForStat = $thinPPC;
+    $thinX86ForStat = $thinX86;
+  }
+  else {
+    # Normally, fat source files will have been converted into temporary
+    # thin files.  During a dry run, that doesn't happen, so fake it up
+    # a little bit by always using the source file, fat or thin, for the
+    # stat.
+    $thinPPCForStat = $sourcePPC;
+    $thinX86ForStat = $sourceX86;
+  }
+
+  if (!defined($sizePPC = $thinPPCForStat->statSize())) {
+    unlink(@tempThinFiles);
+    return complain(1, 'stat ppc: '.$!.' for:',
+                    $thinPPCForStat->path());
+  }
+  if (!defined($sizeX86 = $thinX86ForStat->statSize())) {
+    unlink(@tempThinFiles);
+    return complain(1, 'stat x86: '.$!.' for:',
+                    $thinX86ForStat->path());
+  }
+
+  $sizePPC = $sizePPC % 4096;
+  $sizeX86 = $sizeX86 % 4096;
+
+  my (@thinFiles);
+
+  if ($sizePPC == 0) {
+    # PPC image ends on an alignment boundary, there will be no padding before
+    # starting the x86 image.
+    @thinFiles = ($thinPPC->path(), $thinX86->path());
+  }
+  elsif ($sizeX86 == 0 || $sizeX86 > $sizePPC) {
+    # x86 image ends on an alignment boundary, there will be no padding before
+    # starting the PPC image, or the x86 image exceeds its alignment boundary
+    # by more than the PPC image, so there will be less padding if the x86
+    # comes first.
+    @thinFiles = ($thinX86->path(), $thinPPC->path());
+  }
+  else {
+    # PPC image exceeds its alignment boundary by more than the x86 image, so
+    # there will be less padding if the PPC comes first.
+    @thinFiles = ($thinPPC->path(), $thinX86->path());
+  }
+
+  my ($isExecutable);
+  $isExecutable = $sourcePPC->lIsExecutable() ||
+                  $sourceX86->lIsExecutable();
+
+  if (!$gDryRun) {
+    # Ensure that the file does not yet exist.
+
+    # Set the execute bits (as allowed by the umask) on the new file if any
+    # execute bit is set on either old file.  Yes, it is possible to have
+    # proper Mach-O files without x-bits: think object files (.o) and static
+    # archives (.a).
+    if (!createUniqueFile($targetPath, $isExecutable ? 0777 : 0666)) {
+      # createUniqueFile printed an error.
+      unlink(@tempThinFiles);
+      return 0;
+    }
+  }
+
+  # Create the fat file.
+  if (command($gConfig{'cmd_lipo'}, '-create', @thinFiles,
+              '-output', $targetPath) != 0) {
+    unlink(@tempThinFiles, $targetPath);
+    return complain(1, 'lipo create fat failed for:',
+                    @thinFiles,
+                    $targetPath);
+  }
+
+  unlink(@tempThinFiles);
+
+  if (!$gDryRun) {
+    # lipo seems to think that it's free to set its own file modes that
+    # ignore the umask, which is bogus when the rest of this script
+    # respects the umask.
+    if (!chmod(($isExecutable ? 0777 : 0666) & ~umask(), $targetPath)) {
+      complain(1, 'makeUniversalFile: chmod: '.$!.' for',
+               $targetPath);
+      unlink($targetPath);
+      return 0;
+    }
+  }
+
+  return 1;
+}
+
+# makeUniversalInternal($isToplevel, $filePPC, $fileX86, $fileTargetPath)
+#
+# Given FileAttrCache objects $filePPC and $fileX86, compares filetypes
+# and performs the appropriate action to produce a universal file at
+# path string $fileTargetPath.  $isToplevel should be true if this is
+# the recursive base and false otherwise; this controls cleanup behavior
+# (cleanup is only performed at the base, because cleanup itself is
+# recursive).
+#
+# This handles regular files by determining whether they are Mach-O files
+# and calling makeUniversalFile if so and copyIfIdentical otherwise.  Symbolic
+# links are handled directly in this function by ensuring that the source link
+# targets are identical and creating a new link with the same target
+# at $fileTargetPath.  Directories are handled by calling
+# makeUniversalDirectory.
+#
+# One of $filePPC and $fileX86 is permitted to be undef.  In that case,
+# the defined source file is copied directly to the target if a regular
+# file, and symlinked appropriately if a symbolic link.  This facilitates
+# use of $gOnlyOne = 'copy', although no $gOnlyOne checks are made in this
+# function, they are all handled in makeUniversalDirectory.
+#
+# Returns true on success.  Returns false on failure, including failures
+# in other functions called.
+sub makeUniversalInternal($$$$) {
+  my ($filePPC, $fileTargetPath, $fileX86, $isToplevel);
+  ($isToplevel, $filePPC, $fileX86, $fileTargetPath) = @_;
+
+  my ($typePPC, $typeX86);
+  if (defined($filePPC) && !defined($typePPC = $filePPC->lstatType())) {
+    return complain(1, 'makeUniversal: lstat ppc: '.$!.' for:',
+                    $filePPC->path());
+  }
+  if (defined($fileX86) && !defined($typeX86 = $fileX86->lstatType())) {
+    return complain(1, 'makeUniversal: lstat x86: '.$!.' for:',
+                    $fileX86->path());
+  }
+
+  if (defined($filePPC) && defined($fileX86) && $typePPC != $typeX86) {
+    return complain(1, 'makeUniversal: incompatible types:',
+                    $filePPC->path(),
+                    $fileX86->path());
+  }
+
+  # $aSourceFile will contain a FileAttrCache object that will return
+  # the correct type data.  It's used because it's possible for one of
+  # the two source files to be undefined (indicating a straight copy).
+  my ($aSourceFile);
+  if (defined($filePPC)) { 
+    $aSourceFile = $filePPC;
+  }
+  else {
+    $aSourceFile = $fileX86;
+  }
+
+  if ($aSourceFile->lIsDir()) {
+    if ($gVerbosity >= 3 || $gDryRun) {
+      print('mkdir '.(argumentEscape($fileTargetPath))[0]."\n");
+    }
+    if (!$gDryRun && !mkdir($fileTargetPath)) {
+      return complain(1, 'makeUniversal: mkdir: '.$!.' for:',
+                      $fileTargetPath);
+    }
+
+    my ($rv);
+
+    if (!($rv = makeUniversalDirectory($filePPC, $fileX86, $fileTargetPath))) {
+      # makeUniversalDirectory printed an error.
+      if ($isToplevel) {
+        command($gConfig{'cmd_rm'},'-rf','--',$fileTargetPath);
+      }
+    }
+    else {
+      # Touch the directory when leaving it.  If unify is being run on an
+      # .app bundle, the .app might show up without an icon because the
+      # system might have found the .app before it was completely built.
+      # Touching it dirties it in LaunchServices' mind.
+      if ($gVerbosity >= 3) {
+        print('touch '.(argumentEscape($fileTargetPath))[0]."\n");
+      }
+      utime(undef, undef, $fileTargetPath);
+    }
+
+    return $rv;
+  }
+  elsif ($aSourceFile->lIsSymLink()) {
+    my ($linkPPC, $linkX86);
+    if (defined($filePPC) && !defined($linkPPC=readlink($filePPC->path()))) {
+      return complain(1, 'makeUniversal: readlink ppc: '.$!.' for:',
+                      $filePPC->path());
+    }
+    if (defined($fileX86) && !defined($linkX86=readlink($fileX86->path()))) {
+      return complain(1, 'makeUniversal: readlink x86: '.$!.' for:',
+                      $fileX86->path());
+    }
+    if (defined($filePPC) && defined($fileX86) && $linkPPC ne $linkX86) {
+      return complain(1, 'makeUniversal: symbolic links differ:',
+                      $filePPC->path(),
+                      $fileX86->path());
+    }
+
+    # $aLink here serves the same purpose as $aSourceFile in the enclosing
+    # block: it refers to the target of the symbolic link, whether there
+    # is one valid source or two.
+    my ($aLink);
+    if (defined($linkPPC)) {
+      $aLink = $linkPPC;
+    }
+    else {
+      $aLink = $linkX86;
+    }
+
+    if ($gVerbosity >= 3 || $gDryRun) {
+      print('ln -s '.
+            join(' ',argumentEscape($aLink, $fileTargetPath))."\n");
+    }
+    if (!$gDryRun && !symlink($aLink, $fileTargetPath)) {
+      return complain(1, 'makeUniversal: symlink: '.$!.' for:',
+                      $aLink,
+                      $fileTargetPath);
+    }
+
+    return 1;
+  }
+  elsif($aSourceFile->lIsRegularFile()) {
+    my ($machPPC, $machX86, $fileName);
+    if (!defined($filePPC) || !defined($fileX86)) {
+      # One of the source files isn't present.  The right thing to do is
+      # to just copy what does exist straight over, so skip Mach-O checks.
+      $machPPC = 0;
+      $machX86 = 0;
+      if (defined($filePPC)) {
+        $fileName = $filePPC;
+      } elsif (defined($fileX86)) {
+        $fileName = $fileX86;
+      } else {
+        complain(1, "The file must exist in at least one directory");
+        exit(1);
+      }
+    }
+    else {
+      # both files exist, pick the name of one.
+      $fileName = $fileX86;
+      if (!defined($machPPC=$filePPC->isMachO())) {
+        return complain(1, 'makeUniversal: isFileMachO ppc failed for:',
+                        $filePPC->path());
+      }
+      if (!defined($machX86=$fileX86->isMachO())) {
+        return complain(1, 'makeUniversal: isFileMachO x86 failed for:',
+                        $fileX86->path());
+      }
+    }
+
+    if ($machPPC != $machX86) {
+      return complain(1, 'makeUniversal: variant Mach-O attributes:',
+                      $filePPC->path(),
+                  $fileX86->path());
+    }
+
+    if ($machPPC) {
+      # makeUniversalFile will print an error if it fails.
+      return makeUniversalFile($filePPC, $fileX86, $fileTargetPath);
+    }
+
+    if (grep { $fileName->path() =~ m/$_/; } @gSortMatches) {
+      # Regular files, but should be compared with sorting first.
+      # copyIfIdenticalWhenSorted will print an error if it fails.
+      return copyIfIdenticalWhenSorted($filePPC, $fileX86, $fileTargetPath);
+    }
+
+    # Regular file.  copyIfIdentical will print an error if it fails.
+    return copyIfIdentical($filePPC, $fileX86, $fileTargetPath);
+  }
+
+  # Special file, don't know how to handle.
+  return complain(1, 'makeUniversal: cannot handle special file:',
+                  $filePPC->path(),
+                  $fileX86->path());
+}
+
+# usage()
+#
+# Give the user a hand.
+sub usage() {
+  print STDERR (
+"usage: unify <ppc-path> <x86-path> <universal-path>\n".
+"            [--dry-run]           (print what would be done)\n".
+"            [--only-one <action>] (skip, copy, fail; default=copy)\n".
+"            [--verbosity <level>] (0, 1, 2, 3; default=2)\n");
+  return;
+}
+
+# readZipCRCs($zipFile)
+#
+# $zipFile is the pathname to a zip file whose directory will be read.
+# A reference to a hash is returned, with the member pathnames from the
+# zip file as keys, and reasonably unique identifiers as values.  The
+# format of the values is not specified exactly, but does include the
+# member CRCs and sizes and differentiates between files and directories.
+# It specifically does not distinguish between modification times.  On
+# failure, prints a message and returns undef.
+sub readZipCRCs($) {
+  my ($zipFile);
+  ($zipFile) = @_;
+
+  my ($ze, $zip);
+  $zip = Archive::Zip->new();
+
+  if (($ze = $zip->read($zipFile)) != AZ_OK) {
+    complain(1, 'readZipCRCs: read error '.$ze.' for:',
+             $zipFile);
+    return undef;
+  }
+
+  my ($member, %memberCRCs, @memberList);
+  %memberCRCs = ();
+  @memberList = $zip->members();
+
+  foreach $member (@memberList) {
+    # Take a few of the attributes that identify the file and stuff them into
+    # the members hash.  Directories will show up with size 0 and crc32 0,
+    # so isDirectory() is used to distinguish them from empty files.
+    $memberCRCs{$member->fileName()} = join(',', $member->isDirectory() ? 1 : 0,
+                                                 $member->uncompressedSize(),
+                                                 $member->crc32String());
+  }
+
+  return {%memberCRCs};
+}
+
+{
+  # FileAttrCache allows various attributes about a file to be cached
+  # so that if they are needed again after first use, no system calls
+  # will be made and the program won't need to hit the disk.
+
+  package FileAttrCache;
+
+  # from /usr/include/mach-o/loader.h
+  use constant MH_MAGIC    => 0xfeedface;
+  use constant MH_CIGAM    => 0xcefaedfe;
+  use constant MH_MAGIC_64 => 0xfeedfacf;
+  use constant MH_CIGAM_64 => 0xcffaedfe;
+
+  use Fcntl(':DEFAULT', ':mode');
+
+  # FileAttrCache->new($path)
+  #
+  # Creates a new FileAttrCache object for the file at path $path and
+  # returns it.  The cache is not primed at creation time, values are
+  # fetched lazily as they are needed.
+  sub new($$) {
+    my ($class, $path, $proto, $this);
+    ($proto, $path) = @_;
+    if (!($class = ref($proto))) {
+      $class = $proto;
+    }
+    $this = {
+      'path'        => $path,
+      'lstat'       => undef,
+      'lstatErrno'  => 0,
+      'lstatInit'   => 0,
+      'magic'       => undef,
+      'magic2'       => undef,
+      'magicErrno'  => 0,
+      'magicErrMsg' => undef,
+      'magicInit'   => 0,
+      'stat'        => undef,
+      'statErrno'   => 0,
+      'statInit'    => 0,
+    };
+    bless($this, $class);
+    return($this);
+  }
+
+  # $FileAttrCache->isFat()
+  #
+  # Returns true if the file is a fat Mach-O file, false if it's not, and
+  # undef if an error occurs.  See /usr/include/mach-o/fat.h.
+  sub isFat($) {
+    my ($magic, $magic2, $this);
+    ($this) = @_;
+
+    # magic() caches, there's no separate cache because isFat() doesn't hit
+    # the disk other than by calling magic().
+
+    if (!defined($magic = $this->magic())) {
+      return undef;
+    }
+    $magic2 = $this->magic2();
+
+    # We have to sanity check the second four bytes, because Java class
+    # files use the same magic number as Mach-O fat binaries.
+    # This logic is adapted from file(1), which says that Mach-O uses
+    # these bytes to count the number of architectures within, while
+    # Java uses it for a version number. Conveniently, there are only
+    # 18 labelled Mach-O architectures, and Java's first released
+    # class format used the version 43.0.
+    if ($magic == 0xcafebabe && $magic2 < 20) {
+      return 1;
+    }
+
+    return 0;
+  }
+
+  # $FileAttrCache->isMachO()
+  #
+  # Returns true if the file is a Mach-O image (including a fat file), false
+  # if it's not, and undef if an error occurs.  See
+  # /usr/include/mach-o/loader.h and /usr/include/mach-o/fat.h.
+  sub isMachO($) {
+    my ($magic, $this);
+    ($this) = @_;
+
+    # magic() caches, there's no separate cache because isMachO() doesn't hit
+    # the disk other than by calling magic().
+
+    if (!defined($magic = $this->magic())) {
+      return undef;
+    }
+
+    # Accept Mach-O fat files or Mach-O thin files of either endianness.
+    if ($magic == MH_MAGIC ||
+        $magic == MH_CIGAM ||
+        $magic == MH_MAGIC_64 ||
+        $magic == MH_CIGAM_64 ||
+        $this->isFat()) {
+      return 1;
+    }
+
+    return 0;
+  }
+
+  # $FileAttrCache->isZip()
+  #
+  # Returns true if the file is a zip file, false if it's not, and undef if
+  # an error occurs.  See http://www.pkware.com/business_and_developers/developer/popups/appnote.txt .
+  sub isZip($) {
+    my ($magic, $this);
+    ($this) = @_;
+
+    # magic() caches, there's no separate cache because isFat() doesn't hit
+    # the disk other than by calling magic().
+
+    if (!defined($magic = $this->magic())) {
+      return undef;
+    }
+
+    if ($magic == 0x504b0304) {
+      return 1;
+    }
+
+    return 0;
+  }
+
+  # $FileAttrCache->lIsExecutable()
+  #
+  # Wraps $FileAttrCache->lstat(), returning true if the file is has any,
+  # execute bit set, false if none are set, or undef if an error occurs.
+  # On error, $! is set to lstat's errno.
+  sub lIsExecutable($) {
+    my ($mode, $this);
+    ($this) = @_;
+
+    if (!defined($mode = $this->lstatMode())) {
+      return undef;
+    }
+
+    return $mode & (S_IXUSR | S_IXGRP | S_IXOTH);
+  }
+
+  # $FileAttrCache->lIsDir()
+  #
+  # Wraps $FileAttrCache->lstat(), returning true if the file is a directory,
+  # false if it isn't, or undef if an error occurs.  Because lstat is used,
+  # this will return false even if the file is a symlink pointing to a
+  # directory.  On error, $! is set to lstat's errno.
+  sub lIsDir($) {
+    my ($type, $this);
+    ($this) = @_;
+
+    if (!defined($type = $this->lstatType())) {
+      return undef;
+    }
+
+    return S_ISDIR($type);
+  }
+
+  # $FileAttrCache->lIsRegularFile()
+  #
+  # Wraps $FileAttrCache->lstat(), returning true if the file is a regular,
+  # file, false if it isn't, or undef if an error occurs.  Because lstat is
+  # used, this will return false even if the file is a symlink pointing to a
+  # regular file.  On error, $! is set to lstat's errno.
+  sub lIsRegularFile($) {
+    my ($type, $this);
+    ($this) = @_;
+
+    if (!defined($type = $this->lstatType())) {
+      return undef;
+    }
+
+    return S_ISREG($type);
+  }
+
+  # $FileAttrCache->lIsSymLink()
+  #
+  # Wraps $FileAttrCache->lstat(), returning true if the file is a symbolic,
+  # link, false if it isn't, or undef if an error occurs.  On error, $! is
+  # set to lstat's errno.
+  sub lIsSymLink($) {
+    my ($type, $this);
+    ($this) = @_;
+   
+    if (!defined($type = $this->lstatType())) {
+      return undef;
+    }
+
+    return S_ISLNK($type);
+  }
+
+  # $FileAttrCache->lstat()
+  #
+  # Wraps the lstat system call, providing a cache to speed up multiple
+  # lstat calls for the same file.  See lstat(2) and lstat in perlfunc(1).
+  sub lstat($) {
+    my (@stat, $this);
+    ($this) = @_;
+
+    # Use the cached lstat result.
+    if ($$this{'lstatInit'}) {
+      if (defined($$this{'lstatErrno'})) {
+        $! = $$this{'lstatErrno'};
+      }
+      return @{$$this{'lstat'}};
+    }
+    $$this{'lstatInit'} = 1;
+
+    if (!(@stat = CORE::lstat($$this{'path'}))) {
+      $$this{'lstatErrno'} = $!;
+    }
+
+    $$this{'lstat'} = [@stat];
+    return @stat;
+  }
+
+  # $FileAttrCache->lstatMode()
+  #
+  # Wraps $FileAttrCache->lstat(), returning the mode bits from the st_mode
+  # field, or undef if an error occurs.  On error, $! is set to lstat's
+  # errno.
+  sub lstatMode($) {
+    my (@stat, $this);
+    ($this) = @_;
+
+    if (!(@stat = $this->lstat())) {
+      return undef;
+    }
+
+    return S_IMODE($stat[2]);
+  }
+
+  # $FileAttrCache->lstatType()
+  #
+  # Wraps $FileAttrCache->lstat(), returning the type bits from the st_mode
+  # field, or undef if an error occurs.  On error, $! is set to lstat's
+  # errno.
+  sub lstatType($) {
+    my (@stat, $this);
+    ($this) = @_;
+
+    if (!(@stat = $this->lstat())) {
+      return undef;
+    }
+
+    return S_IFMT($stat[2]);
+  }
+
+  # $FileAttrCache->magic()
+  #
+  # Returns the "magic number" for the file by reading its first four bytes
+  # as a big-endian unsigned 32-bit integer and returning the result.  If an
+  # error occurs, returns undef and prints diagnostic messages to stderr.  If
+  # the file is shorter than 32 bits, returns -1.  A cache is provided to
+  # speed multiple magic calls for the same file.
+  sub magic($) {
+    my ($this);
+    ($this) = @_;
+
+    # Use the cached magic result.
+    if ($$this{'magicInit'}) {
+      if (defined($$this{'magicErrno'})) {
+        if (defined($$this{'magicErrMsg'})) {
+          main::complain(1, 'FileAttrCache::magic: '.$$this{'magicErrMsg'}.' for:',
+                   $$this{'path'});
+        }
+        $! = $$this{'magicErrno'};
+      }
+      return $$this{'magic'};
+    }
+
+    $$this{'magicInit'} = 1;
+
+    my ($fh);
+    if (!sysopen($fh, $$this{'path'}, O_RDONLY)) {
+      $$this{'magicErrno'} = $!;
+      $$this{'magicErrMsg'} = 'open "'.$$this{'path'}.'": '.$!;
+      main::complain(1, 'FileAttrCache::magic: '.$$this{'magicErrMsg'}.' for:',
+               $$this{'path'});
+      return undef;
+    }
+
+    $! = 0;
+    my ($bytes, $magic, $bytes2, $magic2);
+    if (!defined($bytes = sysread($fh, $magic, 4))) {
+      $$this{'magicErrno'} = $!;
+      $$this{'magicErrMsg'} = 'read "'.$$this{'path'}.'": '.$!;
+      main::complain(1, 'FileAttrCache::magic: '.$$this{'magicErrMsg'}.' for:',
+               $$this{'path'});
+      close($fh);
+      return undef;
+    }
+    else {
+      $bytes2 = sysread($fh, $magic2, 4);
+    }
+
+    close($fh);
+
+    if ($bytes != 4) {
+      # The file is too short, didn't read a magic number.  This isn't really
+      # an error.  Return an unlikely value.
+      $$this{'magic'} = -1;
+      $$this{'magic2'} = -1;
+      return -1;
+    }
+    if ($bytes2 != 4) {
+      # File is too short to read a second 4 bytes.
+      $magic2 = -1;
+    }
+
+    $$this{'magic'} = unpack('N', $magic);
+    $$this{'magic2'} = unpack('N', $magic2);
+    return $$this{'magic'};
+  }
+
+  # $FileAttrCache->magic2()
+  #
+  # Returns the second four bytes of the file as a 32-bit little endian number.
+  # See magic(), above for more info.
+  sub magic2($) {
+    my ($this);
+    ($this) = @_;
+
+    # we do the actual work (and cache it) in magic().
+    if (!$$this{'magicInit'}) {
+      my $magic = $$this->magic();
+    }
+
+    return $$this{'magic2'};
+  }
+
+  # $FileAttrCache->path()
+  #
+  # Returns the file's pathname.
+  sub path($) {
+    my ($this);
+    ($this) = @_;
+    return $$this{'path'};
+  }
+
+  # $FileAttrCache->stat()
+  #
+  # Wraps the stat system call, providing a cache to speed up multiple
+  # stat calls for the same file.  If lstat() has already been called and
+  # the file is not a symbolic link, the cached lstat() result will be used.
+  # See stat(2) and lstat in perlfunc(1).
+  sub stat($) {
+    my (@stat, $this);
+    ($this) = @_;
+
+    # Use the cached stat result.
+    if ($$this{'statInit'}) {
+      if (defined($$this{'statErrno'})) {
+        $! = $$this{'statErrno'};
+      }
+      return @{$$this{'stat'}};
+    }
+
+    $$this{'statInit'} = 1;
+
+    # If lstat has already been called, and the file isn't a symbolic link,
+    # use the cached lstat result.
+    if ($$this{'lstatInit'} && !$$this{'lstatErrno'} &&
+        !S_ISLNK(${$$this{'lstat'}}[2])) {
+      $$this{'stat'} = $$this{'lstat'};
+      return @{$$this{'stat'}};
+    }
+
+    if (!(@stat = CORE::stat($$this{'path'}))) {
+      $$this{'statErrno'} = $!;
+    }
+
+    $$this{'stat'} = [@stat];
+    return @stat;
+  }
+
+  # $FileAttrCache->statSize()
+  #
+  # Wraps $FileAttrCache->stat(), returning the st_size field, or undef
+  # undef if an error occurs.  On error, $! is set to stat's errno.
+  sub statSize($) {
+    my (@stat, $this);
+    ($this) = @_;
+
+    if (!(@stat = $this->lstat())) {
+      return undef;
+    }
+
+    return $stat[7];
+  }
+}
diff --git a/src/third_party/mozjs-45/build/mobile/b2gautomation.py b/src/third_party/mozjs-45/build/mobile/b2gautomation.py
new file mode 100644
index 0000000..75a93c6
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/b2gautomation.py
@@ -0,0 +1,450 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this file,
+# You can obtain one at http://mozilla.org/MPL/2.0/.
+
+import datetime
+import mozcrash
+import threading
+import os
+import posixpath
+import Queue
+import re
+import shutil
+import signal
+import tempfile
+import time
+import traceback
+import zipfile
+
+from automation import Automation
+from mozlog import get_default_logger
+from mozprocess import ProcessHandlerMixin
+
+
+class StdOutProc(ProcessHandlerMixin):
+    """Process handler for b2g which puts all output in a Queue.
+    """
+
+    def __init__(self, cmd, queue, **kwargs):
+        self.queue = queue
+        kwargs.setdefault('processOutputLine', []).append(self.handle_output)
+        ProcessHandlerMixin.__init__(self, cmd, **kwargs)
+
+    def handle_output(self, line):
+        self.queue.put_nowait(line)
+
+
+class B2GRemoteAutomation(Automation):
+    _devicemanager = None
+
+    def __init__(self, deviceManager, appName='', remoteLog=None,
+                 marionette=None, context_chrome=True):
+        self._devicemanager = deviceManager
+        self._appName = appName
+        self._remoteProfile = None
+        self._remoteLog = remoteLog
+        self.marionette = marionette
+        self.context_chrome = context_chrome
+        self._is_emulator = False
+        self.test_script = None
+        self.test_script_args = None
+
+        # Default our product to b2g
+        self._product = "b2g"
+        self.lastTestSeen = "b2gautomation.py"
+        # Default log finish to mochitest standard
+        self.logFinish = 'INFO SimpleTest FINISHED'
+        Automation.__init__(self)
+
+    def setEmulator(self, is_emulator):
+        self._is_emulator = is_emulator
+
+    def setDeviceManager(self, deviceManager):
+        self._devicemanager = deviceManager
+
+    def setAppName(self, appName):
+        self._appName = appName
+
+    def setRemoteProfile(self, remoteProfile):
+        self._remoteProfile = remoteProfile
+
+    def setProduct(self, product):
+        self._product = product
+
+    def setRemoteLog(self, logfile):
+        self._remoteLog = logfile
+
+    def getExtensionIDFromRDF(self, rdfSource):
+        """
+        Retrieves the extension id from an install.rdf file (or string).
+        """
+        from xml.dom.minidom import parse, parseString, Node
+
+        if isinstance(rdfSource, file):
+            document = parse(rdfSource)
+        else:
+            document = parseString(rdfSource)
+
+        # Find the <em:id> element. There can be multiple <em:id> tags
+        # within <em:targetApplication> tags, so we have to check this way.
+        for rdfChild in document.documentElement.childNodes:
+            if rdfChild.nodeType == Node.ELEMENT_NODE and rdfChild.tagName == "Description":
+                for descChild in rdfChild.childNodes:
+                    if descChild.nodeType == Node.ELEMENT_NODE and descChild.tagName == "em:id":
+                        return descChild.childNodes[0].data
+        return None
+
+    def installExtension(self, extensionSource, profileDir, extensionID=None):
+        # Bug 827504 - installing special-powers extension separately causes problems in B2G
+        if extensionID != "special-powers@mozilla.org":
+            if not os.path.isdir(profileDir):
+              self.log.info("INFO | automation.py | Cannot install extension, invalid profileDir at: %s", profileDir)
+              return
+
+            installRDFFilename = "install.rdf"
+
+            extensionsRootDir = os.path.join(profileDir, "extensions", "staged")
+            if not os.path.isdir(extensionsRootDir):
+              os.makedirs(extensionsRootDir)
+
+            if os.path.isfile(extensionSource):
+              reader = zipfile.ZipFile(extensionSource, "r")
+
+              for filename in reader.namelist():
+                # Sanity check the zip file.
+                if os.path.isabs(filename):
+                  self.log.info("INFO | automation.py | Cannot install extension, bad files in xpi")
+                  return
+
+                # We may need to dig the extensionID out of the zip file...
+                if extensionID is None and filename == installRDFFilename:
+                  extensionID = self.getExtensionIDFromRDF(reader.read(filename))
+
+              # We must know the extensionID now.
+              if extensionID is None:
+                self.log.info("INFO | automation.py | Cannot install extension, missing extensionID")
+                return
+
+              # Make the extension directory.
+              extensionDir = os.path.join(extensionsRootDir, extensionID)
+              os.mkdir(extensionDir)
+
+              # Extract all files.
+              reader.extractall(extensionDir)
+
+            elif os.path.isdir(extensionSource):
+              if extensionID is None:
+                filename = os.path.join(extensionSource, installRDFFilename)
+                if os.path.isfile(filename):
+                  with open(filename, "r") as installRDF:
+                    extensionID = self.getExtensionIDFromRDF(installRDF)
+
+                if extensionID is None:
+                  self.log.info("INFO | automation.py | Cannot install extension, missing extensionID")
+                  return
+
+              # Copy extension tree into its own directory.
+              # "destination directory must not already exist".
+              shutil.copytree(extensionSource, os.path.join(extensionsRootDir, extensionID))
+
+            else:
+              self.log.info("INFO | automation.py | Cannot install extension, invalid extensionSource at: %s", extensionSource)
+
+    # Set up what we need for the remote environment
+    def environment(self, env=None, xrePath=None, crashreporter=True, debugger=False):
+        # Because we are running remote, we don't want to mimic the local env
+        # so no copying of os.environ
+        if env is None:
+            env = {}
+
+        if crashreporter:
+            env['MOZ_CRASHREPORTER'] = '1'
+            env['MOZ_CRASHREPORTER_NO_REPORT'] = '1'
+
+        # We always hide the results table in B2G; it's much slower if we don't.
+        env['MOZ_HIDE_RESULTS_TABLE'] = '1'
+        return env
+
+    def waitForNet(self):
+        active = False
+        time_out = 0
+        while not active and time_out < 40:
+            data = self._devicemanager._runCmd(['shell', '/system/bin/netcfg']).stdout.readlines()
+            data.pop(0)
+            for line in data:
+                if (re.search(r'UP\s+(?:[0-9]{1,3}\.){3}[0-9]{1,3}', line)):
+                    active = True
+                    break
+            time_out += 1
+            time.sleep(1)
+        return active
+
+    def checkForCrashes(self, directory, symbolsPath):
+        crashed = False
+        remote_dump_dir = self._remoteProfile + '/minidumps'
+        print "checking for crashes in '%s'" % remote_dump_dir
+        if self._devicemanager.dirExists(remote_dump_dir):
+            local_dump_dir = tempfile.mkdtemp()
+            self._devicemanager.getDirectory(remote_dump_dir, local_dump_dir)
+            try:
+                logger = get_default_logger()
+                if logger is not None:
+                    crashed = mozcrash.log_crashes(logger, local_dump_dir, symbolsPath, test=self.lastTestSeen)
+                else:
+                    crashed = mozcrash.check_for_crashes(local_dump_dir, symbolsPath, test_name=self.lastTestSeen)
+            except:
+                traceback.print_exc()
+            finally:
+                shutil.rmtree(local_dump_dir)
+                self._devicemanager.removeDir(remote_dump_dir)
+        return crashed
+
+    def buildCommandLine(self, app, debuggerInfo, profileDir, testURL, extraArgs):
+        # if remote profile is specified, use that instead
+        if (self._remoteProfile):
+            profileDir = self._remoteProfile
+
+        cmd, args = Automation.buildCommandLine(self, app, debuggerInfo, profileDir, testURL, extraArgs)
+
+        return app, args
+
+    def waitForFinish(self, proc, utilityPath, timeout, maxTime, startTime,
+                      debuggerInfo, symbolsPath):
+        """ Wait for tests to finish (as evidenced by a signature string
+            in logcat), or for a given amount of time to elapse with no
+            output.
+        """
+        timeout = timeout or 120
+        while True:
+            currentlog = proc.getStdoutLines(timeout)
+            if currentlog:
+                print currentlog
+                # Match the test filepath from the last TEST-START line found in the new
+                # log content. These lines are in the form:
+                # ... INFO TEST-START | /filepath/we/wish/to/capture.html\n
+                testStartFilenames = re.findall(r"TEST-START \| ([^\s]*)", currentlog)
+                if testStartFilenames:
+                    self.lastTestSeen = testStartFilenames[-1]
+                if hasattr(self, 'logFinish') and self.logFinish in currentlog:
+                    return 0
+            else:
+                self.log.info("TEST-UNEXPECTED-FAIL | %s | application timed "
+                              "out after %d seconds with no output",
+                              self.lastTestSeen, int(timeout))
+                self._devicemanager.killProcess('/system/b2g/b2g', sig=signal.SIGABRT)
+
+                timeout = 10 # seconds
+                starttime = datetime.datetime.now()
+                while datetime.datetime.now() - starttime < datetime.timedelta(seconds=timeout):
+                    if not self._devicemanager.processExist('/system/b2g/b2g'):
+                        break
+                    time.sleep(1)
+                else:
+                    print "timed out after %d seconds waiting for b2g process to exit" % timeout
+                    return 1
+
+                self.checkForCrashes(None, symbolsPath)
+                return 1
+
+    def getDeviceStatus(self, serial=None):
+        # Get the current status of the device.  If we know the device
+        # serial number, we look for that, otherwise we use the (presumably
+        # only) device shown in 'adb devices'.
+        serial = serial or self._devicemanager._deviceSerial
+        status = 'unknown'
+
+        for line in self._devicemanager._runCmd(['devices']).stdout.readlines():
+            result = re.match('(.*?)\t(.*)', line)
+            if result:
+                thisSerial = result.group(1)
+                if not serial or thisSerial == serial:
+                    serial = thisSerial
+                    status = result.group(2)
+
+        return (serial, status)
+
+    def restartB2G(self):
+        # TODO hangs in subprocess.Popen without this delay
+        time.sleep(5)
+        self._devicemanager._checkCmd(['shell', 'stop', 'b2g'])
+        # Wait for a bit to make sure B2G has completely shut down.
+        time.sleep(10)
+        self._devicemanager._checkCmd(['shell', 'start', 'b2g'])
+        if self._is_emulator:
+            self.marionette.emulator.wait_for_port(self.marionette.port)
+
+    def rebootDevice(self):
+        # find device's current status and serial number
+        serial, status = self.getDeviceStatus()
+
+        # reboot!
+        self._devicemanager._runCmd(['shell', '/system/bin/reboot'])
+
+        # The above command can return while adb still thinks the device is
+        # connected, so wait a little bit for it to disconnect from adb.
+        time.sleep(10)
+
+        # wait for device to come back to previous status
+        print 'waiting for device to come back online after reboot'
+        start = time.time()
+        rserial, rstatus = self.getDeviceStatus(serial)
+        while rstatus != 'device':
+            if time.time() - start > 120:
+                # device hasn't come back online in 2 minutes, something's wrong
+                raise Exception("Device %s (status: %s) not back online after reboot" % (serial, rstatus))
+            time.sleep(5)
+            rserial, rstatus = self.getDeviceStatus(serial)
+        print 'device:', serial, 'status:', rstatus
+
+    def Process(self, cmd, stdout=None, stderr=None, env=None, cwd=None):
+        # On a desktop or fennec run, the Process method invokes a gecko
+        # process in which to the tests.  For B2G, we simply
+        # reboot the device (which was configured with a test profile
+        # already), wait for B2G to start up, and then navigate to the
+        # test url using Marionette.  There doesn't seem to be any way
+        # to pass env variables into the B2G process, but this doesn't
+        # seem to matter.
+
+        # reboot device so it starts up with the mochitest profile
+        # XXX:  We could potentially use 'stop b2g' + 'start b2g' to achieve
+        # a similar effect; will see which is more stable while attempting
+        # to bring up the continuous integration.
+        if not self._is_emulator:
+            self.rebootDevice()
+            time.sleep(5)
+            #wait for wlan to come up
+            if not self.waitForNet():
+                raise Exception("network did not come up, please configure the network" +
+                                " prior to running before running the automation framework")
+
+        # stop b2g
+        self._devicemanager._runCmd(['shell', 'stop', 'b2g'])
+        time.sleep(5)
+
+        # For some reason user.js in the profile doesn't get picked up.
+        # Manually copy it over to prefs.js. See bug 1009730 for more details.
+        self._devicemanager.moveTree(posixpath.join(self._remoteProfile, 'user.js'),
+                                     posixpath.join(self._remoteProfile, 'prefs.js'))
+
+        # relaunch b2g inside b2g instance
+        instance = self.B2GInstance(self._devicemanager, env=env)
+
+        time.sleep(5)
+
+        # Set up port forwarding again for Marionette, since any that
+        # existed previously got wiped out by the reboot.
+        if not self._is_emulator:
+            self._devicemanager._checkCmd(['forward',
+                                           'tcp:%s' % self.marionette.port,
+                                           'tcp:%s' % self.marionette.port])
+
+        if self._is_emulator:
+            self.marionette.emulator.wait_for_port(self.marionette.port)
+        else:
+            time.sleep(5)
+
+        # start a marionette session
+        session = self.marionette.start_session()
+        if 'b2g' not in session:
+            raise Exception("bad session value %s returned by start_session" % session)
+
+        self.marionette.set_context(self.marionette.CONTEXT_CHROME)
+        self.marionette.execute_script("""
+            let SECURITY_PREF = "security.turn_off_all_security_so_that_viruses_can_take_over_this_computer";
+            Components.utils.import("resource://gre/modules/Services.jsm");
+            Services.prefs.setBoolPref(SECURITY_PREF, true);
+
+            if (!testUtils.hasOwnProperty("specialPowersObserver")) {
+              let loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
+                .getService(Components.interfaces.mozIJSSubScriptLoader);
+              loader.loadSubScript("chrome://specialpowers/content/SpecialPowersObserver.jsm",
+                testUtils);
+              testUtils.specialPowersObserver = new testUtils.SpecialPowersObserver();
+              testUtils.specialPowersObserver.init();
+            }
+            """)
+
+        if not self.context_chrome:
+            self.marionette.set_context(self.marionette.CONTEXT_CONTENT)
+
+        # run the script that starts the tests
+        if self.test_script:
+            if os.path.isfile(self.test_script):
+                script = open(self.test_script, 'r')
+                self.marionette.execute_script(script.read(), script_args=self.test_script_args)
+                script.close()
+            elif isinstance(self.test_script, basestring):
+                self.marionette.execute_script(self.test_script, script_args=self.test_script_args)
+        else:
+            # assumes the tests are started on startup automatically
+            pass
+
+        return instance
+
+    # be careful here as this inner class doesn't have access to outer class members
+    class B2GInstance(object):
+        """Represents a B2G instance running on a device, and exposes
+           some process-like methods/properties that are expected by the
+           automation.
+        """
+
+        def __init__(self, dm, env=None):
+            self.dm = dm
+            self.env = env or {}
+            self.stdout_proc = None
+            self.queue = Queue.Queue()
+
+            # Launch b2g in a separate thread, and dump all output lines
+            # into a queue.  The lines in this queue are
+            # retrieved and returned by accessing the stdout property of
+            # this class.
+            cmd = [self.dm._adbPath]
+            if self.dm._deviceSerial:
+                cmd.extend(['-s', self.dm._deviceSerial])
+            cmd.append('shell')
+            for k, v in self.env.iteritems():
+                cmd.append("%s=%s" % (k, v))
+            cmd.append('/system/bin/b2g.sh')
+            proc = threading.Thread(target=self._save_stdout_proc, args=(cmd, self.queue))
+            proc.daemon = True
+            proc.start()
+
+        def _save_stdout_proc(self, cmd, queue):
+            self.stdout_proc = StdOutProc(cmd, queue)
+            self.stdout_proc.run()
+            if hasattr(self.stdout_proc, 'processOutput'):
+                self.stdout_proc.processOutput()
+            self.stdout_proc.wait()
+            self.stdout_proc = None
+
+        @property
+        def pid(self):
+            # a dummy value to make the automation happy
+            return 0
+
+        def getStdoutLines(self, timeout):
+            # Return any lines in the queue used by the
+            # b2g process handler.
+            lines = []
+            # get all of the lines that are currently available
+            while True:
+                try:
+                    lines.append(self.queue.get_nowait())
+                except Queue.Empty:
+                    break
+
+            # wait 'timeout' for any additional lines
+            try:
+                lines.append(self.queue.get(True, timeout))
+            except Queue.Empty:
+                pass
+            return '\n'.join(lines)
+
+        def wait(self, timeout=None):
+            # this should never happen
+            raise Exception("'wait' called on B2GInstance")
+
+        def kill(self):
+            # this should never happen
+            raise Exception("'kill' called on B2GInstance")
+
diff --git a/src/third_party/mozjs-45/build/mobile/remoteautomation.py b/src/third_party/mozjs-45/build/mobile/remoteautomation.py
new file mode 100644
index 0000000..c402031
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/remoteautomation.py
@@ -0,0 +1,418 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+import datetime
+import glob
+import time
+import re
+import os
+import tempfile
+import shutil
+import subprocess
+import sys
+
+from automation import Automation
+from devicemanager import DMError, DeviceManager
+from mozlog import get_default_logger
+import mozcrash
+
+# signatures for logcat messages that we don't care about much
+fennecLogcatFilters = [ "The character encoding of the HTML document was not declared",
+                        "Use of Mutation Events is deprecated. Use MutationObserver instead.",
+                        "Unexpected value from nativeGetEnabledTags: 0" ]
+
+class RemoteAutomation(Automation):
+    _devicemanager = None
+
+    # Part of a hack for Robocop: "am COMMAND" is handled specially if COMMAND
+    # is in this set. See usages below.
+    _specialAmCommands = ('instrument', 'start')
+
+    def __init__(self, deviceManager, appName = '', remoteLog = None,
+                 processArgs=None):
+        self._devicemanager = deviceManager
+        self._appName = appName
+        self._remoteProfile = None
+        self._remoteLog = remoteLog
+        self._processArgs = processArgs or {};
+
+        # Default our product to fennec
+        self._product = "fennec"
+        self.lastTestSeen = "remoteautomation.py"
+        Automation.__init__(self)
+
+    def setDeviceManager(self, deviceManager):
+        self._devicemanager = deviceManager
+
+    def setAppName(self, appName):
+        self._appName = appName
+
+    def setRemoteProfile(self, remoteProfile):
+        self._remoteProfile = remoteProfile
+
+    def setProduct(self, product):
+        self._product = product
+
+    def setRemoteLog(self, logfile):
+        self._remoteLog = logfile
+
+    # Set up what we need for the remote environment
+    def environment(self, env=None, xrePath=None, crashreporter=True, debugger=False, dmdPath=None, lsanPath=None):
+        # Because we are running remote, we don't want to mimic the local env
+        # so no copying of os.environ
+        if env is None:
+            env = {}
+
+        if dmdPath:
+            env['MOZ_REPLACE_MALLOC_LIB'] = os.path.join(dmdPath, 'libdmd.so')
+
+        # Except for the mochitest results table hiding option, which isn't
+        # passed to runtestsremote.py as an actual option, but through the
+        # MOZ_HIDE_RESULTS_TABLE environment variable.
+        if 'MOZ_HIDE_RESULTS_TABLE' in os.environ:
+            env['MOZ_HIDE_RESULTS_TABLE'] = os.environ['MOZ_HIDE_RESULTS_TABLE']
+
+        if crashreporter and not debugger:
+            env['MOZ_CRASHREPORTER_NO_REPORT'] = '1'
+            env['MOZ_CRASHREPORTER'] = '1'
+        else:
+            env['MOZ_CRASHREPORTER_DISABLE'] = '1'
+
+        # Crash on non-local network connections by default.
+        # MOZ_DISABLE_NONLOCAL_CONNECTIONS can be set to "0" to temporarily
+        # enable non-local connections for the purposes of local testing.
+        # Don't override the user's choice here.  See bug 1049688.
+        env.setdefault('MOZ_DISABLE_NONLOCAL_CONNECTIONS', '1')
+
+        # Set WebRTC logging in case it is not set yet.
+        # On Android, environment variables cannot contain ',' so the
+        # standard WebRTC setting for NSPR_LOG_MODULES is not available.
+        # env.setdefault('NSPR_LOG_MODULES', 'signaling:5,mtransport:5,datachannel:5,jsep:5,MediaPipelineFactory:5')
+        env.setdefault('R_LOG_LEVEL', '6')
+        env.setdefault('R_LOG_DESTINATION', 'stderr')
+        env.setdefault('R_LOG_VERBOSE', '1')
+
+        return env
+
+    def waitForFinish(self, proc, utilityPath, timeout, maxTime, startTime, debuggerInfo, symbolsPath):
+        """ Wait for tests to finish.
+            If maxTime seconds elapse or no output is detected for timeout
+            seconds, kill the process and fail the test.
+        """
+        # maxTime is used to override the default timeout, we should honor that
+        status = proc.wait(timeout = maxTime, noOutputTimeout = timeout)
+        self.lastTestSeen = proc.getLastTestSeen
+
+        topActivity = self._devicemanager.getTopActivity()
+        if topActivity == proc.procName:
+            proc.kill(True)
+        if status == 1:
+            if maxTime:
+                print "TEST-UNEXPECTED-FAIL | %s | application ran for longer than " \
+                      "allowed maximum time of %s seconds" % (self.lastTestSeen, maxTime)
+            else:
+                print "TEST-UNEXPECTED-FAIL | %s | application ran for longer than " \
+                      "allowed maximum time" % (self.lastTestSeen)
+        if status == 2:
+            print "TEST-UNEXPECTED-FAIL | %s | application timed out after %d seconds with no output" \
+                % (self.lastTestSeen, int(timeout))
+
+        return status
+
+    def deleteANRs(self):
+        # empty ANR traces.txt file; usually need root permissions
+        # we make it empty and writable so we can test the ANR reporter later
+        traces = "/data/anr/traces.txt"
+        try:
+            self._devicemanager.shellCheckOutput(['echo', '', '>', traces], root=True,
+                                                 timeout=DeviceManager.short_timeout)
+            self._devicemanager.shellCheckOutput(['chmod', '666', traces], root=True,
+                                                 timeout=DeviceManager.short_timeout)
+        except DMError:
+            print "Error deleting %s" % traces
+            pass
+
+    def checkForANRs(self):
+        traces = "/data/anr/traces.txt"
+        if self._devicemanager.fileExists(traces):
+            try:
+                t = self._devicemanager.pullFile(traces)
+                if t:
+                    stripped = t.strip()
+                    if len(stripped) > 0:
+                        print "Contents of %s:" % traces
+                        print t
+                # Once reported, delete traces
+                self.deleteANRs()
+            except DMError:
+                print "Error pulling %s" % traces
+            except IOError:
+                print "Error pulling %s" % traces
+        else:
+            print "%s not found" % traces
+
+    def deleteTombstones(self):
+        # delete any existing tombstone files from device
+        remoteDir = "/data/tombstones"
+        try:
+            self._devicemanager.shellCheckOutput(['rm', '-r', remoteDir], root=True,
+                                                 timeout=DeviceManager.short_timeout)
+        except DMError:
+            # This may just indicate that the tombstone directory is missing
+            pass
+
+    def checkForTombstones(self):
+        # pull any tombstones from device and move to MOZ_UPLOAD_DIR
+        remoteDir = "/data/tombstones"
+        blobberUploadDir = os.environ.get('MOZ_UPLOAD_DIR', None)
+        if blobberUploadDir:
+            if not os.path.exists(blobberUploadDir):
+                os.mkdir(blobberUploadDir)
+            if self._devicemanager.dirExists(remoteDir):
+                # copy tombstone files from device to local blobber upload directory
+                try:
+                    self._devicemanager.shellCheckOutput(['chmod', '777', remoteDir], root=True,
+                                                 timeout=DeviceManager.short_timeout)
+                    self._devicemanager.shellCheckOutput(['chmod', '666', os.path.join(remoteDir, '*')], root=True,
+                                                 timeout=DeviceManager.short_timeout)
+                    self._devicemanager.getDirectory(remoteDir, blobberUploadDir, False)
+                except DMError:
+                    # This may just indicate that no tombstone files are present
+                    pass
+                self.deleteTombstones()
+                # add a .txt file extension to each tombstone file name, so
+                # that blobber will upload it
+                for f in glob.glob(os.path.join(blobberUploadDir, "tombstone_??")):
+                    # add a unique integer to the file name, in case there are
+                    # multiple tombstones generated with the same name, for
+                    # instance, after multiple robocop tests
+                    for i in xrange(1, sys.maxint):
+                        newname = "%s.%d.txt" % (f, i)
+                        if not os.path.exists(newname):
+                            os.rename(f, newname)
+                            break
+            else:
+                print "%s does not exist; tombstone check skipped" % remoteDir
+        else:
+            print "MOZ_UPLOAD_DIR not defined; tombstone check skipped"
+
+    def checkForCrashes(self, directory, symbolsPath):
+        self.checkForANRs()
+        self.checkForTombstones()
+
+        logcat = self._devicemanager.getLogcat(filterOutRegexps=fennecLogcatFilters)
+
+        javaException = mozcrash.check_for_java_exception(logcat)
+        if javaException:
+            return True
+
+        # If crash reporting is disabled (MOZ_CRASHREPORTER!=1), we can't say
+        # anything.
+        if not self.CRASHREPORTER:
+            return False
+
+        try:
+            dumpDir = tempfile.mkdtemp()
+            remoteCrashDir = self._remoteProfile + '/minidumps/'
+            if not self._devicemanager.dirExists(remoteCrashDir):
+                # If crash reporting is enabled (MOZ_CRASHREPORTER=1), the
+                # minidumps directory is automatically created when Fennec
+                # (first) starts, so its lack of presence is a hint that
+                # something went wrong.
+                print "Automation Error: No crash directory (%s) found on remote device" % remoteCrashDir
+                # Whilst no crash was found, the run should still display as a failure
+                return True
+            self._devicemanager.getDirectory(remoteCrashDir, dumpDir)
+
+            logger = get_default_logger()
+            if logger is not None:
+                crashed = mozcrash.log_crashes(logger, dumpDir, symbolsPath, test=self.lastTestSeen)
+            else:
+                crashed = Automation.checkForCrashes(self, dumpDir, symbolsPath)
+
+        finally:
+            try:
+                shutil.rmtree(dumpDir)
+            except:
+                print "WARNING: unable to remove directory: %s" % dumpDir
+        return crashed
+
+    def buildCommandLine(self, app, debuggerInfo, profileDir, testURL, extraArgs):
+        # If remote profile is specified, use that instead
+        if (self._remoteProfile):
+            profileDir = self._remoteProfile
+
+        # Hack for robocop, if app & testURL == None and extraArgs contains the rest of the stuff, lets
+        # assume extraArgs is all we need
+        if app == "am" and extraArgs[0] in RemoteAutomation._specialAmCommands:
+            return app, extraArgs
+
+        cmd, args = Automation.buildCommandLine(self, app, debuggerInfo, profileDir, testURL, extraArgs)
+        # Remove -foreground if it exists, if it doesn't this just returns
+        try:
+            args.remove('-foreground')
+        except:
+            pass
+#TODO: figure out which platform require NO_EM_RESTART
+#        return app, ['--environ:NO_EM_RESTART=1'] + args
+        return app, args
+
+    def Process(self, cmd, stdout = None, stderr = None, env = None, cwd = None):
+        if stdout == None or stdout == -1 or stdout == subprocess.PIPE:
+            stdout = self._remoteLog
+
+        return self.RProcess(self._devicemanager, cmd, stdout, stderr, env, cwd, self._appName,
+                             **self._processArgs)
+
+    # be careful here as this inner class doesn't have access to outer class members
+    class RProcess(object):
+        # device manager process
+        dm = None
+        def __init__(self, dm, cmd, stdout=None, stderr=None, env=None, cwd=None, app=None,
+                     messageLogger=None):
+            self.dm = dm
+            self.stdoutlen = 0
+            self.lastTestSeen = "remoteautomation.py"
+            self.proc = dm.launchProcess(cmd, stdout, cwd, env, True)
+            self.messageLogger = messageLogger
+
+            if (self.proc is None):
+                if cmd[0] == 'am':
+                    self.proc = stdout
+                else:
+                    raise Exception("unable to launch process")
+            self.procName = cmd[0].split('/')[-1]
+            if cmd[0] == 'am' and cmd[1] in RemoteAutomation._specialAmCommands:
+                self.procName = app
+
+            # Setting timeout at 1 hour since on a remote device this takes much longer.
+            # Temporarily increased to 90 minutes because no more chunks can be created.
+            self.timeout = 5400
+            # The benefit of the following sleep is unclear; it was formerly 15 seconds
+            time.sleep(1)
+
+            # Used to buffer log messages until we meet a line break
+            self.logBuffer = ""
+
+        @property
+        def pid(self):
+            pid = self.dm.processExist(self.procName)
+            # HACK: we should probably be more sophisticated about monitoring
+            # running processes for the remote case, but for now we'll assume
+            # that this method can be called when nothing exists and it is not
+            # an error
+            if pid is None:
+                return 0
+            return pid
+
+        def read_stdout(self):
+            """ Fetch the full remote log file using devicemanager and return just
+                the new log entries since the last call (as a list of messages or lines).
+            """
+            if not self.dm.fileExists(self.proc):
+                return []
+            try:
+                newLogContent = self.dm.pullFile(self.proc, self.stdoutlen)
+            except DMError:
+                # we currently don't retry properly in the pullFile
+                # function in dmSUT, so an error here is not necessarily
+                # the end of the world
+                return []
+            if not newLogContent:
+                return []
+
+            self.stdoutlen += len(newLogContent)
+
+            if self.messageLogger is None:
+                testStartFilenames = re.findall(r"TEST-START \| ([^\s]*)", newLogContent)
+                if testStartFilenames:
+                    self.lastTestSeen = testStartFilenames[-1]
+                print newLogContent
+                return [newLogContent]
+
+            self.logBuffer += newLogContent
+            lines = self.logBuffer.split('\n')
+            if not lines:
+                return
+
+            # We only keep the last (unfinished) line in the buffer
+            self.logBuffer = lines[-1]
+            del lines[-1]
+            messages = []
+            for line in lines:
+                # This passes the line to the logger (to be logged or buffered)
+                # and returns a list of structured messages (dict)
+                parsed_messages = self.messageLogger.write(line)
+                for message in parsed_messages:
+                    if message['action'] == 'test_start':
+                        self.lastTestSeen = message['test']
+                messages += parsed_messages
+            return messages
+
+        @property
+        def getLastTestSeen(self):
+            return self.lastTestSeen
+
+        # Wait for the remote process to end (or for its activity to go to background).
+        # While waiting, periodically retrieve the process output and print it.
+        # If the process is still running after *timeout* seconds, return 1;
+        # If the process is still running but no output is received in *noOutputTimeout*
+        # seconds, return 2;
+        # Else, once the process exits/goes to background, return 0.
+        def wait(self, timeout = None, noOutputTimeout = None):
+            timer = 0
+            noOutputTimer = 0
+            interval = 10
+            if timeout == None:
+                timeout = self.timeout
+            status = 0
+            top = self.procName
+            slowLog = False
+            while (top == self.procName):
+                # Get log updates on each interval, but if it is taking
+                # too long, only do it every 60 seconds
+                if (not slowLog) or (timer % 60 == 0):
+                    startRead = datetime.datetime.now()
+                    messages = self.read_stdout()
+                    if (datetime.datetime.now() - startRead) > datetime.timedelta(seconds=5):
+                        slowLog = True
+                    if messages:
+                        noOutputTimer = 0
+                time.sleep(interval)
+                timer += interval
+                noOutputTimer += interval
+                if (timer > timeout):
+                    status = 1
+                    break
+                if (noOutputTimeout and noOutputTimer > noOutputTimeout):
+                    status = 2
+                    break
+                top = self.dm.getTopActivity()
+            # Flush anything added to stdout during the sleep
+            self.read_stdout()
+            return status
+
+        def kill(self, stagedShutdown = False):
+            if stagedShutdown:
+                # Trigger an ANR report with "kill -3" (SIGQUIT)
+                self.dm.killProcess(self.procName, 3)
+                time.sleep(3)
+                # Trigger a breakpad dump with "kill -6" (SIGABRT)
+                self.dm.killProcess(self.procName, 6)
+                # Wait for process to end
+                retries = 0
+                while retries < 3:
+                    pid = self.dm.processExist(self.procName)
+                    if pid and pid > 0:
+                        print "%s still alive after SIGABRT: waiting..." % self.procName
+                        time.sleep(5)
+                    else:
+                        return
+                    retries += 1
+                self.dm.killProcess(self.procName, 9)
+                pid = self.dm.processExist(self.procName)
+                if pid and pid > 0:
+                    self.dm.killProcess(self.procName)
+            else:
+                self.dm.killProcess(self.procName)
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/ASMozStub.java b/src/third_party/mozjs-45/build/mobile/sutagent/android/ASMozStub.java
new file mode 100755
index 0000000..7ecf2f2
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/ASMozStub.java
@@ -0,0 +1,327 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package com.mozilla.SUTAgentAndroid.service;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.util.Timer;
+
+import com.mozilla.SUTAgentAndroid.SUTAgentAndroid;
+import com.mozilla.SUTAgentAndroid.R;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.content.Intent;
+import android.net.wifi.WifiManager;
+import android.os.Handler;
+import android.os.IBinder;
+import android.util.Log;
+import android.view.Gravity;
+import android.widget.Toast;
+
+import javax.jmdns.JmDNS;
+import javax.jmdns.ServiceInfo;
+
+public class ASMozStub extends android.app.Service {
+    private final static int COMMAND_PORT = 20701;
+    private final static int DATA_PORT = 20700;
+
+    private ServerSocket cmdChnl = null;
+    private ServerSocket dataChnl = null;
+    private Handler handler = new Handler();
+    RunCmdThread runCmdThrd = null;
+    RunDataThread runDataThrd = null;
+    Thread monitor = null;
+    Timer timer = null;
+    boolean doZeroConfig = false;
+
+    @SuppressWarnings("unchecked")
+    private static final Class<?>[] mSetForegroundSignature = new Class[] {
+    boolean.class};
+    @SuppressWarnings("unchecked")
+    private static final Class<?>[] mStartForegroundSignature = new Class[] {
+        int.class, Notification.class};
+    @SuppressWarnings("unchecked")
+    private static final Class<?>[] mStopForegroundSignature = new Class[] {
+        boolean.class};
+
+    private NotificationManager mNM;
+    private Method mSetForeground;
+    private Method mStartForeground;
+    private Method mStopForeground;
+    private Object[] mSetForegroundArgs = new Object[1];
+    private Object[] mStartForegroundArgs = new Object[2];
+    private Object[] mStopForegroundArgs = new Object[1];
+
+    @Override
+    public IBinder onBind(Intent intent)
+        {
+        return null;
+        }
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+
+        mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
+        try {
+            mStartForeground = getClass().getMethod("startForeground", mStartForegroundSignature);
+            mStopForeground = getClass().getMethod("stopForeground", mStopForegroundSignature);
+            }
+        catch (NoSuchMethodException e) {
+            // Might be running on an older platform.
+            mStartForeground = mStopForeground = null;
+            Log.w("SUTAgent", "unable to find start/stopForeground method(s) -- older platform?");
+            }
+
+        try {
+            mSetForeground = getClass().getMethod("setForeground", mSetForegroundSignature);
+            }
+        catch (NoSuchMethodException e) {
+            mSetForeground = null;
+            Log.e("SUTAgent", "unable to find setForeground method!");
+            }
+
+        doToast("Listener Service created...");
+        }
+
+    WifiManager.MulticastLock multicastLock;
+    JmDNS jmdns;
+
+    void startZeroConf() {
+        if (multicastLock == null) {
+            WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
+            multicastLock = wifi.createMulticastLock("SUTAgent");
+            multicastLock.setReferenceCounted(true);
+        }
+
+        multicastLock.acquire();
+
+        try {
+            InetAddress inetAddress = SUTAgentAndroid.getLocalInetAddress();
+
+            if (jmdns == null) {
+                jmdns = JmDNS.create(inetAddress, null);
+            }
+
+            if (jmdns != null) {
+                String name = "SUTAgent";
+
+                String hwid = SUTAgentAndroid.getHWID(this);
+                if (hwid != null) {
+                    name += " [hwid:" + hwid + "]";
+                }
+
+                // multicast reception is broken for some reason, so
+                // this service can't be resolved; it can only be
+                // broadcast.  So, we cheat -- we put the IP address
+                // in the broadcast that we can pull out later.
+                // However, periods aren't legal, so replace them.
+                // The IP address will show up as [ip:127_0_0_1]
+                name += " [ip:" + inetAddress.getHostAddress().toString().replace('.', '_') + "]";
+
+                final ServiceInfo serviceInfo = ServiceInfo.create("_sutagent._tcp.local.",
+                                                                   name,
+                                                                   COMMAND_PORT,
+                                                                   "Android SUTAgent");
+                final JmDNS dns = jmdns;
+                // we want to call registerService on a new thread, because it can block
+                // for a little while.
+                Thread registerThread = new Thread() {
+                        public void run() {
+                            try {
+                                dns.registerService(serviceInfo);
+                            } catch (IOException e) {
+                                Log.e("SUTAgent", "Failed to register JmDNS service!", e);
+                            }
+                        }
+                    };
+                registerThread.setDaemon(true);
+                registerThread.start();
+            }
+        } catch (IOException e) {
+            Log.e("SUTAgent", "Failed to register JmDNS service!", e);
+        }
+    }
+
+    void stopZeroConf() {
+        if (jmdns != null) {
+            try {
+                jmdns.unregisterAllServices();
+                jmdns.close();
+            } catch (IOException e) {
+                Log.e("SUTAgent", "Failed to close JmDNS service!", e);
+            }
+            jmdns = null;
+        }
+
+        if (multicastLock != null) {
+            multicastLock.release();
+            multicastLock = null;
+        }
+    }
+
+    public void onStart(Intent intent, int startId) {
+        super.onStart(intent, startId);
+
+        try {
+            cmdChnl = new ServerSocket(COMMAND_PORT);
+            runCmdThrd = new RunCmdThread(cmdChnl, this, handler);
+            runCmdThrd.start();
+            doToast(String.format("Command channel port %d ...", COMMAND_PORT));
+
+            dataChnl = new ServerSocket(DATA_PORT);
+            runDataThrd = new RunDataThread(dataChnl, this);
+            runDataThrd.start();
+            doToast(String.format("Data channel port %d ...", DATA_PORT));
+
+            DoCommand tmpdc = new DoCommand(getApplication());
+            File dir = getFilesDir();
+            File iniFile = new File(dir, "SUTAgent.ini");
+            String sIniFile = iniFile.getAbsolutePath();
+            String zeroconf = tmpdc.GetIniData("General", "ZeroConfig", sIniFile);
+            if (zeroconf != "" && Integer.parseInt(zeroconf) == 1) {
+                this.doZeroConfig = true;
+            }
+
+            if (this.doZeroConfig) {
+                startZeroConf();
+            }
+
+            Notification notification = new Notification();
+            startForegroundCompat(R.string.foreground_service_started, notification);
+            }
+        catch (Exception e) {
+            doToast(e.toString());
+            }
+
+        return;
+        }
+
+    public void onDestroy()
+        {
+        super.onDestroy();
+
+        if (this.doZeroConfig) {
+            stopZeroConf();
+        }
+
+        if (runCmdThrd.isAlive())
+            {
+            runCmdThrd.StopListening();
+            }
+
+        if (runDataThrd.isAlive())
+            {
+            runDataThrd.StopListening();
+            }
+
+        NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
+        notificationManager.cancel(1959);
+
+        stopForegroundCompat(R.string.foreground_service_started);
+
+        doToast("Listener Service destroyed...");
+
+        System.exit(0);
+        }
+
+    public void SendToDataChannel(String strToSend)
+        {
+        if (runDataThrd.isAlive())
+            runDataThrd.SendToDataChannel(strToSend);
+        }
+
+    public void doToast(String sMsg) {
+        Toast toast = Toast.makeText(this, sMsg, Toast.LENGTH_LONG);
+        toast.setGravity(Gravity.TOP|Gravity.CENTER_HORIZONTAL, 0, 100);
+        toast.show();
+    }
+
+    /**
+     * This is a wrapper around the new startForeground method, using the older
+     * APIs if it is not available.
+     */
+    void startForegroundCompat(int id, Notification notification) {
+        // If we have the new startForeground API, then use it.
+        if (mStartForeground != null) {
+            mStartForegroundArgs[0] = Integer.valueOf(id);
+            mStartForegroundArgs[1] = notification;
+            try {
+                mStartForeground.invoke(this, mStartForegroundArgs);
+            } catch (InvocationTargetException e) {
+                // Should not happen.
+                Log.e("SUTAgent", "Unable to invoke startForeground", e);
+            } catch (IllegalAccessException e) {
+                // Should not happen.
+                Log.e("SUTAgent", "Unable to invoke startForeground", e);
+            }
+            return;
+        }
+
+        // Fall back on the old API.
+        if  (mSetForeground != null) {
+            try {
+                mSetForegroundArgs[0] = Boolean.TRUE;
+                mSetForeground.invoke(this, mSetForegroundArgs);
+            } catch (IllegalArgumentException e) {
+                Log.e("SUTAgent", "Unable to invoke setForeground", e);
+                e.printStackTrace();
+            } catch (IllegalAccessException e) {
+                Log.e("SUTAgent", "Unable to invoke setForeground", e);
+                e.printStackTrace();
+            } catch (InvocationTargetException e) {
+                Log.e("SUTAgent", "Unable to invoke setForeground", e);
+                e.printStackTrace();
+            }
+        }
+        mNM.notify(id, notification);
+    }
+
+    /**
+     * This is a wrapper around the new stopForeground method, using the older
+     * APIs if it is not available.
+     */
+    void stopForegroundCompat(int id) {
+        // If we have the new stopForeground API, then use it.
+        if (mStopForeground != null) {
+            mStopForegroundArgs[0] = Boolean.TRUE;
+            try {
+                mStopForeground.invoke(this, mStopForegroundArgs);
+            } catch (InvocationTargetException e) {
+                // Should not happen.
+                Log.e("SUTAgent", "Unable to invoke stopForeground", e);
+            } catch (IllegalAccessException e) {
+                // Should not happen.
+                Log.e("SUTAgent", "Unable to invoke stopForeground", e);
+            }
+            return;
+        }
+
+        // Fall back on the old API.  Note to cancel BEFORE changing the
+        // foreground state, since we could be killed at that point.
+        mNM.cancel(id);
+        if  (mSetForeground != null) {
+            try {
+                mSetForegroundArgs[0] = Boolean.FALSE;
+                mSetForeground.invoke(this, mSetForegroundArgs);
+            } catch (IllegalArgumentException e) {
+                Log.e("SUTAgent", "Unable to invoke setForeground", e);
+                e.printStackTrace();
+            } catch (IllegalAccessException e) {
+                Log.e("SUTAgent", "Unable to invoke setForeground", e);
+                e.printStackTrace();
+            } catch (InvocationTargetException e) {
+                Log.e("SUTAgent", "Unable to invoke setForeground", e);
+                e.printStackTrace();
+            }
+        }
+    }
+}
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/AlertLooperThread.java b/src/third_party/mozjs-45/build/mobile/sutagent/android/AlertLooperThread.java
new file mode 100755
index 0000000..01d0b43
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/AlertLooperThread.java
@@ -0,0 +1,63 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package com.mozilla.SUTAgentAndroid.service;
+
+import java.util.Timer;
+
+import android.content.ContextWrapper;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+
+class AlertLooperThread extends Thread
+    {
+    public Handler mHandler;
+    private Looper looper = null;
+    private DoAlert da    = null;
+    private Timer alertTimer = null;
+    private ContextWrapper contextWrapper = null;
+
+    AlertLooperThread(ContextWrapper ctxW)
+        {
+        this.contextWrapper = ctxW;
+        }
+
+    public Timer getAlertTimer()
+        {
+        return alertTimer;
+        }
+
+    public void term()
+        {
+        if (da != null)
+            da.term();
+        }
+
+    public void quit()
+        {
+        if (looper != null)
+            looper.quit();
+        }
+
+    public void run()
+        {
+        Looper.prepare();
+
+        looper = Looper.myLooper();
+
+        mHandler = new Handler()
+            {
+            public void handleMessage(Message msg)
+                {
+                // process incoming messages here
+                }
+            };
+
+        alertTimer = new Timer();
+        da = new DoAlert(contextWrapper);
+        alertTimer.scheduleAtFixedRate(da, 0, 5000);
+        Looper.loop();
+        }
+    }
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/AndroidManifest.xml b/src/third_party/mozjs-45/build/mobile/sutagent/android/AndroidManifest.xml
new file mode 100644
index 0000000..baf140d
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/AndroidManifest.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+      package="com.mozilla.SUTAgentAndroid"
+      android:versionCode="1" android:versionName="1.01">
+    <application android:icon="@drawable/icon" android:label="@string/app_name" android:debuggable="true">
+        <activity android:name=".SUTAgentAndroid"
+                  android:screenOrientation="nosensor"
+                  android:label="@string/app_name">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        <service android:name=".service.ASMozStub">
+		    <intent-filter>
+			    <action android:name="com.mozilla.SUTAgentAndroid.service.LISTENER_SERVICE" />
+		    </intent-filter>
+	    </service>
+	</application>
+    
+    <uses-sdk android:minSdkVersion="5" android:targetSdkVersion="8"/>
+
+<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
+<uses-permission android:name="android.permission.INTERNET"></uses-permission>
+<uses-permission android:name="android.permission.REBOOT"></uses-permission>
+<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
+<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"></uses-permission>
+<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
+<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
+<uses-permission android:name="android.permission.RESTART_PACKAGES"></uses-permission>
+<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission>
+<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"></uses-permission>
+<uses-permission android:name="android.permission.CHANGE_CONFIGURATION"></uses-permission>
+<uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>
+<uses-permission android:name="android.permission.BATTERY_STATS"></uses-permission>
+<uses-permission android:name="android.permission.DEVICE_POWER"></uses-permission>
+<uses-permission android:name="android.permission.DISABLE_KEYGUARD"></uses-permission>
+<uses-permission android:name="android.permission.WAKE_LOCK"></uses-permission>
+<uses-permission android:name="android.permission.WRITE_SETTINGS"></uses-permission>
+<uses-permission android:name="android.permission.READ_SYNC_SETTINGS"></uses-permission>
+<uses-permission android:name="android.permission.BLUETOOTH"></uses-permission>
+<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"></uses-permission>
+<uses-permission android:name="android.permission.INSTALL_PACKAGES"></uses-permission>
+<uses-permission android:name="android.permission.STATUS_BAR"></uses-permission>
+<uses-permission android:name="android.permission.VIBRATE"></uses-permission>
+<uses-permission android:name="android.permission.SET_TIME"></uses-permission>
+<uses-permission android:name="android.permission.SET_TIME_ZONE"></uses-permission>
+
+<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"></uses-permission>
+<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS"></uses-permission>
+<uses-permission android:name="android.permission.GET_TASKS"></uses-permission>
+
+</manifest> 
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/CmdWorkerThread.java b/src/third_party/mozjs-45/build/mobile/sutagent/android/CmdWorkerThread.java
new file mode 100755
index 0000000..e8037ae
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/CmdWorkerThread.java
@@ -0,0 +1,181 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package com.mozilla.SUTAgentAndroid.service;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.net.Socket;
+import java.net.SocketTimeoutException;
+
+import com.mozilla.SUTAgentAndroid.SUTAgentAndroid;
+
+import android.util.Log;
+
+// import com.mozilla.SUTAgentAndroid.DoCommand;
+
+public class CmdWorkerThread extends Thread
+{
+    private RunCmdThread theParent = null;
+    private Socket socket    = null;
+    private String prompt = null;
+    boolean bListening    = true;
+
+    public CmdWorkerThread(RunCmdThread theParent, Socket workerSocket)
+        {
+        super("CmdWorkerThread");
+        this.theParent = theParent;
+        this.socket = workerSocket;
+        byte pr [] = new byte [3];
+        pr[0] = '$';
+        pr[1] = '>';
+        pr[2] = 0;
+        prompt = new String(pr,0,3);
+        }
+
+    public void StopListening()
+        {
+        bListening = false;
+        }
+
+    private String readLine(BufferedInputStream in)
+        {
+        String sRet = "";
+        int nByte = 0;
+        char cChar = 0;
+
+        try
+            {
+            nByte = in.read();
+            while (nByte != -1)
+                {
+                cChar = ((char)(nByte & 0xFF));
+                if ((cChar != '\r') && (cChar != '\n'))
+                    sRet += cChar;
+                else
+                    break;
+                nByte = in.read();
+                }
+
+            if ((in.available() > 0) && (cChar != '\n'))
+                {
+                in.mark(1024);
+                nByte = in.read();
+
+                if (nByte != -1)
+                    {
+                    cChar = ((char)(nByte & 0xFF));
+                    if (cChar != '\n')
+                        {
+                        in.reset();
+                        }
+                    }
+                }
+            }
+        catch (IOException e)
+            {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+            }
+
+        if (sRet.length() == 0)
+            sRet = null;
+
+        return(sRet);
+        }
+
+    public void run()
+        {
+        try {
+            OutputStream cmdOut = socket.getOutputStream();
+            InputStream cmdIn = socket.getInputStream();
+            PrintWriter out = new PrintWriter(cmdOut, true);
+            BufferedInputStream in = new BufferedInputStream(cmdIn);
+            String inputLine, outputLine;
+            DoCommand dc = new DoCommand(theParent.svc);
+
+            SUTAgentAndroid.log(dc, "CmdWorkerThread starts: "+getId());
+
+            int nAvail = cmdIn.available();
+            cmdIn.skip(nAvail);
+
+            out.print(prompt);
+            out.flush();
+
+            while (bListening)
+                {
+                if (!(in.available() > 0))
+                    {
+                    socket.setSoTimeout(500);
+                    try {
+                        int nRead = cmdIn.read();
+                        if (nRead == -1)
+                            {
+                            bListening = false;
+                            continue;
+                            }
+                        else
+                            {
+                            inputLine = ((char)nRead) + "";
+                            socket.setSoTimeout(120000);
+                            }
+                        }
+                    catch(SocketTimeoutException toe)
+                        {
+                        continue;
+                        }
+                    }
+                else
+                    inputLine = "";
+
+                if ((inputLine += readLine(in)) != null)
+                    {
+                    String message = String.format("%s : %s",
+                                     socket.getInetAddress().getHostAddress(), inputLine);
+                    SUTAgentAndroid.log(dc, message);
+
+                    outputLine = dc.processCommand(inputLine, out, in, cmdOut);
+                    if (outputLine == null)
+                        {
+                        outputLine = "";
+                        }
+                    if (outputLine.length() > 0)
+                        {
+                        out.print(outputLine + "\n" + prompt);
+                        }
+                    else
+                        out.print(prompt);
+                    out.flush();
+                    if (outputLine.equals("exit"))
+                        {
+                        theParent.StopListening();
+                        bListening = false;
+                        }
+                    if (outputLine.equals("quit"))
+                        {
+                        bListening = false;
+                        }
+                    outputLine = null;
+                    System.gc();
+                    }
+                else
+                    break;
+                }
+            out.close();
+            out = null;
+            in.close();
+            in = null;
+            socket.close();
+            SUTAgentAndroid.log(dc, "CmdWorkerThread ends: "+getId());
+        }
+    catch (IOException e)
+        {
+        // TODO Auto-generated catch block
+        e.printStackTrace();
+        }
+    }
+}
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/DataWorkerThread.java b/src/third_party/mozjs-45/build/mobile/sutagent/android/DataWorkerThread.java
new file mode 100755
index 0000000..f8e3b6c
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/DataWorkerThread.java
@@ -0,0 +1,208 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package com.mozilla.SUTAgentAndroid.service;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.net.Socket;
+import java.net.SocketTimeoutException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+
+// import com.mozilla.SUTAgentAndroid.DoCommand;
+import com.mozilla.SUTAgentAndroid.SUTAgentAndroid;
+
+public class DataWorkerThread extends Thread
+{
+    private RunDataThread theParent = null;
+    private Socket socket    = null;
+    boolean bListening    = true;
+    PrintWriter out = null;
+    SimpleDateFormat sdf = null;
+
+    public DataWorkerThread(RunDataThread theParent, Socket workerSocket)
+        {
+        super("DataWorkerThread");
+        this.theParent = theParent;
+        this.socket = workerSocket;
+        this.sdf = new SimpleDateFormat("yyyyMMdd-HH:mm:ss");
+        }
+
+    public void StopListening()
+        {
+        bListening = false;
+        }
+
+    public void SendString(String strToSend)
+        {
+        if (this.out != null)
+            {
+            Calendar cal = Calendar.getInstance();
+            String strOut = sdf.format(cal.getTime());
+            strOut += " " + strToSend + "\r\n";
+
+            out.write(strOut);
+            out.flush();
+            }
+        }
+
+    private String readLine(BufferedInputStream in)
+        {
+        String sRet = "";
+        int nByte = 0;
+        char cChar = 0;
+
+        try
+            {
+            nByte = in.read();
+            while (nByte != -1)
+                {
+                cChar = ((char)(nByte & 0xFF));
+                if ((cChar != '\r') && (cChar != '\n'))
+                    sRet += cChar;
+                else
+                    break;
+                nByte = in.read();
+                }
+
+            if (in.available() > 0)
+                {
+                in.mark(1024);
+                nByte = in.read();
+
+                while (nByte != -1)
+                    {
+                    cChar = ((char)(nByte & 0xFF));
+                    if ((cChar == '\r') || (cChar == '\n'))
+                        {
+                        if (in.available() > 0)
+                            {
+                            in.mark(1024);
+                            nByte = in.read();
+                            }
+                        else
+                            nByte = -1;
+                        }
+                    else
+                        {
+                        in.reset();
+                        break;
+                        }
+                    }
+                }
+            }
+        catch (IOException e)
+            {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+            }
+
+        if (sRet.length() == 0)
+            sRet = null;
+
+        return(sRet);
+        }
+
+    public void run()
+        {
+        String    sRet = "";
+        long lEndTime = System.currentTimeMillis() + 60000;
+
+        try {
+            while(bListening)
+                {
+                OutputStream cmdOut = socket.getOutputStream();
+                InputStream cmdIn = socket.getInputStream();
+                this.out = new PrintWriter(cmdOut, true);
+                BufferedInputStream in = new BufferedInputStream(cmdIn);
+                String inputLine, outputLine;
+                DoCommand dc = new DoCommand(theParent.svc);
+
+                Calendar cal = Calendar.getInstance();
+                sRet = sdf.format(cal.getTime());
+                sRet += " trace output";
+
+                out.println(sRet);
+                out.flush();
+                int nAvail = cmdIn.available();
+                cmdIn.skip(nAvail);
+
+                while (bListening)
+                    {
+                    if (System.currentTimeMillis() > lEndTime)
+                        {
+                        cal = Calendar.getInstance();
+                        sRet = sdf.format(cal.getTime());
+                        sRet += " Thump thump - " + SUTAgentAndroid.sUniqueID + "\r\n";
+
+                        out.write(sRet);
+                        out.flush();
+
+                        lEndTime = System.currentTimeMillis() + 60000;
+                        }
+
+                    if (!(in.available() > 0))
+                        {
+                        socket.setSoTimeout(500);
+                        try {
+                            int nRead = cmdIn.read();
+                            if (nRead == -1)
+                                {
+                                bListening = false;
+                                continue;
+                                }
+                            else
+                                inputLine = (char)nRead + "";
+                            }
+                        catch(SocketTimeoutException toe)
+                            {
+                            continue;
+                            }
+                        }
+                    else
+                        inputLine = "";
+
+                    if ((inputLine += readLine(in)) != null)
+                        {
+                        outputLine = dc.processCommand(inputLine, out, in, cmdOut);
+                        if (outputLine == null)
+                            {
+                            outputLine = "";
+                            }
+                        out.print(outputLine + "\n");
+                        out.flush();
+                        if (outputLine.equals("exit"))
+                            {
+                            theParent.StopListening();
+                            bListening = false;
+                            }
+                        if (outputLine.equals("quit"))
+                            {
+                            bListening = false;
+                            }
+                        outputLine = null;
+                        System.gc();
+                        }
+                    else
+                        break;
+                    }
+
+                out.close();
+                out = null;
+                in.close();
+                in = null;
+                socket.close();
+                }
+            }
+        catch (IOException e)
+            {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+            }
+        }
+}
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/DoAlert.java b/src/third_party/mozjs-45/build/mobile/sutagent/android/DoAlert.java
new file mode 100755
index 0000000..ac11f2b
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/DoAlert.java
@@ -0,0 +1,48 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package com.mozilla.SUTAgentAndroid.service;
+
+import java.util.TimerTask;
+
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.media.Ringtone;
+import android.media.RingtoneManager;
+import android.widget.Toast;
+
+class DoAlert extends TimerTask
+    {
+    int    lcv = 0;
+    Toast toast = null;
+    Ringtone rt = null;
+
+    DoAlert(ContextWrapper contextWrapper)
+        {
+        Context    ctx = contextWrapper.getApplicationContext();
+        this.toast = Toast.makeText(ctx, "Help me!", Toast.LENGTH_LONG);
+        rt = RingtoneManager.getRingtone(ctx, RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM));
+        }
+
+    public void term()
+        {
+        if (rt != null)
+            {
+            if (rt.isPlaying())
+                rt.stop();
+            }
+
+        if (toast != null)
+            toast.cancel();
+        }
+
+    public void run ()
+        {
+        String sText =(((lcv++ % 2) == 0)  ? "Help me!" : "I've fallen down!" );
+        toast.setText(sText);
+        toast.show();
+        if (rt != null)
+            rt.play();
+        }
+    }
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/DoCommand.java b/src/third_party/mozjs-45/build/mobile/sutagent/android/DoCommand.java
new file mode 100755
index 0000000..59d0d67
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/DoCommand.java
@@ -0,0 +1,3985 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package com.mozilla.SUTAgentAndroid.service;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.RandomAccessFile;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.SocketException;
+import java.net.UnknownHostException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+import java.util.TimeZone;
+import java.util.zip.Adler32;
+import java.util.zip.CheckedInputStream;
+import java.util.zip.CheckedOutputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipInputStream;
+import java.util.zip.ZipOutputStream;
+
+import org.apache.commons.net.ftp.FTP;
+import org.apache.commons.net.ftp.FTPClient;
+import org.apache.commons.net.ftp.FTPFile;
+import org.apache.commons.net.ftp.FTPReply;
+
+import com.mozilla.SUTAgentAndroid.R;
+import com.mozilla.SUTAgentAndroid.SUTAgentAndroid;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.app.AlarmManager;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.ActivityNotFoundException;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ServiceInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Debug;
+import android.os.Environment;
+import android.os.StatFs;
+import android.os.SystemClock;
+import android.text.TextUtils;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.Surface;
+import android.view.WindowManager;
+
+public class DoCommand {
+
+    String lineSep = System.getProperty("line.separator");
+    Process    pProc;
+    OutputStream sutIn;
+    InputStream    sutErr;
+    InputStream    sutOut;
+    AlertLooperThread alrt = null;
+    ContextWrapper    contextWrapper = null;
+
+    String    currentDir = "/";
+    String    sErrorPrefix = "##AGENT-WARNING## ";
+    boolean bTraceOn = false;
+
+    String ffxProvider = "org.mozilla.ffxcp";
+    String fenProvider = "org.mozilla.fencp";
+
+    private static final int DEFAULT_STARTPRG_TIMEOUT_SECONDS = 300;
+
+    public final String prgVersion = "SUTAgentAndroid Version 1.20";
+
+    public enum Command
+        {
+        RUN ("run"),
+        EXEC ("exec"),
+        EXECSU ("execsu"),
+        EXECCWD ("execcwd"),
+        EXECCWDSU ("execcwdsu"),
+        EXECEXT ("execext"),
+        ENVRUN ("envrun"),
+        KILL ("kill"),
+        PS ("ps"),
+        DEVINFO ("info"),
+        OS ("os"),
+        ID ("id"),
+        UPTIME ("uptime"),
+        UPTIMEMILLIS ("uptimemillis"),
+        SUTUPTIMEMILLIS ("sutuptimemillis"),
+        SETTIME ("settime"),
+        SYSTIME ("systime"),
+        SCREEN ("screen"),
+        ROTATION ("rotation"),
+        MEMORY ("memory"),
+        POWER ("power"),
+        PROCESS ("process"),
+        SUTUSERINFO ("sutuserinfo"),
+        TEMPERATURE ("temperature"),
+        GETAPPROOT ("getapproot"),
+        TESTROOT ("testroot"),
+        ALRT ("alrt"),
+        DISK ("disk"),
+        CP ("cp"),
+        TIME ("time"),
+        HASH ("hash"),
+        CD ("cd"),
+        CAT ("cat"),
+        CWD ("cwd"),
+        MV ("mv"),
+        PUSH ("push"),
+        PULL ("pull"),
+        RM ("rm"),
+        PRUNE ("rmdr"),
+        MKDR ("mkdr"),
+        DIRWRITABLE ("dirw"),
+        ISDIR ("isdir"),
+        DEAD ("dead"),
+        MEMS ("mems"),
+        LS ("ls"),
+        TMPD ("tmpd"),
+        PING ("ping"),
+        REBT ("rebt"),
+        UNZP ("unzp"),
+        ZIP ("zip"),
+        CLOK ("clok"),
+        STAT ("stat"),
+        QUIT ("quit"),
+        EXIT ("exit"),
+        HELP ("help"),
+        FTPG ("ftpg"),
+        FTPP ("ftpp"),
+        INST ("inst"),
+        UPDT ("updt"),
+        UNINST ("uninst"),
+        UNINSTALL ("uninstall"),
+        TEST ("test"),
+        DBG ("dbg"),
+        TRACE ("trace"),
+        VER ("ver"),
+        TZGET ("tzget"),
+        TZSET ("tzset"),
+        ADB ("adb"),
+        CHMOD ("chmod"),
+        TOPACTIVITY ("activity"),
+        UNKNOWN ("unknown");
+
+        private final String theCmd;
+
+        Command(String theCmd) { this.theCmd = theCmd; }
+
+        public String theCmd() {return theCmd;}
+
+        public static Command getCmd(String sCmd)
+            {
+            Command retCmd = UNKNOWN;
+            for (Command cmd : Command.values())
+                {
+                if (cmd.theCmd().equalsIgnoreCase(sCmd))
+                    {
+                    retCmd = cmd;
+                    break;
+                    }
+                }
+            return (retCmd);
+            }
+        }
+
+    public DoCommand(ContextWrapper service)
+        {
+        this.contextWrapper = service;
+        }
+
+    public String processCommand(String theCmdLine, PrintWriter out, BufferedInputStream in, OutputStream cmdOut)
+        {
+        String     strReturn = "";
+        Command    cCmd = null;
+        Command cSubCmd = null;
+
+        if (bTraceOn)
+            ((ASMozStub)this.contextWrapper).SendToDataChannel(theCmdLine);
+
+        String [] Argv = parseCmdLine2(theCmdLine);
+
+        int Argc = Argv.length;
+
+        cCmd = Command.getCmd(Argv[0]);
+
+        switch(cCmd)
+            {
+            case TRACE:
+                if (Argc == 2)
+                    bTraceOn = (Argv[1].equalsIgnoreCase("on") ? true : false);
+                else
+                    strReturn = sErrorPrefix + "Wrong number of arguments for trace command!";
+                break;
+
+            case VER:
+                strReturn = prgVersion;
+                break;
+
+            case CLOK:
+                strReturn = GetClok();
+                break;
+
+            case TZGET:
+                strReturn = GetTimeZone();
+                break;
+
+            case TZSET:
+                if (Argc == 2)
+                    strReturn = SetTimeZone(Argv[1]);
+                else
+                    strReturn = sErrorPrefix + "Wrong number of arguments for settz command!";
+                break;
+
+            case UPDT:
+                if (Argc >= 2)
+                    strReturn = StrtUpdtOMatic(Argv[1], Argv[2], (Argc > 3 ? Argv[3] : null), (Argc > 4 ? Argv[4] : null));
+                else
+                    strReturn = sErrorPrefix + "Wrong number of arguments for updt command!";
+                break;
+
+            case SETTIME:
+                strReturn = SetSystemTime(Argv[1], (Argc > 2 ? Argv[2] : null), cmdOut);
+                break;
+
+            case CWD:
+                try {
+                    strReturn = new java.io.File(currentDir).getCanonicalPath();
+                    }
+                catch (IOException e)
+                    {
+                    e.printStackTrace();
+                    }
+                break;
+
+            case CD:
+                if (Argc == 2)
+                    strReturn = changeDir(Argv[1]);
+                else
+                    strReturn = sErrorPrefix + "Wrong number of arguments for cd command!";
+                break;
+
+            case LS:
+                strReturn = PrintDir(((Argc > 1) ? Argv[1] : currentDir));
+                break;
+
+            case GETAPPROOT:
+                if (Argc == 2)
+                    strReturn = GetAppRoot(Argv[1]);
+                else
+                    strReturn = sErrorPrefix + "Wrong number of arguments for getapproot command!";
+                break;
+
+            case ISDIR:
+                if (Argc == 2)
+                    strReturn = isDirectory(Argv[1]);
+                else
+                    strReturn = sErrorPrefix + "Wrong number of arguments for isdir command!";
+                break;
+
+            case TESTROOT:
+                strReturn = GetTestRoot();
+                break;
+
+            case DEAD:
+                if (Argc == 2)
+                    strReturn = (IsProcessDead(Argv[1]) ? (Argv[1] + " is hung or unresponsive") : (Argv[1] + " is ok"));
+                else
+                    strReturn = sErrorPrefix + "Wrong number of arguments for dead command!";
+                break;
+
+            case PS:
+                strReturn = GetProcessInfo();
+                break;
+
+            case PULL:
+                if (Argc >= 2) {
+                    long lOff = 0;
+                    long lLen = -1;
+                    if (Argc > 2) {
+                        try {
+                            lOff = Long.parseLong(Argv[2].trim());
+                        } catch (NumberFormatException nfe) {
+                            lOff = 0;
+                            System.out.println("NumberFormatException: " + nfe.getMessage());
+                        }
+                    }
+                    if (Argc == 4) {
+                        try {
+                            lLen = Long.parseLong(Argv[3].trim());
+                        } catch (NumberFormatException nfe) {
+                            lLen = -1;
+                            System.out.println("NumberFormatException: " + nfe.getMessage());
+                        }
+                    }
+                    strReturn = Pull(Argv[1], lOff, lLen, cmdOut);
+                } else {
+                    strReturn = sErrorPrefix + "Wrong number of arguments for pull command!";
+                }
+                break;
+
+            case PUSH:
+                if (Argc == 3)
+                    {
+                    long lArg = 0;
+                    try
+                        {
+                        lArg = Long.parseLong(Argv[2].trim());
+                        }
+                    catch (NumberFormatException nfe)
+                        {
+                        System.out.println("NumberFormatException: " + nfe.getMessage());
+                        }
+
+                    strReturn = Push(Argv[1], in, lArg);
+                    }
+                else
+                    strReturn = sErrorPrefix + "Wrong number of arguments for push command!";
+                break;
+
+            case INST:
+                if (Argc >= 2)
+                    strReturn = InstallApp(Argv[1], cmdOut);
+                else
+                    strReturn = sErrorPrefix + "Wrong number of arguments for inst command!";
+                break;
+
+            case UNINST:
+                if (Argc >= 2)
+                    strReturn = UnInstallApp(Argv[1], cmdOut, true);
+                else
+                    strReturn = sErrorPrefix + "Wrong number of arguments for uninst command!";
+                break;
+
+            case UNINSTALL:
+                if (Argc >= 2)
+                    strReturn = UnInstallApp(Argv[1], cmdOut, false);
+                else
+                    strReturn = sErrorPrefix + "Wrong number of arguments for uninstall command!";
+                break;
+
+            case ALRT:
+                if (Argc > 1)
+                    {
+                    if (Argv[1].contentEquals("on"))
+                        {
+                        String sTitle = "Agent Alert";
+                        String sMsg = "The Agent Alert System has been activated!";
+                        if (Argc == 3) {
+                            sTitle = Argv[2];
+                            sMsg = "";
+                        } else if (Argc == 4) {
+                            sTitle = Argv[2];
+                            sMsg = Argv[3];
+                        }
+                        StartAlert(sTitle, sMsg);
+                        }
+                    else
+                        {
+                        StopAlert();
+                        }
+                    }
+                else
+                    {
+                    strReturn = sErrorPrefix + "Wrong number of arguments for alrt command!";
+                    }
+                break;
+
+            case REBT:
+                if (Argc >= 1)
+                    strReturn = RunReboot(cmdOut, (Argc > 1 ? Argv[1] : null), (Argc > 2 ? Argv[2] : null));
+                else
+                    strReturn = sErrorPrefix + "Wrong number of arguments for rebt command!";
+//                RunReboot(cmdOut);
+                break;
+
+            case TMPD:
+                strReturn = GetTmpDir();
+                break;
+
+            case DEVINFO:
+                if (Argc == 1)
+                    {
+                    strReturn += SUTAgentAndroid.sUniqueID;
+                    strReturn += "\n";
+                    strReturn += GetOSInfo();
+                    strReturn += "\n";
+                    strReturn += GetSystemTime();
+                    strReturn += "\n";
+                    strReturn += GetUptime();
+                    strReturn += "\n";
+                    strReturn += GetUptimeMillis();
+                    strReturn += "\n";
+                    strReturn += GetSutUptimeMillis();
+                    strReturn += "\n";
+                    strReturn += GetScreenInfo();
+                    strReturn += "\n";
+                    strReturn += GetRotationInfo();
+                    strReturn += "\n";
+                    strReturn += GetMemoryInfo();
+                    strReturn += "\n";
+                    strReturn += GetPowerInfo();
+                    strReturn += "\n";
+                    strReturn += GetTemperatureInfo();
+                    strReturn += "\n";
+                    strReturn += GetProcessInfo();
+                    strReturn += "\n";
+                    strReturn += GetSutUserInfo();
+                    strReturn += "\n";
+                    strReturn += GetDiskInfo("/data");
+                    strReturn += "\n";
+                    strReturn += GetDiskInfo("/system");
+                    strReturn += "\n";
+                    strReturn += GetDiskInfo("/mnt/sdcard");
+                    }
+                else
+                    {
+                    cSubCmd = Command.getCmd(Argv[1]);
+                    switch(cSubCmd)
+                        {
+                        case ID:
+                            strReturn = SUTAgentAndroid.sUniqueID;
+                            break;
+
+                        case SCREEN:
+                            strReturn = GetScreenInfo();
+                            break;
+
+                        case ROTATION:
+                            strReturn = GetRotationInfo();
+                            break;
+
+                        case PROCESS:
+                            strReturn = GetProcessInfo();
+                            break;
+
+                        case OS:
+                            strReturn = GetOSInfo();
+                            break;
+
+                        case SYSTIME:
+                            strReturn = GetSystemTime();
+                            break;
+
+                        case UPTIME:
+                            strReturn = GetUptime();
+                            break;
+
+                        case UPTIMEMILLIS:
+                            strReturn = GetUptimeMillis();
+                            break;
+
+                        case SUTUPTIMEMILLIS:
+                            strReturn = GetSutUptimeMillis();
+                            break;
+
+                        case MEMORY:
+                            strReturn = GetMemoryInfo();
+                            break;
+
+                        case POWER:
+                            strReturn += GetPowerInfo();
+                            break;
+
+                        case SUTUSERINFO:
+                            strReturn += GetSutUserInfo();
+                            break;
+
+                        case TEMPERATURE:
+                            strReturn += GetTemperatureInfo();
+                            break;
+
+                        case DISK:
+                            strReturn += "\n";
+                            strReturn += GetDiskInfo("/data");
+                            strReturn += "\n";
+                            strReturn += GetDiskInfo("/system");
+                            strReturn += "\n";
+                            strReturn += GetDiskInfo("/mnt/sdcard");
+                            break;
+
+                        default:
+                            break;
+                        }
+                    }
+                break;
+
+            case STAT:
+                if (Argc == 2)
+                    strReturn = StatProcess(Argv[1]);
+                else
+                    strReturn = sErrorPrefix + "Wrong number of arguments for ping command!";
+                break;
+
+            case PING:
+                if (Argc == 2)
+                    strReturn = SendPing(Argv[1], cmdOut);
+                else
+                    strReturn = sErrorPrefix + "Wrong number of arguments for ping command!";
+                break;
+
+            case HASH:
+                if (Argc == 2)
+                    strReturn = HashFile(Argv[1]);
+                else
+                    strReturn = sErrorPrefix + "Wrong number of arguments for hash command!";
+                break;
+
+            case PRUNE:
+                if (Argc == 2)
+                    strReturn = PruneDir(Argv[1]);
+                else
+                    strReturn = sErrorPrefix + "Wrong number of arguments for prune command!";
+                break;
+
+            case FTPG:
+                if (Argc == 4)
+                    strReturn = FTPGetFile(Argv[1], Argv[2], Argv[3], cmdOut);
+                else
+                    strReturn = sErrorPrefix + "Wrong number of arguments for ftpg command!";
+                break;
+
+            case CAT:
+                if (Argc == 2)
+                    strReturn = Cat(Argv[1], cmdOut);
+                else
+                    strReturn = sErrorPrefix + "Wrong number of arguments for cat command!";
+                break;
+
+            case DIRWRITABLE:
+                if (Argc == 2)
+                    strReturn = IsDirWritable(Argv[1]);
+                else
+                    strReturn = sErrorPrefix + "Wrong number of arguments for dirwritable command!";
+                break;
+
+            case TIME:
+                if (Argc == 2)
+                    strReturn = PrintFileTimestamp(Argv[1]);
+                else
+                    strReturn = sErrorPrefix + "Wrong number of arguments for time command!";
+                break;
+
+            case MKDR:
+                if (Argc == 2)
+                    strReturn = MakeDir(Argv[1]);
+                else
+                    strReturn = sErrorPrefix + "Wrong number of arguments for mkdr command!";
+                break;
+
+            case RM:
+                if (Argc == 2)
+                    strReturn = RemoveFile(Argv[1]);
+                else
+                    strReturn = sErrorPrefix + "Wrong number of arguments for rm command!";
+                break;
+
+            case MV:
+                if (Argc == 3)
+                    strReturn = Move(Argv[1], Argv[2]);
+                else
+                    strReturn = sErrorPrefix + "Wrong number of arguments for mv command!";
+                break;
+
+            case CP:
+                if (Argc == 3)
+                    strReturn = CopyFile(Argv[1], Argv[2]);
+                else
+                    strReturn = sErrorPrefix + "Wrong number of arguments for cp command!";
+                break;
+
+            case QUIT:
+            case EXIT:
+                strReturn = Argv[0];
+                break;
+
+            case DBG:
+                Debug.waitForDebugger();
+                strReturn = "waitForDebugger on";
+                break;
+
+            case ADB:
+                if (Argc == 2) {
+                    if (Argv[1].contains("ip") || Argv[1].contains("usb")) {
+                        strReturn = SetADB(Argv[1]);
+                    } else {
+                        strReturn = sErrorPrefix + "Unrecognized argument for adb command!";
+                    }
+                } else {
+                    strReturn = sErrorPrefix + "Wrong number of arguments for adb command!";
+                }
+                break;
+
+            case TEST:
+                long lFreeMemory = Runtime.getRuntime().freeMemory();
+                long lTotMemory = Runtime.getRuntime().totalMemory();
+                long lMaxMemory = Runtime.getRuntime().maxMemory();
+
+
+                if (lFreeMemory > 0) {
+                    strReturn = "Max memory: " + lMaxMemory + "\nTotal Memory: " + lTotMemory + "\nFree memory: " + lFreeMemory;
+                    break;
+                }
+
+                ContentResolver cr = contextWrapper.getContentResolver();
+                Uri ffxFiles = null;
+
+                if (Argv[1].contains("fennec")) {
+                    ffxFiles = Uri.parse("content://" + fenProvider + "/dir");
+                } else if (Argv[1].contains("firefox")) {
+                    ffxFiles = Uri.parse("content://" + ffxProvider + "/dir");
+                }
+
+//                Uri ffxFiles = Uri.parse("content://org.mozilla.fencp/file");
+                String[] columns = new String[] {
+                        "_id",
+                        "isdir",
+                        "filename",
+                        "length"
+                    };
+//                String[] columns = new String[] {
+//                        "_id",
+//                        "chunk"
+//                     };
+                Cursor myCursor = cr.query(    ffxFiles,
+                                            columns,                         // Which columns to return
+                                            (Argc > 1 ? Argv[1] : null),    // Which rows to return (all rows)
+                                            null,                           // Selection arguments (none)
+                                            null);                            // Put the results in ascending order by name
+/*
+                if (myCursor != null) {
+                    int nRows = myCursor.getCount();
+                    String [] colNames = myCursor.getColumnNames();
+                    int    nID = 0;
+                    int nBytesRecvd = 0;
+
+                    for (int lcv = 0; lcv < nRows; lcv++) {
+                        if  (myCursor.moveToPosition(lcv)) {
+                            nID = myCursor.getInt(0);
+                            byte [] buf = myCursor.getBlob(1);
+                            if (buf != null) {
+                                nBytesRecvd += buf.length;
+                                strReturn += new String(buf);
+                                buf = null;
+                            }
+                        }
+                    }
+                    strReturn += "[eof - " + nBytesRecvd + "]";
+                    myCursor.close();
+                }
+
+*/
+                if (myCursor != null)
+                    {
+                    int nRows = myCursor.getCount();
+                    int    nID = 0;
+                    String sFileName = "";
+                    long lFileSize = 0;
+                    boolean bIsDir = false;
+
+                    for (int lcv = 0; lcv < nRows; lcv++)
+                        {
+                        if  (myCursor.moveToPosition(lcv))
+                            {
+                            nID = myCursor.getInt(0);
+                            bIsDir = (myCursor.getInt(1) == 1 ? true : false);
+                            sFileName = myCursor.getString(2);
+                            lFileSize = myCursor.getLong(3);
+                            strReturn += "" + nID + "\t" + (bIsDir ? "<dir> " : "      ") + sFileName + "\t" + lFileSize + "\n";
+                            }
+                        }
+                    myCursor.close();
+                    }
+                break;
+
+            case EXEC:
+            case ENVRUN:
+                if (Argc >= 2)
+                    {
+                    String [] theArgs = new String [Argc - 1];
+
+                    for (int lcv = 1; lcv < Argc; lcv++)
+                        {
+                        theArgs[lcv - 1] = Argv[lcv];
+                        }
+
+                    strReturn = StartPrg2(theArgs, cmdOut, null, false, DEFAULT_STARTPRG_TIMEOUT_SECONDS);
+                    }
+                else
+                    {
+                    strReturn = sErrorPrefix + "Wrong number of arguments for " + Argv[0] + " command!";
+                    }
+                break;
+
+            case EXECSU:
+                if (Argc >= 2)
+                    {
+                    String [] theArgs = new String [Argc - 1];
+
+                    for (int lcv = 1; lcv < Argc; lcv++)
+                        {
+                        theArgs[lcv - 1] = Argv[lcv];
+                        }
+
+                    strReturn = StartPrg2(theArgs, cmdOut, null, true, DEFAULT_STARTPRG_TIMEOUT_SECONDS);
+                    }
+                else
+                    {
+                    strReturn = sErrorPrefix + "Wrong number of arguments for " + Argv[0] + " command!";
+                    }
+                break;
+
+            case EXECCWD:
+                if (Argc >= 3)
+                    {
+                    String [] theArgs = new String [Argc - 2];
+
+                    for (int lcv = 2; lcv < Argc; lcv++)
+                        {
+                        theArgs[lcv - 2] = Argv[lcv];
+                        }
+
+                    strReturn = StartPrg2(theArgs, cmdOut, Argv[1], false, DEFAULT_STARTPRG_TIMEOUT_SECONDS);
+                    }
+                else
+                    {
+                    strReturn = sErrorPrefix + "Wrong number of arguments for " + Argv[0] + " command!";
+                    }
+                break;
+
+            case EXECCWDSU:
+                if (Argc >= 3)
+                    {
+                    String [] theArgs = new String [Argc - 2];
+
+                    for (int lcv = 2; lcv < Argc; lcv++)
+                        {
+                        theArgs[lcv - 2] = Argv[lcv];
+                        }
+
+                    strReturn = StartPrg2(theArgs, cmdOut, Argv[1], true, DEFAULT_STARTPRG_TIMEOUT_SECONDS);
+                    }
+                else
+                    {
+                    strReturn = sErrorPrefix + "Wrong number of arguments for " + Argv[0] + " command!";
+                    }
+                break;
+
+            case RUN:
+                if (Argc >= 2)
+                    {
+                    String [] theArgs = new String [Argc - 1];
+
+                    for (int lcv = 1; lcv < Argc; lcv++)
+                        {
+                        theArgs[lcv - 1] = Argv[lcv];
+                        }
+
+                    if (Argv[1].contains("/") || Argv[1].contains("\\") || !Argv[1].contains("."))
+                        strReturn = StartPrg(theArgs, cmdOut, false, DEFAULT_STARTPRG_TIMEOUT_SECONDS);
+                    else
+                        strReturn = StartJavaPrg(theArgs, null);
+                    }
+                else
+                    {
+                    strReturn = sErrorPrefix + "Wrong number of arguments for " + Argv[0] + " command!";
+                    }
+                break;
+
+            case EXECEXT:
+                // An "extended" exec command with format:
+                //    execext [su] [cwd=<path>] [t=<timeout in seconds>] arg1 ...
+                if (Argc >= 2)
+                    {
+                    boolean su = false;
+                    String cwd = null;
+                    int timeout = DEFAULT_STARTPRG_TIMEOUT_SECONDS;
+                    int extra;
+                    for (extra = 1; extra < Argc; extra++)
+                        {
+                        if (Argv[extra].equals("su"))
+                            {
+                            su = true;
+                            }
+                        else if (Argv[extra].startsWith("cwd="))
+                            {
+                            cwd = Argv[extra].substring(4);
+                            }
+                        else if (Argv[extra].startsWith("t="))
+                            {
+                            timeout = Integer.parseInt(Argv[extra].substring(2));
+                            if (timeout < 1 || timeout > 4*60*60)
+                                {
+                                Log.e("SUTAgentAndroid", 
+                                  "invalid execext timeout "+Argv[extra].substring(2)+"; using default instead");
+                                timeout = DEFAULT_STARTPRG_TIMEOUT_SECONDS;
+                                }
+                            }
+                        else
+                            {
+                            break;
+                            }
+                        }
+
+                    if (extra < Argc)
+                        {
+                        String [] theArgs = new String [Argc - extra];
+                        for (int lcv = extra; lcv < Argc; lcv++)
+                            {
+                            theArgs[lcv - extra] = Argv[lcv];
+                            }
+
+                        strReturn = StartPrg2(theArgs, cmdOut, cwd, su, timeout);
+                        }
+                    else
+                        {
+                        strReturn = sErrorPrefix + "No regular arguments for " + Argv[0] + " command!";
+                        }
+                    }
+                else
+                    {
+                    strReturn = sErrorPrefix + "Wrong number of arguments for " + Argv[0] + " command!";
+                    }
+                break;
+
+            case KILL:
+                if (Argc == 2)
+                    strReturn = KillProcess(Argv[1], cmdOut);
+                else
+                    strReturn = sErrorPrefix + "Wrong number of arguments for kill command!";
+                break;
+
+            case DISK:
+                strReturn = GetDiskInfo((Argc == 2 ? Argv[1] : "/"));
+                break;
+
+            case UNZP:
+                strReturn = Unzip(Argv[1], (Argc == 3 ? Argv[2] : ""));
+                break;
+
+            case ZIP:
+                strReturn = Zip(Argv[1], (Argc == 3 ? Argv[2] : ""));
+                break;
+
+            case CHMOD:
+                if (Argc == 2)
+                    strReturn = ChmodDir(Argv[1]);
+                else
+                    strReturn = sErrorPrefix + "Wrong number of arguments for chmod command!";
+                break;
+
+            case TOPACTIVITY:
+                strReturn = TopActivity();
+                break;
+
+            case HELP:
+                strReturn = PrintUsage();
+                break;
+
+            default:
+                strReturn = sErrorPrefix + "[" + Argv[0] + "] command";
+                if (Argc > 1)
+                    {
+                    strReturn += " with arg(s) =";
+                    for (int lcv = 1; lcv < Argc; lcv++)
+                        {
+                        strReturn += " [" + Argv[lcv] + "]";
+                        }
+                    }
+                strReturn += " is currently not implemented.";
+                break;
+            }
+
+        return(strReturn);
+        }
+
+    private void SendNotification(String tickerText, String expandedText) {
+        NotificationManager notificationManager = (NotificationManager)contextWrapper.getSystemService(Context.NOTIFICATION_SERVICE);
+        int icon = R.drawable.ateamlogo;
+        long when = System.currentTimeMillis();
+
+        Context context = contextWrapper.getApplicationContext();
+
+        // Intent to launch an activity when the extended text is clicked
+        Intent intent2 = new Intent(contextWrapper, SUTAgentAndroid.class);
+        PendingIntent launchIntent = PendingIntent.getActivity(context, 0, intent2, 0);
+
+        Notification notification = new Notification.Builder(context)
+            .setContentTitle(tickerText)
+            .setContentText(expandedText)
+            .setSmallIcon(icon)
+            .setWhen(when)
+            .setContentIntent(launchIntent)
+            .build();
+
+        notification.flags |= (Notification.FLAG_INSISTENT | Notification.FLAG_AUTO_CANCEL);
+        notification.defaults |= Notification.DEFAULT_SOUND;
+        notification.defaults |= Notification.DEFAULT_VIBRATE;
+        notification.defaults |= Notification.DEFAULT_LIGHTS;
+
+        notificationManager.notify(1959, notification);
+    }
+
+private void CancelNotification()
+    {
+    NotificationManager notificationManager = (NotificationManager)contextWrapper.getSystemService(Context.NOTIFICATION_SERVICE);
+    notificationManager.cancel(1959);
+    }
+
+    public void StartAlert(String sTitle, String sMsg)
+        {
+        // start the alert message
+        SendNotification(sTitle, sMsg);
+        }
+
+    public void StopAlert()
+        {
+        CancelNotification();
+        }
+
+    public String [] parseCmdLine2(String theCmdLine)
+        {
+        String    cmdString;
+        String    workingString;
+        String    workingString2;
+        String    workingString3;
+        List<String> lst = new ArrayList<String>();
+        int nLength = 0;
+        int nFirstSpace = -1;
+
+        // Null cmd line
+        if (theCmdLine == null)
+            {
+            String [] theArgs = new String [1];
+            theArgs[0] = new String("");
+            return(theArgs);
+            }
+        else
+            {
+            nLength = theCmdLine.length();
+            nFirstSpace = theCmdLine.indexOf(' ');
+            }
+
+        if (nFirstSpace == -1)
+            {
+            String [] theArgs = new String [1];
+            theArgs[0] = new String(theCmdLine);
+            return(theArgs);
+            }
+
+        // Get the command
+        cmdString = new String(theCmdLine.substring(0, nFirstSpace));
+        lst.add(cmdString);
+
+        // Jump past the command and trim
+        workingString = (theCmdLine.substring(nFirstSpace + 1, nLength)).trim();
+
+        while ((nLength = workingString.length()) > 0)
+            {
+            int nEnd = 0;
+            int    nStart = 0;
+
+            // if we have a quote
+            if (workingString.startsWith("\"") || workingString.startsWith("'"))
+                {
+                char quoteChar = '"';
+                if (workingString.startsWith("\'"))
+                    quoteChar = '\'';
+
+                // point to the first non quote char
+                nStart = 1;
+                // find the matching quote
+                nEnd = workingString.indexOf(quoteChar, nStart);
+
+                char prevChar;
+
+                while(nEnd != -1)
+                    {
+                    // check to see if the quotation mark has been escaped
+                    prevChar = workingString.charAt(nEnd - 1);
+                    if (prevChar == '\\')
+                        {
+                        // if escaped, point past this quotation mark and find the next
+                        nEnd++;
+                        if (nEnd < nLength)
+                            nEnd = workingString.indexOf(quoteChar, nEnd);
+                        else
+                            nEnd = -1;
+                        }
+                    else
+                        break;
+                    }
+
+                // there isn't one
+                if (nEnd == -1)
+                    {
+                    // point at the quote
+                    nStart = 0;
+                    // so find the next space
+                    nEnd = workingString.indexOf(' ', nStart);
+                    // there isn't one of those either
+                    if (nEnd == -1)
+                        nEnd = nLength;    // Just grab the rest of the cmdline
+                    }
+                }
+            else // no quote so find the next space
+                {
+                nEnd = workingString.indexOf(' ', nStart);
+                // there isn't one of those
+                if (nEnd == -1)
+                    nEnd = nLength;    // Just grab the rest of the cmdline
+                }
+
+            // get the substring
+            workingString2 = workingString.substring(nStart, nEnd);
+
+            // if we have escaped quotes, convert them into standard ones
+            while (workingString2.contains("\\\"") || workingString2.contains("\\'"))
+                {
+                    workingString2 = workingString2.replace("\\\"", "\"");
+                    workingString2 = workingString2.replace("\\'", "'");
+                }
+
+            // add it to the list
+            lst.add(new String(workingString2));
+
+            // if we are dealing with a quote
+            if (nStart > 0)
+                nEnd++; //  point past the end one
+
+            // jump past the substring and trim it
+            workingString = (workingString.substring(nEnd)).trim();
+            }
+
+        // ok we're done package up the results
+        int nItems = lst.size();
+
+        String [] theArgs = new String [nItems];
+
+        for (int lcv = 0; lcv < nItems; lcv++)
+            {
+            theArgs[lcv] = lst.get(lcv);
+            }
+
+        return(theArgs);
+        }
+
+    public String [] parseCmdLine(String theCmdLine) {
+        String    cmdString;
+        String    workingString;
+        String    workingString2;
+        List<String> lst = new ArrayList<String>();
+        int nLength = 0;
+        int nFirstSpace = -1;
+
+        // Null cmd line
+        if (theCmdLine == null)
+            {
+            String [] theArgs = new String [1];
+            theArgs[0] = new String("");
+            return(theArgs);
+            }
+        else
+            {
+            nLength = theCmdLine.length();
+            nFirstSpace = theCmdLine.indexOf(' ');
+            }
+
+        if (nFirstSpace == -1)
+            {
+            String [] theArgs = new String [1];
+            theArgs[0] = new String(theCmdLine);
+            return(theArgs);
+            }
+
+        // Get the command
+        cmdString = new String(theCmdLine.substring(0, nFirstSpace));
+        lst.add(cmdString);
+
+        // Jump past the command and trim
+        workingString = (theCmdLine.substring(nFirstSpace + 1, nLength)).trim();
+
+        while ((nLength = workingString.length()) > 0)
+            {
+            int nEnd = 0;
+            int    nStart = 0;
+
+            // if we have a quote
+            if (workingString.startsWith("\""))
+                {
+                // point to the first non quote char
+                nStart = 1;
+                // find the matching quote
+                nEnd = workingString.indexOf('"', nStart);
+                // there isn't one
+                if (nEnd == -1)
+                    {
+                    // point at the quote
+                    nStart = 0;
+                    // so find the next space
+                    nEnd = workingString.indexOf(' ', nStart);
+                    // there isn't one of those either
+                    if (nEnd == -1)
+                        nEnd = nLength;    // Just grab the rest of the cmdline
+                    }
+                else
+                    {
+                    nStart = 0;
+                    nEnd++;
+                    }
+                }
+            else // no quote so find the next space
+                {
+                nEnd = workingString.indexOf(' ', nStart);
+
+                // there isn't one of those
+                if (nEnd == -1)
+                    nEnd = nLength;    // Just grab the rest of the cmdline
+                }
+
+            // get the substring
+            workingString2 = workingString.substring(nStart, nEnd);
+
+            // add it to the list
+            lst.add(new String(workingString2));
+
+            // jump past the substring and trim it
+            workingString = (workingString.substring(nEnd)).trim();
+            }
+
+        int nItems = lst.size();
+
+        String [] theArgs = new String [nItems];
+
+        for (int lcv = 0; lcv < nItems; lcv++)
+            {
+            theArgs[lcv] = lst.get(lcv);
+            }
+
+        return(theArgs);
+        }
+
+    public String fixFileName(String fileName)
+        {
+        String    sRet = "";
+        String    sTmpFileName = "";
+
+        sRet = fileName.replace('\\', '/');
+
+        if (sRet.startsWith("/"))
+            sTmpFileName = sRet;
+        else
+            sTmpFileName = currentDir + "/" + sRet;
+
+        sRet = sTmpFileName.replace('\\', '/');
+        sTmpFileName = sRet;
+        sRet = sTmpFileName.replace("//", "/");
+
+        return(sRet);
+        }
+
+    public String AddFilesToZip(ZipOutputStream out, String baseDir, String relDir)
+    {
+        final int             BUFFER     = 2048;
+        String                sRet    = "";
+        String                 curDir     = "";
+        String                relFN    = "";
+        BufferedInputStream origin = null;
+        byte                 data[] = new byte[BUFFER];
+
+        if (relDir.length() > 0)
+            curDir = baseDir + "/" + relDir;
+        else
+            curDir = baseDir;
+
+        File f = new File(curDir);
+
+        if (f.isFile())
+            {
+            try {
+                relFN = ((relDir.length() > 0) ? relDir + "/" + f.getName() : f.getName());
+                System.out.println("Adding: "+relFN);
+                sRet += "Adding: "+    relFN + lineSep;
+                FileInputStream fi = new FileInputStream(curDir);
+                origin = new BufferedInputStream(fi, BUFFER);
+                ZipEntry entry = new ZipEntry(relFN);
+                out.putNextEntry(entry);
+                int count;
+                while((count = origin.read(data, 0, BUFFER)) != -1)
+                    {
+                    out.write(data, 0, count);
+                    }
+                origin.close();
+                }
+            catch(Exception e)
+                {
+                e.printStackTrace();
+                }
+
+            return(sRet);
+            }
+
+        String    files[] = f.list();
+
+        if (files != null)
+            {
+            try {
+                for(int i = 0; i < files.length; i++)
+                    {
+                    f = new File(curDir + "/" + files[i]);
+                    if (f.isDirectory())
+                        {
+                        if (relDir.length() > 0)
+                            sRet += AddFilesToZip(out, baseDir, relDir + "/" + files[i]);
+                        else
+                            sRet += AddFilesToZip(out, baseDir, files[i]);
+                        }
+                    else
+                        {
+                        relFN = ((relDir.length() > 0) ? relDir + "/" + files[i] : files[i]);
+                        System.out.println("Adding: "+relFN);
+                        sRet += "Adding: "+    relFN + lineSep;
+                        FileInputStream fi = new FileInputStream(curDir + "/" + files[i]);
+                        origin = new BufferedInputStream(fi, BUFFER);
+                        ZipEntry entry = new ZipEntry(relFN);
+                        out.putNextEntry(entry);
+                        int count;
+                        while((count = origin.read(data, 0, BUFFER)) != -1)
+                            {
+                            out.write(data, 0, count);
+                            }
+                        origin.close();
+                        }
+                    }
+                }
+            catch(Exception e)
+                {
+                e.printStackTrace();
+                }
+            }
+
+        return(sRet);
+    }
+
+    public String Zip(String zipFileName, String srcName)
+        {
+        String    fixedZipFileName = fixFileName(zipFileName);
+        String    fixedSrcName = fixFileName(srcName);
+        String sRet = "";
+
+        try {
+            FileOutputStream dest = new FileOutputStream(fixedZipFileName);
+            CheckedOutputStream checksum = new CheckedOutputStream(dest, new Adler32());
+            ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(checksum));
+            out.setMethod(ZipOutputStream.DEFLATED);
+
+            sRet += AddFilesToZip(out, fixedSrcName, "");
+
+            out.close();
+            System.out.println("checksum:                   "+checksum.getChecksum().getValue());
+            sRet += "checksum:                   "+checksum.getChecksum().getValue();
+            }
+        catch(Exception e)
+            {
+            e.printStackTrace();
+            }
+
+        return(sRet);
+    }
+
+    public String Unzip(String zipFileName, String dstDirectory)
+        {
+        String     sRet = "";
+        String    fixedZipFileName = fixFileName(zipFileName);
+        String    fixedDstDirectory = fixFileName(dstDirectory);
+        String    dstFileName = "";
+        int        nNumExtracted = 0;
+        boolean bRet = false;
+
+        try {
+            final int BUFFER = 2048;
+            BufferedOutputStream dest = null;
+            ZipFile zipFile = new ZipFile(fixedZipFileName);
+            int nNumEntries = zipFile.size();
+            zipFile.close();
+
+            FileInputStream fis = new FileInputStream(fixedZipFileName);
+            CheckedInputStream checksum = new CheckedInputStream(fis, new Adler32());
+            ZipInputStream zis = new ZipInputStream(new BufferedInputStream(checksum));
+            ZipEntry entry;
+
+            byte [] data = new byte[BUFFER];
+
+            while((entry = zis.getNextEntry()) != null)
+                {
+                System.out.println("Extracting: " + entry);
+                int count;
+                if (fixedDstDirectory.length() > 0)
+                    dstFileName = fixedDstDirectory + entry.getName();
+                else
+                    dstFileName = entry.getName();
+
+                String tmpDir = dstFileName.substring(0, dstFileName.lastIndexOf('/'));
+                File tmpFile = new File(tmpDir);
+                if (!tmpFile.exists())
+                    {
+                    bRet = tmpFile.mkdirs();
+                    }
+                else
+                    bRet = true;
+
+                if (bRet)
+                    {
+                    // if we aren't just creating a directory
+                    if (dstFileName.lastIndexOf('/') != (dstFileName.length() - 1))
+                        {
+                        // write out the file
+                        FileOutputStream fos = new FileOutputStream(dstFileName);
+                        dest = new BufferedOutputStream(fos, BUFFER);
+                        while ((count = zis.read(data, 0, BUFFER)) != -1)
+                            {
+                            dest.write(data, 0, count);
+                            }
+                        dest.flush();
+                        dest.close();
+                        dest = null;
+                        fos.close();
+                        fos = null;
+                        }
+                    nNumExtracted++;
+                    }
+                else
+                    sRet += " - failed" + lineSep;
+                }
+
+            data = null;
+            zis.close();
+            System.out.println("Checksum:          "+checksum.getChecksum().getValue());
+            sRet += "Checksum:          "+checksum.getChecksum().getValue();
+            sRet += lineSep + nNumExtracted + " of " + nNumEntries + " successfully extracted";
+            }
+        catch(Exception e)
+            {
+            e.printStackTrace();
+            }
+
+        return(sRet);
+        }
+
+    public String StatProcess(String string)
+        {
+        String sRet = "";
+        ActivityManager aMgr = (ActivityManager) contextWrapper.getSystemService(Activity.ACTIVITY_SERVICE);
+        int    [] nPids = new int [1];
+
+        nPids[0] = Integer.parseInt(string);
+
+        android.os.Debug.MemoryInfo[] mi = aMgr.getProcessMemoryInfo(nPids);
+
+        sRet  = "Dalvik Private Dirty pages         " + mi[0].dalvikPrivateDirty     + " kb\n";
+        sRet += "Dalvik Proportional Set Size       " + mi[0].dalvikPss              + " kb\n";
+        sRet += "Dalvik Shared Dirty pages          " + mi[0].dalvikSharedDirty      + " kb\n\n";
+        sRet += "Native Private Dirty pages heap    " + mi[0].nativePrivateDirty     + " kb\n";
+        sRet += "Native Proportional Set Size heap  " + mi[0].nativePss              + " kb\n";
+        sRet += "Native Shared Dirty pages heap     " + mi[0].nativeSharedDirty      + " kb\n\n";
+        sRet += "Other Private Dirty pages          " + mi[0].otherPrivateDirty      + " kb\n";
+        sRet += "Other Proportional Set Size        " + mi[0].otherPss               + " kb\n";
+        sRet += "Other Shared Dirty pages           " + mi[0].otherSharedDirty       + " kb\n\n";
+        sRet += "Total Private Dirty Memory         " + mi[0].getTotalPrivateDirty() + " kb\n";
+        sRet += "Total Proportional Set Size Memory " + mi[0].getTotalPss()          + " kb\n";
+        sRet += "Total Shared Dirty Memory          " + mi[0].getTotalSharedDirty()  + " kb";
+
+
+        return(sRet);
+        }
+
+    public void FixDataLocalPermissions()
+        {
+        String chmodResult;
+        File localDir = new java.io.File("/data/local");
+        if (!localDir.canWrite()) {
+            chmodResult = ChmodDir("/data/local");
+            Log.i("SUTAgentAndroid", "Changed permissions on /data/local to make it writable: " + chmodResult);
+        }
+        File tmpDir = new java.io.File("/data/local/tmp");
+        if (tmpDir.exists() && !tmpDir.isDirectory()) {
+            if (!tmpDir.delete()) {
+                Log.e("SUTAgentAndroid", "Could not delete file /data/local/tmp");
+            }
+        }
+        if (!tmpDir.exists() && !tmpDir.mkdirs()) {
+            Log.e("SUTAgentAndroid", "Could not create directory /data/local/tmp");
+        }
+        chmodResult = ChmodDir("/data/local/tmp");
+        Log.i("SUTAgentAndroid", "Changed permissions on /data/local/tmp to make it writable: " + chmodResult);
+        }
+
+    private Boolean _SetTestRoot(String testroot)
+        {
+        String isWritable = IsDirWritable(testroot);
+        if (isWritable.contains(sErrorPrefix) || isWritable.contains("is not writable")) {
+            Log.w("SUTAgentAndroid", isWritable);
+            Log.w("SUTAgentAndroid", "Unable to set device root to " + testroot);
+            return false;
+        }
+
+        Log.i("SUTAgentAndroid", "Set device root to " + testroot);
+        SUTAgentAndroid.sTestRoot = testroot;
+        return true;
+        }
+
+    public void SetTestRoot(String testroot)
+        {
+        Boolean success = false;
+        if (!testroot.equals("")) {
+            // Device specified the required testroot.
+            success = _SetTestRoot(testroot);
+            if (!success) {
+                Log.e("SUTAgentAndroid", "Unable to set device root to " + testroot);
+            }
+        } else {
+            // Detect the testroot.
+            // Attempt external storage.
+            success = _SetTestRoot(Environment.getExternalStorageDirectory().getAbsolutePath());
+            if (!success) {
+                Log.e("SUTAgentAndroid", "Cannot access world writeable test root");
+            }
+        }
+        }
+
+    public String GetTestRoot()
+        {
+        if (SUTAgentAndroid.sTestRoot.equals("")) {
+            SetTestRoot("");
+        }
+        return SUTAgentAndroid.sTestRoot;
+        }
+
+    public String GetAppRoot(String AppName)
+        {
+        String sRet = sErrorPrefix + " internal error [no context]";
+        Context ctx = contextWrapper.getApplicationContext();
+
+        if (ctx != null)
+            {
+            try {
+                Context appCtx = ctx.createPackageContext(AppName, 0);
+                ContextWrapper appCtxW = new ContextWrapper(appCtx);
+                sRet = appCtxW.getApplicationInfo().dataDir;
+                appCtxW = null;
+                appCtx = null;
+                ctx = null;
+                System.gc();
+                }
+            catch (NameNotFoundException e)
+                {
+                e.printStackTrace();
+                }
+            }
+        return(sRet);
+        }
+
+    public String isDirectory(String sDir)
+        {
+        String    sRet = sErrorPrefix + sDir + " does not exist";
+        String    tmpDir    = fixFileName(sDir);
+        int    nFiles = 0;
+
+        if (tmpDir.contains("org.mozilla.fennec") || tmpDir.contains("org.mozilla.firefox")) {
+            ContentResolver cr = contextWrapper.getContentResolver();
+            Uri ffxFiles = Uri.parse("content://" + (tmpDir.contains("fennec") ? fenProvider : ffxProvider) + "/dir");
+
+            String[] columns = new String[] {
+                    "_id",
+                    "isdir",
+                    "filename",
+                    "length"
+                };
+
+            Cursor myCursor = cr.query(    ffxFiles,
+                                        columns,     // Which columns to return
+                                        tmpDir,     // Which rows to return (all rows)
+                                        null,       // Selection arguments (none)
+                                        null);        // Order clause (none)
+            if (myCursor != null) {
+                nFiles = myCursor.getCount();
+
+                // If no entries the dir is empty
+                if (nFiles > 0) {
+                    if  (myCursor.moveToPosition(0)) {
+                        sRet = ((myCursor.getLong(myCursor.getColumnIndex("isdir")) == 1) ? "TRUE" : "FALSE");
+                    }
+                }
+                myCursor.close();
+            }
+        } else {
+            File tmpFile = new java.io.File(tmpDir);
+
+            if (tmpFile.exists()) {
+                sRet = (tmpFile.isDirectory() ? "TRUE" : "FALSE");
+            }
+            else {
+                try {
+                    pProc = Runtime.getRuntime().exec(this.getSuArgs("ls -l " + sDir));
+                    RedirOutputThread outThrd = new RedirOutputThread(pProc, null);
+                    outThrd.start();
+                    outThrd.joinAndStopRedirect(5000);
+                    sRet = outThrd.strOutput;
+                    if (!sRet.contains("No such file or directory") && sRet.startsWith("l"))
+                        sRet = "FALSE";
+                }
+                catch (IOException e) {
+                    sRet = e.getMessage();
+                    e.printStackTrace();
+                }
+                catch (InterruptedException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+
+        return(sRet);
+        }
+
+
+    public String changeDir(String newDir)
+        {
+        String    tmpDir    = fixFileName(newDir);
+        String    sRet = sErrorPrefix + "Couldn't change directory to " + tmpDir;
+        int    nFiles = 0;
+
+        if (tmpDir.contains("org.mozilla.fennec") || tmpDir.contains("org.mozilla.firefox")) {
+            ContentResolver cr = contextWrapper.getContentResolver();
+            Uri ffxFiles = Uri.parse("content://" + (tmpDir.contains("fennec") ? fenProvider : ffxProvider) + "/dir");
+
+            String[] columns = new String[] {
+                    "_id",
+                    "isdir",
+                    "filename"
+                };
+
+            Cursor myCursor = cr.query(    ffxFiles,
+                                        columns,     // Which columns to return
+                                        tmpDir,     // Which rows to return (all rows)
+                                        null,       // Selection arguments (none)
+                                        null);        // Order clause (none)
+            if (myCursor != null) {
+                nFiles = myCursor.getCount();
+
+                if (nFiles > 0) {
+                    if  (myCursor.moveToPosition(0)) {
+                        if (myCursor.getLong(myCursor.getColumnIndex("isdir")) == 1) {
+                            currentDir = myCursor.getString(myCursor.getColumnIndex("filename"));
+                            sRet = "";
+                        }
+                    }
+                } else {
+                    sRet = sErrorPrefix + tmpDir + " is not a valid directory";
+                }
+                myCursor.close();
+            }
+        } else {
+            File tmpFile = new java.io.File(tmpDir);
+
+            if (tmpFile.exists()) {
+                try {
+                    if (tmpFile.isDirectory()) {
+                        currentDir = tmpFile.getCanonicalPath();
+                        sRet = "";
+                    }
+                else
+                    sRet = sErrorPrefix + tmpDir + " is not a valid directory";
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+
+        return(sRet);
+        }
+
+    static final String HEXES = "0123456789abcdef";
+
+    public static String getHex( byte [] raw )
+        {
+        if ( raw == null )
+            {
+            return null;
+            }
+
+        final StringBuilder hex = new StringBuilder( 2 * raw.length );
+        for ( final byte b : raw )
+            {
+            hex.append(HEXES.charAt((b & 0xF0) >> 4)).append(HEXES.charAt((b & 0x0F)));
+            }
+        return hex.toString();
+        }
+
+    public String HashFile(String fileName)
+        {
+        String            sTmpFileName = fixFileName(fileName);
+        String            sRet         = sErrorPrefix + "Couldn't calculate hash for file " + sTmpFileName;
+        byte[]             buffer         = new byte [4096];
+        int                nRead         = 0;
+        long             lTotalRead     = 0;
+        MessageDigest    digest         = null;
+
+        try {
+            digest = java.security.MessageDigest.getInstance("MD5");
+            }
+        catch (NoSuchAlgorithmException e)
+            {
+            e.printStackTrace();
+            }
+
+        if (sTmpFileName.contains("org.mozilla.fennec") || sTmpFileName.contains("org.mozilla.firefox")) {
+            ContentResolver cr = contextWrapper.getContentResolver();
+            Uri ffxFiles = null;
+
+            ffxFiles = Uri.parse("content://" + (sTmpFileName.contains("fennec") ? fenProvider : ffxProvider) + "/file");
+
+            String[] columns = new String[] {
+                    "_id",
+                    "chunk"
+                    };
+
+            Cursor myCursor = cr.query(    ffxFiles,
+                                        columns,         // Which columns to return
+                                        sTmpFileName,   // Which rows to return (all rows)
+                                        null,           // Selection arguments (none)
+                                        null);            // Order clause (none)
+            if (myCursor != null) {
+                int nRows = myCursor.getCount();
+                int nBytesRecvd = 0;
+
+                for (int lcv = 0; lcv < nRows; lcv++) {
+                    if  (myCursor.moveToPosition(lcv)) {
+                        byte [] buf = myCursor.getBlob(1);
+                        if (buf != null) {
+                            nBytesRecvd += buf.length;
+                            digest.update(buf, 0, buf.length);
+                            lTotalRead += nRead;
+                            buf = null;
+                        }
+                    }
+                }
+                myCursor.close();
+                byte [] hash = digest.digest();
+
+                sRet = getHex(hash);
+            }
+        } else {
+            try {
+                FileInputStream srcFile  = new FileInputStream(sTmpFileName);
+                while((nRead = srcFile.read(buffer)) != -1) {
+                    digest.update(buffer, 0, nRead);
+                    lTotalRead += nRead;
+                }
+                srcFile.close();
+                byte [] hash = digest.digest();
+
+                sRet = getHex(hash);
+            }
+            catch (FileNotFoundException e) {
+                sRet += " file not found";
+            }
+            catch (IOException e) {
+                sRet += " io exception";
+                e.printStackTrace();
+            }
+        }
+        return(sRet);
+    }
+
+    public String RemoveFile(String fileName)
+        {
+        String    sTmpFileName = fixFileName(fileName);
+        String    sRet = sErrorPrefix + "Couldn't delete file " + sTmpFileName;
+
+        if (sTmpFileName.contains("org.mozilla.fennec") || sTmpFileName.contains("org.mozilla.firefox")) {
+            ContentResolver cr = contextWrapper.getContentResolver();
+            Uri ffxFiles = Uri.parse("content://" + (sTmpFileName.contains("fennec") ? fenProvider : ffxProvider) + "/file");
+            if (cr.delete(ffxFiles, sTmpFileName, null) == 1) {
+                sRet = "deleted " + sTmpFileName;
+            }
+        } else {
+            File f = new File(sTmpFileName);
+
+            if (f.delete())
+                sRet = "deleted " + sTmpFileName;
+        }
+
+        return(sRet);
+        }
+
+    public String PruneDir(String sDir)
+        {
+        String    sRet = "";
+        int nFiles = 0;
+        String sSubDir = null;
+        String    sTmpDir = fixFileName(sDir);
+
+        if (sTmpDir.contains("org.mozilla.fennec") || sTmpDir.contains("org.mozilla.firefox")) {
+            ContentResolver cr = contextWrapper.getContentResolver();
+            Uri ffxFiles = Uri.parse("content://" + (sTmpDir.contains("fennec") ? fenProvider : ffxProvider) + "/dir");
+            if (cr.delete(ffxFiles, sTmpDir, null) > 0) {
+                sRet = "deleted " + sTmpDir;
+            }
+        } else {
+            File dir = new File(sTmpDir);
+
+            if (dir.isDirectory()) {
+                sRet = "Deleting file(s) from " + sTmpDir;
+
+                File [] files = dir.listFiles();
+                if (files != null) {
+                    if ((nFiles = files.length) > 0) {
+                        for (int lcv = 0; lcv < nFiles; lcv++) {
+                            if (files[lcv].isDirectory()) {
+                                sSubDir = files[lcv].getAbsolutePath();
+                                sRet += "\n" + PruneDir(sSubDir);
+                            }
+                            else {
+                                if (files[lcv].delete()) {
+                                sRet += "\n\tDeleted " + files[lcv].getName();
+                                }
+                                else {
+                                    sRet += "\n\tUnable to delete " + files[lcv].getName();
+                                }
+                            }
+                        }
+                    }
+                    else
+                        sRet += "\n\t<empty>";
+                }
+
+                if (dir.delete()) {
+                    sRet += "\nDeleting directory " + sTmpDir;
+                }
+                else {
+                    sRet += "\nUnable to delete directory " + sTmpDir;
+                }
+            }
+            else {
+                sRet += sErrorPrefix + sTmpDir + " is not a directory";
+            }
+        }
+
+        return(sRet);
+        }
+
+    public String PrintDir(String sDir)
+        {
+        String    sRet = "";
+        int nFiles = 0;
+        String    sTmpDir = fixFileName(sDir);
+
+        if (sTmpDir.contains("org.mozilla.fennec") || sTmpDir.contains("org.mozilla.firefox")) {
+            ContentResolver cr = contextWrapper.getContentResolver();
+            Uri ffxFiles = null;
+
+            ffxFiles = Uri.parse("content://" + (sTmpDir.contains("fennec") ? fenProvider : ffxProvider) + "/dir");
+
+            String[] columns = new String[] {
+                    "_id",
+                    "isdir",
+                    "filename",
+                    "length"
+                };
+
+            Cursor myCursor = cr.query(    ffxFiles,
+                                        columns,     // Which columns to return
+                                        sTmpDir,    // Which rows to return (all rows)
+                                        null,       // Selection arguments (none)
+                                        null);        // Order clause (none)
+            if (myCursor != null) {
+                nFiles = myCursor.getCount();
+
+                // If only one entry and the index is -1 this is not a directory
+                int nNdx = myCursor.getColumnIndex("_id");
+                // If no entries the dir is empty
+                if (nFiles == 1) {
+                    sRet = "<empty>";
+                } else {
+                    // Show the entries
+                    for (int lcv = 1; lcv < nFiles; lcv++) {
+                        if  (myCursor.moveToPosition(lcv)) {
+                            if ((lcv == 0) && (myCursor.getLong(nNdx) == -1)) {
+                                sRet = sErrorPrefix + sTmpDir + " is not a directory";
+                            } else {
+                                sRet += myCursor.getString(2);
+                                if (lcv < (nFiles - 1))
+                                    sRet += "\n";
+                            }
+                        }
+                    }
+                }
+                myCursor.close();
+            }
+        } else {
+            File dir = new File(sTmpDir);
+
+            if (dir.isDirectory()) {
+                File [] files = dir.listFiles();
+
+                if (files != null) {
+                    if ((nFiles = files.length) > 0) {
+                        for (int lcv = 0; lcv < nFiles; lcv++) {
+                            sRet += files[lcv].getName();
+                            if (lcv < (nFiles - 1)) {
+                                sRet += "\n";
+                            }
+                        }
+                    }
+                    else {
+                        sRet = "<empty>";
+                    }
+                }
+            }
+            else {
+                sRet = sErrorPrefix + sTmpDir + " is not a directory";
+            }
+        }
+        return(sRet);
+    }
+
+    public String Move(String sTmpSrcFileName, String sTmpDstFileName) {
+        String sRet = sErrorPrefix + "Could not move " + sTmpSrcFileName + " to " + sTmpDstFileName;
+        String sTmp = CopyFile(sTmpSrcFileName, sTmpDstFileName);
+        if (sTmp.contains(" copied to ")) {
+            sTmp = RemoveFile(sTmpSrcFileName);
+            if (sTmp.startsWith("deleted ")) {
+                sRet = sTmpSrcFileName + " moved to " + sTmpDstFileName;
+            }
+        }
+
+        return(sRet);
+    }
+
+    public String CopyFile(String sTmpSrcFileName, String sTmpDstFileName) {
+        String sRet = sErrorPrefix + "Could not copy " + sTmpSrcFileName + " to " + sTmpDstFileName;
+        ContentValues cv = null;
+        File destFile = null;
+        Uri ffxSrcFiles = null;
+        Uri ffxDstFiles = null;
+        FileInputStream srcFile  = null;
+        FileOutputStream dstFile  = null;
+        byte[] buffer = new byte [4096];
+        int    nRead = 0;
+        long lTotalRead = 0;
+        long lTotalWritten = 0;
+        ContentResolver crIn = null;
+        ContentResolver crOut = null;
+
+        if (sTmpSrcFileName.contains("org.mozilla.fennec") || sTmpSrcFileName.contains("org.mozilla.firefox")) {
+            ffxSrcFiles = Uri.parse("content://" + (sTmpSrcFileName.contains("fennec") ? fenProvider : ffxProvider) + "/file");
+            crIn = contextWrapper.getContentResolver();
+        } else {
+            try {
+                srcFile  = new FileInputStream(sTmpSrcFileName);
+            } catch (FileNotFoundException e) {
+                e.printStackTrace();
+            }
+        }
+
+        if (sTmpDstFileName.contains("org.mozilla.fennec") || sTmpDstFileName.contains("org.mozilla.firefox")) {
+            ffxDstFiles = Uri.parse("content://" + (sTmpDstFileName.contains("fennec") ? fenProvider : ffxProvider) + "/file");
+            crOut = contextWrapper.getContentResolver();
+            cv = new ContentValues();
+        } else {
+            try {
+                dstFile  = new FileOutputStream(sTmpDstFileName);
+            } catch (FileNotFoundException e) {
+                e.printStackTrace();
+            }
+        }
+
+        if (srcFile != null) {
+            try {
+                while((nRead = srcFile.read(buffer)) != -1)    {
+                    lTotalRead += nRead;
+                    if (dstFile != null) {
+                        dstFile.write(buffer, 0, nRead);
+                        dstFile.flush();
+                    } else {
+                        cv.put("length", nRead);
+                        cv.put("chunk", buffer);
+                        if (crOut.update(ffxDstFiles, cv, sTmpDstFileName, null) == 0)
+                            break;
+                        lTotalWritten += nRead;
+                    }
+                }
+
+                srcFile.close();
+
+                if (dstFile != null) {
+                    dstFile.flush();
+                    dstFile.close();
+
+                    destFile = new File(sTmpDstFileName);
+                    lTotalWritten = destFile.length();
+                }
+
+                if (lTotalWritten == lTotalRead) {
+                    sRet = sTmpSrcFileName + " copied to " + sTmpDstFileName;
+                }
+                else {
+                    sRet = sErrorPrefix + "Failed to copy " + sTmpSrcFileName + " [length = " + lTotalWritten + "] to " + sTmpDstFileName + " [length = " + lTotalRead + "]";
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+
+        } else {
+            String[] columns = new String[] {
+                    "_id",
+                    "chunk",
+                    "length"
+                    };
+
+            Cursor myCursor = crIn.query(ffxSrcFiles,
+                                        columns,             // Which columns to return
+                                        sTmpSrcFileName,       // Which rows to return (all rows)
+                                        null,               // Selection arguments (none)
+                                        null);                // Order clause (none)
+            if (myCursor != null) {
+                int nRows = myCursor.getCount();
+
+                byte [] buf = null;
+
+                for (int lcv = 0; lcv < nRows; lcv++) {
+                    if  (myCursor.moveToPosition(lcv)) {
+                        buf = myCursor.getBlob(myCursor.getColumnIndex("chunk"));
+                        if (buf != null) {
+                            nRead = buf.length;
+                            try {
+                                lTotalRead += nRead;
+                                if (dstFile != null) {
+                                    dstFile.write(buffer, 0, nRead);
+                                    dstFile.flush();
+                                } else {
+                                    cv.put("length", nRead);
+                                    cv.put("chunk", buffer);
+                                    if (crOut.update(ffxDstFiles, cv, sTmpDstFileName, null) == 0)
+                                        break;
+                                    lTotalWritten += nRead;
+                                }
+                            } catch (IOException e) {
+                                e.printStackTrace();
+                            }
+                            buf = null;
+                        }
+                    }
+                }
+
+                if (nRows == -1) {
+                    sRet = sErrorPrefix + sTmpSrcFileName + ",-1\nNo such file or directory";
+                }
+                else {
+                    myCursor.close();
+
+                    if (dstFile != null) {
+                        try {
+                            dstFile.flush();
+                            dstFile.close();
+
+                            destFile = new File(sTmpDstFileName);
+                            lTotalWritten = destFile.length();
+                        } catch (IOException e) {
+                            e.printStackTrace();
+                        }
+                    }
+
+                    if (lTotalWritten == lTotalRead) {
+                        sRet = sTmpSrcFileName + " copied to " + sTmpDstFileName;
+                    }
+                    else {
+                        sRet = sErrorPrefix + "Failed to copy " + sTmpSrcFileName + " [length = " + lTotalWritten + "] to " + sTmpDstFileName + " [length = " + lTotalRead + "]";
+                    }
+                }
+            }
+            else {
+                sRet = sErrorPrefix + sTmpSrcFileName + ",-1\nUnable to access file (internal error)";
+            }
+        }
+
+        return (sRet);
+    }
+
+    public String IsDirWritable(String sDir)
+        {
+        String    sTmpDir = fixFileName(sDir);
+        String sRet = sErrorPrefix + "[" + sTmpDir + "] is not a directory";
+
+        if (sTmpDir.contains("org.mozilla.fennec") || sTmpDir.contains("org.mozilla.firefox")) {
+            ContentResolver cr = contextWrapper.getContentResolver();
+            Uri ffxFiles = null;
+
+            ffxFiles = Uri.parse("content://" + (sTmpDir.contains("fennec") ? fenProvider : ffxProvider) + "/dir");
+
+            String[] columns = new String[] {
+                    "_id",
+                    "isdir",
+                    "filename",
+                    "length",
+                    "writable"
+                };
+
+            Cursor myCursor = cr.query(    ffxFiles,
+                                        columns,     // Which columns to return
+                                        sTmpDir,    // Which rows to return (all rows)
+                                        null,       // Selection arguments (none)
+                                        null);        // Order clause (none)
+            if (myCursor != null) {
+                if (myCursor.getCount() > 0) {
+                    if (myCursor.moveToPosition(0)) {
+                        if (myCursor.getLong(myCursor.getColumnIndex("isdir")) == 1) {
+                            sRet = "[" + sTmpDir + "] " + ((myCursor.getLong(myCursor.getColumnIndex("writable")) == 1) ? "is" : "is not") + " writable";
+                        }
+                    }
+                }
+            }
+        } else {
+            File dir = new File(sTmpDir);
+
+            if (dir.isDirectory()) {
+                sRet = "[" + sTmpDir + "] " + (dir.canWrite() ? "is" : "is not") + " writable";
+            } else {
+                sRet = sErrorPrefix + "[" + sTmpDir + "] is not a directory";
+            }
+        }
+        return(sRet);
+    }
+
+    public String Push(String fileName, BufferedInputStream bufIn, long lSize)
+    {
+        byte []                buffer             = new byte [8192];
+        int                    nRead            = 0;
+        long                lRead            = 0;
+        String                sTmpFileName     = fixFileName(fileName);
+        FileOutputStream     dstFile            = null;
+        ContentResolver     cr                 = null;
+        ContentValues        cv                = null;
+        Uri                 ffxFiles         = null;
+        String                sRet            = sErrorPrefix + "Push failed!";
+
+        try {
+            if (sTmpFileName.contains("org.mozilla.fennec") || sTmpFileName.contains("org.mozilla.firefox")) {
+                cr = contextWrapper.getContentResolver();
+                ffxFiles = Uri.parse("content://" + (sTmpFileName.contains("fennec") ? fenProvider : ffxProvider) + "/file");
+                cv = new ContentValues();
+            }
+            else {
+                dstFile = new FileOutputStream(sTmpFileName, false);
+            }
+
+            while((nRead != -1) && (lRead < lSize))
+                {
+                nRead = bufIn.read(buffer);
+                if (nRead != -1) {
+                    if (dstFile != null) {
+                        dstFile.write(buffer, 0, nRead);
+                        dstFile.flush();
+                    }
+                    else {
+                        cv.put("offset", lRead);
+                        cv.put("length", nRead);
+                        cv.put("chunk", buffer);
+                        cr.update(ffxFiles, cv, sTmpFileName, null);
+                    }
+                    lRead += nRead;
+                }
+            }
+
+            if (dstFile != null) {
+                dstFile.flush();
+                dstFile.close();
+            }
+
+            if (lRead == lSize)    {
+                sRet = HashFile(sTmpFileName);
+            }
+        }
+        catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        buffer = null;
+
+        return(sRet);
+    }
+
+    public String FTPGetFile(String sServer, String sSrcFileName, String sDstFileName, OutputStream out)
+        {
+        byte[] buffer = new byte [4096];
+        int    nRead = 0;
+        long lTotalRead = 0;
+        String sRet = sErrorPrefix + "FTP Get failed for " + sSrcFileName;
+        String strRet = "";
+        int    reply = 0;
+        FileOutputStream outStream = null;
+        String    sTmpDstFileName = fixFileName(sDstFileName);
+
+        FTPClient ftp = new FTPClient();
+        try
+            {
+            ftp.connect(sServer);
+            reply = ftp.getReplyCode();
+            if(FTPReply.isPositiveCompletion(reply))
+                {
+                ftp.login("anonymous", "b@t.com");
+                reply = ftp.getReplyCode();
+                if(FTPReply.isPositiveCompletion(reply))
+                    {
+                    ftp.enterLocalPassiveMode();
+                    if (ftp.setFileType(FTP.BINARY_FILE_TYPE))
+                        {
+                        File dstFile = new File(sTmpDstFileName);
+                        outStream = new FileOutputStream(dstFile);
+                        FTPFile [] ftpFiles = ftp.listFiles(sSrcFileName);
+                        if (ftpFiles.length > 0)
+                            {
+                            long lFtpSize = ftpFiles[0].getSize();
+                            if (lFtpSize <= 0)
+                                lFtpSize = 1;
+
+                            InputStream ftpIn = ftp.retrieveFileStream(sSrcFileName);
+                            while ((nRead = ftpIn.read(buffer)) != -1)
+                                {
+                                lTotalRead += nRead;
+                                outStream.write(buffer, 0, nRead);
+                                strRet = "\r" + lTotalRead + " of " + lFtpSize + " bytes received " + ((lTotalRead * 100) / lFtpSize) + "% completed";
+                                out.write(strRet.getBytes());
+                                out.flush();
+                                }
+                            ftpIn.close();
+                            @SuppressWarnings("unused")
+                            boolean bRet = ftp.completePendingCommand();
+                            outStream.flush();
+                            outStream.close();
+                            strRet = ftp.getReplyString();
+                            reply = ftp.getReplyCode();
+                            }
+                        else
+                            {
+                            strRet = sRet;
+                            }
+                        }
+                    ftp.logout();
+                    ftp.disconnect();
+                    sRet = "\n" + strRet;
+                    }
+                else
+                    {
+                    ftp.disconnect();
+                    System.err.println("FTP server refused login.");
+                    }
+                }
+            else
+                {
+                ftp.disconnect();
+                System.err.println("FTP server refused connection.");
+                }
+            }
+        catch (SocketException e)
+            {
+            sRet = e.getMessage();
+            strRet = ftp.getReplyString();
+            reply = ftp.getReplyCode();
+            sRet += "\n" + strRet;
+            e.printStackTrace();
+            }
+        catch (IOException e)
+            {
+            sRet = e.getMessage();
+            strRet = ftp.getReplyString();
+            reply = ftp.getReplyCode();
+            sRet += "\n" + strRet;
+            e.printStackTrace();
+            }
+        return (sRet);
+    }
+
+    public String Pull(String fileName, long lOffset, long lLength, OutputStream out)
+        {
+        String    sTmpFileName = fixFileName(fileName);
+        String    sRet = sErrorPrefix + "Could not read the file " + sTmpFileName;
+        byte[]    buffer = new byte [4096];
+        int        nRead = 0;
+        long    lSent = 0;
+
+        if (sTmpFileName.contains("org.mozilla.fennec") || sTmpFileName.contains("org.mozilla.firefox")) {
+            ContentResolver cr = contextWrapper.getContentResolver();
+            Uri ffxFiles = null;
+
+            ffxFiles = Uri.parse("content://" + (sTmpFileName.contains("fennec") ? fenProvider : ffxProvider) + "/file");
+
+            String[] columns = new String[] {
+                    "_id",
+                    "chunk",
+                    "length"
+                    };
+
+            String [] args = new String [2];
+            args[0] = Long.toString(lOffset);
+            args[1] = Long.toString(lLength);
+
+            Cursor myCursor = cr.query(    ffxFiles,
+                                        columns,         // Which columns to return
+                                        sTmpFileName,   // Which rows to return (all rows)
+                                        args,           // Selection arguments (none)
+                                        null);            // Order clause (none)
+            if (myCursor != null) {
+                int nRows = myCursor.getCount();
+                long lFileLength = 0;
+
+                for (int lcv = 0; lcv < nRows; lcv++) {
+                    if  (myCursor.moveToPosition(lcv)) {
+                        if (lcv == 0) {
+                            lFileLength = myCursor.getLong(2);
+                            String sTmp = sTmpFileName + "," + lFileLength + "\n";
+                            try {
+                                out.write(sTmp.getBytes());
+                            } catch (IOException e) {
+                                e.printStackTrace();
+                                break;
+                            }
+                        }
+
+                        if (lLength != 0) {
+                            byte [] buf = myCursor.getBlob(1);
+                            if (buf != null) {
+                                nRead = buf.length;
+                                try {
+                                    if ((lSent + nRead) <= lFileLength)    {
+                                        out.write(buf,0,nRead);
+                                        lSent += nRead;
+                                    }
+                                    else {
+                                        nRead = (int) (lFileLength - lSent);
+                                        out.write(buf,0,nRead);
+                                        Log.d("pull warning", "more bytes read than expected");
+                                        break;
+                                    }
+                                } catch (IOException e) {
+                                    e.printStackTrace();
+                                    sRet = sErrorPrefix + "Could not write to out " + sTmpFileName;
+                                }
+                                buf = null;
+                            }
+                        }
+                    }
+                }
+                if (nRows == 0) {
+                    String sTmp = sTmpFileName + "," + lFileLength + "\n";
+                    try {
+                        out.write(sTmp.getBytes());
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                }
+                if (nRows == -1) {
+                    sRet = sErrorPrefix + sTmpFileName + ",-1\nNo such file or directory";
+                }
+                else {
+                    myCursor.close();
+                    sRet = "";
+                }
+            }
+            else {
+                sRet = sErrorPrefix + sTmpFileName + ",-1\nUnable to access file (internal error)";
+            }
+        }
+        else {
+            try {
+                File f = new File(sTmpFileName);
+                long lFileLength = f.length();
+                FileInputStream fin = new FileInputStream(f);
+                if (lFileLength == 0) {
+                    while ((nRead = fin.read(buffer)) != -1) {
+                        lFileLength += nRead;
+                    }
+                    fin.close();
+                    fin = new FileInputStream(f);
+                }
+
+                // lLength == -1 return everything between lOffset and eof
+                // lLength == 0 return file length
+                // lLength > 0 return lLength bytes
+                if (lLength == -1) {
+                    lFileLength = lFileLength - lOffset;
+                } else if (lLength == 0) {
+                    // just return the file length
+                } else {
+                    lFileLength = ((lLength <= (lFileLength - lOffset)) ? lLength : (lFileLength - lOffset));
+                }
+
+                String sTmp = sTmpFileName + "," + lFileLength + "\n";
+                out.write(sTmp.getBytes());
+                if (lLength != 0) {
+                    if  (lOffset > 0) {
+                        fin.skip(lOffset);
+                    }
+                    while ((nRead = fin.read(buffer)) != -1) {
+                        if ((lSent + nRead) <= lFileLength)    {
+                            out.write(buffer,0,nRead);
+                            lSent += nRead;
+                        }
+                        else {
+                            nRead = (int) (lFileLength - lSent);
+                            out.write(buffer,0,nRead);
+                            if (lLength != -1)
+                                Log.d("pull warning", "more bytes read than sent");
+                            break;
+                        }
+                    }
+                }
+                fin.close();
+                out.flush();
+                sRet = "";
+                }
+            catch (FileNotFoundException e)    {
+                sRet = sErrorPrefix + sTmpFileName + ",-1\nNo such file or directory";
+            }
+            catch (IOException e) {
+                sRet = e.toString();
+            }
+        }
+        return (sRet);
+    }
+
+    public String Cat(String fileName, OutputStream out)
+        {
+        String    sTmpFileName = fixFileName(fileName);
+        String    sRet = sErrorPrefix + "Could not read the file " + sTmpFileName;
+        byte[]    buffer = new byte [4096];
+        int        nRead = 0;
+
+        if (sTmpFileName.contains("org.mozilla.fennec") || sTmpFileName.contains("org.mozilla.firefox")) {
+            ContentResolver cr = contextWrapper.getContentResolver();
+            Uri ffxFiles = null;
+
+            ffxFiles = Uri.parse("content://" + (sTmpFileName.contains("fennec") ? fenProvider : ffxProvider) + "/file");
+
+            String[] columns = new String[] {
+                    "_id",
+                    "chunk"
+                    };
+
+            Cursor myCursor = cr.query(    ffxFiles,
+                                        columns,         // Which columns to return
+                                        sTmpFileName,   // Which rows to return (all rows)
+                                        null,           // Selection arguments (none)
+                                        null);            // Order clause (none)
+            if (myCursor != null) {
+                int nRows = myCursor.getCount();
+                int nBytesRecvd = 0;
+
+                for (int lcv = 0; lcv < nRows; lcv++) {
+                    if  (myCursor.moveToPosition(lcv)) {
+                        byte [] buf = myCursor.getBlob(1);
+                        if (buf != null) {
+                            nBytesRecvd += buf.length;
+                            try {
+                                out.write(buf);
+                                sRet = "";
+                            } catch (IOException e) {
+                                e.printStackTrace();
+                                sRet = sErrorPrefix + "Could not write to out " + sTmpFileName;
+                            }
+                            buf = null;
+                        }
+                    }
+                }
+                if (nRows == 0) {
+                    sRet = "";
+                }
+
+                myCursor.close();
+            }
+        } else {
+            try {
+                FileInputStream fin = new FileInputStream(sTmpFileName);
+                while ((nRead = fin.read(buffer)) != -1) {
+                    out.write(buffer,0,nRead);
+                }
+                fin.close();
+                out.flush();
+                sRet = "";
+                }
+            catch (FileNotFoundException e) {
+                sRet = sErrorPrefix + sTmpFileName + " No such file or directory";
+            }
+            catch (IOException e) {
+                sRet = e.toString();
+            }
+        }
+        return (sRet);
+    }
+
+    public String MakeDir(String sDir)
+        {
+        String    sTmpDir = fixFileName(sDir);
+        String sRet = sErrorPrefix + "Could not create the directory " + sTmpDir;
+        if (sTmpDir.contains("org.mozilla.fennec") || sTmpDir.contains("org.mozilla.firefox")) {
+            ContentResolver cr = contextWrapper.getContentResolver();
+            Uri ffxFiles = Uri.parse("content://" + (sTmpDir.contains("fennec") ? fenProvider : ffxProvider) + "/dir");
+            ContentValues cv = new ContentValues();
+
+            if (cr.update(ffxFiles, cv, sTmpDir, null) == 1) {
+                sRet = sDir + " successfully created";
+            }
+        }
+        else {
+            File dir = new File(sTmpDir);
+
+            if (dir.mkdirs()) {
+                sRet = sDir + " successfully created";
+            }
+        }
+
+        return (sRet);
+        }
+    // move this to SUTAgentAndroid.java
+    public String GetScreenInfo()
+        {
+        String sRet = "";
+        DisplayMetrics metrics = new DisplayMetrics();
+        WindowManager wMgr = (WindowManager) contextWrapper.getSystemService(Context.WINDOW_SERVICE);
+        wMgr.getDefaultDisplay().getMetrics(metrics);
+        sRet = "X:" + metrics.widthPixels + " Y:" + metrics.heightPixels;
+        return (sRet);
+        }
+    // move this to SUTAgentAndroid.java
+    public int [] GetScreenXY()
+        {
+            int [] nRetXY = new int [2];
+            DisplayMetrics metrics = new DisplayMetrics();
+            WindowManager wMgr = (WindowManager) contextWrapper.getSystemService(Context.WINDOW_SERVICE);
+            wMgr.getDefaultDisplay().getMetrics(metrics);
+            nRetXY[0] = metrics.widthPixels;
+            nRetXY[1] = metrics.heightPixels;
+            return(nRetXY);
+        }
+
+    public String GetRotationInfo()
+        {
+            WindowManager wMgr = (WindowManager) contextWrapper.getSystemService(Context.WINDOW_SERVICE);
+            int nRotationDegrees = 0; // default
+            switch(wMgr.getDefaultDisplay().getRotation())
+                {
+                case Surface.ROTATION_90:
+                    nRotationDegrees = 90;
+                    break;
+                case Surface.ROTATION_180:
+                    nRotationDegrees = 180;
+                    break;
+                case Surface.ROTATION_270:
+                    nRotationDegrees = 270;
+                    break;
+                }
+            return "ROTATION:" + nRotationDegrees;
+        }
+
+    public String SetADB(String sWhat) {
+        String sRet = "";
+        String sTmp = "";
+        String sCmd;
+
+        if (sWhat.contains("ip")) {
+            sCmd = "setprop service.adb.tcp.port 5555";
+        } else {
+            sCmd = "setprop service.adb.tcp.port -1";
+        }
+
+        try {
+            pProc = Runtime.getRuntime().exec(this.getSuArgs(sCmd));
+            RedirOutputThread outThrd = new RedirOutputThread(pProc, null);
+            outThrd.start();
+            outThrd.joinAndStopRedirect(5000);
+            sTmp = outThrd.strOutput;
+            Log.e("ADB", sTmp);
+            if (outThrd.nExitCode == 0) {
+                pProc = Runtime.getRuntime().exec(this.getSuArgs("stop adbd"));
+                outThrd = new RedirOutputThread(pProc, null);
+                outThrd.start();
+                outThrd.joinAndStopRedirect(5000);
+                sTmp = outThrd.strOutput;
+                Log.e("ADB", sTmp);
+                if (outThrd.nExitCode == 0) {
+                    pProc = Runtime.getRuntime().exec(this.getSuArgs("start adbd"));
+                    outThrd = new RedirOutputThread(pProc, null);
+                    outThrd.start();
+                    outThrd.joinAndStopRedirect(5000);
+                    sTmp = outThrd.strOutput;
+                    Log.e("ADB", sTmp);
+                    if (outThrd.nExitCode == 0) {
+                        sRet = "Successfully set adb to " + sWhat + "\n";
+                    } else {
+                        sRet = sErrorPrefix + "Failed to start adbd\n";
+                    }
+                } else {
+                    sRet = sErrorPrefix + "Failed to stop adbd\n";
+                }
+            } else {
+                sRet = sErrorPrefix + "Failed to setprop service.adb.tcp.port 5555\n";
+            }
+
+        }
+    catch (IOException e)
+        {
+        sRet = e.getMessage();
+        e.printStackTrace();
+        }
+    catch (InterruptedException e)
+        {
+        e.printStackTrace();
+        }
+        return(sRet);
+    }
+
+    public String KillProcess(String sProcName, OutputStream out)
+        {
+        String sRet = sErrorPrefix + "Unable to kill " + sProcName + "\n";
+        ActivityManager aMgr = (ActivityManager) contextWrapper.getSystemService(Activity.ACTIVITY_SERVICE);
+        List <ActivityManager.RunningAppProcessInfo> lProcesses = aMgr.getRunningAppProcesses();
+        int lcv = 0;
+        String sFoundProcName = "";
+        int nProcs = 0;
+        boolean bFoundAppProcess = false;
+
+        if (lProcesses != null)
+            nProcs = lProcesses.size();
+
+        for (lcv = 0; lcv < nProcs; lcv++)
+            {
+            if (lProcesses.get(lcv).processName.contains(sProcName))
+                {
+                sFoundProcName = lProcesses.get(lcv).processName;
+                bFoundAppProcess = true;
+
+                try
+                    {
+                    pProc = Runtime.getRuntime().exec(this.getSuArgs("kill " + lProcesses.get(lcv).pid));
+                    RedirOutputThread outThrd = new RedirOutputThread(pProc, null);
+                    outThrd.start();
+                    outThrd.joinAndStopRedirect(15000);
+                    String sTmp = outThrd.strOutput;
+                    Log.e("KILLPROCESS", sTmp);
+                    }
+                catch (IOException e)
+                    {
+                    sRet = e.getMessage();
+                    e.printStackTrace();
+                    }
+                catch (InterruptedException e)
+                    {
+                    e.printStackTrace();
+                    }
+                }
+            }
+
+        if (bFoundAppProcess)
+            {
+            // Give the messages a chance to be processed
+            try {
+                Thread.sleep(2000);
+                }
+            catch (InterruptedException e)
+                {
+                e.printStackTrace();
+                }
+
+            sRet = "Successfully killed " + sProcName + "\n";
+            lProcesses = aMgr.getRunningAppProcesses();
+            nProcs = 0;
+            if (lProcesses != null)
+                nProcs = lProcesses.size();
+            for (lcv = 0; lcv < nProcs; lcv++)
+                {
+                if (lProcesses.get(lcv).processName.contains(sProcName))
+                    {
+                    sRet = sErrorPrefix + "Unable to kill " + sProcName + " (couldn't kill " + sFoundProcName +")\n";
+                    break;
+                    }
+                }
+            }
+        else
+            {
+            // To kill processes other than Java applications - processes
+            // like xpcshell - a different strategy is necessary: use ps
+            // to find the process' PID.
+            try
+                {
+                pProc = Runtime.getRuntime().exec("ps");
+                RedirOutputThread outThrd = new RedirOutputThread(pProc, null);
+                outThrd.start();
+                outThrd.joinAndStopRedirect(10000);
+                String sTmp = outThrd.strOutput;
+                StringTokenizer stokLines = new StringTokenizer(sTmp, "\n");
+                while(stokLines.hasMoreTokens())
+                    {
+                    String sLine = stokLines.nextToken();
+                    StringTokenizer stokColumns = new StringTokenizer(sLine, " \t\n");
+                    stokColumns.nextToken();
+                    String sPid = stokColumns.nextToken();
+                    stokColumns.nextToken();
+                    stokColumns.nextToken();
+                    stokColumns.nextToken();
+                    stokColumns.nextToken();
+                    stokColumns.nextToken();
+                    stokColumns.nextToken();
+                    String sName = null;
+                    if (stokColumns.hasMoreTokens())
+                        {
+                        sName = stokColumns.nextToken();
+                        if (sName.contains(sProcName))
+                            {
+                            NewKillProc(sPid, out);
+                            sRet = "Successfully killed " + sName + "\n";
+                            }
+                        }
+                    }
+                }
+            catch (Exception e)
+                {
+                e.printStackTrace();
+                }
+            }
+
+        return (sRet);
+        }
+
+    public boolean IsProcessDead(String sProcName)
+        {
+        boolean bRet = false;
+        ActivityManager aMgr = (ActivityManager) contextWrapper.getSystemService(Activity.ACTIVITY_SERVICE);
+        List <ActivityManager.ProcessErrorStateInfo> lProcesses = aMgr.getProcessesInErrorState();
+        int lcv = 0;
+
+        if (lProcesses != null)
+            {
+            for (lcv = 0; lcv < lProcesses.size(); lcv++)
+                {
+                if (lProcesses.get(lcv).processName.contentEquals(sProcName) &&
+                    lProcesses.get(lcv).condition != ActivityManager.ProcessErrorStateInfo.NO_ERROR)
+                    {
+                    bRet = true;
+                    break;
+                    }
+                }
+            }
+
+        return (bRet);
+        }
+
+    public String GetProcessInfo()
+        {
+        String sRet = "";
+        ActivityManager aMgr = (ActivityManager) contextWrapper.getSystemService(Activity.ACTIVITY_SERVICE);
+        List <ActivityManager.RunningAppProcessInfo> lProcesses = aMgr.getRunningAppProcesses();
+        int    nProcs = 0;
+        int lcv = 0;
+        String strProcName = "";
+        int    nPID = 0;
+        int nUser = 0;
+
+        if (lProcesses != null) 
+            nProcs = lProcesses.size();
+
+        for (lcv = 0; lcv < nProcs; lcv++)
+            {
+            strProcName = lProcesses.get(lcv).processName;
+            nPID = lProcesses.get(lcv).pid;
+            nUser = lProcesses.get(lcv).uid;
+            sRet += nUser + "\t" + nPID + "\t" + strProcName;
+            if (lcv < (nProcs - 1))
+                sRet += "\n";
+            }
+
+        return (sRet);
+        }
+
+    public String GetOSInfo()
+        {
+        String sRet = "";
+
+        sRet = Build.DISPLAY;
+
+        return (sRet);
+        }
+
+    public String GetPowerInfo()
+        {
+        String sRet = "";
+
+        sRet = "Power status:\n  AC power " + SUTAgentAndroid.sACStatus + "\n";
+        sRet += "  Battery charge " + SUTAgentAndroid.sPowerStatus + "\n";
+        sRet += "  Remaining charge:      " + SUTAgentAndroid.nChargeLevel + "%\n";
+        sRet += "  Battery Temperature:   " + (((float)(SUTAgentAndroid.nBatteryTemp))/10) + " (c)\n";
+        return (sRet);
+        }
+
+    public String GetSutUserInfo()
+        {
+        String sRet = "";
+        try {
+            // based on patch in https://bugzilla.mozilla.org/show_bug.cgi?id=811763
+            Context context = contextWrapper.getApplicationContext();
+            Object userManager = context.getSystemService("user");
+            if (userManager != null) {
+                // if userManager is non-null that means we're running on 4.2+ and so the rest of this
+                // should just work
+                Object userHandle = android.os.Process.class.getMethod("myUserHandle", (Class[])null).invoke(null);
+                Object userSerial = userManager.getClass().getMethod("getSerialNumberForUser", userHandle.getClass()).invoke(userManager, userHandle);
+                sRet += "User Serial:" + userSerial.toString();
+            }
+        } catch (Exception e) {
+            // Guard against any unexpected failures
+            e.printStackTrace();
+        }
+
+        return sRet;
+        }
+
+    public String GetTemperatureInfo()
+        {
+        String sTempVal = "unknown";
+        String sDeviceFile = "/sys/bus/platform/devices/temp_sensor_hwmon.0/temp1_input";
+        try {
+            pProc = Runtime.getRuntime().exec(this.getSuArgs("cat " + sDeviceFile));
+            RedirOutputThread outThrd = new RedirOutputThread(pProc, null);
+            outThrd.start();
+            outThrd.joinAndStopRedirect(5000);
+            String output = outThrd.strOutput;
+            // this only works on pandas (with the temperature sensors turned
+            // on), other platforms we just get a file not found error... we'll
+            // just return "unknown" for that case
+            try {
+                sTempVal = String.valueOf(Integer.parseInt(output.trim()) / 1000.0);
+            } catch (NumberFormatException e) {
+                // not parsed! probably not a panda
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+
+        return "Temperature: " + sTempVal;
+        }
+
+    public String GetDiskInfo(String sPath)
+        {
+        String sRet = "";
+        StatFs statFS = new StatFs(sPath);
+
+        long nBlockCount = statFS.getBlockCount();
+        long nBlockSize = statFS.getBlockSize();
+        long nBlocksAvail = statFS.getAvailableBlocks();
+        // Free is often the same as Available, but can include reserved
+        // blocks that are not available to normal applications.
+        // long nBlocksFree = statFS.getFreeBlocks();
+
+        sRet = sPath + ": " + (nBlockCount * nBlockSize) + " total, " + (nBlocksAvail * nBlockSize) + " available";
+
+        return (sRet);
+        }
+
+    public String GetMemoryInfo()
+        {
+        String sRet = "PA:" + GetMemoryConfig() + ", FREE: " + GetMemoryUsage();
+        return (sRet);
+        }
+
+    public long GetMemoryConfig()
+        {
+        ActivityManager aMgr = (ActivityManager) contextWrapper.getSystemService(Activity.ACTIVITY_SERVICE);
+        ActivityManager.MemoryInfo outInfo = new ActivityManager.MemoryInfo();
+        aMgr.getMemoryInfo(outInfo);
+        long lMem = outInfo.availMem;
+
+        return (lMem);
+        }
+
+    public long GetMemoryUsage()
+        {
+
+        String load = "";
+        try {
+            RandomAccessFile reader = new RandomAccessFile("/proc/meminfo", "r");
+            load = reader.readLine(); // Read in the MemTotal
+            load = reader.readLine(); // Read in the MemFree
+        } catch (IOException ex) {
+            return (0);
+        }
+
+        String[] toks = load.split(" ");
+        int i = 1;
+        for (i=1; i < toks.length; i++) {
+            String val = toks[i].trim();
+            if (!val.equals("")) {
+                break;
+            }
+        }
+        if (i <= toks.length) {
+            long lMem = Long.parseLong(toks[i].trim());
+            return (lMem * 1024);
+        }
+        return (0);
+        }
+
+    public String UpdateCallBack(String sFileName)
+        {
+        String sRet = sErrorPrefix + "No file specified";
+        String sIP = "";
+        String sPort = "";
+        int nEnd = 0;
+        int nStart = 0;
+
+        if ((sFileName == null) || (sFileName.length() == 0))
+            return(sRet);
+
+        Context ctx = contextWrapper.getApplicationContext();
+        try {
+            FileInputStream fis = ctx.openFileInput(sFileName);
+            int nBytes = fis.available();
+            if (nBytes > 0)
+                {
+                byte [] buffer = new byte [nBytes + 1];
+                int nRead = fis.read(buffer, 0, nBytes);
+                fis.close();
+                ctx.deleteFile(sFileName);
+                if (nRead > 0)
+                    {
+                    String sBuffer = new String(buffer);
+                    nEnd = sBuffer.indexOf(',');
+                    if (nEnd > 0)
+                        {
+                        sIP = (sBuffer.substring(0, nEnd)).trim();
+                        nStart = nEnd + 1;
+                        nEnd = sBuffer.indexOf('\r', nStart);
+                        if (nEnd > 0)
+                            {
+                            sPort = (sBuffer.substring(nStart, nEnd)).trim();
+                            Thread.sleep(5000);
+                            sRet = RegisterTheDevice(sIP, sPort, sBuffer.substring(nEnd + 1));
+                            }
+                        }
+                    }
+                }
+            }
+        catch (FileNotFoundException e)
+            {
+            sRet = sErrorPrefix + "Nothing to do";
+            }
+        catch (IOException e)
+            {
+            sRet = sErrorPrefix + "Couldn't send info to " + sIP + ":" + sPort;
+            }
+        catch (InterruptedException e)
+            {
+            e.printStackTrace();
+            }
+        return(sRet);
+        }
+
+    public String RegisterTheDevice(String sSrvr, String sPort, String sData)
+        {
+        String sRet = "";
+        String line = "";
+
+//        Debug.waitForDebugger();
+
+        if (sSrvr != null && sPort != null && sData != null)
+            {
+            try
+                {
+                int nPort = Integer.parseInt(sPort);
+                Socket socket = new Socket(sSrvr, nPort);
+                PrintWriter out = new PrintWriter(socket.getOutputStream(), false);
+                BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
+                out.println(sData);
+                if ( out.checkError() == false )
+                    {
+                    socket.setSoTimeout(30000);
+                    while (socket.isInputShutdown() == false)
+                        {
+                        line = in.readLine();
+
+                        if (line != null)
+                            {
+                            line = line.toLowerCase();
+                            sRet += line;
+                            // ok means we're done
+                            if (line.contains("ok"))
+                                break;
+                            }
+                        else
+                            {
+                            // end of stream reached
+                            break;
+                            }
+                        }
+                    }
+                out.close();
+                in.close();
+                socket.close();
+                }
+            catch(NumberFormatException e)
+                {
+                sRet += "reg NumberFormatException thrown [" + e.getLocalizedMessage() + "]";
+                e.printStackTrace();
+                }
+            catch (UnknownHostException e)
+                {
+                sRet += "reg UnknownHostException thrown [" + e.getLocalizedMessage() + "]";
+                e.printStackTrace();
+                }
+            catch (IOException e)
+                {
+                sRet += "reg IOException thrown [" + e.getLocalizedMessage() + "]";
+                e.printStackTrace();
+                }
+            }
+        return(sRet);
+        }
+
+    public String GetTimeZone()
+        {
+        String    sRet = "";
+        TimeZone tz;
+
+        tz = TimeZone.getDefault();
+        Date now = new Date();
+        sRet = tz.getDisplayName(tz.inDaylightTime(now), TimeZone.LONG);
+
+        return(sRet);
+        }
+
+    public String SetTimeZone(String sTimeZone)
+        {
+        String            sRet = "Unable to set timezone to " + sTimeZone;
+        TimeZone         tz = null;
+        AlarmManager     amgr = null;
+
+        if ((sTimeZone.length() > 0) && (sTimeZone.startsWith("GMT")))
+            {
+            amgr = (AlarmManager) contextWrapper.getSystemService(Context.ALARM_SERVICE);
+            if (amgr != null)
+                amgr.setTimeZone(sTimeZone);
+            }
+        else
+            {
+            String [] zoneNames = TimeZone.getAvailableIDs();
+            int nNumMatches = zoneNames.length;
+            int    lcv = 0;
+
+            for (lcv = 0; lcv < nNumMatches; lcv++)
+                {
+                if (zoneNames[lcv].equalsIgnoreCase(sTimeZone))
+                    break;
+                }
+
+            if (lcv < nNumMatches)
+                {
+                amgr = (AlarmManager) contextWrapper.getSystemService(Context.ALARM_SERVICE);
+                if (amgr != null)
+                    amgr.setTimeZone(zoneNames[lcv]);
+                }
+            }
+
+        if (amgr != null)
+            {
+            tz = TimeZone.getDefault();
+            Date now = new Date();
+            sRet = tz.getDisplayName(tz.inDaylightTime(now), TimeZone.LONG);
+            }
+
+        return(sRet);
+        }
+
+    public String GetSystemTime()
+        {
+        String sRet = "";
+        Calendar cal = Calendar.getInstance();
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss:SSS");
+        sRet = sdf.format(cal.getTime());
+
+        return (sRet);
+        }
+
+    public String SetSystemTime(String sDate, String sTime, OutputStream out) {
+        String sRet = "";
+        String sM = "";
+        String sMillis = "";
+
+        if (((sDate != null) && (sTime != null)) &&
+            (sDate.contains("/") || sDate.contains(".")) &&
+            (sTime.contains(":"))) {
+            int year = Integer.parseInt(sDate.substring(0,4));
+            int month = Integer.parseInt(sDate.substring(5,7));
+            int day = Integer.parseInt(sDate.substring(8,10));
+
+            int hour = Integer.parseInt(sTime.substring(0,2));
+            int mins = Integer.parseInt(sTime.substring(3,5));
+            int secs = Integer.parseInt(sTime.substring(6,8));
+
+            Calendar cal = new GregorianCalendar(TimeZone.getDefault());
+            cal.set(year, month - 1, day, hour, mins, secs);
+            long lMillisecs = cal.getTime().getTime();
+
+            sM = Long.toString(lMillisecs);
+            sMillis = sM.substring(0, sM.length() - 3) + "." + sM.substring(sM.length() - 3);
+
+        } else {
+            sRet += "Invalid argument(s)";
+        }
+
+        // if we have an argument
+        if (sMillis.length() > 0) {
+            try {
+                pProc = Runtime.getRuntime().exec(this.getSuArgs("date -u " + sMillis));
+                RedirOutputThread outThrd = new RedirOutputThread(pProc, null);
+                outThrd.start();
+                outThrd.joinAndStopRedirect(10000);
+                sRet += GetSystemTime();
+            } catch (IOException e) {
+                sRet = e.getMessage();
+                e.printStackTrace();
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+        }
+
+        return (sRet);
+    }
+
+    public String GetClok()
+        {
+        long lMillisecs = System.currentTimeMillis();
+        String sRet = "";
+
+        if (lMillisecs > 0)
+            sRet = Long.toString(lMillisecs);
+
+        return(sRet);
+        }
+
+    public String GetUptime()
+        {
+        String sRet = "";
+        long lHold = 0;
+        long lUptime = SystemClock.elapsedRealtime();
+        int    nDays = 0;
+        int    nHours = 0;
+        int nMinutes = 0;
+        int nSecs = 0;
+        int nMilliseconds = 0;
+
+        if (lUptime > 0)
+            {
+            nDays = (int)(lUptime / (24L * 60L * 60L * 1000L));
+            lHold = lUptime % (24L * 60L * 60L * 1000L);
+            nHours = (int)(lHold / (60L * 60L * 1000L));
+            lHold %= 60L * 60L * 1000L;
+            nMinutes = (int)(lHold / (60L * 1000L));
+            lHold %= 60L * 1000L;
+            nSecs = (int)(lHold / 1000L);
+            nMilliseconds = (int)(lHold % 1000);
+            sRet = "" + nDays + " days " + nHours + " hours " + nMinutes + " minutes " + nSecs + " seconds " + nMilliseconds + " ms";
+            }
+
+        return (sRet);
+        }
+
+    public String GetUptimeMillis()
+        {
+        return Long.toString(SystemClock.uptimeMillis());
+        }
+ 
+    public String GetSutUptimeMillis()
+        {
+        long now = System.currentTimeMillis();
+        return "SUTagent running for "+Long.toString(now - SUTAgentAndroid.nCreateTimeMillis)+" ms";
+        }
+ 
+    public String NewKillProc(String sProcId, OutputStream out)
+        {
+        String sRet = "";
+
+        try
+            {
+            pProc = Runtime.getRuntime().exec("kill "+sProcId);
+            RedirOutputThread outThrd = new RedirOutputThread(pProc, out);
+            outThrd.start();
+            outThrd.joinAndStopRedirect(5000);
+            }
+        catch (IOException e)
+            {
+            sRet = e.getMessage();
+            e.printStackTrace();
+            }
+        catch (InterruptedException e)
+            {
+            e.printStackTrace();
+            }
+
+        return(sRet);
+        }
+
+    public String SendPing(String sIPAddr, OutputStream out)
+        {
+        String sRet = "";
+        String [] theArgs = new String [4];
+
+        theArgs[0] = "ping";
+        theArgs[1] = "-c";
+        theArgs[2] = "3";
+        theArgs[3] = sIPAddr;
+
+        try
+            {
+            pProc = Runtime.getRuntime().exec(theArgs);
+            RedirOutputThread outThrd = new RedirOutputThread(pProc, out);
+            outThrd.start();
+            outThrd.joinAndStopRedirect(5000);
+            if (out == null)
+                sRet = outThrd.strOutput;
+            }
+        catch (IOException e)
+            {
+            sRet = e.getMessage();
+            e.printStackTrace();
+            }
+        catch (InterruptedException e)
+            {
+            e.printStackTrace();
+            }
+
+        return (sRet);
+        }
+
+    public String GetTmpDir()
+    {
+        String     sRet = "";
+        Context ctx = contextWrapper.getApplicationContext();
+        File dir = ctx.getFilesDir();
+        ctx = null;
+        try {
+            sRet = dir.getCanonicalPath();
+            }
+        catch (IOException e)
+            {
+            e.printStackTrace();
+            }
+        return(sRet);
+    }
+
+    public String PrintFileTimestamp(String sFile)
+        {
+        String     sRet = "";
+        String    sTmpFileName = fixFileName(sFile);
+        long    lModified = -1;
+
+        if (sTmpFileName.contains("org.mozilla.fennec") || sTmpFileName.contains("org.mozilla.firefox")) {
+            ContentResolver cr = contextWrapper.getContentResolver();
+            Uri ffxFiles = Uri.parse("content://" + (sTmpFileName.contains("fennec") ? fenProvider : ffxProvider) + "/dir");
+
+            String[] columns = new String[] {
+                    "_id",
+                    "isdir",
+                    "filename",
+                    "length",
+                    "ts"
+                };
+
+            Cursor myCursor = cr.query(    ffxFiles,
+                                        columns,         // Which columns to return
+                                        sTmpFileName,   // Which rows to return (all rows)
+                                        null,           // Selection arguments (none)
+                                        null);            // Order clause (none)
+            if (myCursor != null) {
+                if (myCursor.getCount() > 0) {
+                    if (myCursor.moveToPosition(0)) {
+                        lModified = myCursor.getLong(myCursor.getColumnIndex("ts"));
+                    }
+                }
+                myCursor.close();
+            }
+        }
+        else {
+            File theFile = new File(sTmpFileName);
+
+            if (theFile.exists()) {
+                lModified = theFile.lastModified();
+            }
+        }
+
+        if (lModified != -1) {
+            Date dtModified = new Date(lModified);
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss:SSS");
+            sRet = "Last modified: " + sdf.format(dtModified);
+        }
+        else {
+            sRet = sErrorPrefix + "[" + sTmpFileName + "] doesn't exist";
+        }
+
+        return(sRet);
+        }
+
+    public String GetIniData(String sSection, String sKey, String sFile)
+        {
+        String sRet = "";
+        String sComp = "";
+        String sLine = "";
+        boolean bFound = false;
+        BufferedReader in = null;
+        String    sTmpFileName = fixFileName(sFile);
+
+        try {
+            in = new BufferedReader(new FileReader(sTmpFileName));
+            sComp = "[" + sSection + "]";
+            while ((sLine = in.readLine()) != null)
+                {
+                if (sLine.equalsIgnoreCase(sComp))
+                    {
+                    bFound = true;
+                    break;
+                    }
+                }
+
+            if (bFound)
+                {
+                sComp = (sKey + " =").toLowerCase();
+                while ((sLine = in.readLine()) != null)
+                    {
+                    if (sLine.toLowerCase().contains(sComp))
+                        {
+                        String [] temp = null;
+                        temp = sLine.split("=");
+                        if (temp != null)
+                            {
+                            if (temp.length > 1)
+                                sRet = temp[1].trim();
+                            }
+                        break;
+                        }
+                    }
+                }
+            in.close();
+            }
+        catch (FileNotFoundException e)
+            {
+            sComp = e.toString();
+            }
+        catch (IOException e)
+            {
+            sComp = e.toString();
+            }
+        return (sRet);
+        }
+
+    public String RunReboot(OutputStream out, String sCallBackIP, String sCallBackPort)
+        {
+        String sRet = "";
+        Context ctx = contextWrapper.getApplicationContext();
+
+        try {
+            if ((sCallBackIP != null) && (sCallBackPort != null) &&
+                (sCallBackIP.length() > 0) && (sCallBackPort.length() > 0))    {
+                FileOutputStream fos = ctx.openFileOutput("update.info", Context.MODE_WORLD_READABLE | Context.MODE_WORLD_WRITEABLE);
+                String sBuffer = sCallBackIP + "," + sCallBackPort + "\rSystem rebooted\r";
+                fos.write(sBuffer.getBytes());
+                fos.flush();
+                fos.close();
+                fos = null;
+            }
+        } catch (FileNotFoundException e) {
+            sRet = sErrorPrefix + "Callback file creation error [rebt] call failed " + e.getMessage();
+            e.printStackTrace();
+        } catch (IOException e) {
+            sRet = sErrorPrefix + "Callback file error [rebt] call failed " + e.getMessage();
+            e.printStackTrace();
+        }
+
+        try {
+            // Tell all of the data channels we are rebooting
+            ((ASMozStub)this.contextWrapper).SendToDataChannel("Rebooting ...");
+
+            pProc = Runtime.getRuntime().exec(this.getSuArgs("reboot"));
+            RedirOutputThread outThrd = new RedirOutputThread(pProc, out);
+            outThrd.start();
+            outThrd.joinAndStopRedirect(10000);
+        } catch (IOException e) {
+            sRet = e.getMessage();
+            e.printStackTrace();
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+
+        return (sRet);
+        }
+
+    private String [] getSuArgs(String cmdString)
+        {
+        String [] theArgs = new String [3];
+        theArgs[0] = "su";
+        theArgs[1] = "-c";
+        // as a security measure, ICS and later resets LD_LIBRARY_PATH. reset
+        // it here when executing the command
+        theArgs[2] = "LD_LIBRARY_PATH=/vendor/lib:/system/lib " + cmdString;
+        return theArgs;
+        }
+
+    public String UnInstallApp(String sApp, OutputStream out, boolean reboot)
+        {
+        String sRet = "";
+
+        try
+            {
+            if (reboot == true) {
+                pProc = Runtime.getRuntime().exec(this.getSuArgs("pm uninstall " + sApp + ";reboot;exit"));
+            } else {
+                pProc = Runtime.getRuntime().exec(this.getSuArgs("pm uninstall " + sApp + ";exit"));
+            }
+
+            RedirOutputThread outThrd = new RedirOutputThread(pProc, out);
+            outThrd.start();
+            try {
+                outThrd.joinAndStopRedirect(60000);
+                int nRet = pProc.exitValue();
+                sRet = "\nuninst complete [" + nRet + "]";
+                }
+            catch (IllegalThreadStateException itse) {
+                itse.printStackTrace();
+                sRet = "\nuninst command timed out";
+                }
+            }
+        catch (IOException e)
+            {
+            sRet = e.getMessage();
+            e.printStackTrace();
+            }
+        catch (InterruptedException e)
+            {
+            e.printStackTrace();
+            }
+
+        return (sRet);
+    }
+
+    public String InstallApp(String sApp, OutputStream out)
+        {
+        String sRet = "";
+        File    srcFile = new File(sApp);
+
+        try
+            {
+            // on android 4.2 and above, we want to pass the "-d" argument to pm so that version
+            // downgrades are allowed... (option unsupported in earlier versions)
+            String sPmCmd;
+
+            if (android.os.Build.VERSION.SDK_INT >= 17) { // JELLY_BEAN_MR1
+                sPmCmd = "pm install -r -d " + sApp + " Cleanup;exit";
+            } else {
+                sPmCmd = "pm install -r " + sApp + " Cleanup;exit";
+            }
+            pProc = Runtime.getRuntime().exec(this.getSuArgs(sPmCmd));
+            RedirOutputThread outThrd3 = new RedirOutputThread(pProc, out);
+            outThrd3.start();
+            try {
+                outThrd3.joinAndStopRedirect(60000);
+                int nRet3 = pProc.exitValue();
+                if (nRet3 == 0) {
+                    sRet = "\ninstallation complete [0]\n";
+                }
+                else {
+                    sRet = "\nFailure pm install [" + nRet3 + "]\n";
+                }
+                }
+            catch (IllegalThreadStateException itse) {
+                itse.printStackTrace();
+                sRet = "\nFailure pm install command timed out\n";
+            }
+            try {
+                out.write(sRet.getBytes());
+                out.flush();
+                }
+            catch (IOException e1)
+                {
+                e1.printStackTrace();
+                }
+            }
+        catch (IOException e)
+            {
+            sRet = e.getMessage();
+            e.printStackTrace();
+            }
+        catch (InterruptedException e)
+            {
+            e.printStackTrace();
+            }
+
+        return (sRet);
+        }
+
+    public String StrtUpdtOMatic(String sPkgName, String sPkgFileName, String sCallBackIP, String sCallBackPort)
+        {
+        String sRet = "";
+
+        Context ctx = contextWrapper.getApplicationContext();
+        PackageManager pm = ctx.getPackageManager();
+
+        Intent prgIntent = new Intent();
+        prgIntent.setPackage("com.mozilla.watcher");
+
+        try {
+            PackageInfo pi = pm.getPackageInfo("com.mozilla.watcher", PackageManager.GET_SERVICES | PackageManager.GET_INTENT_FILTERS);
+            ServiceInfo [] si = pi.services;
+            for (int i = 0; i < si.length; i++)
+                {
+                ServiceInfo s = si[i];
+                if (s.name.length() > 0)
+                    {
+                    prgIntent.setClassName(s.packageName, s.name);
+                    break;
+                    }
+                }
+            }
+        catch (NameNotFoundException e)
+            {
+            e.printStackTrace();
+            sRet = sErrorPrefix + "watcher is not properly installed";
+            return(sRet);
+            }
+
+        prgIntent.putExtra("command", "updt");
+        prgIntent.putExtra("pkgName", sPkgName);
+        prgIntent.putExtra("pkgFile", sPkgFileName);
+        prgIntent.putExtra("reboot", true);
+
+        try
+            {
+            if ((sCallBackIP != null) && (sCallBackPort != null) &&
+                (sCallBackIP.length() > 0) && (sCallBackPort.length() > 0))
+                {
+                FileOutputStream fos = ctx.openFileOutput("update.info", Context.MODE_WORLD_READABLE | Context.MODE_WORLD_WRITEABLE);
+                String sBuffer = sCallBackIP + "," + sCallBackPort + "\rupdate started " + sPkgName + " " + sPkgFileName + "\r";
+                fos.write(sBuffer.getBytes());
+                fos.flush();
+                fos.close();
+                fos = null;
+                prgIntent.putExtra("outFile", ctx.getFilesDir() + "/update.info");
+                }
+            else {
+                if (prgIntent.hasExtra("outFile")) {
+                    System.out.println("outFile extra unset from intent");
+                    prgIntent.removeExtra("outFile");
+                }
+            }
+
+            ComponentName cn = contextWrapper.startService(prgIntent);
+            if (cn != null)
+                sRet = "exit";
+            else
+                sRet = sErrorPrefix + "Unable to use watcher service";
+            }
+        catch(ActivityNotFoundException anf)
+            {
+            sRet = sErrorPrefix + "Activity Not Found Exception [updt] call failed";
+            anf.printStackTrace();
+            }
+        catch (FileNotFoundException e)
+            {
+            sRet = sErrorPrefix + "File creation error [updt] call failed";
+            e.printStackTrace();
+            }
+        catch (IOException e)
+            {
+            sRet = sErrorPrefix + "File error [updt] call failed";
+            e.printStackTrace();
+            }
+
+        ctx = null;
+
+        return (sRet);
+        }
+
+    public String StartJavaPrg(String [] sArgs, Intent preIntent)
+        {
+        String sRet = "";
+        String sArgList = "";
+        String sUrl = "";
+//        String sRedirFileName = "";
+        Intent prgIntent = null;
+
+        Context ctx = contextWrapper.getApplicationContext();
+        PackageManager pm = ctx.getPackageManager();
+
+        if (preIntent == null)
+            prgIntent = new Intent();
+        else
+            prgIntent = preIntent;
+
+        prgIntent.setPackage(sArgs[0]);
+        prgIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+        // Get the main activity for this package
+        try {
+            final ComponentName c = pm.getLaunchIntentForPackage(sArgs[0]).getComponent();
+            prgIntent.setClassName(c.getPackageName(), c.getClassName());
+        } catch (Exception e) {
+            e.printStackTrace();
+            return "Unable to find main activity for package: " + sArgs[0];
+        }
+
+        if (sArgs.length > 1)
+            {
+            if (sArgs[0].contains("android.browser"))
+                prgIntent.setAction(Intent.ACTION_VIEW);
+            else
+                prgIntent.setAction(Intent.ACTION_MAIN);
+
+            if (sArgs[0].contains("fennec") || sArgs[0].contains("firefox"))
+                {
+                sArgList = "";
+                sUrl = "";
+
+                for (int lcv = 1; lcv < sArgs.length; lcv++)
+                    {
+                    if (sArgs[lcv].contains("://"))
+                        {
+                        prgIntent.setAction(Intent.ACTION_VIEW);
+                        sUrl = sArgs[lcv];
+                        }
+                    else
+                        {
+                        if (sArgs[lcv].equals(">"))
+                            {
+                            lcv++;
+                            if (lcv < sArgs.length)
+                                lcv++;
+//                                sRedirFileName = sArgs[lcv++];
+                            }
+                        else
+                            sArgList += " " + sArgs[lcv];
+                        }
+                    }
+
+                if (sArgList.length() > 0)
+                    prgIntent.putExtra("args", sArgList.trim());
+
+                if (sUrl.length() > 0)
+                    prgIntent.setData(Uri.parse(sUrl.trim()));
+                }
+            else
+                {
+                for (int lcv = 1; lcv < sArgs.length; lcv++)
+                    sArgList += " " + sArgs[lcv];
+
+                prgIntent.setData(Uri.parse(sArgList.trim()));
+                }
+            }
+        else
+            {
+            prgIntent.setAction(Intent.ACTION_MAIN);
+            }
+
+        try
+            {
+            contextWrapper.startActivity(prgIntent);
+            FindProcThread findProcThrd = new FindProcThread(contextWrapper, sArgs[0]);
+            findProcThrd.start();
+            findProcThrd.join(7000);
+            if (!findProcThrd.bFoundIt && !findProcThrd.bStillRunning) {
+                sRet = "Unable to start " + sArgs[0] + "";
+                }
+            }
+        catch(ActivityNotFoundException anf)
+            {
+            anf.printStackTrace();
+            }
+        catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+
+        ctx = null;
+        return (sRet);
+        }
+
+    public String StartPrg(String [] progArray, OutputStream out, boolean startAsRoot, int timeoutSeconds)
+        {
+        String sRet = "";
+        int    lcv = 0;
+
+        try {
+            if (startAsRoot)
+                {
+                    // we need to requote the program string here, in case
+                    // there's spaces or other characters which need quoting
+                    // before being passed to su
+                    List<String> quotedProgList = new ArrayList<String>();
+                    for (String arg : progArray)
+                        {
+                            String quotedArg = arg;
+                            quotedArg = quotedArg.replace("\"", "\\\"");
+                            quotedArg = quotedArg.replace("\'", "\\\'");
+                            if (quotedArg.contains(" "))
+                                {
+                                    quotedArg = "\"" + quotedArg + "\"";
+                                }
+                            quotedProgList.add(quotedArg);
+                        }
+                    pProc = Runtime.getRuntime().exec(this.getSuArgs(TextUtils.join(" ", quotedProgList)));
+                }
+            else
+                {
+                    pProc = Runtime.getRuntime().exec(progArray);
+                }
+            RedirOutputThread outThrd = new RedirOutputThread(pProc, out);
+            outThrd.start();
+            try {
+                outThrd.join(timeoutSeconds * 1000);
+                int nRetCode = pProc.exitValue();
+                sRet = "return code [" + nRetCode + "]";
+                }
+            catch (IllegalThreadStateException itse) {
+                }
+            outThrd.stopRedirect();
+            }
+        catch (IOException e)
+            {
+            e.printStackTrace();
+            }
+        catch (InterruptedException e)
+            {
+            e.printStackTrace();
+            sRet = "Timed out!";
+            }
+
+        return (sRet);
+        }
+
+    public String StartPrg2(String [] progArray, OutputStream out, String cwd, boolean startAsRoot, int timeoutSeconds)
+        {
+        String sRet = "";
+
+        int    nArraySize = 0;
+        int    nArgs = progArray.length - 1; // 1st arg is the environment string
+        int    lcv    = 0;
+        int    temp = 0;
+
+        String sEnvString = progArray[0];
+
+        if (!sEnvString.contains("=") && (sEnvString.length() > 0))
+            {
+            if (sEnvString.contains("/") || sEnvString.contains("\\") || !sEnvString.contains("."))
+                sRet = StartPrg(progArray, out, startAsRoot, timeoutSeconds);
+            else
+                sRet = StartJavaPrg(progArray, null);
+            return(sRet);
+            }
+
+        // Set up command line args stripping off the environment string
+        String [] theArgs = new String [nArgs];
+        for (lcv = 0; lcv < nArgs; lcv++)
+            {
+            theArgs[lcv] = progArray[lcv + 1];
+            }
+
+        try
+            {
+            String [] envStrings = sEnvString.split(",");
+            Map<String, String> newEnv = new HashMap<String, String>();
+
+            for (lcv = 0; lcv < envStrings.length; lcv++)
+                {
+                temp = envStrings[lcv].indexOf("=");
+                if (temp > 0)
+                    {
+                    newEnv.put(    envStrings[lcv].substring(0, temp),
+                                envStrings[lcv].substring(temp + 1, envStrings[lcv].length()));
+                    }
+                }
+
+            Map<String, String> sysEnv = System.getenv();
+
+            nArraySize = sysEnv.size();
+
+            for (Map.Entry<String, String> entry : newEnv.entrySet())
+                {
+                if (!sysEnv.containsKey(entry.getKey()))
+                    {
+                    nArraySize++;
+                    }
+                }
+
+            String[] envArray = new String[nArraySize];
+
+            int        i = 0;
+            int        offset;
+            String    sKey = "";
+            String     sValue = "";
+
+            for (Map.Entry<String, String> entry : sysEnv.entrySet())
+                {
+                sKey = entry.getKey();
+                if (newEnv.containsKey(sKey))
+                    {
+                    sValue = newEnv.get(sKey);
+                    if ((offset = sValue.indexOf("$" + sKey)) != -1)
+                        {
+                        envArray[i++] = sKey +
+                                        "=" +
+                                        sValue.substring(0, offset) +
+                                        entry.getValue() +
+                                        sValue.substring(offset + sKey.length() + 1);
+                        }
+                    else
+                        envArray[i++] = sKey + "=" + sValue;
+                    newEnv.remove(sKey);
+                    }
+                else
+                    envArray[i++] = entry.getKey() + "=" + entry.getValue();
+                }
+
+            for (Map.Entry<String, String> entry : newEnv.entrySet())
+                {
+                envArray[i++] = entry.getKey() + "=" + entry.getValue();
+                }
+
+            if (theArgs[0].contains("/") || theArgs[0].contains("\\") || !theArgs[0].contains("."))
+                {
+                if (cwd != null)
+                    {
+                    File f = new File(cwd);
+                    pProc = Runtime.getRuntime().exec(theArgs, envArray, f);
+                    }
+                else
+                    {
+                    pProc = Runtime.getRuntime().exec(theArgs, envArray);
+                    }
+
+                RedirOutputThread outThrd = new RedirOutputThread(pProc, out);
+                outThrd.start();
+
+                try {
+                    outThrd.join(timeoutSeconds * 1000);
+                    int nRetCode = pProc.exitValue();
+                    sRet = "return code [" + nRetCode + "]";
+                    }
+                catch (IllegalThreadStateException itse) {
+                    }
+                outThrd.stopRedirect();
+                }
+            else
+                {
+                Intent preIntent = new Intent();
+                for (lcv = 0; lcv < envArray.length; lcv++)
+                    {
+                    preIntent.putExtra("env" + lcv, envArray[lcv]);
+                    }
+                sRet = StartJavaPrg(theArgs, preIntent);
+                }
+            }
+        catch(UnsupportedOperationException e)
+            {
+            if (e != null)
+                e.printStackTrace();
+            }
+        catch(ClassCastException e)
+            {
+            if (e != null)
+                e.printStackTrace();
+            }
+        catch(IllegalArgumentException e)
+            {
+            if (e != null)
+                e.printStackTrace();
+            }
+        catch(NullPointerException e)
+            {
+            if (e != null)
+                e.printStackTrace();
+            }
+        catch (IOException e)
+            {
+            e.printStackTrace();
+            }
+        catch (InterruptedException e)
+            {
+            e.printStackTrace();
+            sRet = "Timed out!";
+            }
+
+        return (sRet);
+        }
+
+    public String ChmodDir(String sDir)
+        {
+        String sRet = "";
+        int nFiles = 0;
+        String sSubDir = null;
+        String sTmpDir = fixFileName(sDir);
+
+        File dir = new File(sTmpDir);
+
+        if (dir.isDirectory()) {
+            sRet = "Changing permissions for " + sTmpDir;
+
+            File [] files = dir.listFiles();
+            if (files != null) {
+                if ((nFiles = files.length) > 0) {
+                    for (int lcv = 0; lcv < nFiles; lcv++) {
+                        if (files[lcv].isDirectory()) {
+                            sSubDir = files[lcv].getAbsolutePath();
+                            sRet += "\n" + ChmodDir(sSubDir);
+                        }
+                        else {
+                            // set the new file's permissions to rwxrwxrwx, if possible
+                            try {
+                                Process pProc = Runtime.getRuntime().exec(this.getSuArgs("chmod 777 "+files[lcv]));
+                                RedirOutputThread outThrd = new RedirOutputThread(pProc, null);
+                                outThrd.start();
+                                outThrd.joinAndStopRedirect(5000);
+                                sRet += "\n\tchmod " + files[lcv].getName() + " ok";
+                            } catch (InterruptedException e) {
+                                sRet += "\n\ttimeout waiting for chmod " + files[lcv].getName();
+                            } catch (IOException e) {
+                                sRet += "\n\tunable to chmod " + files[lcv].getName();
+                            }
+                        }
+                    }
+                }
+                else
+                    sRet += "\n\t<empty>";
+                }
+            }
+
+        // set the new directory's (or file's) permissions to rwxrwxrwx, if possible
+        try {
+            Process pProc = Runtime.getRuntime().exec(this.getSuArgs("chmod 777 "+sTmpDir));
+            RedirOutputThread outThrd = new RedirOutputThread(pProc, null);
+            outThrd.start();
+            outThrd.joinAndStopRedirect(5000);
+            sRet += "\n\tchmod " + sTmpDir + " ok";
+        } catch (InterruptedException e) {
+            sRet += "\n\ttimeout waiting for chmod " + sTmpDir;
+        } catch (IOException e) {
+            sRet += "\n\tunable to chmod " + sTmpDir;
+        }
+
+        return(sRet);
+        }
+
+    public String TopActivity()
+        {
+        String sRet = "";
+        ActivityManager aMgr = (ActivityManager) contextWrapper.getSystemService(Activity.ACTIVITY_SERVICE);
+        List< ActivityManager.RunningTaskInfo > taskInfo = null;
+        ComponentName componentInfo = null;
+        if (aMgr != null)
+            {
+            taskInfo = aMgr.getRunningTasks(1);
+            }
+        if (taskInfo != null)
+            {
+            // topActivity: "The activity component at the top of the history stack of the task.
+            // This is what the user is currently doing."
+            componentInfo = taskInfo.get(0).topActivity;
+            }
+        if (componentInfo != null)
+            {
+            sRet = componentInfo.getPackageName();
+            }
+        return(sRet);
+        }
+
+    private String PrintUsage()
+        {
+        String sRet =
+            "run [cmdline]                   - start program no wait\n" +
+            "exec [env pairs] [cmdline]      - start program no wait optionally pass env\n" +
+            "                                  key=value pairs (comma separated)\n" +
+            "execcwd <dir> [env pairs] [cmdline] - start program from specified directory\n" +
+            "execsu [env pairs] [cmdline]    - start program as privileged user\n" +
+            "execcwdsu <dir> [env pairs] [cmdline] - start program from specified directory as privileged user\n" +
+            "execext [su] [cwd=<dir>] [t=<timeout>] [env pairs] [cmdline] - start program with extended options\n" +
+            "kill [program name]             - kill program no path\n" +
+            "killall                         - kill all processes started\n" +
+            "ps                              - list of running processes\n" +
+            "info                            - list of device info\n" +
+            "        [os]                    - os version for device\n" +
+            "        [id]                    - unique identifier for device\n" +
+            "        [uptime]                - uptime for device\n" +
+            "        [uptimemillis]          - uptime for device in milliseconds\n" +
+            "        [sutuptimemillis]       - uptime for SUT in milliseconds\n" +
+            "        [systime]               - current system time\n" +
+            "        [screen]                - width, height and bits per pixel for device\n" +
+            "        [memory]                - physical, free, available, storage memory\n" +
+            "                                  for device\n" +
+            "        [processes]             - list of running processes see 'ps'\n" +
+            "alrt [on/off]                   - start or stop sysalert behavior\n" +
+            "disk [arg]                      - prints disk space info\n" +
+            "cp file1 file2                  - copy file1 to file2\n" +
+            "time file                       - timestamp for file\n" +
+            "hash file                       - generate hash for file\n" +
+            "cd directory                    - change cwd\n" +
+            "cat file                        - cat file\n" +
+            "cwd                             - display cwd\n" +
+            "mv file1 file2                  - move file1 to file2\n" +
+            "push filename                   - push file to device\n" +
+            "rm file                         - delete file\n" +
+            "rmdr directory                  - delete directory even if not empty\n" +
+            "mkdr directory                  - create directory\n" +
+            "dirw directory                  - tests whether the directory is writable\n" +
+            "isdir directory                 - test whether the directory exists\n" +
+            "chmod directory|file            - change permissions of directory and contents (or file) to 777\n" +
+            "stat processid                  - stat process\n" +
+            "dead processid                  - print whether the process is alive or hung\n" +
+            "mems                            - dump memory stats\n" +
+            "ls                              - print directory\n" +
+            "tmpd                            - print temp directory\n" +
+            "ping [hostname/ipaddr]          - ping a network device\n" +
+            "unzp zipfile destdir            - unzip the zipfile into the destination dir\n" +
+            "zip zipfile src                 - zip the source file/dir into zipfile\n" +
+            "rebt                            - reboot device\n" +
+            "inst /path/filename.apk         - install the referenced apk file\n" +
+            "uninst packagename              - uninstall the referenced package and reboot\n" +
+            "uninstall packagename           - uninstall the referenced package without a reboot\n" +
+            "updt pkgname pkgfile            - unpdate the referenced package\n" +
+            "clok                            - the current device time expressed as the" +
+            "                                  number of millisecs since epoch\n" +
+            "settime date time               - sets the device date and time\n" +
+            "                                  (YYYY/MM/DD HH:MM:SS)\n" +
+            "tzset timezone                  - sets the device timezone format is\n" +
+            "                                  GMTxhh:mm x = +/- or a recognized Olsen string\n" +
+            "tzget                           - returns the current timezone set on the device\n" +
+            "rebt                            - reboot device\n" +
+            "adb ip|usb                      - set adb to use tcp/ip on port 5555 or usb\n" +
+            "activity                        - print package name of top (foreground) activity\n" +
+            "quit                            - disconnect SUTAgent\n" +
+            "exit                            - close SUTAgent\n" +
+            "ver                             - SUTAgent version\n" +
+            "help                            - you're reading it";
+        return (sRet);
+        }
+}
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/FindProcThread.java b/src/third_party/mozjs-45/build/mobile/sutagent/android/FindProcThread.java
new file mode 100644
index 0000000..f62d3b7
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/FindProcThread.java
@@ -0,0 +1,68 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package com.mozilla.SUTAgentAndroid.service;
+
+import java.util.List;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.content.ContextWrapper;
+
+public class FindProcThread extends Thread {
+    ContextWrapper    contextWrapper = null;
+    String sProcNameToFind = "";
+    boolean bFoundIt = false;
+    boolean bStillRunning = true;
+
+    public FindProcThread(ContextWrapper ctx, String sProcessName) {
+        super("FindProcThread");
+        this.contextWrapper = ctx;
+        this.sProcNameToFind = sProcessName;
+        this.bFoundIt = false;
+    }
+
+    public void run() {
+        ActivityManager aMgr = (ActivityManager) contextWrapper.getSystemService(Activity.ACTIVITY_SERVICE);
+        List <ActivityManager.RunningAppProcessInfo> lProcesses;
+        int lcv = 0;
+        int nNumLoops = 0;
+        String strProcName = "";
+        int    nPID = 0;
+
+        if (aMgr == null)
+            return;
+
+
+        // While we are still looping looking for the process in the list and we haven't found it
+        while (bStillRunning && !bFoundIt) {
+            lProcesses = aMgr.getRunningAppProcesses();
+            if (lProcesses != null) {
+                for (lcv = 0; lcv < lProcesses.size(); lcv++) {
+                    if (lProcesses.get(lcv).processName.contains(sProcNameToFind)) {
+                        strProcName = lProcesses.get(lcv).processName;
+                        nPID = lProcesses.get(lcv).pid;
+                        bFoundIt = true;
+                        break;
+                    }
+                }
+                if (bFoundIt)             // This saves you half a second of wait time if we've found it in the list
+                    continue;
+            }
+            try {
+                Thread.sleep(500);         // Sleep half a second
+                if (++nNumLoops > 10) { // loop up to 10 times
+                    bStillRunning = false;
+                }
+                lProcesses = null;
+                System.gc();
+                Thread.yield();
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+                bStillRunning = false;
+            }
+        }
+    }
+
+}
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/Makefile.in b/src/third_party/mozjs-45/build/mobile/sutagent/android/Makefile.in
new file mode 100644
index 0000000..51e93a0
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/Makefile.in
@@ -0,0 +1,28 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+include $(topsrcdir)/config/config.mk
+
+JAVAFILES = \
+  AlertLooperThread.java \
+  ASMozStub.java \
+  CmdWorkerThread.java \
+  DataWorkerThread.java \
+  DoAlert.java \
+  DoCommand.java \
+  FindProcThread.java \
+  Power.java \
+  RedirOutputThread.java \
+  RunCmdThread.java \
+  RunDataThread.java \
+  SUTAgentAndroid.java \
+  WifiConfiguration.java \
+  $(NULL)
+
+ANDROID_EXTRA_JARS = \
+  $(srcdir)/network-libs/commons-net-2.0.jar \
+  $(srcdir)/network-libs/jmdns.jar \
+  $(NULL)
+
+tools:: $(ANDROID_APK_NAME).apk
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/Power.java b/src/third_party/mozjs-45/build/mobile/sutagent/android/Power.java
new file mode 100755
index 0000000..47497e5
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/Power.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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.
+ */
+
+package android.os;
+
+import java.io.IOException;
+
+/**
+ * Class that provides access to some of the power management functions.
+ *
+ * {@hide}
+ */
+public class Power
+{
+    // can't instantiate this class
+    private Power()
+    {
+    }
+
+    /**
+     * Wake lock that ensures that the CPU is running.  The screen might
+     * not be on.
+     */
+    public static final int PARTIAL_WAKE_LOCK = 1;
+
+    /**
+     * Wake lock that ensures that the screen is on.
+     */
+    public static final int FULL_WAKE_LOCK = 2;
+
+    public static native void acquireWakeLock(int lock, String id);
+    public static native void releaseWakeLock(String id);
+
+    /**
+     * Brightness value for fully off
+     */
+    public static final int BRIGHTNESS_OFF = 0;
+
+    /**
+     * Brightness value for dim backlight
+     */
+    public static final int BRIGHTNESS_DIM = 20;
+
+    /**
+     * Brightness value for fully on
+     */
+    public static final int BRIGHTNESS_ON = 255;
+
+    /**
+     * Brightness value to use when battery is low
+     */
+    public static final int BRIGHTNESS_LOW_BATTERY = 10;
+
+    /**
+     * Threshold for BRIGHTNESS_LOW_BATTERY (percentage)
+     * Screen will stay dim if battery level is <= LOW_BATTERY_THRESHOLD
+     */
+    public static final int LOW_BATTERY_THRESHOLD = 10;
+
+    /**
+     * Turn the screen on or off
+     *
+     * @param on Whether you want the screen on or off
+     */
+    public static native int setScreenState(boolean on);
+
+    public static native int setLastUserActivityTimeout(long ms);
+
+    /**
+     * Turn the device off.
+     *
+     * This method is considered deprecated in favor of
+     * {@link android.policy.ShutdownThread.shutdownAfterDisablingRadio()}.
+     *
+     * @deprecated
+     * @hide
+     */
+    @Deprecated
+    public static native void shutdown();
+
+    /**
+     * Reboot the device.
+     * @param reason code to pass to the kernel (e.g. "recovery"), or null.
+     *
+     * @throws IOException if reboot fails for some reason (eg, lack of
+     *         permission)
+     */
+    public static native void reboot(String reason) throws IOException;
+}
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/RedirOutputThread.java b/src/third_party/mozjs-45/build/mobile/sutagent/android/RedirOutputThread.java
new file mode 100755
index 0000000..a70bcdd
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/RedirOutputThread.java
@@ -0,0 +1,197 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package com.mozilla.SUTAgentAndroid.service;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+
+public class RedirOutputThread extends Thread
+    {
+    OutputStream out;
+    InputStream    sutErr;
+    InputStream    sutOut;
+    Process pProc;
+    String    strOutput;
+    int    nExitCode = -1;
+    private volatile boolean stopRedirRequested = false;
+    private volatile boolean redirStopped = false;
+
+    public RedirOutputThread(Process pProc, OutputStream out)
+        {
+        super("RedirOutputThread");
+        if (pProc != null)
+            {
+            this.pProc = pProc;
+            sutErr = pProc.getErrorStream(); // Stderr
+            sutOut = pProc.getInputStream(); // Stdout
+            }
+        if (out != null)
+            this.out = out;
+
+        strOutput = "";
+        }
+
+    public void run()
+        {
+        boolean bStillRunning = true;
+        int    nBytesOut = 0;
+        int nBytesErr = 0;
+        int nBytesRead = 0;
+        PrintWriter pOut = null;
+        byte[] buffer = new byte[1024];
+
+        if (out != null)
+            pOut = new PrintWriter(out);
+        else
+            bStillRunning = true;
+
+        while (bStillRunning)
+            {
+            try
+                {
+                // If there's no output to collect, sleep for a while
+                // rather than checking again immediately, to avoid 
+                // using up cpu capacity in a tight loop.
+                if (sutOut.available() == 0 && sutErr.available() == 0)
+                    {
+                    Thread.sleep(50);
+                    }
+                if ((nBytesOut = sutOut.available()) > 0)
+                    {
+                    if (nBytesOut > buffer.length)
+                        {
+                        buffer = null;
+                        System.gc();
+                        buffer = new byte[nBytesOut];
+                        }
+                    nBytesRead = sutOut.read(buffer, 0, nBytesOut);
+                    if (nBytesRead == -1)
+                        bStillRunning = false;
+                    else
+                        {
+                        String sRep = new String(buffer,0,nBytesRead).replace("\n", "\r\n");
+                        if (pOut != null)
+                            {
+                            pOut.print(sRep);
+                            pOut.flush();
+                            }
+                        else
+                            strOutput += sRep;
+                        }
+                    }
+
+                if ((nBytesErr = sutErr.available()) > 0)
+                    {
+                    if (nBytesErr > buffer.length)
+                        {
+                        buffer = null;
+                        System.gc();
+                        buffer = new byte[nBytesErr];
+                        }
+                    nBytesRead = sutErr.read(buffer, 0, nBytesErr);
+                    if (nBytesRead == -1)
+                        bStillRunning = false;
+                    else
+                        {
+                        String sRep = new String(buffer,0,nBytesRead).replace("\n", "\r\n");
+                        if (pOut != null)
+                            {
+                            pOut.print(sRep);
+                            pOut.flush();
+                            }
+                        else
+                            strOutput += sRep;
+                        }
+                    }
+
+                bStillRunning = (stopRedirRequested == false) &&
+                    (IsProcRunning(pProc) || (sutOut.available() > 0) || (sutErr.available() > 0));
+                }
+            catch (IOException e)
+                {
+                e.printStackTrace();
+                }
+            catch (java.lang.IllegalArgumentException e)
+                {
+                // Bug 743766: InputStream.available() unexpectedly throws this sometimes
+                e.printStackTrace();
+                }
+            catch (InterruptedException e) 
+                {
+                e.printStackTrace();
+                }
+            }
+
+        // notify stopRedirect that redirection has stopped
+        redirStopped = true;
+        if (stopRedirRequested)
+            {
+            synchronized(this) 
+                {
+                notifyAll();
+                }
+            }
+
+        // wait for process to end; if it has not already ended, then destroy it
+        try
+            {
+            pProc.waitFor();
+            }
+        catch (InterruptedException e) 
+            {
+            e.printStackTrace();
+            pProc.destroy();
+            }
+        buffer = null;
+        System.gc();
+        }
+
+    private boolean IsProcRunning(Process pProc)
+        {
+        boolean bRet = false;
+
+        try
+            {
+            nExitCode = pProc.exitValue();
+            }
+        catch (IllegalThreadStateException z)
+            {
+            nExitCode = -1;
+            bRet = true;
+            }
+
+        return(bRet);
+        }
+
+    public synchronized void stopRedirect()
+        {
+        stopRedirRequested = true;
+        // wait for notification that redirection has stopped
+        if (!redirStopped)
+            {
+            try 
+                {
+                // max wait time is somewhat arbitrary and provided "just in case";
+                // we expect to be notified as soon as run() completes its current
+                // sleep and checks the stopRedirRequested flag
+                wait(500);
+                }
+            catch (InterruptedException e) 
+                {
+                e.printStackTrace();
+                }
+            }
+        }
+
+    public void joinAndStopRedirect(long millis) throws InterruptedException
+        {
+        super.join(millis);
+        if (out != null)
+            stopRedirect();
+        }
+
+    }
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/RunCmdThread.java b/src/third_party/mozjs-45/build/mobile/sutagent/android/RunCmdThread.java
new file mode 100755
index 0000000..a0293c4
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/RunCmdThread.java
@@ -0,0 +1,278 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package com.mozilla.SUTAgentAndroid.service;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketTimeoutException;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.mozilla.SUTAgentAndroid.R;
+import com.mozilla.SUTAgentAndroid.SUTAgentAndroid;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Handler;
+
+public class RunCmdThread extends Thread
+    {
+    private ServerSocket SvrSocket = null;
+    private Socket socket    = null;
+    private Handler handler = null;
+    boolean bListening    = true;
+    boolean bNetError = false;
+    List<CmdWorkerThread> theWorkers = new ArrayList<CmdWorkerThread>();
+    android.app.Service    svc = null;
+
+    public RunCmdThread(ServerSocket socket, android.app.Service service, Handler handler)
+        {
+        super("RunCmdThread");
+        this.SvrSocket = socket;
+        this.svc = service;
+        this.handler = handler;
+        }
+
+    public void StopListening()
+        {
+        bListening = false;
+        }
+
+    public void run() {
+        try {
+            SvrSocket.setSoTimeout(5000);
+            while (bListening)
+                {
+                try
+                    {
+                    socket = SvrSocket.accept();
+                    CmdWorkerThread theWorker = new CmdWorkerThread(this, socket);
+                    theWorker.start();
+                    theWorkers.add(theWorker);
+                    }
+                catch (SocketTimeoutException toe)
+                    {
+                    continue;
+                    }
+                catch (IOException e)
+                    {
+                    e.printStackTrace();
+                    continue;
+                    }
+                }
+
+            int nNumWorkers = theWorkers.size();
+            for (int lcv = 0; lcv < nNumWorkers; lcv++)
+                {
+                if (theWorkers.get(lcv).isAlive())
+                    {
+                    theWorkers.get(lcv).StopListening();
+                    while(theWorkers.get(lcv).isAlive())
+                        ;
+                    }
+                }
+
+            theWorkers.clear();
+
+            SvrSocket.close();
+
+            svc.stopSelf();
+
+//            SUTAgentAndroid.me.finish();
+            }
+        catch (IOException e)
+            {
+            e.printStackTrace();
+            }
+        return;
+        }
+
+    private String SendPing(String sIPAddr)
+        {
+        Process    pProc;
+        String sRet = "";
+        String [] theArgs = new String [4];
+        boolean bStillRunning = true;
+        int    nBytesOut = 0;
+        int nBytesErr = 0;
+        int nBytesRead = 0;
+        byte[] buffer = new byte[1024];
+
+        theArgs[0] = "ping";
+        theArgs[1] = "-c";
+        theArgs[2] = "3";
+        theArgs[3] = sIPAddr;
+
+        try
+            {
+            pProc = Runtime.getRuntime().exec(theArgs);
+
+            InputStream sutOut = pProc.getInputStream();
+            InputStream sutErr = pProc.getErrorStream();
+
+            while (bStillRunning)
+                {
+                try
+                    {
+                    if ((nBytesOut = sutOut.available()) > 0)
+                        {
+                        if (nBytesOut > buffer.length)
+                            {
+                            buffer = null;
+                            System.gc();
+                            buffer = new byte[nBytesOut];
+                            }
+                        nBytesRead = sutOut.read(buffer, 0, nBytesOut);
+                        if (nBytesRead == -1)
+                            bStillRunning = false;
+                        else
+                            {
+                            String sRep = new String(buffer,0,nBytesRead).replace("\n", "\r\n");
+                            sRet += sRep;
+                            sRep = null;
+                            }
+                        }
+
+                    if ((nBytesErr = sutErr.available()) > 0)
+                        {
+                        if (nBytesErr > buffer.length)
+                            {
+                            buffer = null;
+                            System.gc();
+                            buffer = new byte[nBytesErr];
+                            }
+                        nBytesRead = sutErr.read(buffer, 0, nBytesErr);
+                        if (nBytesRead == -1)
+                            bStillRunning = false;
+                        else
+                            {
+                            String sRep = new String(buffer,0,nBytesRead).replace("\n", "\r\n");
+                            sRet += sRep;
+                            sRep = null;
+                            }
+                        }
+
+                    bStillRunning = (IsProcRunning(pProc) || (sutOut.available() > 0) || (sutErr.available() > 0));
+                    }
+                catch (IOException e)
+                    {
+                    e.printStackTrace();
+                    }
+
+                if ((bStillRunning == true) && (nBytesErr == 0) && (nBytesOut == 0))
+                    {
+                    try {
+                        sleep(2000);
+                        }
+                    catch (InterruptedException e) {
+                        e.printStackTrace();
+                        }
+                    }
+                }
+
+            pProc.destroy();
+            pProc = null;
+            }
+        catch (IOException e)
+            {
+            sRet = e.getMessage();
+            e.printStackTrace();
+            }
+
+        return (sRet);
+        }
+
+    private boolean IsProcRunning(Process pProc)
+        {
+        boolean bRet = false;
+        @SuppressWarnings("unused")
+        int nExitCode = 0;
+
+        try
+            {
+            nExitCode = pProc.exitValue();
+            }
+        catch (IllegalThreadStateException z)
+            {
+            bRet = true;
+            }
+        catch (Exception e)
+            {
+            e.printStackTrace();
+            }
+
+        return(bRet);
+        }
+
+    private void SendNotification(String tickerText, String expandedText)
+        {
+        NotificationManager notificationManager = (NotificationManager)svc.getSystemService(Context.NOTIFICATION_SERVICE);
+
+//        int icon = android.R.drawable.stat_notify_more;
+//        int icon = R.drawable.ic_stat_first;
+//        int icon = R.drawable.ic_stat_second;
+//        int icon = R.drawable.ic_stat_neterror;
+        int icon = R.drawable.ateamlogo;
+        long when = System.currentTimeMillis();
+
+        Context context = svc.getApplicationContext();
+
+        // Intent to launch an activity when the extended text is clicked
+        Intent intent2 = new Intent(svc, SUTAgentAndroid.class);
+        PendingIntent launchIntent = PendingIntent.getActivity(context, 0, intent2, 0);
+
+
+        Notification notification = new Notification.Builder(context)
+            .setSmallIcon(icon)
+            .setContentTitle(tickerText)
+            .setContentText(expandedText)
+            .setContentIntent(launchIntent)
+            .setWhen(when)
+            .build();
+
+        notification.flags |= (Notification.FLAG_INSISTENT | Notification.FLAG_AUTO_CANCEL);
+        notification.defaults |= Notification.DEFAULT_SOUND;
+        notification.defaults |= Notification.DEFAULT_VIBRATE;
+        notification.defaults |= Notification.DEFAULT_LIGHTS;
+
+        notificationManager.notify(1959, notification);
+        }
+
+    private void CancelNotification()
+        {
+        NotificationManager notificationManager = (NotificationManager)svc.getSystemService(Context.NOTIFICATION_SERVICE);
+        notificationManager.cancel(1959);
+        }
+
+    class doCancelNotification implements Runnable
+        {
+        public void run()
+            {
+            CancelNotification();
+            }
+        };
+
+    class doSendNotification implements Runnable
+        {
+        private String sTitle = "";
+        private String sBText = "";
+
+        doSendNotification(String sTitle, String sBodyText)
+            {
+            this.sTitle = sTitle;
+            this.sBText = sBodyText;
+            }
+
+        public void run()
+            {
+            SendNotification(sTitle, sBText);
+            }
+        };
+}
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/RunDataThread.java b/src/third_party/mozjs-45/build/mobile/sutagent/android/RunDataThread.java
new file mode 100755
index 0000000..7783737
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/RunDataThread.java
@@ -0,0 +1,92 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package com.mozilla.SUTAgentAndroid.service;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketTimeoutException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Timer;
+
+public class RunDataThread extends Thread
+    {
+    Timer heartBeatTimer;
+
+    private ServerSocket SvrSocket = null;
+    private Socket socket    = null;
+    boolean bListening    = true;
+    List<DataWorkerThread> theWorkers = new ArrayList<DataWorkerThread>();
+    android.app.Service    svc = null;
+
+    public RunDataThread(ServerSocket socket, android.app.Service service)
+        {
+        super("RunDataThread");
+        this.SvrSocket = socket;
+        this.svc = service;
+        }
+
+    public void StopListening()
+        {
+        bListening = false;
+        }
+
+    public void SendToDataChannel(String strToSend)
+        {
+        int nNumWorkers = theWorkers.size();
+        for (int lcv = 0; lcv < nNumWorkers; lcv++)
+            {
+            if (theWorkers.get(lcv).isAlive())
+                {
+                theWorkers.get(lcv).SendString(strToSend);
+                }
+            }
+        return;
+        }
+
+    public void run() {
+        try {
+            SvrSocket.setSoTimeout(5000);
+            while (bListening)
+                {
+                try
+                    {
+                    socket = SvrSocket.accept();
+                    DataWorkerThread theWorker = new DataWorkerThread(this, socket);
+                    theWorker.start();
+                    theWorkers.add(theWorker);
+                    }
+                catch (SocketTimeoutException toe)
+                    {
+                    continue;
+                    }
+                }
+
+            int nNumWorkers = theWorkers.size();
+            for (int lcv = 0; lcv < nNumWorkers; lcv++)
+                {
+                if (theWorkers.get(lcv).isAlive())
+                    {
+                    theWorkers.get(lcv).StopListening();
+                    while(theWorkers.get(lcv).isAlive())
+                        ;
+                    }
+                }
+
+            theWorkers.clear();
+
+            SvrSocket.close();
+
+            svc.stopSelf();
+            }
+        catch (IOException e)
+            {
+//            Toast.makeText(SUTAgentAndroid.me.getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG).show();
+            e.printStackTrace();
+            }
+        return;
+        }
+    }
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/SUTAgentAndroid.java b/src/third_party/mozjs-45/build/mobile/sutagent/android/SUTAgentAndroid.java
new file mode 100755
index 0000000..73639c6
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/SUTAgentAndroid.java
@@ -0,0 +1,903 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package com.mozilla.SUTAgentAndroid;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.net.UnknownHostException;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Formatter;
+import java.util.List;
+import java.util.regex.Pattern;
+import java.util.Timer;
+
+import com.mozilla.SUTAgentAndroid.service.ASMozStub;
+import com.mozilla.SUTAgentAndroid.service.DoCommand;
+import android.app.Activity;
+import android.bluetooth.BluetoothAdapter;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ActivityInfo;
+import android.content.res.Configuration;
+import android.net.Uri;
+import android.net.wifi.SupplicantState;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+import android.net.wifi.WifiManager.WifiLock;
+import android.os.BatteryManager;
+import android.os.Build;
+import android.os.Build.VERSION;
+import android.os.Bundle;
+import android.os.Handler;
+import android.telephony.TelephonyManager;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.TextView;
+import android.widget.Toast;
+
+public class SUTAgentAndroid extends Activity
+    {
+    final Handler mHandler = new Handler();
+
+    private static final Pattern IPV4_PATTERN = Pattern.compile("^(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}$");
+
+    public static final int START_PRG = 1959;
+    MenuItem mExitMenuItem;
+    Timer timer = null;
+
+    public static String sUniqueID = null;
+    public static String sLocalIPAddr = null;
+    public static String sACStatus = null;
+    public static String sPowerStatus = null;
+    public static int    nChargeLevel = 0;
+    public static int    nBatteryTemp = 0;
+    public static long   nCreateTimeMillis = System.currentTimeMillis();
+    public static String sTestRoot = "";
+
+    String lineSep = System.getProperty("line.separator");
+    public PrintWriter dataOut = null;
+
+    private static boolean bNetworkingStarted = false;
+    private static String RegSvrIPAddr = "";
+    private static String RegSvrIPPort = "";
+    private static String HardwareID = "";
+    private static String Pool = "";
+    private static String Abi = "";
+    private static String sRegString = "";
+    private static boolean LogCommands = false;
+
+    private WifiLock wl = null;
+
+    private BroadcastReceiver battReceiver = null;
+
+    private TextView  tv = null;
+
+    public boolean onCreateOptionsMenu(Menu menu)
+        {
+        mExitMenuItem = menu.add("Exit");
+        mExitMenuItem.setIcon(android.R.drawable.ic_menu_close_clear_cancel);
+        return super.onCreateOptionsMenu(menu);
+        }
+
+    public boolean onMenuItemSelected(int featureId, MenuItem item)
+        {
+        if (item == mExitMenuItem)
+            {
+            finish();
+            }
+        return super.onMenuItemSelected(featureId, item);
+        }
+
+    public static String getRegSvrIPAddr()
+        {
+        return(RegSvrIPAddr);
+        }
+
+    public void pruneCommandLog(String datestamp, String testroot)
+        {
+
+        String today = "";
+        String yesterday = "";
+
+        // test root can be null (if getTestRoot fails), handle that:
+        if (testroot == null) {
+            testroot = "";
+        }
+
+        try {
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss:SSS");
+            Date dateObj = sdf.parse(datestamp);
+            SimpleDateFormat sdf_file = new SimpleDateFormat("yyyy-MM-dd");
+
+            today     = sdf_file.format(dateObj);
+            yesterday = sdf_file.format(new Date(dateObj.getTime() - 1000*60*60*24));
+        } catch (ParseException pe) {}
+
+        File dir = new File(testroot);
+
+        if (!dir.isDirectory())
+            return;
+
+        File [] files = dir.listFiles();
+        if (files == null)
+            return;
+
+        for (int iter = 0; iter < files.length; iter++) {
+            String fName = files[iter].getName();
+            if (fName.endsWith("sutcommands.txt")) {
+                if (fName.endsWith(today + "-sutcommands.txt") || fName.endsWith(yesterday + "-sutcommands.txt"))
+                    continue;
+
+                if (files[iter].delete())
+                    Log.i("SUTAgentAndroid", "Deleted old command logfile: " + files[iter]);
+                else
+                    Log.e("SUTAgentAndroid", "Unable to delete old command logfile: " + files[iter]);
+            }
+        }
+        }
+
+    /** Called when the activity is first created. */
+    @Override
+    public void onCreate(Bundle savedInstanceState)
+        {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.main);
+
+        fixScreenOrientation();
+
+        DoCommand dc = new DoCommand(getApplication());
+
+        Log.i("SUTAgentAndroid", dc.prgVersion);
+        dc.FixDataLocalPermissions();
+
+        // Get configuration settings from "ini" file
+        File dir = getFilesDir();
+        File iniFile = new File(dir, "SUTAgent.ini");
+        String sIniFile = iniFile.getAbsolutePath();
+
+        String lc = dc.GetIniData("General", "LogCommands", sIniFile);
+        if (lc != "" && Integer.parseInt(lc) == 1) {
+            SUTAgentAndroid.LogCommands = true;
+        }
+        SUTAgentAndroid.RegSvrIPAddr = dc.GetIniData("Registration Server", "IPAddr", sIniFile);
+        SUTAgentAndroid.RegSvrIPPort = dc.GetIniData("Registration Server", "PORT", sIniFile);
+        SUTAgentAndroid.HardwareID = dc.GetIniData("Registration Server", "HARDWARE", sIniFile);
+        SUTAgentAndroid.Pool = dc.GetIniData("Registration Server", "POOL", sIniFile);
+        SUTAgentAndroid.sTestRoot = dc.GetIniData("Device", "TestRoot", sIniFile);
+        SUTAgentAndroid.Abi = android.os.Build.CPU_ABI;
+        log(dc, "onCreate");
+
+        dc.SetTestRoot(SUTAgentAndroid.sTestRoot);
+
+        Log.i("SUTAgentAndroid", "Test Root: " + SUTAgentAndroid.sTestRoot);
+
+        tv = (TextView) this.findViewById(R.id.Textview01);
+
+        if (getLocalIpAddress() == null)
+            setUpNetwork(sIniFile);
+
+        String macAddress = "Unknown";
+        if (android.os.Build.VERSION.SDK_INT > 8) {
+            try {
+                NetworkInterface iface = NetworkInterface.getByInetAddress(InetAddress.getAllByName(getLocalIpAddress())[0]);
+                if (iface != null)
+                    {
+                        byte[] mac = iface.getHardwareAddress();
+                        if (mac != null)
+                            {
+                                StringBuilder sb = new StringBuilder();
+                                Formatter f = new Formatter(sb);
+                                for (int i = 0; i < mac.length; i++)
+                                    {
+                                        f.format("%02x%s", mac[i], (i < mac.length - 1) ? ":" : "");
+                                    }
+                                macAddress = sUniqueID = sb.toString();
+                            }
+                    }
+            }
+            catch (UnknownHostException ex) {}
+            catch (SocketException ex) {}
+        }
+        else
+            {
+                // Fall back to getting info from wifiman on older versions of Android,
+                // which don't support the NetworkInterface interface
+                WifiManager wifiMan = (WifiManager)getSystemService(Context.WIFI_SERVICE);
+                if (wifiMan != null)
+                    {
+                        WifiInfo wifi = wifiMan.getConnectionInfo();
+                        if (wifi != null)
+                            macAddress = wifi.getMacAddress();
+                        if (macAddress != null)
+                            sUniqueID = macAddress;
+                    }
+            }
+
+        if (sUniqueID == null)
+            {
+            BluetoothAdapter ba = BluetoothAdapter.getDefaultAdapter();
+            if ((ba != null) && (ba.isEnabled() != true))
+                {
+                ba.enable();
+                while(ba.getState() != BluetoothAdapter.STATE_ON)
+                    {
+                    try {
+                        Thread.sleep(1000);
+                        }
+                    catch (InterruptedException e)
+                        {
+                        e.printStackTrace();
+                        }
+                    }
+
+                sUniqueID = ba.getAddress();
+
+                ba.disable();
+                while(ba.getState() != BluetoothAdapter.STATE_OFF)
+                    {
+                    try {
+                        Thread.sleep(1000);
+                        }
+                    catch (InterruptedException e)
+                        {
+                        e.printStackTrace();
+                        }
+                    }
+                }
+            else
+                {
+                if (ba != null)
+                    {
+                    sUniqueID = ba.getAddress().toLowerCase();
+                    }
+                }
+            }
+
+        if (sUniqueID == null)
+            {
+            TelephonyManager mTelephonyMgr = (TelephonyManager)getSystemService(TELEPHONY_SERVICE);
+            if (mTelephonyMgr != null)
+                {
+                sUniqueID = mTelephonyMgr.getDeviceId();
+                if (sUniqueID == null)
+                    {
+                    sUniqueID = "0011223344556677";
+                    }
+                }
+            }
+
+        String hwid = getHWID(this);
+
+        sLocalIPAddr = getLocalIpAddress();
+        Toast.makeText(getApplication().getApplicationContext(), "SUTAgent [" + sLocalIPAddr + "] ...", Toast.LENGTH_LONG).show();
+
+        String sConfig = dc.prgVersion + lineSep;
+        sConfig += "Test Root: " + sTestRoot + lineSep;
+        sConfig += "Unique ID: " + sUniqueID + lineSep;
+        sConfig += "HWID: " + hwid + lineSep;
+        sConfig += "ABI: " + Abi + lineSep;
+        sConfig += "OS Info" + lineSep;
+        sConfig += "\t" + dc.GetOSInfo() + lineSep;
+        sConfig += "Screen Info" + lineSep;
+        int [] xy = dc.GetScreenXY();
+        sConfig += "\t Width: " + xy[0] + lineSep;
+        sConfig += "\t Height: " + xy[1] + lineSep;
+        sConfig += "Memory Info" + lineSep;
+        sConfig += "\t" + dc.GetMemoryInfo() + lineSep;
+        sConfig += "Network Info" + lineSep;
+        sConfig += "\tMac Address: " + macAddress + lineSep;
+        sConfig += "\tIP Address: " + sLocalIPAddr + lineSep;
+
+        displayStatus(sConfig);
+
+        sRegString = "NAME=" + sUniqueID;
+        sRegString += "&IPADDR=" + sLocalIPAddr;
+        sRegString += "&CMDPORT=" + 20701;
+        sRegString += "&DATAPORT=" + 20700;
+        sRegString += "&OS=Android-" + dc.GetOSInfo();
+        sRegString += "&SCRNWIDTH=" + xy[0];
+        sRegString += "&SCRNHEIGHT=" + xy[1];
+        sRegString += "&BPP=8";
+        sRegString += "&MEMORY=" + dc.GetMemoryConfig();
+        sRegString += "&HARDWARE=" + HardwareID;
+        sRegString += "&POOL=" + Pool;
+        sRegString += "&ABI=" + Abi;
+
+        String sTemp = Uri.encode(sRegString,"=&");
+        sRegString = "register " + sTemp;
+
+        pruneCommandLog(dc.GetSystemTime(), dc.GetTestRoot());
+
+        if (!bNetworkingStarted)
+            {
+            Thread thread = new Thread(null, doStartService, "StartServiceBkgnd");
+            thread.start();
+            bNetworkingStarted = true;
+
+            Thread thread2 = new Thread(null, doRegisterDevice, "RegisterDeviceBkgnd");
+            thread2.start();
+            }
+
+        monitorBatteryState();
+
+        // If we are returning from an update let'em know we're back
+        Thread thread3 = new Thread(null, doUpdateCallback, "UpdateCallbackBkgnd");
+        thread3.start();
+
+        final Button goButton = (Button) findViewById(R.id.Button01);
+        goButton.setOnClickListener(new OnClickListener() {
+            public void onClick(View v) {
+                finish();
+                }
+            });
+        }
+
+    private class UpdateStatus implements Runnable {
+        public String sText = "";
+
+        UpdateStatus(String sStatus) {
+            sText = sStatus;
+        }
+
+        public void run() {
+            displayStatus(sText);
+        }
+    }
+
+    public synchronized void displayStatus(String sStatus) {
+        String sTVText = (String) tv.getText();
+        sTVText += sStatus;
+        tv.setText(sTVText);
+    }
+
+    public void fixScreenOrientation()
+        {
+        setRequestedOrientation((getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) ?
+                                ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE : ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+        }
+
+    protected void onActivityResult(int requestCode, int resultCode, Intent data)
+        {
+        if (requestCode == START_PRG)
+            {
+               Toast.makeText(getApplication().getApplicationContext(), "SUTAgent startprg finished ...", Toast.LENGTH_LONG).show();
+            }
+        }
+
+    @Override
+    public void onDestroy()
+        {
+        DoCommand dc = new DoCommand(getApplication());
+        super.onDestroy();
+        if (isFinishing())
+            {
+            log(dc, "onDestroy - finishing");
+            Intent listenerSvc = new Intent(this, ASMozStub.class);
+            listenerSvc.setAction("com.mozilla.SUTAgentAndroid.service.LISTENER_SERVICE");
+            stopService(listenerSvc);
+            bNetworkingStarted = false;
+
+            unregisterReceiver(battReceiver);
+
+            if (wl != null)
+                wl.release();
+
+            System.exit(0);
+            }
+        else
+            {
+            log(dc, "onDestroy - not finishing");
+            }
+        }
+
+    private void logMemory(String caller)
+        {
+        DoCommand dc = new DoCommand(getApplication());
+        if (dc != null)
+            {
+            log(dc, caller);
+            log(dc, dc.GetMemoryInfo());
+            String procInfo = dc.GetProcessInfo();
+            if (procInfo != null)
+                {
+                String lines[] = procInfo.split("\n");
+                for (String line : lines) 
+                    {
+                    if (line.contains("mozilla"))
+                        {
+                        log(dc, line);
+                        String words[] = line.split("\t");
+                        if ((words != null) && (words.length > 1))
+                            {
+                            log(dc, dc.StatProcess(words[1]));
+                            }
+                        }
+                    }
+                }
+            }
+        else
+            {
+            Log.e("SUTAgentAndroid", "logMemory: unable to log to file!");
+            }
+        }
+
+    @Override
+    public void onLowMemory()
+        {
+        System.gc();
+        logMemory("onLowMemory");
+        }
+
+    @Override
+    public void onTrimMemory(int level)
+        {
+        System.gc();
+        logMemory("onTrimMemory"+level);
+        }
+
+    private void monitorBatteryState()
+        {
+        battReceiver = new BroadcastReceiver()
+            {
+            public void onReceive(Context context, Intent intent)
+                {
+                StringBuilder sb = new StringBuilder();
+
+                int rawlevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1); // charge level from 0 to scale inclusive
+                int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1); // Max value for charge level
+                int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
+                int health = intent.getIntExtra(BatteryManager.EXTRA_HEALTH, -1);
+                boolean present = intent.getBooleanExtra(BatteryManager.EXTRA_PRESENT, false);
+                int plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1); //0 if the device is not plugged in; 1 if plugged into an AC power adapter; 2 if plugged in via USB.
+//                int voltage = intent.getIntExtra(BatteryManager.EXTRA_VOLTAGE, -1); // voltage in millivolts
+                nBatteryTemp = intent.getIntExtra(BatteryManager.EXTRA_TEMPERATURE, -1); // current battery temperature in tenths of a degree Centigrade
+//                String technology = intent.getStringExtra(BatteryManager.EXTRA_TECHNOLOGY);
+
+                nChargeLevel = -1;  // percentage, or -1 for unknown
+                if (rawlevel >= 0 && scale > 0)
+                    {
+                    nChargeLevel = (rawlevel * 100) / scale;
+                    }
+
+                if (plugged > 0)
+                    sACStatus = "ONLINE";
+                else
+                    sACStatus = "OFFLINE";
+
+                if (present == false)
+                    sb.append("NO BATTERY");
+                else
+                    {
+                    if (nChargeLevel < 10)
+                        sb.append("Critical");
+                    else if (nChargeLevel < 33)
+                        sb.append("LOW");
+                    else if (nChargeLevel > 80)
+                        sb.append("HIGH");
+                    }
+
+                if (BatteryManager.BATTERY_HEALTH_OVERHEAT == health)
+                    {
+                    sb.append("Overheated ");
+                    sb.append((((float)(nBatteryTemp))/10));
+                    sb.append("(C)");
+                    }
+                else
+                    {
+                    switch(status)
+                        {
+                        case BatteryManager.BATTERY_STATUS_UNKNOWN:
+                            // old emulator; maybe also when plugged in with no battery
+                            if (present == true)
+                                sb.append(" UNKNOWN");
+                            break;
+                        case BatteryManager.BATTERY_STATUS_CHARGING:
+                            sb.append(" CHARGING");
+                            break;
+                        case BatteryManager.BATTERY_STATUS_DISCHARGING:
+                            sb.append(" DISCHARGING");
+                            break;
+                        case BatteryManager.BATTERY_STATUS_NOT_CHARGING:
+                            sb.append(" NOTCHARGING");
+                            break;
+                        case BatteryManager.BATTERY_STATUS_FULL:
+                            sb.append(" FULL");
+                            break;
+                        default:
+                            if (present == true)
+                                sb.append("Unknown");
+                            break;
+                        }
+                    }
+
+                sPowerStatus = sb.toString();
+                }
+            };
+
+        IntentFilter battFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
+        registerReceiver(battReceiver, battFilter);
+        }
+
+    public boolean setUpNetwork(String sIniFile)
+        {
+        boolean    bRet = false;
+        int    lcv    = 0;
+        int    lcv2 = 0;
+        WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
+        WifiConfiguration wc = new WifiConfiguration();
+        DoCommand tmpdc = new DoCommand(getApplication());
+
+        String ssid = tmpdc.GetIniData("Network Settings", "SSID", sIniFile);
+        String auth = tmpdc.GetIniData("Network Settings", "AUTH", sIniFile);
+        String encr = tmpdc.GetIniData("Network Settings", "ENCR", sIniFile);
+        String key = tmpdc.GetIniData("Network Settings", "KEY", sIniFile);
+        String eap = tmpdc.GetIniData("Network Settings", "EAP", sIniFile);
+        String adhoc = tmpdc.GetIniData("Network Settings", "ADHOC", sIniFile);
+
+        Toast.makeText(getApplication().getApplicationContext(), "Starting and configuring network", Toast.LENGTH_LONG).show();
+/*
+        ContentResolver cr = getContentResolver();
+        int nRet;
+        try {
+            nRet = Settings.System.getInt(cr, Settings.System.WIFI_USE_STATIC_IP);
+            String foo2 = "" + nRet;
+        } catch (SettingNotFoundException e1) {
+            e1.printStackTrace();
+        }
+*/
+/*
+        wc.SSID = "\"Mozilla-Build\"";
+        wc.preSharedKey  = "\"MozillaBuildQA500\"";
+        wc.hiddenSSID = true;
+        wc.status = WifiConfiguration.Status.ENABLED;
+        wc.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
+        wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
+        wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
+        wc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
+        wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
+        wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
+        wc.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
+*/
+        wc.SSID = "\"" + ssid + "\"";
+//        wc.SSID = "\"Mozilla-G\"";
+//        wc.SSID = "\"Mozilla\"";
+
+        if (auth.contentEquals("wpa2"))
+            {
+            wc.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
+            wc.preSharedKey  = null;
+            }
+
+        if (encr.contentEquals("aes"))
+            {
+            wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
+            wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
+            }
+
+        if (eap.contentEquals("peap"))
+            {
+            wc.eap.setValue("PEAP");
+            wc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
+            wc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X);
+            }
+
+        wc.status = WifiConfiguration.Status.ENABLED;
+
+        if (!wifi.isWifiEnabled())
+            wifi.setWifiEnabled(true);
+
+        while(wifi.getWifiState() != WifiManager.WIFI_STATE_ENABLED)
+            {
+            Thread.yield();
+            if (++lcv > 10000)
+                return(bRet);
+            }
+
+        wl = wifi.createWifiLock(WifiManager.WIFI_MODE_FULL, "SUTAgent");
+        if (wl != null)
+            wl.acquire();
+
+        WifiConfiguration    foo = null;
+        int                    nNetworkID = -1;
+
+        List<WifiConfiguration> connsLst =  wifi.getConfiguredNetworks();
+        int nConns = connsLst.size();
+        for (int i = 0; i < nConns; i++)
+            {
+
+            foo = connsLst.get(i);
+            if (foo.SSID.equalsIgnoreCase(wc.SSID))
+                {
+                nNetworkID = foo.networkId;
+                wc.networkId = foo.networkId;
+                break;
+                }
+            }
+
+        int res;
+
+        if (nNetworkID != -1)
+            {
+            res = wifi.updateNetwork(wc);
+            }
+        else
+            {
+            res = wifi.addNetwork(wc);
+            }
+
+        Log.d("WifiPreference", "add Network returned " + res );
+
+        boolean b = wifi.enableNetwork(res, true);
+        Log.d("WifiPreference", "enableNetwork returned " + b );
+
+        wifi.saveConfiguration();
+
+        WifiInfo wi = wifi.getConnectionInfo();
+        SupplicantState ss = wi.getSupplicantState();
+
+        lcv = 0;
+        lcv2 = 0;
+
+        while (ss.compareTo(SupplicantState.COMPLETED) != 0)
+            {
+            try {
+                Thread.sleep(1000);
+                }
+            catch (InterruptedException e)
+                {
+                e.printStackTrace();
+                }
+
+            if (wi != null)
+                wi = null;
+            if (ss != null)
+                ss = null;
+            wi = wifi.getConnectionInfo();
+            ss = wi.getSupplicantState();
+            if (++lcv > 60)
+                {
+                if (++lcv2 > 5)
+                    {
+                    Toast.makeText(getApplication().getApplicationContext(), "Unable to start and configure network", Toast.LENGTH_LONG).show();
+                    return(bRet);
+                    }
+                else
+                    {
+                    Toast.makeText(getApplication().getApplicationContext(), "Resetting wifi interface", Toast.LENGTH_LONG).show();
+                    if (wl != null)
+                        wl.release();
+                    wifi.setWifiEnabled(false);
+                    while(wifi.getWifiState() != WifiManager.WIFI_STATE_DISABLED)
+                        {
+                        Thread.yield();
+                        }
+
+                    wifi.setWifiEnabled(true);
+                    while(wifi.getWifiState() != WifiManager.WIFI_STATE_ENABLED)
+                        {
+                        Thread.yield();
+                        }
+                    b = wifi.enableNetwork(res, true);
+                    Log.d("WifiPreference", "enableNetwork returned " + b );
+                    if (wl != null)
+                        wl.acquire();
+                    lcv = 0;
+                    }
+                }
+            }
+
+        lcv = 0;
+        while(getLocalIpAddress() == null)
+            {
+            if (++lcv > 10000)
+                return(bRet);
+            }
+
+        Toast.makeText(getApplication().getApplicationContext(), "Network started and configured", Toast.LENGTH_LONG).show();
+        bRet = true;
+
+        return(bRet);
+        }
+
+    // If there is an update.info file callback the server and send the status
+    private Runnable doUpdateCallback = new Runnable() {
+        public void run() {
+            DoCommand dc = new DoCommand(getApplication());
+            String sRet = dc.UpdateCallBack("update.info");
+            if (sRet.length() > 0) {
+                if (sRet.contains("ok")) {
+                    sRet = "Callback Server contacted successfully" + lineSep;
+                } else if (sRet.contains("Nothing to do")) {
+                    sRet = "";
+                } else {
+                    sRet = "Callback Server NOT contacted successfully" + lineSep;
+                }
+            }
+            if (sRet.length() > 0)
+                mHandler.post(new UpdateStatus(sRet));
+            dc = null;
+        }
+    };
+
+    // registers with the reg server defined in the SUTAgent.ini file
+    private Runnable doRegisterDevice = new Runnable() {
+        public void run() {
+            DoCommand dc = new DoCommand(getApplication());
+            String sRet = "";
+            if (RegSvrIPAddr.length() > 0) {
+                String sRegRet = dc.RegisterTheDevice(RegSvrIPAddr, RegSvrIPPort, sRegString);
+                if (sRegRet.contains("ok")) {
+                    sRet += "Registered with testserver" + lineSep;
+                    sRet += "\tIPAddress: " + RegSvrIPAddr + lineSep;
+                    if (RegSvrIPPort.length() > 0)
+                        sRet += "\tPort: " + RegSvrIPPort + lineSep;
+                } else {
+                    sRet += "Not registered with testserver" + lineSep;
+                }
+            } else {
+                sRet += "Not registered with testserver" + lineSep;
+            }
+
+        if (sRet.length() > 0)
+            mHandler.post(new UpdateStatus(sRet));
+        dc = null;
+        }
+    };
+
+    // this starts the listener service for the command and data channels
+    private Runnable doStartService = new Runnable()
+        {
+        public void run()
+            {
+            Intent listenerService = new Intent();
+            listenerService.setAction("com.mozilla.SUTAgentAndroid.service.LISTENER_SERVICE");
+            startService(listenerService);
+            }
+        };
+
+    static String sHWID = null;
+    public static String getHWID(Context cx) {
+        if (sHWID != null)
+            return sHWID;
+
+        // If we're on SDK version > 8, use Build.SERIAL
+        if (android.os.Build.VERSION.SDK_INT > 8) {
+            sHWID = android.os.Build.SERIAL;
+        }
+
+        if (sHWID != null)
+            return sHWID;
+
+        // Otherwise, try from the telephony manager
+        TelephonyManager mTelephonyMgr = (TelephonyManager) cx.getSystemService(TELEPHONY_SERVICE);
+        if (mTelephonyMgr != null) {
+            sHWID = mTelephonyMgr.getDeviceId();
+        }
+
+        if (sHWID != null)
+            return sHWID;
+
+        // Otherwise, try WIFI_SERVICE and use the wifi manager
+        WifiManager wifiMan = (WifiManager) cx.getSystemService(Context.WIFI_SERVICE);
+        if (wifiMan != null) {
+            WifiInfo wifi = wifiMan.getConnectionInfo();
+            if (wifi != null) {
+                sHWID = "wifimac" + wifi.getMacAddress();
+            }
+        }
+
+        if (sHWID != null)
+            return sHWID;
+
+        sHWID = "0011223344556677";
+
+        return sHWID;
+    }
+
+    public static boolean isIPv4Address(final String input) {
+        return IPV4_PATTERN.matcher(input).matches();
+    }
+
+    public static InetAddress getLocalInetAddress() throws SocketException
+        {
+        for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();)
+            {
+            NetworkInterface intf = en.nextElement();
+            for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();)
+                {
+                InetAddress inetAddress = enumIpAddr.nextElement();
+                if (!inetAddress.isLoopbackAddress() && isIPv4Address(inetAddress.getHostAddress()))
+                    {
+                        return inetAddress;
+                    }
+                }
+            }
+
+        return null;
+        }
+
+    public String getLocalIpAddress()
+        {
+        try {
+            InetAddress inetAddress = getLocalInetAddress();
+            if (inetAddress != null)
+                return inetAddress.getHostAddress().toString();
+            }
+        catch (SocketException ex)
+            {
+            Toast.makeText(getApplication().getApplicationContext(), ex.toString(), Toast.LENGTH_LONG).show();
+            }
+        return null;
+        }
+
+    public static void log(DoCommand dc, String message)
+        {
+        Log.i("SUTAgentAndroid", message);
+
+        if (SUTAgentAndroid.LogCommands == false)
+            {
+            return;
+            }
+
+        if (message == null)
+            {
+            Log.e("SUTAgentAndroid", "bad arguments in log()!");
+            return;
+            }
+        String fileDateStr = "00";
+        String testRoot = dc.GetTestRoot();
+        String datestamp = dc.GetSystemTime();
+        if (testRoot == null || datestamp == null)
+            {
+            Log.e("SUTAgentAndroid", "Unable to get testRoot or datestamp in log!");
+            return;
+            }
+
+
+        try 
+            {
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss:SSS");
+            Date dateStr = sdf.parse(datestamp);
+            SimpleDateFormat sdf_file = new SimpleDateFormat("yyyy-MM-dd");
+            fileDateStr = sdf_file.format(dateStr);
+            } 
+        catch (ParseException pe) {}
+        String logFile = testRoot + "/" + fileDateStr + "-sutcommands.txt";
+        PrintWriter pw = null;
+        try 
+            {
+            pw = new PrintWriter(new FileWriter(logFile, true));
+            pw.println(datestamp + " : " + message);
+            } 
+            catch (IOException ioe) 
+            {
+                Log.e("SUTAgentAndroid", "exception with file writer on: " + logFile);
+            } 
+            finally 
+            {
+                if (pw != null)
+                {
+                    pw.close();
+                }
+            }
+
+        }
+}
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/WifiConfiguration.java b/src/third_party/mozjs-45/build/mobile/sutagent/android/WifiConfiguration.java
new file mode 100755
index 0000000..56db51d
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/WifiConfiguration.java
@@ -0,0 +1,480 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * 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.
+ */
+
+package android.net.wifi;
+
+import android.os.Parcelable;
+import android.os.Parcel;
+
+import java.util.BitSet;
+
+/**
+ * A class representing a configured Wi-Fi network, including the
+ * security configuration. Android will not necessarily support
+ * all of these security schemes initially.
+ */
+public class WifiConfiguration implements Parcelable {
+
+    /** {@hide} */
+    public static final String ssidVarName = "ssid";
+    /** {@hide} */
+    public static final String bssidVarName = "bssid";
+    /** {@hide} */
+    public static final String pskVarName = "psk";
+    /** {@hide} */
+    public static final String[] wepKeyVarNames = { "wep_key0", "wep_key1", "wep_key2", "wep_key3" };
+    /** {@hide} */
+    public static final String wepTxKeyIdxVarName = "wep_tx_keyidx";
+    /** {@hide} */
+    public static final String priorityVarName = "priority";
+    /** {@hide} */
+    public static final String hiddenSSIDVarName = "scan_ssid";
+
+    public class EnterpriseField {
+        private String varName;
+        private String value;
+
+        private EnterpriseField(String varName) {
+            this.varName = varName;
+            this.value = null;
+        }
+
+        public void setValue(String value) {
+            this.value = value;
+        }
+
+        public String varName() {
+            return varName;
+        }
+
+        public String value() {
+            return value;
+        }
+    }
+
+    public EnterpriseField eap = new EnterpriseField("eap");
+    public EnterpriseField phase2 = new EnterpriseField("phase2");
+    public EnterpriseField identity = new EnterpriseField("identity");
+    public EnterpriseField anonymous_identity = new EnterpriseField("anonymous_identity");
+    public EnterpriseField password = new EnterpriseField("password");
+    public EnterpriseField client_cert = new EnterpriseField("client_cert");
+    public EnterpriseField private_key = new EnterpriseField("private_key");
+    public EnterpriseField ca_cert = new EnterpriseField("ca_cert");
+
+    public EnterpriseField[] enterpriseFields = {
+            eap, phase2, identity, anonymous_identity, password, client_cert,
+            private_key, ca_cert };
+
+    /**
+     * Recognized key management schemes.
+     */
+    public static class KeyMgmt {
+        private KeyMgmt() { }
+
+        /** WPA is not used; plaintext or static WEP could be used. */
+        public static final int NONE = 0;
+        /** WPA pre-shared key (requires {@code preSharedKey} to be specified). */
+        public static final int WPA_PSK = 1;
+        /** WPA using EAP authentication. Generally used with an external authentication server. */
+        public static final int WPA_EAP = 2;
+        /** IEEE 802.1X using EAP authentication and (optionally) dynamically
+         * generated WEP keys. */
+        public static final int IEEE8021X = 3;
+
+        public static final String varName = "key_mgmt";
+
+        public static final String[] strings = { "NONE", "WPA_PSK", "WPA_EAP", "IEEE8021X" };
+    }
+
+    /**
+     * Recognized security protocols.
+     */
+    public static class Protocol {
+        private Protocol() { }
+
+        /** WPA/IEEE 802.11i/D3.0 */
+        public static final int WPA = 0;
+        /** WPA2/IEEE 802.11i */
+        public static final int RSN = 1;
+
+        public static final String varName = "proto";
+
+        public static final String[] strings = { "WPA", "RSN" };
+    }
+
+    /**
+     * Recognized IEEE 802.11 authentication algorithms.
+     */
+    public static class AuthAlgorithm {
+        private AuthAlgorithm() { }
+
+        /** Open System authentication (required for WPA/WPA2) */
+        public static final int OPEN = 0;
+        /** Shared Key authentication (requires static WEP keys) */
+        public static final int SHARED = 1;
+        /** LEAP/Network EAP (only used with LEAP) */
+        public static final int LEAP = 2;
+
+        public static final String varName = "auth_alg";
+
+        public static final String[] strings = { "OPEN", "SHARED", "LEAP" };
+    }
+
+    /**
+     * Recognized pairwise ciphers for WPA.
+     */
+    public static class PairwiseCipher {
+        private PairwiseCipher() { }
+
+        /** Use only Group keys (deprecated) */
+        public static final int NONE = 0;
+        /** Temporal Key Integrity Protocol [IEEE 802.11i/D7.0] */
+        public static final int TKIP = 1;
+        /** AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] */
+        public static final int CCMP = 2;
+
+        public static final String varName = "pairwise";
+
+        public static final String[] strings = { "NONE", "TKIP", "CCMP" };
+    }
+
+    /**
+     * Recognized group ciphers.
+     * <pre>
+     * CCMP = AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0]
+     * TKIP = Temporal Key Integrity Protocol [IEEE 802.11i/D7.0]
+     * WEP104 = WEP (Wired Equivalent Privacy) with 104-bit key
+     * WEP40 = WEP (Wired Equivalent Privacy) with 40-bit key (original 802.11)
+     * </pre>
+     */
+    public static class GroupCipher {
+        private GroupCipher() { }
+
+        /** WEP40 = WEP (Wired Equivalent Privacy) with 40-bit key (original 802.11) */
+        public static final int WEP40 = 0;
+        /** WEP104 = WEP (Wired Equivalent Privacy) with 104-bit key */
+        public static final int WEP104 = 1;
+        /** Temporal Key Integrity Protocol [IEEE 802.11i/D7.0] */
+        public static final int TKIP = 2;
+        /** AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] */
+        public static final int CCMP = 3;
+
+        public static final String varName = "group";
+
+        public static final String[] strings = { "WEP40", "WEP104", "TKIP", "CCMP" };
+    }
+
+    /** Possible status of a network configuration. */
+    public static class Status {
+        private Status() { }
+
+        /** this is the network we are currently connected to */
+        public static final int CURRENT = 0;
+        /** supplicant will not attempt to use this network */
+        public static final int DISABLED = 1;
+        /** supplicant will consider this network available for association */
+        public static final int ENABLED = 2;
+
+        public static final String[] strings = { "current", "disabled", "enabled" };
+    }
+
+    /**
+     * The ID number that the supplicant uses to identify this
+     * network configuration entry. This must be passed as an argument
+     * to most calls into the supplicant.
+     */
+    public int networkId;
+
+    /**
+     * The current status of this network configuration entry.
+     * @see Status
+     */
+    public int status;
+    /**
+     * The network's SSID. Can either be an ASCII string,
+     * which must be enclosed in double quotation marks
+     * (e.g., {@code &quot;MyNetwork&quot;}, or a string of
+     * hex digits,which are not enclosed in quotes
+     * (e.g., {@code 01a243f405}).
+     */
+    public String SSID;
+    /**
+     * When set, this network configuration entry should only be used when
+     * associating with the AP having the specified BSSID. The value is
+     * a string in the format of an Ethernet MAC address, e.g.,
+     * <code>XX:XX:XX:XX:XX:XX</code> where each <code>X</code> is a hex digit.
+     */
+    public String BSSID;
+
+    /**
+     * Pre-shared key for use with WPA-PSK.
+     * <p/>
+     * When the value of this key is read, the actual key is
+     * not returned, just a "*" if the key has a value, or the null
+     * string otherwise.
+     */
+    public String preSharedKey;
+    /**
+     * Up to four WEP keys. Either an ASCII string enclosed in double
+     * quotation marks (e.g., {@code &quot;abcdef&quot;} or a string
+     * of hex digits (e.g., {@code 0102030405}).
+     * <p/>
+     * When the value of one of these keys is read, the actual key is
+     * not returned, just a "*" if the key has a value, or the null
+     * string otherwise.
+     */
+    public String[] wepKeys;
+
+    /** Default WEP key index, ranging from 0 to 3. */
+    public int wepTxKeyIndex;
+
+    /**
+     * Priority determines the preference given to a network by {@code wpa_supplicant}
+     * when choosing an access point with which to associate.
+     */
+    public int priority;
+
+    /**
+     * This is a network that does not broadcast its SSID, so an
+     * SSID-specific probe request must be used for scans.
+     */
+    public boolean hiddenSSID;
+
+    /**
+     * The set of key management protocols supported by this configuration.
+     * See {@link KeyMgmt} for descriptions of the values.
+     * Defaults to WPA-PSK WPA-EAP.
+     */
+    public BitSet allowedKeyManagement;
+    /**
+     * The set of security protocols supported by this configuration.
+     * See {@link Protocol} for descriptions of the values.
+     * Defaults to WPA RSN.
+     */
+    public BitSet allowedProtocols;
+    /**
+     * The set of authentication protocols supported by this configuration.
+     * See {@link AuthAlgorithm} for descriptions of the values.
+     * Defaults to automatic selection.
+     */
+    public BitSet allowedAuthAlgorithms;
+    /**
+     * The set of pairwise ciphers for WPA supported by this configuration.
+     * See {@link PairwiseCipher} for descriptions of the values.
+     * Defaults to CCMP TKIP.
+     */
+    public BitSet allowedPairwiseCiphers;
+    /**
+     * The set of group ciphers supported by this configuration.
+     * See {@link GroupCipher} for descriptions of the values.
+     * Defaults to CCMP TKIP WEP104 WEP40.
+     */
+    public BitSet allowedGroupCiphers;
+
+
+    public WifiConfiguration() {
+        networkId = -1;
+        SSID = null;
+        BSSID = null;
+        priority = 0;
+        hiddenSSID = false;
+        allowedKeyManagement = new BitSet();
+        allowedProtocols = new BitSet();
+        allowedAuthAlgorithms = new BitSet();
+        allowedPairwiseCiphers = new BitSet();
+        allowedGroupCiphers = new BitSet();
+        wepKeys = new String[4];
+        for (int i = 0; i < wepKeys.length; i++)
+            wepKeys[i] = null;
+        for (EnterpriseField field : enterpriseFields) {
+            field.setValue(null);
+        }
+    }
+
+    public String toString() {
+        StringBuilder sbuf = new StringBuilder();
+        if (this.status == WifiConfiguration.Status.CURRENT) {
+            sbuf.append("* ");
+        } else if (this.status == WifiConfiguration.Status.DISABLED) {
+            sbuf.append("- ");
+        }
+        sbuf.append("ID: ").append(this.networkId).append(" SSID: ").append(this.SSID).
+                append(" BSSID: ").append(this.BSSID).append(" PRIO: ").append(this.priority).
+                append('\n');
+        sbuf.append(" KeyMgmt:");
+        for (int k = 0; k < this.allowedKeyManagement.size(); k++) {
+            if (this.allowedKeyManagement.get(k)) {
+                sbuf.append(" ");
+                if (k < KeyMgmt.strings.length) {
+                    sbuf.append(KeyMgmt.strings[k]);
+                } else {
+                    sbuf.append("??");
+                }
+            }
+        }
+        sbuf.append(" Protocols:");
+        for (int p = 0; p < this.allowedProtocols.size(); p++) {
+            if (this.allowedProtocols.get(p)) {
+                sbuf.append(" ");
+                if (p < Protocol.strings.length) {
+                    sbuf.append(Protocol.strings[p]);
+                } else {
+                    sbuf.append("??");
+                }
+            }
+        }
+        sbuf.append('\n');
+        sbuf.append(" AuthAlgorithms:");
+        for (int a = 0; a < this.allowedAuthAlgorithms.size(); a++) {
+            if (this.allowedAuthAlgorithms.get(a)) {
+                sbuf.append(" ");
+                if (a < AuthAlgorithm.strings.length) {
+                    sbuf.append(AuthAlgorithm.strings[a]);
+                } else {
+                    sbuf.append("??");
+                }
+            }
+        }
+        sbuf.append('\n');
+        sbuf.append(" PairwiseCiphers:");
+        for (int pc = 0; pc < this.allowedPairwiseCiphers.size(); pc++) {
+            if (this.allowedPairwiseCiphers.get(pc)) {
+                sbuf.append(" ");
+                if (pc < PairwiseCipher.strings.length) {
+                    sbuf.append(PairwiseCipher.strings[pc]);
+                } else {
+                    sbuf.append("??");
+                }
+            }
+        }
+        sbuf.append('\n');
+        sbuf.append(" GroupCiphers:");
+        for (int gc = 0; gc < this.allowedGroupCiphers.size(); gc++) {
+            if (this.allowedGroupCiphers.get(gc)) {
+                sbuf.append(" ");
+                if (gc < GroupCipher.strings.length) {
+                    sbuf.append(GroupCipher.strings[gc]);
+                } else {
+                    sbuf.append("??");
+                }
+            }
+        }
+        sbuf.append('\n').append(" PSK: ");
+        if (this.preSharedKey != null) {
+            sbuf.append('*');
+        }
+
+        for (EnterpriseField field : enterpriseFields) {
+            sbuf.append('\n').append(" " + field.varName() + ": ");
+            String value = field.value();
+            if (value != null) sbuf.append(value);
+        }
+        sbuf.append('\n');
+        return sbuf.toString();
+    }
+
+    /**
+     * Construct a WifiConfiguration from a scanned network
+     * @param scannedAP the scan result used to construct the config entry
+     * TODO: figure out whether this is a useful way to construct a new entry.
+     *
+    public WifiConfiguration(ScanResult scannedAP) {
+        networkId = -1;
+        SSID = scannedAP.SSID;
+        BSSID = scannedAP.BSSID;
+    }
+    */
+
+    private static BitSet readBitSet(Parcel src) {
+        int cardinality = src.readInt();
+
+        BitSet set = new BitSet();
+        for (int i = 0; i < cardinality; i++)
+            set.set(src.readInt());
+
+        return set;
+    }
+
+    private static void writeBitSet(Parcel dest, BitSet set) {
+        int nextSetBit = -1;
+
+        dest.writeInt(set.cardinality());
+
+        while ((nextSetBit = set.nextSetBit(nextSetBit + 1)) != -1)
+            dest.writeInt(nextSetBit);
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(networkId);
+        dest.writeInt(status);
+        dest.writeString(SSID);
+        dest.writeString(BSSID);
+        dest.writeString(preSharedKey);
+        for (String wepKey : wepKeys)
+            dest.writeString(wepKey);
+        dest.writeInt(wepTxKeyIndex);
+        dest.writeInt(priority);
+        dest.writeInt(hiddenSSID ? 1 : 0);
+
+        writeBitSet(dest, allowedKeyManagement);
+        writeBitSet(dest, allowedProtocols);
+        writeBitSet(dest, allowedAuthAlgorithms);
+        writeBitSet(dest, allowedPairwiseCiphers);
+        writeBitSet(dest, allowedGroupCiphers);
+
+        for (EnterpriseField field : enterpriseFields) {
+            dest.writeString(field.value());
+        }
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    public static final Creator<WifiConfiguration> CREATOR =
+        new Creator<WifiConfiguration>() {
+            public WifiConfiguration createFromParcel(Parcel in) {
+                WifiConfiguration config = new WifiConfiguration();
+                config.networkId = in.readInt();
+                config.status = in.readInt();
+                config.SSID = in.readString();
+                config.BSSID = in.readString();
+                config.preSharedKey = in.readString();
+                for (int i = 0; i < config.wepKeys.length; i++)
+                    config.wepKeys[i] = in.readString();
+                config.wepTxKeyIndex = in.readInt();
+                config.priority = in.readInt();
+                config.hiddenSSID = in.readInt() != 0;
+                config.allowedKeyManagement   = readBitSet(in);
+                config.allowedProtocols       = readBitSet(in);
+                config.allowedAuthAlgorithms  = readBitSet(in);
+                config.allowedPairwiseCiphers = readBitSet(in);
+                config.allowedGroupCiphers    = readBitSet(in);
+
+                for (EnterpriseField field : config.enterpriseFields) {
+                    field.setValue(in.readString());
+                }
+                return config;
+            }
+
+            public WifiConfiguration[] newArray(int size) {
+                return new WifiConfiguration[size];
+            }
+        };
+}
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/default.properties b/src/third_party/mozjs-45/build/mobile/sutagent/android/default.properties
new file mode 100644
index 0000000..a2d729b
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/default.properties
@@ -0,0 +1,17 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+# 
+# This file must be checked in Version Control Systems.
+# 
+# To customize properties used by the Ant build system use,
+# "build.properties", and override values to adapt the script to your
+# project structure.
+
+# Indicates whether an apk should be generated for each density.
+split.density=false
+# Project target.
+target=android-5
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/fencp/AndroidManifest.xml b/src/third_party/mozjs-45/build/mobile/sutagent/android/fencp/AndroidManifest.xml
new file mode 100644
index 0000000..65bb6ca
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/fencp/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+      package="org.mozilla.fencp"
+      android:versionCode="1"
+      android:versionName="1.0" android:sharedUserId="org.mozilla.fennec.sharedID">
+    <application android:icon="@drawable/icon" android:label="@string/app_name" android:debuggable="true">
+        <activity android:label="@string/app_name" android:name="FenCP">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+    <provider android:name="FenCPFP" 
+              android:enabled="true" 
+              android:authorities="org.mozilla.fencp" 
+              android:exported="true">
+	</provider>
+</application>
+    <uses-sdk android:minSdkVersion="6" />
+
+</manifest> 
\ No newline at end of file
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/fencp/DirCursor.java b/src/third_party/mozjs-45/build/mobile/sutagent/android/fencp/DirCursor.java
new file mode 100644
index 0000000..12832dd
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/fencp/DirCursor.java
@@ -0,0 +1,175 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+package org.mozilla.fencp;
+
+import java.io.File;
+import java.io.IOException;
+
+import android.database.MatrixCursor;
+
+public class DirCursor extends MatrixCursor {
+    public static final String _ID = "_id";
+    public static final String ISDIR = "isdir";
+    public static final String FILENAME = "filename";
+    public static final String LENGTH = "length";
+    public static final String TIMESTAMP = "ts";
+    public static final String WRITABLE = "writable";
+    static final String[] DEFCOLUMNS = new String[] {
+            _ID,
+            ISDIR,
+            FILENAME,
+            LENGTH,
+            TIMESTAMP,
+            WRITABLE
+         };
+    private String dirPath = null;
+    private String [] theColumns = null;
+
+    public DirCursor(String[] columnNames, String sPath) {
+        super((columnNames == null ? DEFCOLUMNS : columnNames));
+        theColumns = (columnNames == null ? DEFCOLUMNS : columnNames);
+        dirPath = sPath;
+        doLoadCursor(dirPath);
+    }
+
+    public DirCursor(String[] columnNames, int initialCapacity, String sPath) {
+        super((columnNames == null ? DEFCOLUMNS : columnNames), initialCapacity);
+        theColumns = (columnNames == null ? DEFCOLUMNS : columnNames);
+        dirPath = sPath;
+        doLoadCursor(dirPath);
+    }
+    
+    private void doLoadCursor(String sDir) {
+        File dir = new File(sDir);
+        int    nFiles = 0;
+        int nCols = theColumns.length;
+        int    lcvFiles = 0;
+        int    nCIndex = 0;
+        Object [] vals = new Object[nCols];
+        
+        if (dir.isDirectory()) {
+            try {
+                nCIndex = getColumnIndex(_ID);
+                if (nCIndex > -1)
+                    vals[nCIndex] = -1;
+
+                nCIndex = getColumnIndex(ISDIR);
+                if (nCIndex > -1)
+                    vals[nCIndex] = 1;
+                
+                nCIndex = getColumnIndex(FILENAME);
+                if (nCIndex > -1)
+                    try {
+                        vals[nCIndex] = dir.getCanonicalPath();
+                    } catch (IOException e) {
+                        vals[nCIndex] = dir.getName();
+                    }
+
+                nCIndex = getColumnIndex(LENGTH);
+                if (nCIndex > -1)
+                    vals[nCIndex] = 0;
+                
+                nCIndex = getColumnIndex(TIMESTAMP);
+                if (nCIndex > -1)
+                    vals[nCIndex] = 0;
+                
+                nCIndex = getColumnIndex(WRITABLE);
+                if (nCIndex > -1)
+                    vals[nCIndex] = (dir.canWrite() ? 1 : 0);
+                
+                addRow(vals);
+                }
+            catch (IllegalArgumentException iae) {
+                iae.printStackTrace();
+            }
+            
+            File [] files = dir.listFiles();
+            if (files != null) {
+                if ((nFiles = files.length) > 0) {
+                    for (lcvFiles = 0; lcvFiles < nFiles; lcvFiles++) {
+                        nCIndex = getColumnIndex(_ID);
+                        if (nCIndex > -1)
+                            vals[nCIndex] = lcvFiles;
+
+                        nCIndex = getColumnIndex(ISDIR);
+                        if (nCIndex > -1)
+                            vals[nCIndex] = (files[lcvFiles].isDirectory() ? 1 : 0);
+                        
+                        nCIndex = getColumnIndex(FILENAME);
+                        if (nCIndex > -1)
+                                vals[nCIndex] = files[lcvFiles].getName();
+
+                        nCIndex = getColumnIndex(LENGTH);
+                        if (nCIndex > -1)
+                            vals[nCIndex] = (files[lcvFiles].isDirectory() ? -1 : files[lcvFiles].length());
+
+                        try {
+                            addRow(vals);
+                        } catch (IllegalArgumentException iae) {
+                            iae.printStackTrace();
+                        }
+                    }
+                }
+            }
+        } else {
+            if (dir.isFile()) {
+                nCIndex = getColumnIndex(_ID);
+                if (nCIndex > -1)
+                    vals[nCIndex] = -1;
+
+                nCIndex = getColumnIndex(ISDIR);
+                if (nCIndex > -1)
+                    vals[nCIndex] = 0;
+                
+                nCIndex = getColumnIndex(FILENAME);
+                if (nCIndex > -1)
+                    vals[nCIndex] = dir.getName();
+
+                nCIndex = getColumnIndex(LENGTH);
+                if (nCIndex > -1)
+                    vals[nCIndex] = dir.length();
+
+                nCIndex = getColumnIndex(TIMESTAMP);
+                if (nCIndex > -1) {
+                    vals[nCIndex] = dir.lastModified();
+                }
+                
+                try {
+                    addRow(vals);
+                    }
+                catch (IllegalArgumentException iae) {
+                    iae.printStackTrace();
+                }
+            }
+            else {
+                try {
+                    nCIndex = getColumnIndex(_ID);
+                    if (nCIndex > -1)
+                        vals[nCIndex] = -1;
+
+                    nCIndex = getColumnIndex(ISDIR);
+                    if (nCIndex > -1)
+                        vals[nCIndex] = 0;
+                    
+                    nCIndex = getColumnIndex(FILENAME);
+                    if (nCIndex > -1)
+                        vals[nCIndex] = null;
+
+                    nCIndex = getColumnIndex(LENGTH);
+                    if (nCIndex > -1)
+                        vals[nCIndex] = 0;
+                    
+                    nCIndex = getColumnIndex(TIMESTAMP);
+                    if (nCIndex > -1)
+                        vals[nCIndex] = 0;
+                    
+                    addRow(vals);
+                    }
+                catch (IllegalArgumentException iae) {
+                    iae.printStackTrace();
+                }
+            }
+        }
+    }
+}
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/fencp/FenCP.java b/src/third_party/mozjs-45/build/mobile/sutagent/android/fencp/FenCP.java
new file mode 100644
index 0000000..1910698
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/fencp/FenCP.java
@@ -0,0 +1,16 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+package org.mozilla.fencp;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class FenCP extends Activity {
+    /** Called when the activity is first created. */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.main);
+    }
+}
\ No newline at end of file
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/fencp/FenCPFP.java b/src/third_party/mozjs-45/build/mobile/sutagent/android/fencp/FenCPFP.java
new file mode 100644
index 0000000..a5bea9a
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/fencp/FenCPFP.java
@@ -0,0 +1,193 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+package org.mozilla.fencp;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.content.UriMatcher;
+import android.database.Cursor;
+import android.net.Uri;
+
+public class FenCPFP extends ContentProvider {
+    public static final String PROVIDER_NAME = "org.mozilla.fencp";
+    public static final Uri CONTENT_URI = Uri.parse("content://" + PROVIDER_NAME + "/file");
+
+    public static final String _ID = "_id";
+    public static final String ISDIR = "isdir";
+    public static final String FILENAME = "filename";
+    public static final String LENGTH = "length";
+    public static final String CHUNK = "chunk";
+    static String[] dircolumns = new String[] {
+        _ID,
+        ISDIR,
+        FILENAME,
+        LENGTH
+     };
+
+    static String[] filecolumns = new String[] {
+        _ID,
+        CHUNK
+     };
+
+    private static final int DIR = 1;
+    private static final int FILE_NAME = 2;
+
+    private static final UriMatcher uriMatcher;
+    static {
+        uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
+           uriMatcher.addURI(PROVIDER_NAME, "dir", DIR);
+           uriMatcher.addURI(PROVIDER_NAME, "file", FILE_NAME);
+        }
+
+    public int PruneDir(String sTmpDir) {
+        int    nRet = 0;
+        int nFiles = 0;
+        String sSubDir = null;
+
+        File dir = new File(sTmpDir);
+
+        if (dir.isDirectory()) {
+            File [] files = dir.listFiles();
+            if (files != null) {
+                if ((nFiles = files.length) > 0) {
+                    for (int lcv = 0; lcv < nFiles; lcv++) {
+                        if (files[lcv].isDirectory()) {
+                            sSubDir = files[lcv].getAbsolutePath();
+                            nRet += PruneDir(sSubDir);
+                        }
+                        else {
+                            if (files[lcv].delete()) {
+                                nRet++;
+                            }
+                        }
+                    }
+                }
+            }
+            if (dir.delete()) {
+                nRet++;
+            }
+            if ((nFiles + 1) > nRet) {
+                nRet = -1;
+            }
+        }
+
+    return(nRet);
+    }
+
+    @Override
+    public int delete(Uri uri, String selection, String[] selectionArgs) {
+        int nFiles = 0;
+        switch (uriMatcher.match(uri)) {
+            case FILE_NAME:
+                File f = new File(selection);
+                if (f.delete())
+                    nFiles = 1;
+                break;
+
+            case DIR:
+                nFiles = PruneDir(selection);
+                break;
+
+            default:
+                break;
+        }
+        return nFiles;
+    }
+
+    @Override
+    public String getType(Uri uri)
+        {
+        switch (uriMatcher.match(uri))
+            {
+            //---get directory---
+            case DIR:
+                return "vnd.android.cursor.dir/vnd.mozilla.dir ";
+            //---get a particular file---
+            case FILE_NAME:
+                return "vnd.android.cursor.item/vnd.mozilla.file ";
+            //---Unknown---
+            default:
+                throw new IllegalArgumentException("Unsupported URI: " + uri);
+            }
+    }
+
+    @Override
+    public Uri insert(Uri uri, ContentValues values) {
+        return null;
+    }
+
+    @Override
+    public boolean onCreate() {
+        return true;
+    }
+
+    @Override
+    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
+        Cursor retCursor = null;
+
+        switch(uriMatcher.match(uri)) {
+            case DIR:
+                retCursor = new DirCursor(projection, selection);
+                break;
+
+            case FILE_NAME:
+                retCursor = new FileCursor(projection, selection, selectionArgs);
+                break;
+
+            default:
+                break;
+        }
+        return (retCursor);
+    }
+
+    @Override
+    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+        int    nRet = 0;
+        FileOutputStream dstFile = null;
+
+        switch(uriMatcher.match(uri)) {
+            case DIR:
+                File dir = new File(selection);
+                if (dir.mkdirs())
+                    nRet = 1;
+                break;
+
+            case FILE_NAME:
+                try {
+                    long lOffset = values.getAsLong("offset");
+                    byte [] buf = values.getAsByteArray(CHUNK);
+                    int    nLength = values.getAsInteger(LENGTH);
+                    if ((buf != null) && (nLength > 0)) {
+                        File f = new File(selection);
+                        dstFile = new FileOutputStream(f, (lOffset == 0 ? false : true));
+                        dstFile.write(buf,0, nLength);
+                        dstFile.flush();
+                        dstFile.close();
+                        nRet = nLength;
+                    }
+                } catch (FileNotFoundException fnfe) {
+                    fnfe.printStackTrace();
+                } catch (IOException ioe) {
+                    try {
+                        dstFile.flush();
+                    } catch (IOException e) {
+                    }
+                    try {
+                        dstFile.close();
+                    } catch (IOException e) {
+                    }
+                }
+                break;
+
+            default:
+                break;
+        }
+        return nRet;
+    }
+}
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/fencp/FileCursor.java b/src/third_party/mozjs-45/build/mobile/sutagent/android/fencp/FileCursor.java
new file mode 100644
index 0000000..036f36a
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/fencp/FileCursor.java
@@ -0,0 +1,168 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+package org.mozilla.fencp;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import android.database.AbstractWindowedCursor;
+import android.database.CursorWindow;
+
+public class FileCursor extends AbstractWindowedCursor {
+    public static final String _ID = "_id";
+    public static final String CHUNK = "chunk";
+    public static final String LENGTH = "length";
+    static final String[] DEFCOLUMNS = new String[] {
+            _ID,
+            CHUNK,
+            LENGTH
+         };
+    private String filePath = null;
+    private String [] theColumns = null;
+
+    private static final int BUFSIZE = 4096;
+    private long lFileSize = 0;
+    private int nCount = 0;
+    private File theFile = null;
+    private byte [] theBuffer = null;
+    private long lOffset = 0;
+    private long lLength = -1;
+
+    public FileCursor(String[] columnNames, String sFilePath, String [] selectionArgs) {
+        super();
+        theColumns = (columnNames == null ? DEFCOLUMNS : columnNames);
+        filePath = sFilePath;
+        nCount = -1;
+
+        if ((selectionArgs != null) && (selectionArgs.length > 0)) {
+            lOffset = Long.parseLong(selectionArgs[0]);
+            lLength = Long.parseLong(selectionArgs[1]);
+        }
+
+        if (filePath.length() > 0) {
+            theFile = new File(filePath);
+            if (theFile.exists() && theFile.canRead()) {
+                lFileSize = theFile.length();
+
+                // lLength == -1 return everything between lOffset and eof
+                // lLength == 0 return file length
+                // lLength > 0 return lLength bytes
+                if (lLength == -1) {
+                    lFileSize = lFileSize - lOffset;
+                } else if (lLength == 0) {
+                    // just return the file length
+                } else {
+                    lFileSize = ((lLength <= (lFileSize - lOffset)) ? lLength : (lFileSize - lOffset));
+                }
+
+                if (lLength != 0) {
+                    nCount = (int) (lFileSize / BUFSIZE);
+                    if ((lFileSize % BUFSIZE) > 0)
+                        nCount++;
+                } else {
+                    nCount = 1;
+                }
+
+            }
+        }
+    }
+
+    public String getColumnName (int columnIndex) {
+        return theColumns[columnIndex];
+    }
+
+    @Override
+    public String[] getColumnNames() {
+        return theColumns;
+    }
+
+    @Override
+    public int getCount() {
+        return nCount;
+    }
+
+    @Override
+    public boolean onMove(int oldPosition, int newPosition) {
+        boolean bRet = true;
+
+        // get rid of old data
+        mWindow.clear();
+        bRet = mWindow.setNumColumns(theColumns.length);
+        fillWindow(newPosition, mWindow);
+
+        return bRet;
+    }
+
+    @Override
+    public void fillWindow (int pos, CursorWindow window) {
+        int    nNumRows = window.getNumRows();
+        int nCIndex = 0;
+        window.setStartPosition(0);
+
+        if (pos > -1) {
+            if (nNumRows == 0) {
+                window.allocRow();
+                nNumRows = window.getNumRows();
+            }
+
+            if (nNumRows == 1) {
+                nCIndex = getColumnIndex(LENGTH);
+                if (nCIndex > -1) {
+                    window.putLong(lFileSize, 0, nCIndex);
+                }
+                nCIndex = getColumnIndex(_ID);
+                if (nCIndex > -1) {
+                    window.putLong((long)pos, 0, nCIndex);
+                }
+                nCIndex = getColumnIndex(CHUNK);
+                if (nCIndex > -1) {
+                    if (lLength != 0) {
+                        byte[] value = getABlob (pos, 1);
+                        window.putBlob(value, 0, nCIndex);
+                    }
+                }
+            }
+            window.setStartPosition(pos);
+        }
+        return;
+    }
+
+    public byte[] getABlob (int row, int column) {
+        int    nRead = 0;
+        int    nOffset = 0;
+        int nBufSize = 0;
+
+        if ((column == 1) && (theFile != null)) {
+            try {
+                FileInputStream fin = new FileInputStream(theFile);
+                nOffset = row * BUFSIZE;
+                if (row < (nCount - 1)) {
+                    nBufSize = BUFSIZE;
+                } else {
+                    nBufSize = (int) (lFileSize - nOffset);
+                }
+                theBuffer = new byte[nBufSize];
+
+                if (theBuffer != null) {
+                    if (fin.skip(nOffset + lOffset) == (nOffset + lOffset)) {
+                        if ((nRead = fin.read(theBuffer, 0, nBufSize)) != -1) {
+                            if (nRead != nBufSize) {
+                                return null;
+                            }
+                        }
+                    }
+                }
+
+            fin.close();
+            } catch (FileNotFoundException e) {
+                e.printStackTrace();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+
+        return theBuffer;
+    }
+}
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/fencp/Makefile.in b/src/third_party/mozjs-45/build/mobile/sutagent/android/fencp/Makefile.in
new file mode 100644
index 0000000..adcfb8f
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/fencp/Makefile.in
@@ -0,0 +1,14 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+include $(topsrcdir)/config/config.mk
+
+JAVAFILES = \
+  DirCursor.java \
+  FenCP.java \
+  FenCPFP.java \
+  FileCursor.java \
+  $(NULL)
+
+tools:: $(ANDROID_APK_NAME).apk
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/fencp/default.properties b/src/third_party/mozjs-45/build/mobile/sutagent/android/fencp/default.properties
new file mode 100644
index 0000000..06596fb
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/fencp/default.properties
@@ -0,0 +1,15 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+# 
+# This file must be checked in Version Control Systems.
+# 
+# To customize properties used by the Ant build system use,
+# "build.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-6
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/fencp/moz.build b/src/third_party/mozjs-45/build/mobile/sutagent/android/fencp/moz.build
new file mode 100644
index 0000000..19fbe97
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/fencp/moz.build
@@ -0,0 +1,8 @@
+# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+ANDROID_APK_NAME = 'FenCP'
+ANDROID_APK_PACKAGE = 'org.mozilla.fencp'
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/fencp/res/drawable-hdpi/icon.png b/src/third_party/mozjs-45/build/mobile/sutagent/android/fencp/res/drawable-hdpi/icon.png
new file mode 100644
index 0000000..8074c4c
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/fencp/res/drawable-hdpi/icon.png
Binary files differ
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/fencp/res/drawable-ldpi/icon.png b/src/third_party/mozjs-45/build/mobile/sutagent/android/fencp/res/drawable-ldpi/icon.png
new file mode 100644
index 0000000..1095584
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/fencp/res/drawable-ldpi/icon.png
Binary files differ
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/fencp/res/drawable-mdpi/icon.png b/src/third_party/mozjs-45/build/mobile/sutagent/android/fencp/res/drawable-mdpi/icon.png
new file mode 100644
index 0000000..a07c69f
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/fencp/res/drawable-mdpi/icon.png
Binary files differ
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/fencp/res/layout/main.xml b/src/third_party/mozjs-45/build/mobile/sutagent/android/fencp/res/layout/main.xml
new file mode 100644
index 0000000..1256b1a
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/fencp/res/layout/main.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    >
+<TextView  
+    android:layout_width="fill_parent" 
+    android:layout_height="wrap_content" 
+    android:text="@string/hello"
+    />
+</LinearLayout>
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/fencp/res/values/strings.xml b/src/third_party/mozjs-45/build/mobile/sutagent/android/fencp/res/values/strings.xml
new file mode 100644
index 0000000..1daeb1a
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/fencp/res/values/strings.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<resources>
+    <string name="hello">Hello World, FennecCP!</string>
+    <string name="app_name">FennecCP</string>
+</resources>
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/ffxcp/AndroidManifest.xml b/src/third_party/mozjs-45/build/mobile/sutagent/android/ffxcp/AndroidManifest.xml
new file mode 100644
index 0000000..f070f66
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/ffxcp/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+      package="org.mozilla.ffxcp"
+      android:versionCode="1"
+      android:versionName="1.0" android:sharedUserId="org.mozilla.firefox.sharedID">
+    <application android:icon="@drawable/icon" android:label="@string/app_name" android:debuggable="true">
+        <activity android:label="@string/app_name" android:name="ffxcp">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+    <provider android:name="FfxCPFP" 
+              android:enabled="true" 
+              android:authorities="org.mozilla.ffxcp" 
+              android:exported="true">
+	</provider>
+    </application>
+    <uses-sdk android:minSdkVersion="6" />
+
+</manifest> 
\ No newline at end of file
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/ffxcp/DirCursor.java b/src/third_party/mozjs-45/build/mobile/sutagent/android/ffxcp/DirCursor.java
new file mode 100644
index 0000000..57ed076
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/ffxcp/DirCursor.java
@@ -0,0 +1,175 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+package org.mozilla.ffxcp;
+
+import java.io.File;
+import java.io.IOException;
+
+import android.database.MatrixCursor;
+
+public class DirCursor extends MatrixCursor {
+    public static final String _ID = "_id";
+    public static final String ISDIR = "isdir";
+    public static final String FILENAME = "filename";
+    public static final String LENGTH = "length";
+    public static final String TIMESTAMP = "ts";
+    public static final String WRITABLE = "writable";
+    static final String[] DEFCOLUMNS = new String[] {
+            _ID,
+            ISDIR,
+            FILENAME,
+            LENGTH,
+            TIMESTAMP,
+            WRITABLE
+         };
+    private String dirPath = null;
+    private String [] theColumns = null;
+
+    public DirCursor(String[] columnNames, String sPath) {
+        super((columnNames == null ? DEFCOLUMNS : columnNames));
+        theColumns = (columnNames == null ? DEFCOLUMNS : columnNames);
+        dirPath = sPath;
+        doLoadCursor(dirPath);
+    }
+
+    public DirCursor(String[] columnNames, int initialCapacity, String sPath) {
+        super((columnNames == null ? DEFCOLUMNS : columnNames), initialCapacity);
+        theColumns = (columnNames == null ? DEFCOLUMNS : columnNames);
+        dirPath = sPath;
+        doLoadCursor(dirPath);
+    }
+
+    private void doLoadCursor(String sDir) {
+        File dir = new File(sDir);
+        int    nFiles = 0;
+        int nCols = theColumns.length;
+        int    lcvFiles = 0;
+        int    nCIndex = 0;
+        Object [] vals = new Object[nCols];
+
+        if (dir.isDirectory()) {
+            try {
+                nCIndex = getColumnIndex(_ID);
+                if (nCIndex > -1)
+                    vals[nCIndex] = -1;
+
+                nCIndex = getColumnIndex(ISDIR);
+                if (nCIndex > -1)
+                    vals[nCIndex] = 1;
+
+                nCIndex = getColumnIndex(FILENAME);
+                if (nCIndex > -1)
+                    try {
+                        vals[nCIndex] = dir.getCanonicalPath();
+                    } catch (IOException e) {
+                        vals[nCIndex] = dir.getName();
+                    }
+
+                nCIndex = getColumnIndex(LENGTH);
+                if (nCIndex > -1)
+                    vals[nCIndex] = 0;
+
+                nCIndex = getColumnIndex(TIMESTAMP);
+                if (nCIndex > -1)
+                    vals[nCIndex] = 0;
+
+                nCIndex = getColumnIndex(WRITABLE);
+                if (nCIndex > -1)
+                    vals[nCIndex] = (dir.canWrite() ? 1 : 0);
+
+                addRow(vals);
+                }
+            catch (IllegalArgumentException iae) {
+                iae.printStackTrace();
+            }
+
+            File [] files = dir.listFiles();
+            if (files != null) {
+                if ((nFiles = files.length) > 0) {
+                    for (lcvFiles = 0; lcvFiles < nFiles; lcvFiles++) {
+                        nCIndex = getColumnIndex(_ID);
+                        if (nCIndex > -1)
+                            vals[nCIndex] = lcvFiles;
+
+                        nCIndex = getColumnIndex(ISDIR);
+                        if (nCIndex > -1)
+                            vals[nCIndex] = (files[lcvFiles].isDirectory() ? 1 : 0);
+
+                        nCIndex = getColumnIndex(FILENAME);
+                        if (nCIndex > -1)
+                                vals[nCIndex] = files[lcvFiles].getName();
+
+                        nCIndex = getColumnIndex(LENGTH);
+                        if (nCIndex > -1)
+                            vals[nCIndex] = (files[lcvFiles].isDirectory() ? -1 : files[lcvFiles].length());
+
+                        try {
+                            addRow(vals);
+                        } catch (IllegalArgumentException iae) {
+                            iae.printStackTrace();
+                        }
+                    }
+                }
+            }
+        } else {
+            if (dir.isFile()) {
+                nCIndex = getColumnIndex(_ID);
+                if (nCIndex > -1)
+                    vals[nCIndex] = -1;
+
+                nCIndex = getColumnIndex(ISDIR);
+                if (nCIndex > -1)
+                    vals[nCIndex] = 0;
+
+                nCIndex = getColumnIndex(FILENAME);
+                if (nCIndex > -1)
+                    vals[nCIndex] = dir.getName();
+
+                nCIndex = getColumnIndex(LENGTH);
+                if (nCIndex > -1)
+                    vals[nCIndex] = dir.length();
+
+                nCIndex = getColumnIndex(TIMESTAMP);
+                if (nCIndex > -1) {
+                    vals[nCIndex] = dir.lastModified();
+                }
+
+                try {
+                    addRow(vals);
+                    }
+                catch (IllegalArgumentException iae) {
+                    iae.printStackTrace();
+                }
+            }
+            else {
+                try {
+                    nCIndex = getColumnIndex(_ID);
+                    if (nCIndex > -1)
+                        vals[nCIndex] = -1;
+
+                    nCIndex = getColumnIndex(ISDIR);
+                    if (nCIndex > -1)
+                        vals[nCIndex] = 0;
+
+                    nCIndex = getColumnIndex(FILENAME);
+                    if (nCIndex > -1)
+                        vals[nCIndex] = null;
+
+                    nCIndex = getColumnIndex(LENGTH);
+                    if (nCIndex > -1)
+                        vals[nCIndex] = 0;
+
+                    nCIndex = getColumnIndex(TIMESTAMP);
+                    if (nCIndex > -1)
+                        vals[nCIndex] = 0;
+
+                    addRow(vals);
+                    }
+                catch (IllegalArgumentException iae) {
+                    iae.printStackTrace();
+                }
+            }
+        }
+    }
+}
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/ffxcp/FfxCPFP.java b/src/third_party/mozjs-45/build/mobile/sutagent/android/ffxcp/FfxCPFP.java
new file mode 100644
index 0000000..de58689
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/ffxcp/FfxCPFP.java
@@ -0,0 +1,193 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+package org.mozilla.ffxcp;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.content.UriMatcher;
+import android.database.Cursor;
+import android.net.Uri;
+
+public class FfxCPFP extends ContentProvider {
+    public static final String PROVIDER_NAME = "org.mozilla.ffxcp";
+    public static final Uri CONTENT_URI = Uri.parse("content://" + PROVIDER_NAME + "/file");
+
+    public static final String _ID = "_id";
+    public static final String ISDIR = "isdir";
+    public static final String FILENAME = "filename";
+    public static final String LENGTH = "length";
+    public static final String CHUNK = "chunk";
+    static String[] dircolumns = new String[] {
+        _ID,
+        ISDIR,
+        FILENAME,
+        LENGTH
+     };
+
+    static String[] filecolumns = new String[] {
+        _ID,
+        CHUNK
+     };
+
+    private static final int DIR = 1;
+    private static final int FILE_NAME = 2;
+
+    private static final UriMatcher uriMatcher;
+    static {
+        uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
+           uriMatcher.addURI(PROVIDER_NAME, "dir", DIR);
+           uriMatcher.addURI(PROVIDER_NAME, "file", FILE_NAME);
+        }
+
+    public int PruneDir(String sTmpDir) {
+        int    nRet = 0;
+        int nFiles = 0;
+        String sSubDir = null;
+
+        File dir = new File(sTmpDir);
+
+        if (dir.isDirectory()) {
+            File [] files = dir.listFiles();
+            if (files != null) {
+                if ((nFiles = files.length) > 0) {
+                    for (int lcv = 0; lcv < nFiles; lcv++) {
+                        if (files[lcv].isDirectory()) {
+                            sSubDir = files[lcv].getAbsolutePath();
+                            nRet += PruneDir(sSubDir);
+                        }
+                        else {
+                            if (files[lcv].delete()) {
+                                nRet++;
+                            }
+                        }
+                    }
+                }
+            }
+            if (dir.delete()) {
+                nRet++;
+            }
+            if ((nFiles + 1) > nRet) {
+                nRet = -1;
+            }
+        }
+
+    return(nRet);
+    }
+
+    @Override
+    public int delete(Uri uri, String selection, String[] selectionArgs) {
+        int nFiles = 0;
+        switch (uriMatcher.match(uri)) {
+            case FILE_NAME:
+                File f = new File(selection);
+                if (f.delete())
+                    nFiles = 1;
+                break;
+
+            case DIR:
+                nFiles = PruneDir(selection);
+                break;
+
+            default:
+                break;
+        }
+        return nFiles;
+    }
+
+    @Override
+    public String getType(Uri uri)
+        {
+        switch (uriMatcher.match(uri))
+            {
+            //---get directory---
+            case DIR:
+                return "vnd.android.cursor.dir/vnd.mozilla.dir ";
+            //---get a particular file---
+            case FILE_NAME:
+                return "vnd.android.cursor.item/vnd.mozilla.file ";
+            //---Unknown---
+            default:
+                throw new IllegalArgumentException("Unsupported URI: " + uri);
+            }
+    }
+
+    @Override
+    public Uri insert(Uri uri, ContentValues values) {
+        return null;
+    }
+
+    @Override
+    public boolean onCreate() {
+        return true;
+    }
+
+    @Override
+    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
+        Cursor retCursor = null;
+
+        switch(uriMatcher.match(uri)) {
+            case DIR:
+                retCursor = new DirCursor(projection, selection);
+                break;
+
+            case FILE_NAME:
+                retCursor = new FileCursor(projection, selection, selectionArgs);
+                break;
+
+            default:
+                break;
+        }
+        return (retCursor);
+    }
+
+    @Override
+    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+        int    nRet = 0;
+        FileOutputStream dstFile = null;
+
+        switch(uriMatcher.match(uri)) {
+            case DIR:
+                File dir = new File(selection);
+                if (dir.mkdirs())
+                    nRet = 1;
+                break;
+
+            case FILE_NAME:
+                try {
+                    long lOffset = values.getAsLong("offset");
+                    byte [] buf = values.getAsByteArray(CHUNK);
+                    int    nLength = values.getAsInteger(LENGTH);
+                    if ((buf != null) && (nLength > 0)) {
+                        File f = new File(selection);
+                        dstFile = new FileOutputStream(f, (lOffset == 0 ? false : true));
+                        dstFile.write(buf,0, nLength);
+                        dstFile.flush();
+                        dstFile.close();
+                        nRet = nLength;
+                    }
+                } catch (FileNotFoundException fnfe) {
+                    fnfe.printStackTrace();
+                } catch (IOException ioe) {
+                    try {
+                        dstFile.flush();
+                    } catch (IOException e) {
+                    }
+                    try {
+                        dstFile.close();
+                    } catch (IOException e) {
+                    }
+                }
+                break;
+
+            default:
+                break;
+        }
+        return nRet;
+    }
+}
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/ffxcp/FileCursor.java b/src/third_party/mozjs-45/build/mobile/sutagent/android/ffxcp/FileCursor.java
new file mode 100644
index 0000000..52b15e6
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/ffxcp/FileCursor.java
@@ -0,0 +1,169 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+package org.mozilla.ffxcp;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+import android.database.AbstractWindowedCursor;
+import android.database.CursorWindow;
+
+public class FileCursor extends AbstractWindowedCursor {
+    public static final String _ID = "_id";
+    public static final String CHUNK = "chunk";
+    public static final String LENGTH = "length";
+    static final String[] DEFCOLUMNS = new String[] {
+            _ID,
+            CHUNK,
+            LENGTH
+         };
+    private String filePath = null;
+    private String [] theColumns = null;
+
+    private static final int BUFSIZE = 4096;
+    private long lFileSize = 0;
+    private int nCount = 0;
+    private File theFile = null;
+    private byte [] theBuffer = null;
+    private long lOffset = 0;
+    private long lLength = -1;
+
+    public FileCursor(String[] columnNames, String sFilePath, String [] selectionArgs) {
+        super();
+        theColumns = (columnNames == null ? DEFCOLUMNS : columnNames);
+        filePath = sFilePath;
+        nCount = -1;
+
+        if ((selectionArgs != null) && (selectionArgs.length > 0)) {
+            lOffset = Long.parseLong(selectionArgs[0]);
+            lLength = Long.parseLong(selectionArgs[1]);
+        }
+
+        if (filePath.length() > 0) {
+            theFile = new File(filePath);
+            if (theFile.exists() && theFile.canRead()) {
+                lFileSize = theFile.length();
+
+                // lLength == -1 return everything between lOffset and eof
+                // lLength == 0 return file length
+                // lLength > 0 return lLength bytes
+                if (lLength == -1) {
+                    lFileSize = lFileSize - lOffset;
+                } else if (lLength == 0) {
+                    // just return the file length
+                } else {
+                    lFileSize = ((lLength <= (lFileSize - lOffset)) ? lLength : (lFileSize - lOffset));
+                }
+
+                if (lLength != 0) {
+                    nCount = (int) (lFileSize / BUFSIZE);
+                    if ((lFileSize % BUFSIZE) > 0)
+                        nCount++;
+                } else {
+                    nCount = 1;
+                }
+
+            }
+        }
+    }
+
+    public String getColumnName (int columnIndex) {
+        return theColumns[columnIndex];
+    }
+
+    @Override
+    public String[] getColumnNames() {
+        return theColumns;
+    }
+
+    @Override
+    public int getCount() {
+        return nCount;
+    }
+
+    @Override
+    public boolean onMove(int oldPosition, int newPosition) {
+        boolean bRet = true;
+
+        // get rid of old data
+        mWindow.clear();
+        bRet = mWindow.setNumColumns(theColumns.length);
+        fillWindow(newPosition, mWindow);
+
+        return bRet;
+    }
+
+    @Override
+    public void fillWindow (int pos, CursorWindow window) {
+        int    nNumRows = window.getNumRows();
+        int nCIndex = 0;
+        window.setStartPosition(0);
+
+        if (pos > -1) {
+            if (nNumRows == 0) {
+                window.allocRow();
+                nNumRows = window.getNumRows();
+            }
+
+            if (nNumRows == 1) {
+                nCIndex = getColumnIndex(LENGTH);
+                if (nCIndex > -1) {
+                    window.putLong(lFileSize, 0, nCIndex);
+                }
+                nCIndex = getColumnIndex(_ID);
+                if (nCIndex > -1) {
+                    window.putLong((long)pos, 0, nCIndex);
+                }
+                nCIndex = getColumnIndex(CHUNK);
+                if (nCIndex > -1) {
+                    if (lLength != 0) {
+                        byte[] value = getABlob (pos, 1);
+                        window.putBlob(value, 0, nCIndex);
+                    }
+                }
+            }
+            window.setStartPosition(pos);
+        }
+        return;
+    }
+
+    public byte[] getABlob (int row, int column) {
+        int    nRead = 0;
+        int    nOffset = 0;
+        int nBufSize = 0;
+
+        if ((column == 1) && (theFile != null)) {
+            try {
+                FileInputStream fin = new FileInputStream(theFile);
+                nOffset = row * BUFSIZE;
+                if (row < (nCount - 1)) {
+                    nBufSize = BUFSIZE;
+                } else {
+                    nBufSize = (int) (lFileSize - nOffset);
+                }
+                theBuffer = new byte[nBufSize];
+
+                if (theBuffer != null) {
+                    if (fin.skip(nOffset + lOffset) == (nOffset + lOffset)) {
+                        if ((nRead = fin.read(theBuffer, 0, nBufSize)) != -1) {
+                            if (nRead != nBufSize) {
+                                return null;
+                            }
+                        }
+                    }
+                }
+
+            fin.close();
+            } catch (FileNotFoundException e) {
+                e.printStackTrace();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+
+        return theBuffer;
+    }
+}
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/ffxcp/Makefile.in b/src/third_party/mozjs-45/build/mobile/sutagent/android/ffxcp/Makefile.in
new file mode 100644
index 0000000..001fc81
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/ffxcp/Makefile.in
@@ -0,0 +1,14 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+include $(topsrcdir)/config/config.mk
+
+JAVAFILES = \
+  DirCursor.java \
+  ffxcp.java \
+  FfxCPFP.java \
+  FileCursor.java \
+  $(NULL)
+
+tools:: $(ANDROID_APK_NAME).apk
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/ffxcp/default.properties b/src/third_party/mozjs-45/build/mobile/sutagent/android/ffxcp/default.properties
new file mode 100644
index 0000000..06596fb
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/ffxcp/default.properties
@@ -0,0 +1,15 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+# 
+# This file must be checked in Version Control Systems.
+# 
+# To customize properties used by the Ant build system use,
+# "build.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-6
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/ffxcp/ffxcp.java b/src/third_party/mozjs-45/build/mobile/sutagent/android/ffxcp/ffxcp.java
new file mode 100644
index 0000000..39d3c58
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/ffxcp/ffxcp.java
@@ -0,0 +1,16 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+package org.mozilla.ffxcp;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class ffxcp extends Activity {
+    /** Called when the activity is first created. */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.main);
+    }
+}
\ No newline at end of file
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/ffxcp/moz.build b/src/third_party/mozjs-45/build/mobile/sutagent/android/ffxcp/moz.build
new file mode 100644
index 0000000..5abafd2
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/ffxcp/moz.build
@@ -0,0 +1,8 @@
+# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+ANDROID_APK_NAME = 'FfxCP'
+ANDROID_APK_PACKAGE = 'org.mozilla.ffxcp'
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/ffxcp/res/drawable-hdpi/icon.png b/src/third_party/mozjs-45/build/mobile/sutagent/android/ffxcp/res/drawable-hdpi/icon.png
new file mode 100644
index 0000000..8074c4c
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/ffxcp/res/drawable-hdpi/icon.png
Binary files differ
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/ffxcp/res/drawable-ldpi/icon.png b/src/third_party/mozjs-45/build/mobile/sutagent/android/ffxcp/res/drawable-ldpi/icon.png
new file mode 100644
index 0000000..1095584
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/ffxcp/res/drawable-ldpi/icon.png
Binary files differ
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/ffxcp/res/drawable-mdpi/icon.png b/src/third_party/mozjs-45/build/mobile/sutagent/android/ffxcp/res/drawable-mdpi/icon.png
new file mode 100644
index 0000000..a07c69f
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/ffxcp/res/drawable-mdpi/icon.png
Binary files differ
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/ffxcp/res/layout/main.xml b/src/third_party/mozjs-45/build/mobile/sutagent/android/ffxcp/res/layout/main.xml
new file mode 100644
index 0000000..1256b1a
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/ffxcp/res/layout/main.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    >
+<TextView  
+    android:layout_width="fill_parent" 
+    android:layout_height="wrap_content" 
+    android:text="@string/hello"
+    />
+</LinearLayout>
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/ffxcp/res/values/strings.xml b/src/third_party/mozjs-45/build/mobile/sutagent/android/ffxcp/res/values/strings.xml
new file mode 100644
index 0000000..e7e8d7b
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/ffxcp/res/values/strings.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<resources>
+    <string name="hello">Hello World, firefoxcp!</string>
+    <string name="app_name">FirefoxCP</string>
+</resources>
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/moz.build b/src/third_party/mozjs-45/build/mobile/sutagent/android/moz.build
new file mode 100644
index 0000000..c9505ec
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/moz.build
@@ -0,0 +1,8 @@
+# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+ANDROID_APK_NAME = 'sutAgentAndroid'
+ANDROID_APK_PACKAGE = 'com.mozilla.SUTAgentAndroid'
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/network-libs/commons-net-2.0-javadoc.jar b/src/third_party/mozjs-45/build/mobile/sutagent/android/network-libs/commons-net-2.0-javadoc.jar
new file mode 100755
index 0000000..c68405d
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/network-libs/commons-net-2.0-javadoc.jar
Binary files differ
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/network-libs/commons-net-2.0-sources.jar b/src/third_party/mozjs-45/build/mobile/sutagent/android/network-libs/commons-net-2.0-sources.jar
new file mode 100755
index 0000000..50cc210
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/network-libs/commons-net-2.0-sources.jar
Binary files differ
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/network-libs/commons-net-2.0.jar b/src/third_party/mozjs-45/build/mobile/sutagent/android/network-libs/commons-net-2.0.jar
new file mode 100755
index 0000000..dd7a52a
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/network-libs/commons-net-2.0.jar
Binary files differ
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/network-libs/commons-net-ftp-2.0.jar b/src/third_party/mozjs-45/build/mobile/sutagent/android/network-libs/commons-net-ftp-2.0.jar
new file mode 100755
index 0000000..f697534
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/network-libs/commons-net-ftp-2.0.jar
Binary files differ
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/network-libs/jmdns.jar b/src/third_party/mozjs-45/build/mobile/sutagent/android/network-libs/jmdns.jar
new file mode 100755
index 0000000..ec1c263
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/network-libs/jmdns.jar
Binary files differ
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/res/drawable/ateamlogo.png b/src/third_party/mozjs-45/build/mobile/sutagent/android/res/drawable/ateamlogo.png
new file mode 100644
index 0000000..6f65bd6
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/res/drawable/ateamlogo.png
Binary files differ
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/res/drawable/ic_stat_first.png b/src/third_party/mozjs-45/build/mobile/sutagent/android/res/drawable/ic_stat_first.png
new file mode 100644
index 0000000..95b0904
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/res/drawable/ic_stat_first.png
Binary files differ
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/res/drawable/ic_stat_neterror.png b/src/third_party/mozjs-45/build/mobile/sutagent/android/res/drawable/ic_stat_neterror.png
new file mode 100644
index 0000000..90c0bf8
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/res/drawable/ic_stat_neterror.png
Binary files differ
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/res/drawable/ic_stat_second.png b/src/third_party/mozjs-45/build/mobile/sutagent/android/res/drawable/ic_stat_second.png
new file mode 100644
index 0000000..e3304e5
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/res/drawable/ic_stat_second.png
Binary files differ
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/res/drawable/ic_stat_warning.png b/src/third_party/mozjs-45/build/mobile/sutagent/android/res/drawable/ic_stat_warning.png
new file mode 100644
index 0000000..be00f47
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/res/drawable/ic_stat_warning.png
Binary files differ
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/res/drawable/icon.png b/src/third_party/mozjs-45/build/mobile/sutagent/android/res/drawable/icon.png
new file mode 100644
index 0000000..a07c69f
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/res/drawable/icon.png
Binary files differ
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/res/layout/main.xml b/src/third_party/mozjs-45/build/mobile/sutagent/android/res/layout/main.xml
new file mode 100755
index 0000000..07ae83b
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/res/layout/main.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    >
+<TextView  
+    android:layout_width="fill_parent" 
+    android:layout_height="wrap_content" 
+    android:id="@+id/Textview01"/>
+
+
+
+
+<Button android:id="@+id/Button01" android:layout_width="wrap_content" android:layout_height="wrap_content" android:clickable="true" android:text="Exit"></Button>
+
+
+
+</LinearLayout>
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/res/values/strings.xml b/src/third_party/mozjs-45/build/mobile/sutagent/android/res/values/strings.xml
new file mode 100755
index 0000000..518e77a
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/res/values/strings.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<resources>
+    
+    <string name="hello">Hello World, SUTAgentAndroid!</string>
+    <string name="app_name">SUTAgentAndroid</string>
+	
+
+<string name="foreground_service_started">Foreground Service Started (ASMozStub)</string>
+
+</resources>
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/AndroidManifest.xml b/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/AndroidManifest.xml
new file mode 100644
index 0000000..b78dce5
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/AndroidManifest.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+      package="com.mozilla.watcher"
+      android:versionCode="1"
+      android:versionName="1.0">
+    <uses-permission android:name="android.permission.WRITE_SETTINGS"></uses-permission>
+    <application android:icon="@drawable/icon" android:label="@string/app_name">
+        <activity android:name=".WatcherMain"
+                  android:label="@string/app_name">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        <receiver android:name=".WatcherReceiver">
+            <intent-filter>
+                 <action android:value="android.intent.action.BOOT_COMPLETED" android:name="android.intent.action.BOOT_COMPLETED"/>
+                 <category android:value="android.intent.category.HOME" android:name="android.intent.category.HOME"/>
+            </intent-filter>
+        </receiver>
+	<service android:name="WatcherService">
+		<intent-filter>
+			<action android:name="com.mozilla.watcher.LISTENER_SERVICE" />
+		</intent-filter>
+	</service>
+
+    </application>
+    <uses-sdk android:minSdkVersion="5" />
+    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> 
+
+
+<uses-permission android:name="android.permission.INTERNET"></uses-permission>
+
+<uses-permission android:name="android.permission.DISABLE_KEYGUARD"></uses-permission>
+
+<uses-permission android:name="android.permission.WAKE_LOCK"></uses-permission>
+
+<uses-permission android:name="android.permission.VIBRATE"></uses-permission>
+
+</manifest> 
\ No newline at end of file
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/IWatcherService.java b/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/IWatcherService.java
new file mode 100644
index 0000000..9883c8a
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/IWatcherService.java
@@ -0,0 +1,108 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * This file is auto-generated.  DO NOT MODIFY.
+ * Original file: C:\\Users\\Bob\\workspace\\Watcher\\src\\com\\mozilla\\watcher\\IWatcherService.aidl
+ */
+package com.mozilla.watcher;
+public interface IWatcherService extends android.os.IInterface
+{
+/** Local-side IPC implementation stub class. */
+public static abstract class Stub extends android.os.Binder implements com.mozilla.watcher.IWatcherService
+{
+private static final java.lang.String DESCRIPTOR = "com.mozilla.watcher.IWatcherService";
+/** Construct the stub at attach it to the interface. */
+public Stub()
+{
+this.attachInterface(this, DESCRIPTOR);
+}
+/**
+ * Cast an IBinder object into an com.mozilla.watcher.IWatcherService interface,
+ * generating a proxy if needed.
+ */
+public static com.mozilla.watcher.IWatcherService asInterface(android.os.IBinder obj)
+{
+if ((obj==null)) {
+return null;
+}
+android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);
+if (((iin!=null)&&(iin instanceof com.mozilla.watcher.IWatcherService))) {
+return ((com.mozilla.watcher.IWatcherService)iin);
+}
+return new com.mozilla.watcher.IWatcherService.Stub.Proxy(obj);
+}
+public android.os.IBinder asBinder()
+{
+return this;
+}
+@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
+{
+switch (code)
+{
+case INTERFACE_TRANSACTION:
+{
+reply.writeString(DESCRIPTOR);
+return true;
+}
+case TRANSACTION_UpdateApplication:
+{
+data.enforceInterface(DESCRIPTOR);
+java.lang.String _arg0;
+_arg0 = data.readString();
+java.lang.String _arg1;
+_arg1 = data.readString();
+java.lang.String _arg2;
+_arg2 = data.readString();
+int _arg3;
+_arg3 = data.readInt();
+int _result = this.UpdateApplication(_arg0, _arg1, _arg2, _arg3);
+reply.writeNoException();
+reply.writeInt(_result);
+return true;
+}
+}
+return super.onTransact(code, data, reply, flags);
+}
+private static class Proxy implements com.mozilla.watcher.IWatcherService
+{
+private android.os.IBinder mRemote;
+Proxy(android.os.IBinder remote)
+{
+mRemote = remote;
+}
+public android.os.IBinder asBinder()
+{
+return mRemote;
+}
+public java.lang.String getInterfaceDescriptor()
+{
+return DESCRIPTOR;
+}
+public int UpdateApplication(java.lang.String sPkgName, java.lang.String sPkgFileName, java.lang.String sOutFile, int bReboot) throws android.os.RemoteException
+{
+android.os.Parcel _data = android.os.Parcel.obtain();
+android.os.Parcel _reply = android.os.Parcel.obtain();
+int _result;
+try {
+_data.writeInterfaceToken(DESCRIPTOR);
+_data.writeString(sPkgName);
+_data.writeString(sPkgFileName);
+_data.writeString(sOutFile);
+_data.writeInt(bReboot);
+mRemote.transact(Stub.TRANSACTION_UpdateApplication, _data, _reply, 0);
+_reply.readException();
+_result = _reply.readInt();
+}
+finally {
+_reply.recycle();
+_data.recycle();
+}
+return _result;
+}
+}
+static final int TRANSACTION_UpdateApplication = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
+}
+public int UpdateApplication(java.lang.String sPkgName, java.lang.String sPkgFileName, java.lang.String sOutFile, int bReboot) throws android.os.RemoteException;
+}
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/Makefile.in b/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/Makefile.in
new file mode 100644
index 0000000..2c23532
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/Makefile.in
@@ -0,0 +1,15 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+include $(topsrcdir)/config/config.mk
+
+JAVAFILES = \
+  IWatcherService.java \
+  RedirOutputThread.java \
+  WatcherMain.java \
+  WatcherReceiver.java \
+  WatcherService.java \
+  $(NULL)
+
+tools:: $(ANDROID_APK_NAME).apk
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/RedirOutputThread.java b/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/RedirOutputThread.java
new file mode 100644
index 0000000..f72289a
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/RedirOutputThread.java
@@ -0,0 +1,130 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package com.mozilla.watcher;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+
+public class RedirOutputThread extends Thread
+    {
+    OutputStream out;
+    InputStream    sutErr;
+    InputStream    sutOut;
+    Process pProc;
+    String    strOutput;
+
+    public RedirOutputThread(Process pProc, OutputStream out)
+        {
+        if (pProc != null)
+            {
+            this.pProc = pProc;
+            sutErr = pProc.getErrorStream(); // Stderr
+            sutOut = pProc.getInputStream(); // Stdout
+            }
+        if (out != null)
+            this.out = out;
+
+        strOutput = "";
+        }
+
+    public void run()
+        {
+        boolean bStillRunning = true;
+        int    nBytesOut = 0;
+        int nBytesErr = 0;
+        int nBytesRead = 0;
+        PrintWriter pOut = null;
+        byte[] buffer = new byte[1024];
+
+        if (out != null)
+            pOut = new PrintWriter(out);
+        else
+            bStillRunning = true;
+
+        while (bStillRunning)
+            {
+            try
+                {
+                if ((nBytesOut = sutOut.available()) > 0)
+                    {
+                    if (nBytesOut > buffer.length)
+                        {
+                        buffer = null;
+                        System.gc();
+                        buffer = new byte[nBytesOut];
+                        }
+                    nBytesRead = sutOut.read(buffer, 0, nBytesOut);
+                    if (nBytesRead == -1)
+                        bStillRunning = false;
+                    else
+                        {
+                        String sRep = new String(buffer,0,nBytesRead).replace("\n", "\r\n");
+                        if (pOut != null)
+                            {
+                            pOut.print(sRep);
+                            pOut.flush();
+                            }
+                        else
+                            strOutput += sRep;
+                        }
+                    }
+
+                if ((nBytesErr = sutErr.available()) > 0)
+                    {
+                    if (nBytesErr > buffer.length)
+                        {
+                        buffer = null;
+                        System.gc();
+                        buffer = new byte[nBytesErr];
+                        }
+                    nBytesRead = sutErr.read(buffer, 0, nBytesErr);
+                    if (nBytesRead == -1)
+                        bStillRunning = false;
+                    else
+                        {
+                        String sRep = new String(buffer,0,nBytesRead).replace("\n", "\r\n");
+                        if (pOut != null)
+                            {
+                            pOut.print(sRep);
+                            pOut.flush();
+                            }
+                        else
+                            strOutput += sRep;
+                        }
+                    }
+
+                bStillRunning = (IsProcRunning(pProc) || (sutOut.available() > 0) || (sutErr.available() > 0));
+                }
+            catch (IOException e)
+                {
+                e.printStackTrace();
+                }
+            }
+
+        pProc.destroy();
+        buffer = null;
+        System.gc();
+        }
+
+    private boolean IsProcRunning(Process pProc)
+        {
+        boolean bRet = false;
+        @SuppressWarnings("unused")
+        int nExitCode = 0;
+
+        try
+            {
+            nExitCode = pProc.exitValue();
+            }
+        catch (IllegalThreadStateException z)
+            {
+            bRet = true;
+            }
+
+        return(bRet);
+        }
+    }
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/WatcherMain.java b/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/WatcherMain.java
new file mode 100644
index 0000000..d0c5ee6
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/WatcherMain.java
@@ -0,0 +1,16 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+package com.mozilla.watcher;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class WatcherMain extends Activity {
+    /** Called when the activity is first created. */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.main);
+    }
+}
\ No newline at end of file
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/WatcherReceiver.java b/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/WatcherReceiver.java
new file mode 100644
index 0000000..f47b424
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/WatcherReceiver.java
@@ -0,0 +1,22 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+package com.mozilla.watcher;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+// import android.os.Debug;
+
+public class WatcherReceiver extends BroadcastReceiver {
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+//        Debug.waitForDebugger();
+        Intent serviceIntent = new Intent();
+        serviceIntent.putExtra("command", "start");
+        serviceIntent.setAction("com.mozilla.watcher.LISTENER_SERVICE");
+        context.startService(serviceIntent);
+    }
+
+}
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/WatcherService.java b/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/WatcherService.java
new file mode 100644
index 0000000..7a6b5e9
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/WatcherService.java
@@ -0,0 +1,1034 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+package com.mozilla.watcher;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Date;
+import java.util.List;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.app.KeyguardManager;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.content.ActivityNotFoundException;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.BatteryManager;
+import android.os.Debug;
+import android.os.IBinder;
+import android.os.PowerManager;
+import android.os.RemoteException;
+import android.provider.Settings;
+import android.util.Log;
+import android.os.Environment;
+
+public class WatcherService extends Service
+{
+    private final String prgVersion = "Watcher Version 1.17";
+    private final String LOGTAG = "Watcher";
+
+    String sErrorPrefix = "##Installer Error## ";
+    String currentDir = "/";
+    String sPingTarget = "";
+    long lDelay = 60000;
+    long lPeriod = 300000;
+    int nMaxStrikes = 0; // maximum number of tries before we consider network unreachable (0 means don't check)
+    boolean bStartSUTAgent = true;
+    boolean bStartedTimer = false;
+
+    Process pProc;
+    Context myContext = null;
+    Timer myTimer = null;
+    private PowerManager.WakeLock pwl = null;
+    public static final int NOTIFICATION_ID = 1964;
+    boolean bInstalling = false;
+
+    @SuppressWarnings("unchecked")
+    private static final Class<?>[] mSetForegroundSignature = new Class[] {
+        boolean.class};
+    @SuppressWarnings("unchecked")
+    private static final Class<?>[] mStartForegroundSignature = new Class[] {
+        int.class, Notification.class};
+    @SuppressWarnings("unchecked")
+    private static final Class<?>[] mStopForegroundSignature = new Class[] {
+        boolean.class};
+
+    private NotificationManager mNM;
+    private Method mSetForeground;
+    private Method mStartForeground;
+    private Method mStopForeground;
+    private Object[] mSetForegroundArgs = new Object[1];
+    private Object[] mStartForegroundArgs = new Object[2];
+    private Object[] mStopForegroundArgs = new Object[1];
+
+
+    private IWatcherService.Stub stub = new IWatcherService.Stub() {
+        public int UpdateApplication(String sAppName, String sFileName, String sOutFile, int bReboot) throws RemoteException
+            {
+            return UpdtApp(sAppName, sFileName, sOutFile, bReboot);
+            }
+    };
+
+    @Override
+    public IBinder onBind(Intent arg0) {
+        return stub;
+    }
+
+    @Override
+    public void onCreate()
+        {
+        super.onCreate();
+
+        Log.i(LOGTAG, prgVersion);
+
+        myContext = this;
+
+        getKeyGuardAndWakeLock();
+
+        File dir = getFilesDir();
+        File iniFile = new File(dir, "watcher.ini");
+        String sIniFile = iniFile.getAbsolutePath();
+        String sHold = "";
+
+        Log.i(LOGTAG, String.format("Loading settings from %s", sIniFile));
+        this.sPingTarget = GetIniData("watcher", "PingTarget", sIniFile, "www.mozilla.org");
+        sHold = GetIniData("watcher", "delay", sIniFile, "60000");
+        this.lDelay = Long.parseLong(sHold.trim());
+        sHold = GetIniData("watcher", "period", sIniFile,"300000");
+        this.lPeriod = Long.parseLong(sHold.trim());
+        sHold = GetIniData("watcher", "strikes", sIniFile,"0");
+        this.nMaxStrikes = Integer.parseInt(sHold.trim());
+        Log.i(LOGTAG, String.format("Pinging %s after a delay of %s sec, period of %s sec, max number of failed attempts is %s (if max # of failed attempts is 0, then no checking)",
+             this.sPingTarget, this.lDelay / 1000.0, this.lPeriod / 1000.0, nMaxStrikes));
+
+        sHold = GetIniData("watcher", "StartSUTAgent", sIniFile, "true");
+        this.bStartSUTAgent = Boolean.parseBoolean(sHold.trim());
+
+        sHold = GetIniData("watcher", "stayon", sIniFile,"0");
+        int nStayOn = Integer.parseInt(sHold.trim());
+        
+        try {
+            if (nStayOn != 0) {
+                if (!Settings.System.putInt(getContentResolver(), Settings.System.STAY_ON_WHILE_PLUGGED_IN, BatteryManager.BATTERY_PLUGGED_AC | BatteryManager.BATTERY_PLUGGED_USB)) {
+                    Log.e(LOGTAG, "Screen couldn't be set to Always On [stay on while plugged in]");
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            String sExcept = e.getMessage();
+            Log.e(LOGTAG, "Screen couldn't be set to Always On [exception " + sExcept + "]");
+        }
+
+        Log.i(LOGTAG, "WatcherService created");
+        }
+
+    public String GetIniData(String sSection, String sKey, String sFile, String sDefault)
+        {
+        String sRet = sDefault;
+        String sComp = "";
+        String sLine = "";
+        boolean bFound = false;
+        BufferedReader in = null;
+        String sTmpFileName = fixFileName(sFile);
+
+        try {
+            in = new BufferedReader(new FileReader(sTmpFileName));
+            sComp = "[" + sSection + "]";
+            while ((sLine = in.readLine()) != null)
+                {
+                if (sLine.equalsIgnoreCase(sComp))
+                    {
+                    bFound = true;
+                    break;
+                    }
+                }
+
+            if (bFound)
+                {
+                sComp = (sKey + " =").toLowerCase();
+                while ((sLine = in.readLine()) != null)
+                    {
+                    if (sLine.toLowerCase().contains(sComp))
+                        {
+                        String [] temp = null;
+                        temp = sLine.split("=");
+                        if (temp != null)
+                            {
+                            if (temp.length > 1)
+                                sRet = temp[1].trim();
+                            }
+                        break;
+                        }
+                    }
+                }
+            in.close();
+            }
+        catch (FileNotFoundException e)
+            {
+            sComp = e.toString();
+            }
+        catch (IOException e)
+            {
+            sComp = e.toString();
+            }
+        return (sRet);
+        }
+
+    private void handleCommand(Intent intent)
+        {
+        // Note: intent can be null "if the service is being restarted after its process
+        // has gone away". In this case, we will consider that to be equivalent to a start
+        // http://developer.android.com/reference/android/app/Service.html#onStartCommand%28android.content.Intent,%20int,%20int%29
+
+        String sCmd = "start";
+        if (intent != null)
+            {
+            sCmd = intent.getStringExtra("command");
+            }
+
+        if (sCmd != null)
+            {
+            if (sCmd.equalsIgnoreCase("updt"))
+                {
+                String sPkgName = intent.getStringExtra("pkgName");
+                String sPkgFile = intent.getStringExtra("pkgFile");
+                String sOutFile = intent.getStringExtra("outFile");
+                boolean bReboot = intent.getBooleanExtra("reboot", true);
+                int nReboot = bReboot ? 1 : 0;
+                Log.i(LOGTAG, "WatcherService updating " + sPkgName + " using file " + sPkgFile);
+
+                UpdateApplication worker = new UpdateApplication(sPkgName, sPkgFile, sOutFile, nReboot);
+                }
+            else if (sCmd.equalsIgnoreCase("start"))
+                {
+                if (!this.bStartedTimer) 
+                    {
+                    Log.i(LOGTAG, "WatcherService started");
+                    myTimer = new Timer();
+                    Date startSchedule = new Date(System.currentTimeMillis() + lDelay);
+                    myTimer.schedule(new MyTime(), startSchedule, lPeriod);
+                    this.bStartedTimer = true;
+                    }
+                }
+            else
+                {
+                Log.w(LOGTAG, "WatcherService unknown command");
+                }
+            }
+        else
+            Log.w(LOGTAG, "WatcherService intent had null command");
+        }
+
+    public void writeVersion() {
+        PrintWriter pw = null;
+        String appPath = getApplicationContext().getFilesDir().getAbsolutePath();
+        String versionPath = appPath + "/version.txt";
+        Log.i(LOGTAG, "writing version string to: " + versionPath);
+        try {
+            pw = new PrintWriter(new FileWriter(versionPath, true));
+            pw.println(this.prgVersion);
+        } catch (IOException ioe) {
+            Log.e(LOGTAG, "Exception writing version: " + this.prgVersion + " to file: " + versionPath);
+        } finally {
+            if (pw != null) {
+                pw.close();
+            }
+        }
+    }
+
+    @Override
+    public void onStart(Intent intent, int startId) {
+        Log.i(LOGTAG, "onStart");
+        writeVersion();
+        handleCommand(intent);
+        return;
+    }
+
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startId) {
+        Log.i(LOGTAG, "onStartCommand");
+        writeVersion();
+        handleCommand(intent);
+        return START_STICKY;
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        Log.i(LOGTAG, "WatcherService destroyed");
+        if (pwl != null)
+            pwl.release();
+        stopForegroundCompat(R.string.foreground_service_started);
+    }
+
+    @Override
+    public void onLowMemory() {
+        Log.e(LOGTAG, "onLowMemory");
+        System.gc();
+    }
+
+    @Override
+    public void onTrimMemory(int level) {
+        Log.e(LOGTAG, "onTrimMemory: "+level);
+        System.gc();
+    }
+
+    protected void getKeyGuardAndWakeLock()
+        {
+        // Fire off a thread to do some work that we shouldn't do directly in the UI thread
+        Thread t = new Thread() {
+            public void run() {
+                Log.i(LOGTAG, "worker thread started");
+                // Keep phone from locking or remove lock on screen
+                KeyguardManager km = (KeyguardManager)getSystemService(Context.KEYGUARD_SERVICE);
+                if (km != null)
+                    {
+                    KeyguardManager.KeyguardLock kl = km.newKeyguardLock("watcher");
+                    if (kl != null)
+                        {
+                        kl.disableKeyguard();
+                        Log.i(LOGTAG, "keyguard disabled");
+                        }
+                    }
+
+                // No sleeping on the job
+                PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
+                if (pm != null)
+                    {
+                    pwl = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "watcher");
+                    if (pwl != null)
+                        {
+                        pwl.acquire();
+                        Log.i(LOGTAG, "wake lock acquired");
+                        }
+                    }
+
+                Class<?> serviceClass = null;
+                try {
+                    serviceClass = Class.forName("com.mozilla.watcher.WatcherService");
+                    }
+                catch (Exception e)
+                    {
+                    Log.e(LOGTAG, "unable to find service class: "+e.toString());
+                    return;
+                    }
+                mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
+                try {
+                    mStartForeground = serviceClass.getMethod("startForeground", mStartForegroundSignature);
+                    mStopForeground = serviceClass.getMethod("stopForeground", mStopForegroundSignature);
+                    }
+                catch (NoSuchMethodException e)
+                    {
+                    // Might be running on an older platform.
+                    mStartForeground = mStopForeground = null;
+                    Log.w(LOGTAG, "unable to find start/stopForeground method(s) -- older platform?");
+                    }
+                try {
+                    mSetForeground = serviceClass.getMethod("setForeground", mSetForegroundSignature);
+                    }
+                catch (NoSuchMethodException e) 
+                    {
+                    mSetForeground = null;
+                    Log.e(LOGTAG, "unable to find setForeground method!");
+                    }
+                Notification notification = new Notification();
+                startForegroundCompat(R.string.foreground_service_started, notification);
+                }
+            };
+        t.start();
+        }
+
+    /**
+     * This is a wrapper around the new startForeground method, using the older
+     * APIs if it is not available.
+     */
+    void startForegroundCompat(int id, Notification notification) {
+        // If we have the new startForeground API, then use it.
+        if (mStartForeground != null) {
+            mStartForegroundArgs[0] = Integer.valueOf(id);
+            mStartForegroundArgs[1] = notification;
+            try {
+                mStartForeground.invoke(this, mStartForegroundArgs);
+                Log.i(LOGTAG, "startForeground invoked");
+            } catch (InvocationTargetException e) {
+                // Should not happen.
+                Log.e(LOGTAG, "Unable to invoke startForeground", e);
+            } catch (IllegalAccessException e) {
+                // Should not happen.
+                Log.e(LOGTAG, "Unable to invoke startForeground", e);
+            }
+            return;
+        }
+
+        // Fall back on the old API.
+        if  (mSetForeground != null) {
+            try {
+                mSetForegroundArgs[0] = Boolean.TRUE;
+                mSetForeground.invoke(this, mSetForegroundArgs);
+                Log.i(LOGTAG, "setForeground(TRUE) invoked");
+            } catch (IllegalArgumentException e) {
+                Log.e(LOGTAG, "Unable to invoke setForeground", e);
+                e.printStackTrace();
+            } catch (IllegalAccessException e) {
+                Log.e(LOGTAG, "Unable to invoke setForeground", e);
+                e.printStackTrace();
+            } catch (InvocationTargetException e) {
+                Log.e(LOGTAG, "Unable to invoke setForeground", e);
+                e.printStackTrace();
+            }
+        }
+        mNM.notify(id, notification);
+    }
+
+    /**
+     * This is a wrapper around the new stopForeground method, using the older
+     * APIs if it is not available.
+     */
+    void stopForegroundCompat(int id) {
+        // If we have the new stopForeground API, then use it.
+        if (mStopForeground != null) {
+            mStopForegroundArgs[0] = Boolean.TRUE;
+            try {
+                mStopForeground.invoke(this, mStopForegroundArgs);
+                Log.i(LOGTAG, "stopForeground invoked");
+            } catch (InvocationTargetException e) {
+                // Should not happen.
+                Log.e(LOGTAG, "Unable to invoke stopForeground", e);
+            } catch (IllegalAccessException e) {
+                // Should not happen.
+                Log.e(LOGTAG, "Unable to invoke stopForeground", e);
+            }
+            return;
+        }
+
+        // Fall back on the old API.  Note to cancel BEFORE changing the
+        // foreground state, since we could be killed at that point.
+        mNM.cancel(id);
+        if  (mSetForeground != null) {
+            try {
+                mSetForegroundArgs[0] = Boolean.FALSE;
+                mSetForeground.invoke(this, mSetForegroundArgs);
+                Log.i(LOGTAG, "setForeground(FALSE) invoked");
+            } catch (IllegalArgumentException e) {
+                Log.e(LOGTAG, "Unable to invoke setForeground", e);
+                e.printStackTrace();
+            } catch (IllegalAccessException e) {
+                Log.e(LOGTAG, "Unable to invoke setForeground", e);
+                e.printStackTrace();
+            } catch (InvocationTargetException e) {
+                Log.e(LOGTAG, "Unable to invoke setForeground", e);
+                e.printStackTrace();
+            }
+        }
+    }
+
+    public void CheckMem() 
+        {
+        System.gc();
+        long lFreeMemory = Runtime.getRuntime().freeMemory();
+        long lTotMemory = Runtime.getRuntime().totalMemory();
+        long lMaxMemory = Runtime.getRuntime().maxMemory();
+
+        Log.i(LOGTAG, "Free: " + lFreeMemory + "Total: " + lTotMemory + "Max: " + lMaxMemory);
+        }
+
+    public int UpdtApp(String sPkgName, String sPkgFileName, String sOutFile, int bReboot)
+        {
+        int nRet = 1;
+        int lcv = 0;
+        String sRet = "";
+
+        FileOutputStream f = null;
+
+        try {
+            Log.i(LOGTAG, "Step 1: Kill " + sPkgName + " if running");
+            while (!IsProcessDead(sPkgName) && (lcv < 5)) {
+                if (KillProcess(sPkgName, null).startsWith("Successfully"))
+                    break;
+                else
+                    lcv++;
+                Thread.sleep(2000);
+            }
+
+            CheckMem();
+
+            if ((sOutFile != null) && (sOutFile.length() > 0)) {
+                File outFile = new File(sOutFile);
+                if (outFile.exists() && outFile.canWrite()) {
+                    f = new FileOutputStream(outFile, true);
+                } else {
+                    Log.e(LOGTAG, "File not found or cannot write to " + sOutFile);
+                }
+            }
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        } catch (FileNotFoundException e) {
+            Log.e(LOGTAG, "Couldn't open " + sOutFile + " " + e.getLocalizedMessage());
+            e.printStackTrace();
+        } catch (SecurityException e) {
+            Log.e(LOGTAG, "Exception message " + e.getLocalizedMessage());
+            e.printStackTrace();
+        }
+
+        if ((sPkgName != null) && (sPkgName.length() > 0))
+            {
+            Log.i(LOGTAG, "Step 2: Uninstall " + sPkgName);
+            sRet = UnInstallApp(sPkgName, null);
+            CheckMem();
+            if ((sRet.length() > 0) && (f != null))
+                {
+                try {
+                    f.write(sRet.getBytes());
+                    f.flush();
+                    }
+                catch (IOException e)
+                    {
+                    e.printStackTrace();
+                    }
+                }
+            }
+
+        if ((sPkgFileName != null) && (sPkgFileName.length() > 0))
+            {
+            Log.i(LOGTAG, "Step 3: Install " + sPkgFileName);
+            sRet = InstallApp(sPkgFileName, null);
+            Log.i(LOGTAG, "" + sRet);
+            CheckMem();
+            if ((sRet.length() > 0) && (f != null))
+                {
+                try {
+                    f.write(sRet.getBytes());
+                    f.flush();
+                    f.close();
+                    }
+                catch (IOException e)
+                    {
+                    e.printStackTrace();
+                    }
+                }
+            }
+
+        if (bReboot > 0)
+            RunReboot(null);
+
+        return(nRet);
+        }
+
+    public boolean GetProcessInfo(String sProcName)
+        {
+        boolean bRet = false;
+        ActivityManager aMgr = (ActivityManager) getApplicationContext().getSystemService(Activity.ACTIVITY_SERVICE);
+        List <ActivityManager.RunningAppProcessInfo> lProcesses = aMgr.getRunningAppProcesses();
+        int    nProcs = 0;
+        int lcv = 0;
+        String strProcName = "";
+
+        if (lProcesses != null)
+            nProcs = lProcesses.size();
+
+        for (lcv = 0; lcv < nProcs; lcv++)
+            {
+            strProcName = lProcesses.get(lcv).processName;
+            if (strProcName.contains(sProcName))
+                {
+                bRet = true;
+                break;
+                }
+            }
+        return (bRet);
+        }
+
+    public String RunReboot(OutputStream out)
+        {
+        String sRet = "";
+        String [] theArgs = new String [3];
+
+        theArgs[0] = "su";
+        theArgs[1] = "-c";
+        theArgs[2] = "reboot";
+        Log.i(LOGTAG, "Running reboot!");
+
+        try
+            {
+            pProc = Runtime.getRuntime().exec(theArgs);
+            RedirOutputThread outThrd = new RedirOutputThread(pProc, out);
+            outThrd.start();
+            outThrd.join(10000);
+            }
+        catch (IOException e)
+            {
+            sRet = e.getMessage();
+            e.printStackTrace();
+            }
+        catch (InterruptedException e)
+            {
+            e.printStackTrace();
+            }
+
+        return (sRet);
+        }
+
+    public String KillProcess(String sProcName, OutputStream out)
+        {
+        String [] theArgs = new String [3];
+
+        theArgs[0] = "su";
+        theArgs[1] = "-c";
+        theArgs[2] = "kill";
+
+        String sRet = sErrorPrefix + "Unable to kill " + sProcName + "\n";
+        ActivityManager aMgr = (ActivityManager) getSystemService(Activity.ACTIVITY_SERVICE);
+        List <ActivityManager.RunningAppProcessInfo> lProcesses = aMgr.getRunningAppProcesses();
+        int lcv = 0;
+        String strProcName = "";
+        int nPID = 0;
+        int nProcs = 0;
+
+        if (lProcesses != null)
+            nProcs = lProcesses.size();
+
+        for (lcv = 0; lcv < nProcs; lcv++)
+            {
+            if (lProcesses.get(lcv).processName.contains(sProcName))
+                {
+                strProcName = lProcesses.get(lcv).processName;
+                nPID = lProcesses.get(lcv).pid;
+                sRet = sErrorPrefix + "Failed to kill " + nPID + " " + strProcName + "\n";
+
+                theArgs[2] += " " + nPID;
+
+                try
+                    {
+                    pProc = Runtime.getRuntime().exec(theArgs);
+                    RedirOutputThread outThrd = new RedirOutputThread(pProc, out);
+                    outThrd.start();
+                    outThrd.join(5000);
+                    }
+                catch (IOException e)
+                    {
+                    sRet = e.getMessage();
+                    e.printStackTrace();
+                    }
+                catch (InterruptedException e)
+                    {
+                    e.printStackTrace();
+                    }
+
+                // Give the messages a chance to be processed
+                try {
+                    Thread.sleep(2000);
+                    }
+                catch (InterruptedException e)
+                    {
+                    e.printStackTrace();
+                    }
+                break;
+                }
+            }
+
+        if (nPID > 0)
+            {
+            sRet = "Successfully killed " + nPID + " " + strProcName + "\n";
+            lProcesses = aMgr.getRunningAppProcesses();
+            nProcs = 0;
+            if (lProcesses != null)
+                nProcs = lProcesses.size();
+            for (lcv = 0; lcv < nProcs; lcv++)
+                {
+                if (lProcesses.get(lcv).processName.contains(sProcName))
+                    {
+                    sRet = sErrorPrefix + "Unable to kill " + nPID + " " + strProcName + "\n";
+                    break;
+                    }
+                }
+            }
+
+        return (sRet);
+        }
+
+    public String GetAppRoot(String AppName)
+        {
+        String sRet = sErrorPrefix + " internal error [no context]";
+        Context ctx = getApplicationContext();
+
+        if (ctx != null)
+            {
+            try {
+                Context appCtx = ctx.createPackageContext(AppName, 0);
+                ContextWrapper appCtxW = new ContextWrapper(appCtx);
+                sRet = appCtxW.getPackageResourcePath();
+                appCtxW = null;
+                appCtx = null;
+                ctx = null;
+                System.gc();
+                }
+            catch (NameNotFoundException e)
+                {
+                e.printStackTrace();
+                }
+            }
+        return(sRet);
+        }
+
+    public boolean IsProcessDead(String sProcName)
+        {
+        boolean bRet = true;
+        ActivityManager aMgr = (ActivityManager) getSystemService(Activity.ACTIVITY_SERVICE);
+        List <ActivityManager.RunningAppProcessInfo> lProcesses = aMgr.getRunningAppProcesses(); //    .getProcessesInErrorState();
+        int lcv = 0;
+
+        if (lProcesses != null)
+            {
+            for (lcv = 0; lcv < lProcesses.size(); lcv++)
+                {
+                if (lProcesses.get(lcv).processName.contentEquals(sProcName))
+                    {
+                    bRet = false;
+                    break;
+                    }
+                }
+            }
+
+        return (bRet);
+        }
+
+    public String fixFileName(String fileName)
+        {
+        String    sRet = "";
+        String    sTmpFileName = "";
+
+        sRet = fileName.replace('\\', '/');
+
+        if (sRet.startsWith("/"))
+            sTmpFileName = sRet;
+        else
+            sTmpFileName = currentDir + "/" + sRet;
+
+        sRet = sTmpFileName.replace('\\', '/');
+        sTmpFileName = sRet;
+        sRet = sTmpFileName.replace("//", "/");
+
+        return(sRet);
+        }
+
+    public String UnInstallApp(String sApp, OutputStream out)
+        {
+        String sRet = "";
+        try
+            {
+            pProc = Runtime.getRuntime().exec(this.getSuArgs("pm uninstall " + sApp + ";exit"));
+
+            RedirOutputThread outThrd = new RedirOutputThread(pProc, out);
+            outThrd.start();
+            outThrd.join(60000);
+            int nRet = pProc.exitValue();
+            sRet = "\nuninst complete [" + nRet + "]";
+            }
+        catch (IOException e)
+            {
+            sRet = e.getMessage();
+            e.printStackTrace();
+            }
+        catch (InterruptedException e)
+            {
+            e.printStackTrace();
+            }
+
+        return (sRet);
+        }
+
+    private String [] getSuArgs(String cmdString)
+        {
+        String [] theArgs = new String [3];
+        theArgs[0] = "su";
+        theArgs[1] = "-c";
+        // as a security measure, ICS and later resets LD_LIBRARY_PATH. reset
+        // it here when executing the command
+        theArgs[2] = "LD_LIBRARY_PATH=/vendor/lib:/system/lib " + cmdString;
+        return theArgs;
+        }
+
+    public String InstallApp(String sApp, OutputStream out)
+        {
+        String sRet = "";
+        String sHold = "";
+        try
+            {
+            pProc = Runtime.getRuntime().exec(this.getSuArgs("pm install -r " + sApp + " Cleanup;exit"));
+
+            RedirOutputThread outThrd = new RedirOutputThread(pProc, out);
+            outThrd.start();
+            outThrd.join(180000);
+            int nRet = pProc.exitValue();
+            sRet += "\ninstall complete [" + nRet + "]";
+            sHold = outThrd.strOutput;
+            sRet += "\nSuccess";
+            }
+        catch (IOException e)
+            {
+            sRet = e.getMessage();
+            e.printStackTrace();
+            }
+        catch (InterruptedException e)
+            {
+            e.printStackTrace();
+            }
+
+        return (sRet);
+        }
+
+    private String SendPing(String sIPAddr)
+        {
+        Process pProc;
+        String sRet = "";
+        String [] theArgs = new String [4];
+        boolean bStillRunning = true;
+        int nBytesOut = 0;
+        int nBytesErr = 0;
+        int nBytesRead = 0;
+        byte[] buffer = new byte[1024];
+
+        theArgs[0] = "ping";
+        theArgs[1] = "-c";
+        theArgs[2] = "3";
+        theArgs[3] = sIPAddr;
+        Log.i(LOGTAG, "Pinging " + sIPAddr);
+
+        try
+            {
+            pProc = Runtime.getRuntime().exec(theArgs);
+            InputStream sutOut = pProc.getInputStream();
+            InputStream sutErr = pProc.getErrorStream();
+
+            while (bStillRunning)
+                {
+                try
+                    {
+                    if ((nBytesOut = sutOut.available()) > 0)
+                        {
+                        if (nBytesOut > buffer.length)
+                            {
+                            buffer = null;
+                            System.gc();
+                            buffer = new byte[nBytesOut];
+                            }
+                        nBytesRead = sutOut.read(buffer, 0, nBytesOut);
+                        if (nBytesRead == -1)
+                            bStillRunning = false;
+                        else
+                            {
+                            String sRep = new String(buffer,0,nBytesRead).replace("\n", "\r\n");
+                            sRet += sRep;
+                            sRep = null;
+                            }
+                        }
+
+                    if ((nBytesErr = sutErr.available()) > 0)
+                        {
+                        if (nBytesErr > buffer.length)
+                            {
+                            buffer = null;
+                            System.gc();
+                            buffer = new byte[nBytesErr];
+                            }
+                        nBytesRead = sutErr.read(buffer, 0, nBytesErr);
+                        if (nBytesRead == -1)
+                            bStillRunning = false;
+                        else
+                            {
+                            String sRep = new String(buffer,0,nBytesRead).replace("\n", "\r\n");
+                            sRet += sRep;
+                            sRep = null;
+                            }
+                        }
+
+                    bStillRunning = (IsProcRunning(pProc) || (sutOut.available() > 0) || (sutErr.available() > 0));
+                    }
+                catch (IOException e)
+                    {
+                    e.printStackTrace();
+                    }
+
+                if ((bStillRunning == true) && (nBytesErr == 0) && (nBytesOut == 0))
+                    {
+                    try {
+                        Thread.sleep(2000);
+                        }
+                    catch (InterruptedException e) {
+                        e.printStackTrace();
+                        }
+                    }
+                }
+
+            pProc.destroy();
+            pProc = null;
+            }
+        catch (IOException e)
+            {
+            sRet = e.getMessage();
+            e.printStackTrace();
+            }
+
+        Log.i(LOGTAG, String.format("Ping result was: '%s'", sRet.trim()));
+        return (sRet);
+        }
+
+    private boolean IsProcRunning(Process pProc)
+        {
+        boolean bRet = false;
+        @SuppressWarnings("unused")
+        int nExitCode = 0;
+
+        try
+            {
+            nExitCode = pProc.exitValue();
+            }
+        catch (IllegalThreadStateException z)
+            {
+            bRet = true;
+            }
+        catch (Exception e)
+            {
+            e.printStackTrace();
+            }
+
+        return(bRet);
+        }
+
+    private class UpdateApplication implements Runnable {
+        Thread    runner;
+        String    msPkgName = "";
+        String    msPkgFileName = "";
+        String    msOutFile = "";
+        int       mbReboot = 0;
+
+        public UpdateApplication(String sPkgName, String sPkgFileName, String sOutFile, int bReboot) {
+            runner = new Thread(this);
+            msPkgName = sPkgName;
+            msPkgFileName = sPkgFileName;
+            msOutFile = sOutFile;
+            mbReboot = bReboot;
+            runner.start();
+        }
+
+        public void run() {
+            bInstalling = true;
+            UpdtApp(msPkgName, msPkgFileName, msOutFile, mbReboot);
+            bInstalling = false;
+        }
+    }
+
+    private class MyTime extends TimerTask
+        {
+        int    nStrikes = 0;
+        final int PERIODS_TO_WAIT_FOR_SDCARD = 3;
+        int    nPeriodsWaited = 0;
+
+        public MyTime()
+            {
+            }
+
+        @Override
+        public void run()
+            {
+            if (bInstalling)
+                return;
+
+            // See if the network is up, if not reboot after a configurable
+            // number of tries
+            if (nMaxStrikes > 0)
+                {
+                    String sRet = SendPing(sPingTarget);
+                    if (!sRet.contains("3 received"))
+                        {
+                            Log.i(LOGTAG, String.format("Failed ping attempt (remaining: %s)!",
+                                 nMaxStrikes - nStrikes));
+                            if (++nStrikes >= nMaxStrikes)
+                                {
+                                    Log.e(LOGTAG, String.format("Number of failed ping attempts to %s (%s) exceeded maximum (%s), running reboot!", sPingTarget, nStrikes, nMaxStrikes));
+                                    RunReboot(null);
+                                }
+                        }
+                    else
+                        {
+                            nStrikes = 0;
+                        }
+                }
+
+            String sProgramName = "com.mozilla.SUTAgentAndroid";
+
+            // Ensure the sdcard is mounted before we even attempt to start the agent
+            // We will wait for the sdcard to mount for PERIODS_TO_WAIT_FOR_SDCARD
+            // after which time we go ahead and attempt to start the agent.
+            if (nPeriodsWaited++ < PERIODS_TO_WAIT_FOR_SDCARD) {
+                String state = Environment.getExternalStorageState();
+                if (Environment.MEDIA_MOUNTED.compareTo(state) != 0) {
+                    Log.i(LOGTAG, "SDcard not mounted, waiting another turn");
+                    return;
+                } else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
+                    Log.e(LOGTAG, "SDcard mounted read only not starting agent now, try again in 60s");
+                    return;
+                }
+            }
+
+            boolean isProc = GetProcessInfo(sProgramName);
+            if (bStartSUTAgent && !isProc)
+                {
+                Log.i(LOGTAG, "Starting SUTAgent from watcher code");
+                Intent agentIntent = new Intent();
+                agentIntent.setPackage(sProgramName);
+                agentIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                agentIntent.setAction(Intent.ACTION_MAIN);
+                try {
+                    PackageManager pm = myContext.getPackageManager();
+                    PackageInfo pi = pm.getPackageInfo(sProgramName, PackageManager.GET_ACTIVITIES | PackageManager.GET_INTENT_FILTERS);
+                    ActivityInfo [] ai = pi.activities;
+                    for (int i = 0; i < ai.length; i++)
+                        {
+                        ActivityInfo a = ai[i];
+                        if (a.name.length() > 0)
+                            {
+                            agentIntent.setClassName(a.packageName, a.name);
+                            break;
+                            }
+                        }
+                    }
+                catch (NameNotFoundException e)
+                    {
+                    e.printStackTrace();
+                    }
+                try
+                    {
+                    myContext.startActivity(agentIntent);
+                    }
+                catch(ActivityNotFoundException anf)
+                    {
+                    anf.printStackTrace();
+                    }
+                }
+            }
+        }
+}
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/default.properties b/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/default.properties
new file mode 100644
index 0000000..07bdb54
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/default.properties
@@ -0,0 +1,15 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+# 
+# This file must be checked in Version Control Systems.
+# 
+# To customize properties used by the Ant build system use,
+# "build.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-5
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/moz.build b/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/moz.build
new file mode 100644
index 0000000..938ff53
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/moz.build
@@ -0,0 +1,8 @@
+# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+ANDROID_APK_NAME = 'Watcher'
+ANDROID_APK_PACKAGE = 'com.mozilla.watcher'
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/res/drawable-hdpi/ateamlogo.png b/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/res/drawable-hdpi/ateamlogo.png
new file mode 100644
index 0000000..6f65bd6
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/res/drawable-hdpi/ateamlogo.png
Binary files differ
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/res/drawable-hdpi/icon.png b/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/res/drawable-hdpi/icon.png
new file mode 100644
index 0000000..8074c4c
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/res/drawable-hdpi/icon.png
Binary files differ
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/res/drawable-ldpi/ateamlogo.png b/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/res/drawable-ldpi/ateamlogo.png
new file mode 100644
index 0000000..6f65bd6
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/res/drawable-ldpi/ateamlogo.png
Binary files differ
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/res/drawable-ldpi/icon.png b/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/res/drawable-ldpi/icon.png
new file mode 100644
index 0000000..1095584
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/res/drawable-ldpi/icon.png
Binary files differ
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/res/drawable-mdpi/ateamlogo.png b/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/res/drawable-mdpi/ateamlogo.png
new file mode 100644
index 0000000..6f65bd6
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/res/drawable-mdpi/ateamlogo.png
Binary files differ
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/res/drawable-mdpi/icon.png b/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/res/drawable-mdpi/icon.png
new file mode 100644
index 0000000..a07c69f
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/res/drawable-mdpi/icon.png
Binary files differ
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/res/layout/main.xml b/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/res/layout/main.xml
new file mode 100644
index 0000000..1256b1a
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/res/layout/main.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    >
+<TextView  
+    android:layout_width="fill_parent" 
+    android:layout_height="wrap_content" 
+    android:text="@string/hello"
+    />
+</LinearLayout>
diff --git a/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/res/values/strings.xml b/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/res/values/strings.xml
new file mode 100644
index 0000000..a2190f7
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mobile/sutagent/android/watcher/res/values/strings.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<resources>
+    <string name="hello">Hello World, WatcherMain!</string>
+    <string name="app_name">watcher</string>
+<string name="foreground_service_started">Foreground Service Started</string>
+
+</resources>
diff --git a/src/third_party/mozjs-45/build/moz-automation.mk b/src/third_party/mozjs-45/build/moz-automation.mk
new file mode 100644
index 0000000..ec63233
--- /dev/null
+++ b/src/third_party/mozjs-45/build/moz-automation.mk
@@ -0,0 +1,120 @@
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+ifneq (,$(filter automation/%,$(MAKECMDGOALS)))
+ifeq (4.0,$(firstword $(sort 4.0 $(MAKE_VERSION))))
+MAKEFLAGS += --output-sync=target
+else
+.NOTPARALLEL:
+endif
+endif
+
+include $(topsrcdir)/toolkit/mozapps/installer/package-name.mk
+include $(topsrcdir)/toolkit/mozapps/installer/upload-files.mk
+
+# Clear out DIST_FILES if it was set by upload-files.mk (for Android builds)
+DIST_FILES =
+
+# Helper variables to convert from MOZ_AUTOMATION_* variables to the
+# corresponding the make target
+tier_MOZ_AUTOMATION_BUILD_SYMBOLS = buildsymbols
+tier_MOZ_AUTOMATION_L10N_CHECK = l10n-check
+tier_MOZ_AUTOMATION_PRETTY_L10N_CHECK = pretty-l10n-check
+tier_MOZ_AUTOMATION_INSTALLER = installer
+tier_MOZ_AUTOMATION_PRETTY_INSTALLER = pretty-installer
+tier_MOZ_AUTOMATION_PACKAGE = package
+tier_MOZ_AUTOMATION_PRETTY_PACKAGE = pretty-package
+tier_MOZ_AUTOMATION_PACKAGE_TESTS = package-tests
+tier_MOZ_AUTOMATION_PRETTY_PACKAGE_TESTS = pretty-package-tests
+tier_MOZ_AUTOMATION_UPDATE_PACKAGING = update-packaging
+tier_MOZ_AUTOMATION_PRETTY_UPDATE_PACKAGING = pretty-update-packaging
+tier_MOZ_AUTOMATION_UPLOAD_SYMBOLS = uploadsymbols
+tier_MOZ_AUTOMATION_UPLOAD = upload
+tier_MOZ_AUTOMATION_SDK = sdk
+
+# Automation build steps. Everything in MOZ_AUTOMATION_TIERS also gets used in
+# TIERS for mach display. As such, the MOZ_AUTOMATION_TIERS are roughly sorted
+# here in the order that they will be executed (since mach doesn't know of the
+# dependencies between them).
+moz_automation_symbols = \
+  MOZ_AUTOMATION_PACKAGE_TESTS \
+  MOZ_AUTOMATION_PRETTY_PACKAGE_TESTS \
+  MOZ_AUTOMATION_BUILD_SYMBOLS \
+  MOZ_AUTOMATION_UPLOAD_SYMBOLS \
+  MOZ_AUTOMATION_PACKAGE \
+  MOZ_AUTOMATION_PRETTY_PACKAGE \
+  MOZ_AUTOMATION_INSTALLER \
+  MOZ_AUTOMATION_PRETTY_INSTALLER \
+  MOZ_AUTOMATION_UPDATE_PACKAGING \
+  MOZ_AUTOMATION_PRETTY_UPDATE_PACKAGING \
+  MOZ_AUTOMATION_L10N_CHECK \
+  MOZ_AUTOMATION_PRETTY_L10N_CHECK \
+  MOZ_AUTOMATION_UPLOAD \
+  MOZ_AUTOMATION_SDK \
+  $(NULL)
+MOZ_AUTOMATION_TIERS := $(foreach sym,$(moz_automation_symbols),$(if $(filter 1,$($(sym))),$(tier_$(sym))))
+
+# Dependencies between automation build steps
+automation/uploadsymbols: automation/buildsymbols
+
+automation/update-packaging: automation/package
+automation/update-packaging: automation/installer
+automation/pretty-update-packaging: automation/pretty-package
+automation/pretty-update-packaging: automation/pretty-installer
+
+automation/l10n-check: automation/package
+automation/l10n-check: automation/installer
+automation/pretty-l10n-check: automation/pretty-package
+automation/pretty-l10n-check: automation/pretty-installer
+
+automation/upload: automation/installer
+automation/upload: automation/package
+automation/upload: automation/package-tests
+automation/upload: automation/buildsymbols
+automation/upload: automation/update-packaging
+automation/upload: automation/sdk
+
+# automation/{pretty-}package should depend on build (which is implicit due to
+# the way client.mk invokes automation/build), but buildsymbols changes the
+# binaries/libs, and that's what we package/test.
+automation/pretty-package: automation/buildsymbols
+
+# The installer, sdk and packager all run stage-package, and may conflict
+# with each other.
+automation/installer: automation/package
+automation/sdk: automation/installer automation/package
+
+# The 'pretty' versions of targets run before the regular ones to avoid
+# conflicts in writing to the same files.
+automation/installer: automation/pretty-installer
+automation/package: automation/pretty-package
+automation/package-tests: automation/pretty-package-tests
+automation/l10n-check: automation/pretty-l10n-check
+automation/update-packaging: automation/pretty-update-packaging
+
+automation/build: $(addprefix automation/,$(MOZ_AUTOMATION_TIERS))
+	@echo Automation steps completed.
+
+# Note: We have to force -j1 here, at least until bug 1036563 is fixed.
+AUTOMATION_EXTRA_CMDLINE-l10n-check = -j1
+AUTOMATION_EXTRA_CMDLINE-pretty-l10n-check = -j1
+
+# The commands only run if the corresponding MOZ_AUTOMATION_* variable is
+# enabled. This means, for example, if we enable MOZ_AUTOMATION_UPLOAD, then
+# 'buildsymbols' will only run if MOZ_AUTOMATION_BUILD_SYMBOLS is also set.
+# However, the target automation/buildsymbols will still be executed in this
+# case because it is a prerequisite of automation/upload.
+define automation_commands
+@+$(MAKE) $1 $(AUTOMATION_EXTRA_CMDLINE-$1)
+$(call BUILDSTATUS,TIER_FINISH $1)
+endef
+
+# The tier start message is in a separate target so make doesn't buffer it
+# until the step completes with output syncing enabled.
+automation-start/%:
+	$(if $(filter $*,$(MOZ_AUTOMATION_TIERS)),$(call BUILDSTATUS,TIER_START $*))
+
+automation/%: automation-start/%
+	$(if $(filter $*,$(MOZ_AUTOMATION_TIERS)),$(call automation_commands,$*))
diff --git a/src/third_party/mozjs-45/build/moz.build b/src/third_party/mozjs-45/build/moz.build
new file mode 100644
index 0000000..21ea098
--- /dev/null
+++ b/src/third_party/mozjs-45/build/moz.build
@@ -0,0 +1,77 @@
+# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+with Files('**'):
+    BUG_COMPONENT = ('Core', 'Build Config')
+
+# This cannot be named "build" because of bug 922191.
+SPHINX_TREES['buildsystem'] = 'docs'
+
+if CONFIG['OS_ARCH'] == 'WINNT':
+    DIRS += ['win32']
+else:
+    DIRS += ['unix']
+
+if CONFIG['OS_TARGET'] == 'Android' and CONFIG['MOZ_ANDROID_CXX_STL'] == 'mozstlport':
+    DIRS += ['stlport']
+    if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android' and CONFIG['ENABLE_INTL_API']:
+        DIRS += ['gabi++']
+
+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
+    DIRS += ['annotationProcessors']
+    TEST_DIRS += [
+        'mobile/sutagent/android',
+        'mobile/sutagent/android/watcher',
+        'mobile/sutagent/android/ffxcp',
+        'mobile/sutagent/android/fencp',
+    ]
+
+for var in ('GRE_MILESTONE', 'MOZ_APP_VERSION', 'MOZ_APP_BASENAME',
+            'MOZ_APP_VENDOR', 'MOZ_APP_ID', 'MAR_CHANNEL_ID',
+            'ACCEPTED_MAR_CHANNEL_IDS', 'MOZ_APP_REMOTINGNAME'):
+    DEFINES[var] = CONFIG[var]
+
+if CONFIG['MOZ_APP_DISPLAYNAME'] != CONFIG['MOZ_APP_BASENAME']:
+    DEFINES['MOZ_APP_DISPLAYNAME'] = CONFIG['MOZ_APP_DISPLAYNAME']
+
+if CONFIG['MOZ_BUILD_APP'] == 'browser':
+    DEFINES['MOZ_BUILD_APP_IS_BROWSER'] = True
+
+if CONFIG['MOZ_APP_PROFILE']:
+    DEFINES['MOZ_APP_PROFILE'] = CONFIG['MOZ_APP_PROFILE']
+
+for var in ('MOZ_CRASHREPORTER', 'MOZ_PROFILE_MIGRATOR',
+            'MOZ_APP_STATIC_INI'):
+    if CONFIG[var]:
+        DEFINES[var] = True
+
+if CONFIG['MOZ_BUILD_APP'] == 'browser':
+    PYTHON_UNIT_TESTS += [
+        'compare-mozconfig/compare-mozconfigs-wrapper.py',
+    ]
+
+if CONFIG['ENABLE_TESTS'] or CONFIG['MOZ_DMD']:
+    FINAL_TARGET_FILES += ['/tools/rb/fix_stack_using_bpsyms.py']
+    if CONFIG['OS_ARCH'] == 'Darwin':
+        FINAL_TARGET_FILES += ['/tools/rb/fix_macosx_stack.py']
+    if CONFIG['OS_ARCH'] == 'Linux':
+        FINAL_TARGET_FILES += ['/tools/rb/fix_linux_stack.py']
+
+if CONFIG['MOZ_DMD']:
+    FINAL_TARGET_FILES += ['/memory/replace/dmd/dmd.py']
+
+# Put a useful .gdbinit in the bin directory, to be picked up automatically
+# by GDB when we debug executables there.
+FINAL_TARGET_FILES += ['/.gdbinit']
+
+# Install the clang-cl runtime library for ASAN next to the binaries we produce.
+if CONFIG['MOZ_ASAN'] and CONFIG['CLANG_CL']:
+    FINAL_TARGET_FILES += ['%' + CONFIG['MOZ_CLANG_RT_ASAN_LIB_PATH']]
+
+if CONFIG['MOZ_APP_BASENAME']:
+    FINAL_TARGET_PP_FILES += ['application.ini']
+    if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'android' and CONFIG['MOZ_UPDATER']:
+        FINAL_TARGET_PP_FILES += ['update-settings.ini']
diff --git a/src/third_party/mozjs-45/build/mozconfig.automation b/src/third_party/mozjs-45/build/mozconfig.automation
new file mode 100644
index 0000000..057a4a0
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mozconfig.automation
@@ -0,0 +1,33 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# Common mozconfig for automation builds.
+#
+# We export MOZ_AUTOMATION_* variables here to trigger various steps in
+# automation builds.  For example, if MOZ_AUTOMATION_PACKAGE is set, then the
+# package step will run.  This file contains the default settings, which can be
+# overridden by setting them earlier in the appropriate mozconfig.
+
+mk_add_options "export MOZ_AUTOMATION_BUILD_SYMBOLS=${MOZ_AUTOMATION_BUILD_SYMBOLS-1}"
+mk_add_options "export MOZ_AUTOMATION_L10N_CHECK=${MOZ_AUTOMATION_L10N_CHECK-1}"
+mk_add_options "export MOZ_AUTOMATION_PACKAGE=${MOZ_AUTOMATION_PACKAGE-1}"
+mk_add_options "export MOZ_AUTOMATION_PACKAGE_TESTS=${MOZ_AUTOMATION_PACKAGE_TESTS-1}"
+mk_add_options "export MOZ_AUTOMATION_INSTALLER=${MOZ_AUTOMATION_INSTALLER-0}"
+mk_add_options "export MOZ_AUTOMATION_UPDATE_PACKAGING=${MOZ_AUTOMATION_UPDATE_PACKAGING-0}"
+mk_add_options "export MOZ_AUTOMATION_UPLOAD=${MOZ_AUTOMATION_UPLOAD-1}"
+mk_add_options "export MOZ_AUTOMATION_UPLOAD_SYMBOLS=${MOZ_AUTOMATION_UPLOAD_SYMBOLS-0}"
+mk_add_options "export MOZ_AUTOMATION_SDK=${MOZ_AUTOMATION_SDK-0}"
+
+# If we are also building with MOZ_PKG_PRETTYNAMES, set the corresponding
+# stages.
+if test "$MOZ_AUTOMATION_PRETTY" = "1"; then
+    mk_add_options "export MOZ_AUTOMATION_PRETTY_PACKAGE=${MOZ_AUTOMATION_PACKAGE-1}"
+    mk_add_options "export MOZ_AUTOMATION_PRETTY_PACKAGE_TESTS=${MOZ_AUTOMATION_PACKAGE_TESTS-1}"
+    mk_add_options "export MOZ_AUTOMATION_PRETTY_L10N_CHECK=${MOZ_AUTOMATION_L10N_CHECK-1}"
+    mk_add_options "export MOZ_AUTOMATION_PRETTY_INSTALLER=${MOZ_AUTOMATION_INSTALLER-0}"
+
+    # Note that we always build the update packaging with pretty names even if
+    # we don't build it without, so this is set to 1.
+    mk_add_options "export MOZ_AUTOMATION_PRETTY_UPDATE_PACKAGING=1"
+fi
diff --git a/src/third_party/mozjs-45/build/mozconfig.cache b/src/third_party/mozjs-45/build/mozconfig.cache
new file mode 100644
index 0000000..69be996
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mozconfig.cache
@@ -0,0 +1,80 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# Setup for build cache
+
+# Avoid duplication if the file happens to be included twice.
+if test -z "$bucket"; then
+
+read branch platform master <<EOF
+$(python2.7 -c 'import json; p = json.loads(open("'"$topsrcdir"'/../buildprops.json").read())["properties"]; print p["branch"], p["platform"], p["master"]' 2> /dev/null)
+EOF
+
+bucket=
+if test -z "$SCCACHE_DISABLE" -a -z "$no_sccache" -a -z "$MOZ_PGO_IS_SET" -a -z "$MOZ_PGO"; then
+    case "${branch}" in
+    try)
+        case "${master}" in
+        *scl1.mozilla.com*|*.scl3.mozilla.com*)
+            bucket=mozilla-releng-s3-cache-us-west-1-try
+            ;;
+        *use1.mozilla.com*)
+            bucket=mozilla-releng-s3-cache-us-east-1-try
+            ;;
+        *usw2.mozilla.com*)
+            bucket=mozilla-releng-s3-cache-us-west-2-try
+            ;;
+        esac
+        ;;
+    b2g-inbound|mozilla-inbound|fx-team)
+        case "${master}" in
+        *use1.mozilla.com*)
+            bucket=mozilla-releng-s3-cache-us-east-1-prod
+            ;;
+        *usw2.mozilla.com*)
+            bucket=mozilla-releng-s3-cache-us-west-2-prod
+            ;;
+        esac
+        ;;
+    esac
+fi
+
+if test -z "$bucket"; then
+    case "$platform" in
+    win*) : ;;
+    *)
+        ac_add_options --with-ccache
+    esac
+else
+    if ! test -e $topsrcdir/sccache/sccache.py; then
+        echo "Sccache missing in the tooltool manifest" >&2
+        exit 1
+    fi
+    mk_add_options "export SCCACHE_BUCKET=$bucket"
+    case "$master" in
+    *use1.mozilla.com*|*usw2.mozilla.com*)
+        mk_add_options "export SCCACHE_NAMESERVER=169.254.169.253"
+        ;;
+    esac
+    ac_add_options "--with-compiler-wrapper=python2.7 $topsrcdir/sccache/sccache.py"
+    mk_add_options MOZ_PREFLIGHT_ALL+=build/sccache.mk
+    mk_add_options MOZ_POSTFLIGHT_ALL+=build/sccache.mk
+    mk_add_options "UPLOAD_EXTRA_FILES+=sccache.log.gz"
+    case "$platform" in
+    win*)
+        # sccache supports a special flag to create depfiles.
+        export _DEPEND_CFLAGS='-deps$(MDDEPDIR)/$(@F).pp'
+        # Windows builds have a default wrapper that needs to be overridden
+        mk_add_options "export CC_WRAPPER="
+        mk_add_options "export CXX_WRAPPER="
+        # For now, sccache doesn't support separate PDBs so force debug info to be
+        # in object files.
+        mk_add_options "export COMPILE_PDB_FLAG="
+        mk_add_options "export HOST_PDB_FLAG="
+        mk_add_options "export MOZ_DEBUG_FLAGS=-Z7"
+        ;;
+    esac
+fi
+
+fi
diff --git a/src/third_party/mozjs-45/build/mozconfig.common b/src/third_party/mozjs-45/build/mozconfig.common
new file mode 100644
index 0000000..3b49b81
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mozconfig.common
@@ -0,0 +1,19 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# Common mozconfig for official builds.
+#
+# Add options to this file that will be inherited by all in-tree mozconfigs.
+# This is useful for eg try builds with nondefault options that apply to all
+# architectures, though note that if you want to override options set in
+# another mozconfig file, you'll need to use mozconfig.common.override instead
+# of this file.
+
+mk_add_options AUTOCLOBBER=1
+
+ac_add_options --enable-crashreporter
+
+ac_add_options --enable-release
+
+. "$topsrcdir/build/mozconfig.automation"
diff --git a/src/third_party/mozjs-45/build/mozconfig.common.override b/src/third_party/mozjs-45/build/mozconfig.common.override
new file mode 100644
index 0000000..7285aa9
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mozconfig.common.override
@@ -0,0 +1,11 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# Common mozconfig for all users
+#
+# Add options to this file that will be inherited by all in-tree mozconfigs.
+# This file is included at the *end* of the mozconfigs, and so may be used
+# to override anything done previously.
+#
+# The common expected usage is for try builds with nondefault options.
diff --git a/src/third_party/mozjs-45/build/mozconfig.vs-common b/src/third_party/mozjs-45/build/mozconfig.vs-common
new file mode 100644
index 0000000..ca5df2f
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mozconfig.vs-common
@@ -0,0 +1,4 @@
+# Pymake needs Windows-style paths. Use cmd.exe to hack around this.

+mk_export_correct_style() {

+  mk_add_options "export $1=$(cmd.exe //c echo %$1%)"

+}

diff --git a/src/third_party/mozjs-45/build/mozconfig.win-common b/src/third_party/mozjs-45/build/mozconfig.win-common
new file mode 100644
index 0000000..6e25b7c
--- /dev/null
+++ b/src/third_party/mozjs-45/build/mozconfig.win-common
@@ -0,0 +1,16 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+if [ "x$IS_NIGHTLY" = "xyes" ]; then
+  # Some nightlies (eg: Mulet) don't want these set.
+  MOZ_AUTOMATION_UPLOAD_SYMBOLS=${MOZ_AUTOMATION_UPLOAD_SYMBOLS-1}
+  MOZ_AUTOMATION_UPDATE_PACKAGING=${MOZ_AUTOMATION_UPDATE_PACKAGING-1}
+  MOZ_AUTOMATION_SDK=${MOZ_AUTOMATION_SDK-1}
+fi
+
+# Some builds (eg: Mulet) don't want the installer, so only set this if it
+# hasn't already been set.
+MOZ_AUTOMATION_INSTALLER=${MOZ_AUTOMATION_INSTALLER-1}
+
+export SOCORRO_SYMBOL_UPLOAD_TOKEN_FILE=c:/builds/crash-stats-api.token
diff --git a/src/third_party/mozjs-45/build/msys-perl-wrapper b/src/third_party/mozjs-45/build/msys-perl-wrapper
new file mode 100644
index 0000000..8ba78ed
--- /dev/null
+++ b/src/third_party/mozjs-45/build/msys-perl-wrapper
@@ -0,0 +1,20 @@
+#!/bin/sh
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+
+args=""
+
+for i in "${@}"
+do
+    case "$i" in
+    -I?:/*)
+        i="$(echo "${i}" | sed -e 's|^-I\(.\):/|-I/\1/|')"
+	;;
+    esac
+
+    args="${args} '${i}'"
+done
+
+eval "exec perl $args"
diff --git a/src/third_party/mozjs-45/build/package/mac_osx/make-diskimage b/src/third_party/mozjs-45/build/package/mac_osx/make-diskimage
new file mode 100755
index 0000000..c214ceb
--- /dev/null
+++ b/src/third_party/mozjs-45/build/package/mac_osx/make-diskimage
@@ -0,0 +1,47 @@
+#!/bin/sh
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# Create a read-only disk image of the contents of a folder
+#
+# Usage: make-diskimage <image_file>
+#                       <src_folder>
+#                       <volume_name>
+#                       <eula_resource_file>
+#                       <.dsstore_file>
+#                       <background_image_file>
+#
+# tip: use '-null-' for <eula-resource-file> if you only want to
+# provide <.dsstore_file> and <background_image_file>
+
+DMG_PATH=$1
+SRC_FOLDER=$2
+VOLUME_NAME=$3
+
+# optional arguments
+EULA_RSRC=$4
+DMG_DSSTORE=$5
+DMG_BKGND_IMG=$6
+
+EXTRA_ARGS=
+
+if test -n "$EULA_RSRC" && test "$EULA_RSRC" != "-null-" ; then
+  EXTRA_ARGS="--resource $EULA_RSRC"
+fi
+
+if test -n "$DMG_DSSTORE" ; then
+  EXTRA_ARGS="$EXTRA_ARGS --copy $DMG_DSSTORE:/.DS_Store"
+fi
+
+if test -n "$DMG_BKGND_IMG" ; then
+  EXTRA_ARGS="$EXTRA_ARGS --mkdir /.background --copy $DMG_BKGND_IMG:/.background"
+fi
+
+echo `dirname $0`/pkg-dmg --target "$DMG_PATH" --source "$SRC_FOLDER" \
+ --volname "$VOLUME_NAME" $EXTRA_ARGS
+
+`dirname $0`/pkg-dmg --target "$DMG_PATH" --source "$SRC_FOLDER" \
+ --volname "$VOLUME_NAME" $EXTRA_ARGS
+
+exit $?
diff --git a/src/third_party/mozjs-45/build/package/mac_osx/mozilla-background.jpg b/src/third_party/mozjs-45/build/package/mac_osx/mozilla-background.jpg
new file mode 100644
index 0000000..adb4df0
--- /dev/null
+++ b/src/third_party/mozjs-45/build/package/mac_osx/mozilla-background.jpg
Binary files differ
diff --git a/src/third_party/mozjs-45/build/package/mac_osx/mozilla.dsstore b/src/third_party/mozjs-45/build/package/mac_osx/mozilla.dsstore
new file mode 100644
index 0000000..520eb08
--- /dev/null
+++ b/src/third_party/mozjs-45/build/package/mac_osx/mozilla.dsstore
Binary files differ
diff --git a/src/third_party/mozjs-45/build/package/mac_osx/unpack-diskimage b/src/third_party/mozjs-45/build/package/mac_osx/unpack-diskimage
new file mode 100755
index 0000000..3ba9778
--- /dev/null
+++ b/src/third_party/mozjs-45/build/package/mac_osx/unpack-diskimage
@@ -0,0 +1,54 @@
+#!/bin/bash
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# Unpack a disk image to a specified target folder
+#
+# Usage: unpack-diskimage <image_file>
+#                         <mountpoint>
+#                         <target_path>
+
+DMG_PATH=$1
+MOUNTPOINT=$2
+TARGETPATH=$3
+
+# How long to wait before giving up waiting for the mount to finish (seconds)
+TIMEOUT=90
+
+# If mnt already exists, then the previous run may not have cleaned up
+# properly.  We should try to umount and remove the mnt directory.
+if [ -d $MOUNTPOINT ]; then
+    echo "mnt already exists, trying to clean up"
+    hdiutil detach $MOUNTPOINT -force
+    rm -rdfv $MOUNTPOINT
+fi
+
+# Install an on-exit handler that will unmount and remove the '$MOUNTPOINT' directory
+trap "{ if [ -d $MOUNTPOINT ]; then hdiutil detach $MOUNTPOINT -force; rm -rdfv $MOUNTPOINT; fi; }" EXIT
+
+mkdir -p $MOUNTPOINT
+
+hdiutil attach -verbose -noautoopen -mountpoint $MOUNTPOINT "$DMG_PATH"
+# Wait for files to show up
+# hdiutil uses a helper process, diskimages-helper, which isn't always done its
+# work by the time hdiutil exits. So we wait until something shows up in the
+# mnt directory. Due to the async nature of diskimages-helper, the best thing
+# we can do is to make sure the glob() rsync is making can find files.
+i=0
+while [ "$(echo $MOUNTPOINT/*)" == "$MOUNTPOINT/*" ]; do
+    if [ $i -gt $TIMEOUT ]; then
+        echo "No files found, exiting"
+        exit 1
+    fi
+    sleep 1
+    i=$(expr $i + 1)
+done
+# Now we can copy everything out of the $MOUNTPOINT directory into the target directory
+rsync -av $MOUNTPOINT/* $MOUNTPOINT/.DS_Store $MOUNTPOINT/.background $MOUNTPOINT/.VolumeIcon.icns $TARGETPATH/.
+hdiutil detach $MOUNTPOINT
+rm -rdf $MOUNTPOINT
+# diskimage-helper prints messages to stdout asynchronously as well, sleep
+# for a bit to ensure they don't disturb following commands in a script that
+# might parse stdout messages
+sleep 5
diff --git a/src/third_party/mozjs-45/build/pgo/blueprint/LICENSE b/src/third_party/mozjs-45/build/pgo/blueprint/LICENSE
new file mode 100644
index 0000000..d747410
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/blueprint/LICENSE
@@ -0,0 +1,314 @@
+Blueprint CSS Framework License
+----------------------------------------------------------------
+
+Copyright (c) 2007-2008 Olav Bjorkoy (olav at bjorkoy.com)
+
+The Blueprint CSS Framework is available for use in all personal or 
+commercial projects, under both the (modified) MIT and the GPL license. You
+may choose the one that fits your project.
+
+
+The (modified) MIT License
+----------------------------------------------------------------
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice, and every other copyright notice found in this 
+software, and all the attributions in every file, and this permission notice 
+shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+
+The GPL License
+----------------------------------------------------------------
+
+        GNU GENERAL PUBLIC LICENSE
+           Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+          Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+        GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+          NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
\ No newline at end of file
diff --git a/src/third_party/mozjs-45/build/pgo/blueprint/elements.html b/src/third_party/mozjs-45/build/pgo/blueprint/elements.html
new file mode 100644
index 0000000..51d79fa
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/blueprint/elements.html
@@ -0,0 +1,250 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
+   "http://www.w3.org/TR/html4/strict.dtd">
+
+<html lang="en">
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>Blueprint HTML Elements Tests</title>
+
+  <!-- Framework CSS -->
+	<link rel="stylesheet" href="screen.css" type="text/css" media="screen, projection">
+	<link rel="stylesheet" href="print.css" type="text/css" media="print">
+  <!--[if IE]><link rel="stylesheet" href="ie.css" type="text/css" media="screen, projection"><![endif]-->
+
+</head>
+<body>
+
+	<div class="container showgrid">
+		<h2>Tests for common HTML elements</h2>
+		<hr>
+    
+    <h5>PARAGRAPHS <span class="alt">&amp;</span> BOXES</h5>
+    
+    <div class="span-8">    
+			<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
+			<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor <sub>sub text</sub> ut labore et <sup>sup text</sup> magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
+    </div>
+    
+    <div class="span-8">
+			<p class="small">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
+			<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
+			<p class="large">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
+    </div>
+    
+    <div class="span-8 last">
+
+			<div class="box">
+				<p class="last">Aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
+			</div>
+      <blockquote>
+				<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
+			</blockquote>    
+    
+    </div>
+    <hr>
+    
+    <h5>LISTS</h5>
+    
+    <div class="span-8">    
+			<ul>
+				<li>Unordered list test</li>
+				<li>Another list element. Lorem ipsum dolor sit amet, consectetur adipisicing elit.</li>
+				<li>Yet another element in the list</li>
+				<li>Some long text. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Lorem ipsum dolor sit amet, consectetur adipisicing elit.</li>
+			</ul>
+			<ol>
+				<li>Ordered list test</li>
+				<li>Another list element</li>
+				<li>Yet another element in the list</li>
+			</ol>
+    </div>
+    
+    <div class="span-8">
+			<ol>
+				<li>Ordered list</li>
+				<li>Here's a nested unordered list
+				  <ul>
+  				  <li>Nested Unordered list</li>
+  				  <li>Nested ordered list
+  				    <ol>
+  				      <li>The first</li>
+  				      <li>And the second</li>
+  				    </ol>
+  				  </li>
+  			  </ul>
+  			</li>
+				<li>Ordered List item</li>
+				<li>Nested Ordered list
+				  <ol>
+				    <li>Some point</li>
+				    <li>Nested Unordered list
+				      <ul>
+  				      <li>The first</li>
+  				      <li>And the second</li>
+				      </ul>
+				    </li>
+				  </ol>
+				</li>
+			</ol>
+    </div>
+    
+    <div class="span-8 last">
+      <dl>
+      	<dt>definition list dt</dt>
+      	<dd>definition list dd</dd>
+      	<dt>definition list dt</dt>
+      	<dd>definition list dd</dd>
+      	<dt>Lorem ipsum dolor sit amet, consectetur adipisicing elit adipisicing elit adipisicing elit</dt>
+      	<dd>Lorem ipsum dolor sit amet, consectetur adipisicing elit adipisicing elit adipisicing elit</dd>
+      	<dt>Lorem ipsum dolor sit amet, consectetur adipisicing elit adipisicing elit adipisicing elit</dt>
+      	<dd>Lorem ipsum dolor sit amet, consectetur adipisicing elit adipisicing elit adipisicing elit</dd>
+      </dl>			
+    </div>
+    <hr>
+    
+    <h5>HEADINGS</h5>
+    
+    <div class="span-8">    
+			<h1>H1: Lorem ipsum dolor sit amet</h1>
+			<h2>H2: Lorem ipsum dolor sit amet, consectetur elit</h2>
+			<h3>H3: Lorem ipsum dolor sit amet, consectetur adipisicing elit</h3>
+			<h4>H4: Lorem ipsum dolor sit amet, consectetur adipisicing elit adipis</h4>
+			<h5>H5: Lorem ipsum dolor sit amet, consectetur adipisicing elit adipisicing elit adipisicing elit</h5>
+			<h6>H6: Lorem ipsum dolor sit amet, consectetur adipisicing elit adipisicing elit adipisicing elit</h6>
+    </div>
+    
+    <div class="span-8">
+			<h1>Heading 1</h1><hr>
+			<h2>Heading 2</h2><hr>
+			<h3>Heading 3</h3><hr>
+			<h4>Heading 4</h4><hr>
+			<h5>Heading 5</h5><hr>
+			<h6>Heading 6</h6>
+    </div>
+    
+    <div class="span-8 last">
+			<h1>Heading 1</h1>
+			<h2>Heading 2</h2>
+			<h3>Heading 3</h3>
+			<h4>Heading 4</h4>
+			<h5>Heading 5</h5>
+			<h6>Heading 6</h6>
+    </div>
+    <hr>    
+    
+    <h5>MISC ELEMENTS</h5>
+    
+    <div class="span-8">    
+      <p>
+        <strong>&lt;strong&gt;</strong><br>
+        <del>&lt;del&gt; deleted</del><br>
+        <dfn>&lt;dfn&gt; dfn</dfn><br>
+        <em>&lt;em&gt; emphasis</em>
+      </p>
+      <p>
+        <a>&lt;a&gt; anchor</a><br>
+        <a href="http://www.google.com">&lt;a&gt; a + href</a>
+      </p>
+      <p>
+        <abbr title="extended abbr text should show when mouse over">&lt;abbr&gt; abbr - extended text when mouseover.</abbr><br>
+        <acronym title="extended acronym text should show when mouse over">&lt;acronym&gt; acronym - extended text when mouseover.</acronym>
+      </p>
+      <address>
+        &lt;address&gt;<br>
+        Donald Duck<br>
+        Box 555<br>
+        Disneyland
+      </address>
+      <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore dolore.</p>
+    </div>
+    
+    <div class="span-8">
+      <table summary="This is the summary text for this table."  border="0" cellspacing="0" cellpadding="0">
+      	<caption><em>A standard test table with a caption, tr, td elements</em></caption>
+      	<tr>
+      		<th class="span-4">Table Header One</th>
+        	<th class="span-4 last">Table Header Two</th>
+      	</tr>
+      	<tr>
+      		<td>TD One</td>
+        	<td>TD Two</td>
+      	</tr>
+      	<tr>
+      		<td colspan="2">TD colspan 2</td>
+      	</tr>
+      </table>
+      
+      <table summary="This is the summary text for this table."  border="0" cellspacing="0" cellpadding="0">
+      	<caption><em>A test table with a thead, tfoot, and tbody elements</em></caption>
+      	<thead>
+      		<tr>
+      			<th class="span-4">Table Header One</th>
+      	  	<th class="span-4 last">Table Header Two</th>
+      		</tr>
+      	</thead>
+      	<tfoot>
+      		<tr>
+      			<td colspan="2">tfoot footer</td>
+      		</tr>
+      	</tfoot>
+      	<tbody>
+      		<tr>
+      			<td>TD One</td>
+      	  	<td>TD Two</td>
+      		</tr>
+      		<tr>
+      			<td>TD One</td>
+      	  	<td>TD Two</td>
+      		</tr>
+      	</tbody>
+      	<tbody>
+      		<tr>
+      			<td>TD One</td>
+      	  	<td>TD Two</td>
+      		</tr>
+      		<tr>
+      			<td>TD One</td>
+      	  	<td>TD Two</td>
+      		</tr>
+      	</tbody>
+      </table>
+    </div>
+    
+    <div class="span-8 last">
+
+<pre>&lt;pre&gt;
+pre  space1
+pre  space1
+pre    space2
+pre    space2
+pre	tab
+pre	tab</pre>
+
+<code>&lt;code&gt;
+Not indented
+	indent1
+	indent1
+		indent2
+			indent3</code>
+
+      <tt>&lt;tt&gt;
+      This tt text should be monospaced
+        and 
+        wrap as if 
+          one line of text
+            even though the code has newlines, spaces, and tabs. 
+      It should be the same size as &lt;p&gt; text.
+      </tt>
+    </div>
+    <hr>
+    
+    <p><a href="http://validator.w3.org/check?uri=referer">
+    <img src="valid.png" alt="Valid HTML 4.01 Strict" height="31" width="88" class="top"></a></p>
+		
+	</div>
+</body>
+</html>
diff --git a/src/third_party/mozjs-45/build/pgo/blueprint/fancytype-screen.css b/src/third_party/mozjs-45/build/pgo/blueprint/fancytype-screen.css
new file mode 100644
index 0000000..0d3feb7
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/blueprint/fancytype-screen.css
@@ -0,0 +1,75 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* -------------------------------------------------------------- 
+  
+   fancy-type.css
+   * Lots of pretty advanced classes for manipulating text.
+   
+   See the Readme file in this folder for additional instructions.
+
+-------------------------------------------------------------- */
+
+/* Indentation instead of line shifts for sibling paragraphs. */
+   p + p { text-indent:2em; margin-top:-1.5em; }
+   form p + p  { text-indent: 0; } /* Don't want this in forms. */
+   
+
+/* For great looking type, use this code instead of asdf: 
+   <span class="alt">asdf</span>  
+   Best used on prepositions and ampersands. */
+  
+.alt { 
+  color: #666; 
+  font-family: "Warnock Pro", "Goudy Old Style","Palatino","Book Antiqua", Georgia, serif; 
+  font-style: italic;
+  font-weight: normal;
+}
+
+
+/* For great looking quote marks in titles, replace "asdf" with:
+   <span class="dquo">&#8220;</span>asdf&#8221;
+   (That is, when the title starts with a quote mark). 
+   (You may have to change this value depending on your font size). */  
+   
+.dquo { margin-left: -.5em; } 
+
+
+/* Reduced size type with incremental leading
+   (http://www.markboulton.co.uk/journal/comments/incremental_leading/)
+
+   This could be used for side notes. For smaller type, you don't necessarily want to 
+   follow the 1.5x vertical rhythm -- the line-height is too much. 
+   
+   Using this class, it reduces your font size and line-height so that for 
+   every four lines of normal sized type, there is five lines of the sidenote. eg:
+
+   New type size in em's:
+     10px (wanted side note size) / 12px (existing base size) = 0.8333 (new type size in ems)
+
+   New line-height value:
+     12px x 1.5 = 18px (old line-height)
+     18px x 4 = 72px 
+     72px / 5 = 14.4px (new line height)
+     14.4px / 10px = 1.44 (new line height in em's) */
+
+p.incr, .incr p {
+	font-size: 10px;
+	line-height: 1.44em;  
+	margin-bottom: 1.5em;
+}
+
+
+/* Surround uppercase words and abbreviations with this class.
+   Based on work by Jørgen Arnor Gårdsø Lom [http://twistedintellect.com/] */
+   
+.caps { 
+  font-variant: small-caps; 
+  letter-spacing: 1px; 
+  text-transform: lowercase; 
+  font-size:1.2em;
+  line-height:1%;
+  font-weight:bold;
+  padding:0 2px;
+}
diff --git a/src/third_party/mozjs-45/build/pgo/blueprint/forms.html b/src/third_party/mozjs-45/build/pgo/blueprint/forms.html
new file mode 100644
index 0000000..8310ba4
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/blueprint/forms.html
@@ -0,0 +1,104 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
+   "http://www.w3.org/TR/html4/strict.dtd">
+
+<html lang="en">
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>Blueprint Forms Tests</title>
+
+  <!-- Framework CSS -->
+	<link rel="stylesheet" href="screen.css" type="text/css" media="screen, projection">
+	<link rel="stylesheet" href="print.css" type="text/css" media="print">
+  <!--[if IE]><link rel="stylesheet" href="ie.css" type="text/css" media="screen, projection"><![endif]-->
+</head>
+<body>
+
+	<div class="container showgrid">
+		<h1>Forms</h1>
+		<hr>
+    
+    <div class="span-12">
+    
+      <form id="dummy" action="" method="post">
+
+      	<fieldset>
+      		<legend>Simple sample form</legend>
+
+      		<p><label for="dummy0">Text input (title)</label><br>
+      		  <input type="text" class="title" name="dummy0" id="dummy0" value="Field with class .title"></p>
+        
+          <p><label for="dummy1">Another field</label><br>
+      		  <input type="text" class="text" id="dummy1" name="dummy1" value="Field with class .text"></p>
+
+      	  <p><label for="dummy2">Textarea</label><br>
+      	    <textarea name="dummy2" id="dummy2" rows="5" cols="20"></textarea></p>
+
+      		<p><input type="submit" value="Submit">
+      		  <input type="reset" value="Reset"></p>
+
+      	</fieldset>
+      </form>
+    
+    </div>
+    <div class="span-12 last">
+    
+      <div class="error">
+        This is a &lt;div&gt; with the class <strong>.error</strong>. <a href="#">Link</a>.
+      </div>
+      <div class="notice">
+        This is a &lt;div&gt; with the class <strong>.notice</strong>. <a href="#">Link</a>.
+      </div>		
+      <div class="success">
+        This is a &lt;div&gt; with the class <strong>.success</strong>. <a href="#">Link</a>.
+      </div>    
+      
+      <fieldset>
+        <legend>Select, checkboxes, lists</legend>
+
+    		<p><label for="dummy3">Select field</label><br>
+    		  <select id="dummy3" name="dummy3">
+    			  <option value="1">Ottawa</option>
+    			  <option value="2">Calgary</option>
+    			  <option value="3">Moosejaw</option>
+    		  </select></p>
+
+    		<p><label for="dummy4">Select with groups</label><br>
+    		  <select id="dummy4" name="dummy4">
+    			  <option>Favorite pet</option>
+    			  <optgroup label="mammals">
+    			    <option>dog</option>
+    			    <option>cat</option>
+    			    <option>rabbit</option>
+    			    <option>horse</option>
+    			  </optgroup>
+    			  <optgroup label="reptiles">
+    			    <option>iguana</option>
+    			    <option>snake</option>
+    			  </optgroup>
+    		  </select></p>
+    		  
+    		  <p><label>Radio buttons</label><br>
+    		    <input type="radio" name="example"> Radio one<br>
+    		    <input type="radio" name="example"> Radio two<br>
+    		    <input type="radio" name="example"> Radio three<br></p>
+          
+    		  <p><label>Checkboxes</label><br>
+    		    <input type="checkbox"> Check one<br>
+    		    <input type="checkbox"> Check two<br>
+    		    <input type="checkbox"> Check three<br></p>
+        
+      </fieldset>
+    
+    </div>
+    <hr>
+
+    <p><a href="http://validator.w3.org/check?uri=referer">
+    <img src="valid.png" alt="Valid HTML 4.01 Strict" height="31" width="88" class="top"></a></p>
+    
+  </div>
+</body>
+</html>
diff --git a/src/third_party/mozjs-45/build/pgo/blueprint/grid.html b/src/third_party/mozjs-45/build/pgo/blueprint/grid.html
new file mode 100644
index 0000000..e851a63
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/blueprint/grid.html
@@ -0,0 +1,210 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
+   "http://www.w3.org/TR/html4/strict.dtd">
+
+<html lang="en">
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>Blueprint Grid Tests</title>
+
+  <!-- Framework CSS -->
+	<link rel="stylesheet" href="screen.css" type="text/css" media="screen, projection">
+	<link rel="stylesheet" href="print.css" type="text/css" media="print">
+  <!--[if IE]><link rel="stylesheet" href="ie.css" type="text/css" media="screen, projection"><![endif]-->
+</head>
+<body>
+
+	<div class="container showgrid">
+		<h1>Blueprint Tests: grid.css</h1>
+		
+
+		<div class="span-8">
+			<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
+		</div>
+		<div class="span-8">
+			<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
+		</div>
+		<div class="span-8 last">
+			<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
+		</div>
+		
+
+		<div class="span-6 append-1">
+			<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
+		</div>
+		<div class="span-6 append-2">
+			<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
+		</div>
+		<div class="span-6 append-3 last">
+			<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
+		</div>
+		
+
+		<div class="span-6 prepend-1">
+			<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
+		</div>
+		<div class="span-6 prepend-2">
+			<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
+		</div>
+		<div class="span-6 prepend-3 last">
+			<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
+		</div>
+		<hr>
+
+		<div class="span-12 border">
+			<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
+		</div>
+		<div class="span-12 last">
+			<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
+		</div>
+		<hr>
+
+		<div class="span-1 prepend-1"><p>1</p></div>
+		<div class="span-1 prepend-2"><p>2</p></div>
+		<div class="span-1 prepend-3"><p>3</p></div>
+		<div class="span-1 prepend-4"><p>4</p></div>
+		<div class="span-1 prepend-5"><p>5</p></div>
+		<div class="span-1 prepend-3 last"><p>3</p></div>
+
+		<div class="span-1 append-1"><p>1</p></div>
+		<div class="span-1 append-2"><p>2</p></div>
+		<div class="span-1 append-3"><p>3</p></div>
+		<div class="span-1 append-4"><p>4</p></div>
+		<div class="span-1 append-5"><p>5</p></div>
+		<div class="span-1 append-3 last"><p>3</p></div>
+		
+		<div class="span-1 border"><p>1</p></div>
+		<div class="span-1 border"><p>2</p></div>
+		<div class="span-1 border"><p>3</p></div>
+		<div class="span-1 border"><p>4</p></div>
+		<div class="span-1 border"><p>5</p></div>
+		<div class="span-1 border"><p>6</p></div>
+		<div class="span-1 border"><p>7</p></div>
+		<div class="span-1 border"><p>8</p></div>
+		<div class="span-1 border"><p>9</p></div>
+		<div class="span-1 border"><p>10</p></div>
+		<div class="span-1 border"><p>11</p></div>
+		<div class="span-1 border"><p>12</p></div>
+		<div class="span-1 border"><p>13</p></div>
+		<div class="span-1 border"><p>14</p></div>
+		<div class="span-1 border"><p>15</p></div>
+		<div class="span-1 border"><p>16</p></div>
+		<div class="span-1 border"><p>17</p></div>
+		<div class="span-1 border"><p>18</p></div>
+		<div class="span-1 border"><p>19</p></div>
+		<div class="span-1 border"><p>20</p></div>
+		<div class="span-1 border"><p>21</p></div>
+		<div class="span-1 border"><p>22</p></div>
+		<div class="span-1 border"><p>23</p></div>
+		<div class="span-1 last"><p>24</p></div>
+		
+		
+		<div class="span-4"><p>1</p></div>
+		<div class="span-4"><p>2</p></div>
+		<div class="span-4"><p>3</p></div>
+		<div class="span-4"><p>4</p></div>
+		<div class="span-4"><p>5</p></div>
+		<div class="span-4 last"><p>6</p></div>
+		
+		
+		<div class="prepend-23 span-1 last"><p>24</p></div>
+		
+		
+		<div class="prepend-1 span-1"><p>2</p></div>
+		<div class="prepend-20 span-1 append-1 last"><p>23</p></div>
+		<hr>
+		
+		<div class="span-24">
+			<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
+		</div>
+		
+
+		<div class="span-12">
+			<div class="span-6">
+				<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod.</p>
+			</div>
+
+			<div class="span-6 last">
+				<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
+			</div>
+
+			<div class="span-12 last">
+				<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
+			</div>
+		</div>
+
+		<div class="span-12 last">
+			<div class="span-6">
+				<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod.</p>
+			</div>
+
+			<div class="span-6 last">
+				<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
+			</div>
+
+			<div class="span-12 last">
+				<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
+			</div>
+		</div>
+		
+
+		<div class="span-14 prepend-5 append-5 last">
+			<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
+		</div>
+		<hr>
+		
+		<div class="span-12">
+		  <h5>TESTING .PUSH-1 TO .PUSH-5</h5>
+		
+			<div class="span-2"><img src="test-small.jpg" class="push-1"></div>
+			<div class="span-10 last"><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p></div>
+
+			<div class="span-2"><img src="test-small.jpg" class="push-2"></div>
+			<div class="span-10 last"><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p></div>
+		
+			<div class="span-2"><img src="test-small.jpg" class="push-3"></div>
+			<div class="span-10 last"><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p></div>
+
+			<div class="span-2"><img src="test-small.jpg" class="push-4"></div>
+			<div class="span-10 last"><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p></div>
+
+			<div class="span-2"><img src="test-small.jpg" class="push-5"></div>
+			<div class="span-10 last"><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p></div>
+		
+		</div>
+
+		<div class="span-12 last">
+		  <h5>TESTING .PULL-1 TO .PULL-5</h5>
+			
+			<div class="span-10"><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p></div>
+			<div class="span-2 last"><img src="test-small.jpg" class="top pull-1"></div>
+
+			<div class="span-10"><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p></div>
+			<div class="span-2 last"><img src="test-small.jpg" class="top pull-2"></div>		
+
+			<div class="span-10"><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p></div>
+			<div class="span-2 last"><img src="test-small.jpg" class="top pull-3"></div>		
+
+			<div class="span-10"><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p></div>
+			<div class="span-2 last"><img src="test-small.jpg" class="top pull-4"></div>		
+
+			<div class="span-10"><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p></div>
+			<div class="span-2 last"><img src="test-small.jpg" class="top pull-5"></div>		
+
+		</div>
+		
+		
+		
+		
+		
+  	<div class="span-24">
+	    <p><a href="http://validator.w3.org/check?uri=referer">
+	    <img src="valid.png" alt="Valid HTML 4.01 Strict" height="31" width="88" class="bottom"></a></p>
+  	</div>		
+
+	</div>
+</body>
+</html>
diff --git a/src/third_party/mozjs-45/build/pgo/blueprint/grid.png b/src/third_party/mozjs-45/build/pgo/blueprint/grid.png
new file mode 100644
index 0000000..129d4a2
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/blueprint/grid.png
Binary files differ
diff --git a/src/third_party/mozjs-45/build/pgo/blueprint/print.css b/src/third_party/mozjs-45/build/pgo/blueprint/print.css
new file mode 100644
index 0000000..6618614
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/blueprint/print.css
@@ -0,0 +1,29 @@
+/* -----------------------------------------------------------------------
+
+   Blueprint CSS Framework 0.7.1
+   http://blueprintcss.googlecode.com
+
+   * Copyright (c) 2007-2008. See LICENSE for more info.
+   * See README for instructions on how to use Blueprint.
+   * For credits and origins, see AUTHORS.
+   * This is a compressed file. See the sources in the 'src' directory.
+
+----------------------------------------------------------------------- */
+
+/* print.css */
+body {line-height:1.5;font-family:"Helvetica Neue", Helvetica, Arial, sans-serif;color:#000;background:none;font-size:10pt;}
+.container {background:none;}
+hr {background:#ccc;color:#ccc;width:100%;height:2px;margin:2em 0;padding:0;border:none;}
+hr.space {background:#fff;color:#fff;}
+h1, h2, h3, h4, h5, h6 {font-family:"Helvetica Neue", Arial, "Lucida Grande", sans-serif;}
+code {font:.9em "Courier New", Monaco, Courier, monospace;}
+img {float:left;margin:1.5em 1.5em 1.5em 0;}
+a img {border:none;}
+p img.top {margin-top:0;}
+blockquote {margin:1.5em;padding:1em;font-style:italic;font-size:.9em;}
+.small {font-size:.9em;}
+.large {font-size:1.1em;}
+.quiet {color:#999;}
+.hide {display:none;}
+a:link, a:visited {background:transparent;font-weight:700;text-decoration:underline;}
+a:link:after, a:visited:after {content:" (" attr(href) ") ";font-size:90%;}
\ No newline at end of file
diff --git a/src/third_party/mozjs-45/build/pgo/blueprint/sample.html b/src/third_party/mozjs-45/build/pgo/blueprint/sample.html
new file mode 100644
index 0000000..d2c4dfe
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/blueprint/sample.html
@@ -0,0 +1,91 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
+   "http://www.w3.org/TR/html4/strict.dtd">
+
+<html lang="en">
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+	<title>Blueprint Sample Page</title>
+
+  <!-- Framework CSS -->
+	<link rel="stylesheet" href="screen.css" type="text/css" media="screen, projection">
+	<link rel="stylesheet" href="print.css" type="text/css" media="print">
+  <!--[if IE]><link rel="stylesheet" href="ie.css" type="text/css" media="screen, projection"><![endif]-->
+	
+	<!-- Import fancy-type plugin for the sample page. -->
+	<link rel="stylesheet" href="fancytype-screen.css" type="text/css" media="screen, projection">
+</head>
+
+<body>
+
+	<div class="container">  
+		<h1>A simple sample page</h1>
+		<hr>
+		<h2 class="alt">This sample page demonstrates a tiny fraction of what you get with Blueprint.</h2>
+		<hr>
+		
+		<div class="span-7 colborder">
+		  <h6>Here's a box</h6>
+		  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip.</p>
+		</div>
+
+		<div class="span-8 colborder">
+		  <h6>And another box</h6>
+		  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat laboris nisi ut aliquip.</p>
+		</div>
+		
+		<div class="span-7 last">
+		  <h6>This box is aligned with the sidebar</h6>
+		  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip.</p>
+		</div>
+		<hr>
+		<hr class="space">
+
+		<div class="span-15 prepend-1 colborder">
+			<p><img src="test.jpg" class="top pull-1" alt="test">Lorem ipsum dolor sit amet, <em>consectetuer adipiscing elit</em>. Nunc congue ipsum vestibulum libero. Aenean vitae justo. Nam eget tellus. Etiam convallis, est eu lobortis mattis, lectus tellus tempus felis, a ultricies erat ipsum at metus.</p>
+			<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. <a href="#">Morbi et risus</a>. Aliquam nisl. Nulla facilisi. Cras accumsan vestibulum ante. Vestibulum sed tortor. Praesent <span class="caps">SMALL CAPS</span> tempus fringilla elit. Ut elit diam, sagittis in, nonummy in, gravida non, nunc. Ut orci. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Nam egestas, orci eu imperdiet malesuada, nisl purus fringilla odio, quis commodo est orci vitae justo. Aliquam placerat odio tincidunt nulla. Cras in libero. Aenean rutrum, magna non tristique posuere, erat odio eleifend nisl, non convallis est tortor blandit ligula. Nulla id augue.</p>
+			<p>Nullam mattis, odio ut tempus facilisis, metus nisl facilisis metus, auctor consectetuer felis ligula nec mauris. Vestibulum odio erat, fermentum at, commodo vitae, ultrices et, urna. Mauris vulputate, mi pulvinar sagittis condimentum, sem nulla aliquam velit, sed imperdiet mi purus eu magna. Nulla varius metus ut eros. Aenean aliquet magna eget orci. Class aptent taciti sociosqu ad litora.</p>
+			<p>Vivamus euismod. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Suspendisse vel nibh ut turpis dictum sagittis. Aliquam vel velit a elit auctor sollicitudin. Nam vel dui vel neque lacinia pretium. Quisque nunc erat, venenatis id, volutpat ut, scelerisque sed, diam. Mauris ante. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Donec mattis. Morbi dignissim sollicitudin libero. Nulla lorem.</p>
+			<blockquote>
+				<p>Integer cursus ornare mauris. Praesent nisl arcu, imperdiet eu, ornare id, scelerisque ut, nunc. Praesent sagittis erat sed velit tempus imperdiet. Ut tristique, ante in interdum hendrerit, erat enim faucibus felis, quis rutrum mauris lorem quis sem. Vestibulum ligula nisi, mattis nec, posuere et, blandit eu, ligula. Nam suscipit placerat odio. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Pellentesque tortor libero, venenatis vitae, rhoncus eu, placerat ut, mi. Nulla nulla.</p>
+			</blockquote>
+			<p>Maecenas vel metus quis magna pharetra fermentum. <em>Integer sit amet tortor</em>. Maecenas porttitor, pede sed gravida auctor, nulla augue aliquet elit, at pretium urna orci ut metus. Aliquam in dolor. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed aliquam, tellus id ornare posuere, quam nunc accumsan turpis, at convallis tellus orci et nisl. Phasellus congue neque a lorem.</p>
+			
+			<hr>
+			<div class="span-7 colborder">
+			  <h6>This is a nested column</h6>
+			  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</p>
+			</div>
+			<div class="span-7 last">
+			  <h6>This is another nested column</h6>
+			  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</p>
+			</div>
+			
+		</div>
+    <div class="span-7 last">
+			
+			<h3>A <span class="alt">Simple</span> Sidebar</h3>
+
+			<p>Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Cras ornare mattis nunc. Mauris venenatis, pede sed aliquet vehicula, lectus tellus pulvinar neque, non cursus sem nisi vel augue.</p>
+			<p>Mauris a lectus. Aliquam erat volutpat. Phasellus ultrices mi a sapien. Nunc rutrum egestas lorem. Duis ac sem sagittis elit tincidunt gravida. Mauris a lectus. Aliquam erat volutpat. Phasellus ultrices mi a sapien. Nunc rutrum egestas lorem. Duis ac sem sagittis elit tincidunt gravida.</p>
+			<p class="quiet">Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Cras ornare mattis nunc. Mauris venenatis, pede sed aliquet vehicula, lectus tellus pulvinar neque, non cursus sem nisi vel augue.</p>
+
+			<h5>Incremental leading</h5>
+			<p class="incr">Vestibulum ante ipsum primis in faucibus orci luctus vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Cras ornare mattis nunc. Mauris venenatis, pede sed aliquet vehicula, lectus tellus pulvinar neque, non cursus sem nisi vel augue. sed aliquet vehicula, lectus tellus.</p>
+			<p class="incr">Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Cras ornare mattis nunc. Mauris venenatis, pede sed aliquet vehicula, lectus tellus pulvinar neque, non cursus sem nisi vel augue. sed aliquet vehicula, lectus tellus pulvinar neque, non cursus sem nisi vel augue. ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Cras ornare mattis nunc. Mauris venenatis, pede sed aliquet vehicula, lectus tellus pulvinar neque, non cursus sem nisi vel augue. sed aliquet vehicula, lectus tellus pulvinar neque, non cursus sem nisi vel augue.</p>
+		
+		</div>
+		
+		<hr>
+		<h2 class="alt">You may pick and choose amongst these and many more features, so be bold.</h2>
+		<hr>
+
+    <p><a href="http://validator.w3.org/check?uri=referer">
+    <img src="valid.png" alt="Valid HTML 4.01 Strict" height="31" width="88" class="top"></a></p>
+	</div>
+
+</body>
+</html>
diff --git a/src/third_party/mozjs-45/build/pgo/blueprint/screen.css b/src/third_party/mozjs-45/build/pgo/blueprint/screen.css
new file mode 100644
index 0000000..c631ead
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/blueprint/screen.css
@@ -0,0 +1,226 @@
+/* -----------------------------------------------------------------------
+
+   Blueprint CSS Framework 0.7.1
+   http://blueprintcss.googlecode.com
+
+   * Copyright (c) 2007-2008. See LICENSE for more info.
+   * See README for instructions on how to use Blueprint.
+   * For credits and origins, see AUTHORS.
+   * This is a compressed file. See the sources in the 'src' directory.
+
+----------------------------------------------------------------------- */
+
+/* reset.css */
+html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, code, del, dfn, em, img, q, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td {margin:0;padding:0;border:0;font-weight:inherit;font-style:inherit;font-size:100%;font-family:inherit;vertical-align:baseline;}
+body {line-height:1.5;}
+table {border-collapse:separate;border-spacing:0;}
+caption, th, td {text-align:left;font-weight:normal;}
+table, td, th {vertical-align:middle;}
+blockquote:before, blockquote:after, q:before, q:after {content:"";}
+blockquote, q {quotes:"" "";}
+a img {border:none;}
+
+/* typography.css */
+body {font-size:75%;color:#222;background:#fff;font-family:"Helvetica Neue", Helvetica, Arial, sans-serif;}
+h1, h2, h3, h4, h5, h6 {font-weight:normal;color:#111;}
+h1 {font-size:3em;line-height:1;margin-bottom:0.5em;}
+h2 {font-size:2em;margin-bottom:0.75em;}
+h3 {font-size:1.5em;line-height:1;margin-bottom:1em;}
+h4 {font-size:1.2em;line-height:1.25;margin-bottom:1.25em;height:1.25em;}
+h5 {font-size:1em;font-weight:bold;margin-bottom:1.5em;}
+h6 {font-size:1em;font-weight:bold;}
+h1 img, h2 img, h3 img, h4 img, h5 img, h6 img {margin:0;}
+p {margin:0 0 1.5em;}
+p img {float:left;margin:1.5em 1.5em 1.5em 0;padding:0;}
+p img.right {float:right;margin:1.5em 0 1.5em 1.5em;}
+a:focus, a:hover {color:#000;}
+a {color:#009;text-decoration:underline;}
+blockquote {margin:1.5em;color:#666;font-style:italic;}
+strong {font-weight:bold;}
+em, dfn {font-style:italic;}
+dfn {font-weight:bold;}
+sup, sub {line-height:0;}
+abbr, acronym {border-bottom:1px dotted #666;}
+address {margin:0 0 1.5em;font-style:italic;}
+del {color:#666;}
+pre, code {margin:1.5em 0;white-space:pre;}
+pre, code, tt {font:1em 'andale mono', 'lucida console', monospace;line-height:1.5;}
+li ul, li ol {margin:0 1.5em;}
+ul, ol {margin:0 1.5em 1.5em 1.5em;}
+ul {list-style-type:disc;}
+ol {list-style-type:decimal;}
+dl {margin:0 0 1.5em 0;}
+dl dt {font-weight:bold;}
+dd {margin-left:1.5em;}
+table {margin-bottom:1.4em;width:100%;}
+th {font-weight:bold;background:#C3D9FF;}
+th, td {padding:4px 10px 4px 5px;}
+tr.even td {background:#E5ECF9;}
+tfoot {font-style:italic;}
+caption {background:#eee;}
+.small {font-size:.8em;margin-bottom:1.875em;line-height:1.875em;}
+.large {font-size:1.2em;line-height:2.5em;margin-bottom:1.25em;}
+.hide {display:none;}
+.quiet {color:#666;}
+.loud {color:#000;}
+.highlight {background:#ff0;}
+.added {background:#060;color:#fff;}
+.removed {background:#900;color:#fff;}
+.first {margin-left:0;padding-left:0;}
+.last {margin-right:0;padding-right:0;}
+.top {margin-top:0;padding-top:0;}
+.bottom {margin-bottom:0;padding-bottom:0;}
+
+/* grid.css */
+.container {width:950px;margin:0 auto;}
+.showgrid {background:url(grid.png);}
+body {margin:1.5em 0;}
+div.span-1, div.span-2, div.span-3, div.span-4, div.span-5, div.span-6, div.span-7, div.span-8, div.span-9, div.span-10, div.span-11, div.span-12, div.span-13, div.span-14, div.span-15, div.span-16, div.span-17, div.span-18, div.span-19, div.span-20, div.span-21, div.span-22, div.span-23, div.span-24 {float:left;margin-right:10px;}
+div.last {margin-right:0;}
+.span-1 {width:30px;}
+.span-2 {width:70px;}
+.span-3 {width:110px;}
+.span-4 {width:150px;}
+.span-5 {width:190px;}
+.span-6 {width:230px;}
+.span-7 {width:270px;}
+.span-8 {width:310px;}
+.span-9 {width:350px;}
+.span-10 {width:390px;}
+.span-11 {width:430px;}
+.span-12 {width:470px;}
+.span-13 {width:510px;}
+.span-14 {width:550px;}
+.span-15 {width:590px;}
+.span-16 {width:630px;}
+.span-17 {width:670px;}
+.span-18 {width:710px;}
+.span-19 {width:750px;}
+.span-20 {width:790px;}
+.span-21 {width:830px;}
+.span-22 {width:870px;}
+.span-23 {width:910px;}
+.span-24, div.span-24 {width:950px;margin:0;}
+.append-1 {padding-right:40px;}
+.append-2 {padding-right:80px;}
+.append-3 {padding-right:120px;}
+.append-4 {padding-right:160px;}
+.append-5 {padding-right:200px;}
+.append-6 {padding-right:240px;}
+.append-7 {padding-right:280px;}
+.append-8 {padding-right:320px;}
+.append-9 {padding-right:360px;}
+.append-10 {padding-right:400px;}
+.append-11 {padding-right:440px;}
+.append-12 {padding-right:480px;}
+.append-13 {padding-right:520px;}
+.append-14 {padding-right:560px;}
+.append-15 {padding-right:600px;}
+.append-16 {padding-right:640px;}
+.append-17 {padding-right:680px;}
+.append-18 {padding-right:720px;}
+.append-19 {padding-right:760px;}
+.append-20 {padding-right:800px;}
+.append-21 {padding-right:840px;}
+.append-22 {padding-right:880px;}
+.append-23 {padding-right:920px;}
+.prepend-1 {padding-left:40px;}
+.prepend-2 {padding-left:80px;}
+.prepend-3 {padding-left:120px;}
+.prepend-4 {padding-left:160px;}
+.prepend-5 {padding-left:200px;}
+.prepend-6 {padding-left:240px;}
+.prepend-7 {padding-left:280px;}
+.prepend-8 {padding-left:320px;}
+.prepend-9 {padding-left:360px;}
+.prepend-10 {padding-left:400px;}
+.prepend-11 {padding-left:440px;}
+.prepend-12 {padding-left:480px;}
+.prepend-13 {padding-left:520px;}
+.prepend-14 {padding-left:560px;}
+.prepend-15 {padding-left:600px;}
+.prepend-16 {padding-left:640px;}
+.prepend-17 {padding-left:680px;}
+.prepend-18 {padding-left:720px;}
+.prepend-19 {padding-left:760px;}
+.prepend-20 {padding-left:800px;}
+.prepend-21 {padding-left:840px;}
+.prepend-22 {padding-left:880px;}
+.prepend-23 {padding-left:920px;}
+div.border {padding-right:4px;margin-right:5px;border-right:1px solid #eee;}
+div.colborder {padding-right:24px;margin-right:25px;border-right:1px solid #eee;}
+.pull-1 {margin-left:-40px;}
+.pull-2 {margin-left:-80px;}
+.pull-3 {margin-left:-120px;}
+.pull-4 {margin-left:-160px;}
+.pull-5 {margin-left:-200px;}
+.pull-6 {margin-left:-240px;}
+.pull-7 {margin-left:-280px;}
+.pull-8 {margin-left:-320px;}
+.pull-9 {margin-left:-360px;}
+.pull-10 {margin-left:-400px;}
+.pull-11 {margin-left:-440px;}
+.pull-12 {margin-left:-480px;}
+.pull-13 {margin-left:-520px;}
+.pull-14 {margin-left:-560px;}
+.pull-15 {margin-left:-600px;}
+.pull-16 {margin-left:-640px;}
+.pull-17 {margin-left:-680px;}
+.pull-18 {margin-left:-720px;}
+.pull-19 {margin-left:-760px;}
+.pull-20 {margin-left:-800px;}
+.pull-21 {margin-left:-840px;}
+.pull-22 {margin-left:-880px;}
+.pull-23 {margin-left:-920px;}
+.pull-24 {margin-left:-960px;}
+.pull-1, .pull-2, .pull-3, .pull-4, .pull-5, .pull-6, .pull-7, .pull-8, .pull-9, .pull-10, .pull-11, .pull-12, .pull-13, .pull-14, .pull-15, .pull-16, .pull-17, .pull-18, .pull-19, .pull-20, .pull-21, .pull-22, .pull-23, .pull-24 {float:left;position:relative;}
+.push-1 {margin:0 -40px 1.5em 40px;}
+.push-2 {margin:0 -80px 1.5em 80px;}
+.push-3 {margin:0 -120px 1.5em 120px;}
+.push-4 {margin:0 -160px 1.5em 160px;}
+.push-5 {margin:0 -200px 1.5em 200px;}
+.push-6 {margin:0 -240px 1.5em 240px;}
+.push-7 {margin:0 -280px 1.5em 280px;}
+.push-8 {margin:0 -320px 1.5em 320px;}
+.push-9 {margin:0 -360px 1.5em 360px;}
+.push-10 {margin:0 -400px 1.5em 400px;}
+.push-11 {margin:0 -440px 1.5em 440px;}
+.push-12 {margin:0 -480px 1.5em 480px;}
+.push-13 {margin:0 -520px 1.5em 520px;}
+.push-14 {margin:0 -560px 1.5em 560px;}
+.push-15 {margin:0 -600px 1.5em 600px;}
+.push-16 {margin:0 -640px 1.5em 640px;}
+.push-17 {margin:0 -680px 1.5em 680px;}
+.push-18 {margin:0 -720px 1.5em 720px;}
+.push-19 {margin:0 -760px 1.5em 760px;}
+.push-20 {margin:0 -800px 1.5em 800px;}
+.push-21 {margin:0 -840px 1.5em 840px;}
+.push-22 {margin:0 -880px 1.5em 880px;}
+.push-23 {margin:0 -920px 1.5em 920px;}
+.push-24 {margin:0 -960px 1.5em 960px;}
+.push-1, .push-2, .push-3, .push-4, .push-5, .push-6, .push-7, .push-8, .push-9, .push-10, .push-11, .push-12, .push-13, .push-14, .push-15, .push-16, .push-17, .push-18, .push-19, .push-20, .push-21, .push-22, .push-23, .push-24 {float:right;position:relative;}
+.box {padding:1.5em;margin-bottom:1.5em;background:#E5ECF9;}
+hr {background:#ddd;color:#ddd;clear:both;float:none;width:100%;height:.1em;margin:0 0 1.45em;border:none;}
+hr.space {background:#fff;color:#fff;}
+.clearfix:after, .container:after {content:".";display:block;height:0;clear:both;visibility:hidden;}
+.clearfix, .container {display:inline-block;}
+* html .clearfix, * html .container {height:1%;}
+.clearfix, .container {display:block;}
+.clear {clear:both;}
+
+/* forms.css */
+label {font-weight:bold;}
+fieldset {padding:1.4em;margin:0 0 1.5em 0;border:1px solid #ccc;}
+legend {font-weight:bold;font-size:1.2em;}
+input.text, input.title, textarea, select {margin:0.5em 0;border:1px solid #bbb;}
+input.text:focus, input.title:focus, textarea:focus, select:focus {border:1px solid #666;}
+input.text, input.title {width:300px;padding:5px;}
+input.title {font-size:1.5em;}
+textarea {width:390px;height:250px;padding:5px;}
+.error, .notice, .success {padding:.8em;margin-bottom:1em;border:2px solid #ddd;}
+.error {background:#FBE3E4;color:#8a1f11;border-color:#FBC2C4;}
+.notice {background:#FFF6BF;color:#514721;border-color:#FFD324;}
+.success {background:#E6EFC2;color:#264409;border-color:#C6D880;}
+.error a {color:#8a1f11;}
+.notice a {color:#514721;}
+.success a {color:#264409;}
\ No newline at end of file
diff --git a/src/third_party/mozjs-45/build/pgo/blueprint/test-small.jpg b/src/third_party/mozjs-45/build/pgo/blueprint/test-small.jpg
new file mode 100644
index 0000000..aa599d9
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/blueprint/test-small.jpg
Binary files differ
diff --git a/src/third_party/mozjs-45/build/pgo/blueprint/test.jpg b/src/third_party/mozjs-45/build/pgo/blueprint/test.jpg
new file mode 100644
index 0000000..0107be2
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/blueprint/test.jpg
Binary files differ
diff --git a/src/third_party/mozjs-45/build/pgo/blueprint/valid.png b/src/third_party/mozjs-45/build/pgo/blueprint/valid.png
new file mode 100644
index 0000000..dd20e49
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/blueprint/valid.png
Binary files differ
diff --git a/src/third_party/mozjs-45/build/pgo/certs/README b/src/third_party/mozjs-45/build/pgo/certs/README
new file mode 100644
index 0000000..ba2b346
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/certs/README
@@ -0,0 +1,9 @@
+The certificate authority and server certificates here are generated by $topsrcdir/build/pgo/genpgocert.py.
+
+You can generate a new CA cert by running:
+$objdir/_virtualenv/bin/python $topsrcdir/build/pgo/genpgocert.py --gen-ca
+
+You can generate new server certificates by running:
+$objdir/_virtualenv/bin/python $topsrcdir/build/pgo/genpgocert.py --gen-server
+
+These will place the new files in this directory where you can commit them.
diff --git a/src/third_party/mozjs-45/build/pgo/certs/alternateroot.ca b/src/third_party/mozjs-45/build/pgo/certs/alternateroot.ca
new file mode 100644
index 0000000..058b9f5
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/certs/alternateroot.ca
@@ -0,0 +1,18 @@
+-----BEGIN CERTIFICATE-----
+MIIC2jCCAcKgAwIBAgIBATANBgkqhkiG9w0BAQsFADAmMSQwIgYDVQQDExtBbHRl

+cm5hdGUgVHJ1c3RlZCBBdXRob3JpdHkwHhcNMTQwOTI1MjEyMTU0WhcNMjQwOTI1

+MjEyMTU0WjAmMSQwIgYDVQQDExtBbHRlcm5hdGUgVHJ1c3RlZCBBdXRob3JpdHkw

+ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDBT+BwAhO52IWgSIdZZifU

+9LHOs3IR/+8DCC0WP5d/OuyKlZ6Rqd0tsd3i7durhQyjHSbLf2lJStcnFjcVEbEn

+NI76RuvlN8xLLn5eV+2Ayr4cZYKztudwRmw+DV/iYAiMSy0hs7m3ssfX7qpoi1aN

+RjUanwU0VTCPQhF1bEKAC2du+C5Z8e92zN5t87w7bYr7lt+m8197XliXEu+0s9Rg

+nGwGaZ296BIRz6NOoJYTa43n06LU1I1+Z4d6lPdzUFrSR0GBaMhUSurUBtOin3yW

+iMhg1VHX/KwqGc4als5GyCVXy8HGrA/0zQPOhetxrlhEVAdK/xBt7CZvByj1Rcc7

+AgMBAAGjEzARMA8GA1UdEwQIMAYBAf8CAQAwDQYJKoZIhvcNAQELBQADggEBAJq/

+hogSRqzPWTwX4wTn/DVSNdWwFLv53qep9YrSMJ8ZsfbfK9Es4VP4dBLRQAVMJ0Z5

+mW1I6d/n0KayTanuUBvemYdxPi/qQNSs8UJcllqdhqWzmzAg6a0LxrMnEeKzPBPD

+6q8PwQ7tYP+B4sBN9tnnsnyPgti9ZiNZn5FwXZliHXseQ7FE9/SqHlLw5LXW3YtK

+juti6RmuV6fq3j+D4oeC5vb1mKgIyoTqGN6ze57v8RHi+pQ8Q+kmoUn/L3Z2YmFe

+4SKN/4WoyXr8TdejpThGOCGCAd3565s5gOx5QfSQX11P8NZKO8hcN0tme3VzmGpH

+K0Z/6MTmdpNaTwQ6odk=
+-----END CERTIFICATE-----
diff --git a/src/third_party/mozjs-45/build/pgo/certs/cert8.db b/src/third_party/mozjs-45/build/pgo/certs/cert8.db
new file mode 100644
index 0000000..3f2ef83
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/certs/cert8.db
Binary files differ
diff --git a/src/third_party/mozjs-45/build/pgo/certs/evintermediate.ca b/src/third_party/mozjs-45/build/pgo/certs/evintermediate.ca
new file mode 100644
index 0000000..17a048a
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/certs/evintermediate.ca
@@ -0,0 +1,34 @@
+-----BEGIN CERTIFICATE-----
+MIIF9zCCBN+gAwIBAgIBAzANBgkqhkiG9w0BAQUFADCB4TELMAkGA1UEBhMCVVMx

+CzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MSMwIQYDVQQKExpN

+b3ppbGxhIC0gRVYgZGVidWcgdGVzdCBDQTEdMBsGA1UECxMUU2VjdXJpdHkgRW5n

+aW5lZXJpbmcxJjAkBgNVBAMTHUVWIFRlc3RpbmcgKHVudHJ1c3R3b3J0aHkpIENB

+MRMwEQYDVQQpEwpldi10ZXN0LWNhMSwwKgYJKoZIhvcNAQkBFh1jaGFybGF0YW5A

+dGVzdGluZy5leGFtcGxlLmNvbTAeFw0xMzAyMTQxNzU5MDlaFw0yMzAyMTIxNzU5

+MDlaMIHRMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDU1vdW50

+YWluIFZpZXcxIzAhBgNVBAoTGk1vemlsbGEgLSBFViBkZWJ1ZyB0ZXN0IENBMR0w

+GwYDVQQLExRTZWN1cml0eSBFbmdpbmVlcmluZzEWMBQGA1UEAxMNaW50ZXJtZWRp

+YXRlMzETMBEGA1UEKRMKZXYtdGVzdC1jYTEsMCoGCSqGSIb3DQEJARYdY2hhcmxh

+dGFuQHRlc3RpbmcuZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw

+ggEKAoIBAQDAfzrlJdawr7v8m7lslODk5FTqCiBO7tPxnWhAOEL5g05knLTZTc5J

+3ywmGoW6ae6RwPlWuqRuFd2Ea+yCawyjkUoLOpFH/xziDzvaS6LXNdJoxQqWk/LX

+8YYQVFfmxh8E11fz74IoCzX++mY1byaNONf3bLU2HU8vnVvENr1gy9Bzpm8wUuKm

+HkBYuG0SVzaeym2H/mo5PJICPVhPa+YxfEVS8EIFCigXGH7xrz/bPXnpfgsSJTnN

+4amBNkORfjf7H9x6IWkJGEkIvkVoYKT4iQ9q6/C4YDjWa9p5lA4F/qxnJefezH/I

+6hcqEODSaDsY+I6vsN8ks8r8MTTnd7BjAgMBAAGjggHGMIIBwjAdBgNVHQ4EFgQU

+fluXMAT0ZS21pV13vv46m8k7nRkwggEYBgNVHSMEggEPMIIBC4AUyJg651hwk+3B

+V0rQvQZv9n2bWPahgeekgeQwgeExCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEW

+MBQGA1UEBxMNTW91bnRhaW4gVmlldzEjMCEGA1UEChMaTW96aWxsYSAtIEVWIGRl

+YnVnIHRlc3QgQ0ExHTAbBgNVBAsTFFNlY3VyaXR5IEVuZ2luZWVyaW5nMSYwJAYD

+VQQDEx1FViBUZXN0aW5nICh1bnRydXN0d29ydGh5KSBDQTETMBEGA1UEKRMKZXYt

+dGVzdC1jYTEsMCoGCSqGSIb3DQEJARYdY2hhcmxhdGFuQHRlc3RpbmcuZXhhbXBs

+ZS5jb22CCQCvxT0iZiZJMjAMBgNVHRMEBTADAQH/MDYGA1UdHwQvMC0wK6ApoCeG

+JWh0dHA6Ly9leGFtcGxlLmNvbS9yb290LWV2LXRlc3Rlci5jcmwwPwYDVR0gBDgw

+NjA0BgRVHSAAMCwwKgYIKwYBBQUHAgEWHmh0dHA6Ly9teXRlc3Rkb21haW4ubG9j

+YWwvY3BzOzANBgkqhkiG9w0BAQUFAAOCAQEAC4grNTV5K8yqiAJ/0f6oIkTMqyJ4

+lyHXvvKXMHTpRZ7Jdy0aq5KTSHswx64ZRN7V2ds+czzDWgxX3rBuZZAgOW1JYva3

+Ps3XRYUiaTW8eeaWjuVRFAp7ytRmSsOGeOtHbez8jDmTqPRQ1mTMsMzpY4bFD8do

+5y0xsbz4DYIeeNnX9+XGB5u2ml8t5L8Cj65wwMAx9HlsjTrfQTMIwpwbNle6GuZ3

+9FzmE2piAND73yCgU5W66K2lZg8N6vHBq0UhPDCF72y8MlHxQOpTr3/jIGr4X7k9

+uyYq0Pw5Y/LKyGbyW5iMFdLzabm1ua8IWAf7DSFMH6L3WlK8mngCfJ1icQ==
+-----END CERTIFICATE-----
diff --git a/src/third_party/mozjs-45/build/pgo/certs/jartests-object.ca b/src/third_party/mozjs-45/build/pgo/certs/jartests-object.ca
new file mode 100644
index 0000000..fc6d0ff
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/certs/jartests-object.ca
@@ -0,0 +1,15 @@
+-----BEGIN CERTIFICATE-----
+MIICTTCCAbagAwIBAgIBADANBgkqhkiG9w0BAQUFADBaMRMwEQYDVQQLEwpVbml0

+IFRlc3RzMRgwFgYDVQQKEw9Nb3ppbGxhIFRlc3RpbmcxKTAnBgNVBAMTIFNpZ25l

+ZCBKQVIgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTA5MDExNTE0MDkwM1oXDTM0

+MDExNTE0MDkwM1owWjETMBEGA1UECxMKVW5pdCBUZXN0czEYMBYGA1UEChMPTW96

+aWxsYSBUZXN0aW5nMSkwJwYDVQQDEyBTaWduZWQgSkFSIENlcnRpZmljYXRlIEF1

+dGhvcml0eTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAsQd8eUw4WSK7YoKl

+hqe+CjEgI5Rs3TirWtDsfmMtMBmTvRhJpdTeMAFTpWvlOPuXJwkKXMMFLxE8ayNX

+fO5ixCgJ7LrpguOVZ3pY4RvEyE6yh3Hv81Ztblbo120IdcrkyN4KMs5EgeauDllU

+ehhbq9lmnmQxIQs3KPcoMteqAXcCAwEAAaMjMCEwEQYJYIZIAYb4QgEBBAQDAgAH

+MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAAZHhPT133TcavAKnn37X

+0VE9davrX7t20CLb06KYpgkg7yO0BjIjTnYeJBQgaH652pZVEFT7dbi0JTn4BMXz

+EwOQ2JjzjwNUDHpWAopiCKxAnjwy/kGcZfkKUydwQHKr8m1Faywu1Cyrj0gBHClL

+b2b9ywK4pb545mE6V9pi1zg=
+-----END CERTIFICATE-----
diff --git a/src/third_party/mozjs-45/build/pgo/certs/key3.db b/src/third_party/mozjs-45/build/pgo/certs/key3.db
new file mode 100644
index 0000000..6a9f398
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/certs/key3.db
Binary files differ
diff --git a/src/third_party/mozjs-45/build/pgo/certs/mochitest.client b/src/third_party/mozjs-45/build/pgo/certs/mochitest.client
new file mode 100644
index 0000000..5d72cd2
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/certs/mochitest.client
Binary files differ
diff --git a/src/third_party/mozjs-45/build/pgo/certs/pgoca.ca b/src/third_party/mozjs-45/build/pgo/certs/pgoca.ca
new file mode 100644
index 0000000..65fb8a5
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/certs/pgoca.ca
@@ -0,0 +1,15 @@
+-----BEGIN CERTIFICATE-----
+MIICXTCCAcagAwIBAgIBATANBgkqhkiG9w0BAQUFADBqMSQwIgYDVQQLExtQcm9m
+aWxlIEd1aWRlZCBPcHRpbWl6YXRpb24xGDAWBgNVBAoTD01vemlsbGEgVGVzdGlu
+ZzEoMCYGA1UEAxMfVGVtcG9yYXJ5IENlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0w
+ODA1MjIwMDM4MDVaFw0xODA1MjIwMDM4MDVaMGoxJDAiBgNVBAsTG1Byb2ZpbGUg
+R3VpZGVkIE9wdGltaXphdGlvbjEYMBYGA1UEChMPTW96aWxsYSBUZXN0aW5nMSgw
+JgYDVQQDEx9UZW1wb3JhcnkgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MIGfMA0GCSqG
+SIb3DQEBAQUAA4GNADCBiQKBgQDg6iipAXGZYmgTcHfx8M2hcLqmqDalcj7sZ1A7
+a3LiCBb+1uHKKy9hUxRUe61aJF4NgMAF5oc+HpXN0hpvkiNHxqqD7R6hrkP3gAJ3
+eczEFKsFUI6AqaCL0+xpyhaaZmmarcHxU+PL2h5zq6VssxfBAsO0DkzWzk6E8vM+
+jrku7QIDAQABoxMwETAPBgNVHRMECDAGAQH/AgEAMA0GCSqGSIb3DQEBBQUAA4GB
+ALPbn3Ztg0m8qDt8Vkf5You6HEqIxZe+ffDTrfq/L7ofHk/OXEpL7OWKRHU33pNG
+QS8khBG+sO461C51s6u9giW+eq2PaQv2HGASBpDbvPqc/Hf+zupZsdsXzHv6rt0V
+lu5B6nOpMse1nhA494i1ARSuBNzLv5mas38YWG8Rr6jR
+-----END CERTIFICATE-----
diff --git a/src/third_party/mozjs-45/build/pgo/certs/pgoca.p12 b/src/third_party/mozjs-45/build/pgo/certs/pgoca.p12
new file mode 100644
index 0000000..4867c28
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/certs/pgoca.p12
Binary files differ
diff --git a/src/third_party/mozjs-45/build/pgo/certs/secmod.db b/src/third_party/mozjs-45/build/pgo/certs/secmod.db
new file mode 100644
index 0000000..a3341f7
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/certs/secmod.db
Binary files differ
diff --git a/src/third_party/mozjs-45/build/pgo/favicon.ico b/src/third_party/mozjs-45/build/pgo/favicon.ico
new file mode 100644
index 0000000..d444389
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/favicon.ico
Binary files differ
diff --git a/src/third_party/mozjs-45/build/pgo/genpgocert.py b/src/third_party/mozjs-45/build/pgo/genpgocert.py
new file mode 100644
index 0000000..c58bcd4
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/genpgocert.py
@@ -0,0 +1,192 @@
+#!/usr/bin/env python
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# This script exists to generate the Certificate Authority and server
+# certificates used for SSL testing in Mochitest. The already generated
+# certs are located at $topsrcdir/build/pgo/certs/ .
+
+import mozinfo
+import os
+import random
+import re
+import shutil
+import subprocess
+import sys
+import tempfile
+
+from mozbuild.base import MozbuildObject
+from mozfile import NamedTemporaryFile
+from mozprofile.permissions import ServerLocations
+
+dbFiles = [
+  re.compile("^cert[0-9]+\.db$"),
+  re.compile("^key[0-9]+\.db$"),
+  re.compile("^secmod\.db$")
+]
+
+def unlinkDbFiles(path):
+  for root, dirs, files in os.walk(path):
+    for name in files:
+      for dbFile in dbFiles:
+        if dbFile.match(name) and os.path.exists(os.path.join(root, name)):
+          os.unlink(os.path.join(root, name))
+
+def dbFilesExist(path):
+  for root, dirs, files in os.walk(path):
+    for name in files:
+      for dbFile in dbFiles:
+        if dbFile.match(name) and os.path.exists(os.path.join(root, name)):
+          return True
+  return False
+
+
+def runUtil(util, args, inputdata = None):
+  env = os.environ.copy()
+  if mozinfo.os == "linux":
+    pathvar = "LD_LIBRARY_PATH"
+    app_path = os.path.dirname(util)
+    if pathvar in env:
+      env[pathvar] = "%s%s%s" % (app_path, os.pathsep, env[pathvar])
+    else:
+      env[pathvar] = app_path
+  proc = subprocess.Popen([util] + args, env=env,
+                          stdin=subprocess.PIPE if inputdata else None)
+  proc.communicate(inputdata)
+  return proc.returncode
+
+
+def createRandomFile(randomFile):
+  for count in xrange(0, 2048):
+    randomFile.write(chr(random.randint(0, 255)))
+
+
+def createCertificateAuthority(build, srcDir):
+  certutil = build.get_binary_path(what="certutil")
+  pk12util = build.get_binary_path(what="pk12util")
+
+  #TODO: mozfile.TemporaryDirectory
+  tempDbDir = tempfile.mkdtemp()
+  with NamedTemporaryFile() as pwfile, NamedTemporaryFile() as rndfile:
+    pgoCAModulePathSrc = os.path.join(srcDir, "pgoca.p12")
+    pgoCAPathSrc = os.path.join(srcDir, "pgoca.ca")
+
+    pwfile.write("\n")
+
+    # Create temporary certification database for CA generation
+    status = runUtil(certutil, ["-N", "-d", tempDbDir, "-f", pwfile.name])
+    if status:
+      return status
+
+    createRandomFile(rndfile)
+    status = runUtil(certutil, ["-S", "-d", tempDbDir, "-s", "CN=Temporary Certificate Authority, O=Mozilla Testing, OU=Profile Guided Optimization", "-t", "C,,", "-x", "-m", "1", "-v", "120", "-n", "pgo temporary ca", "-2", "-f", pwfile.name, "-z", rndfile.name], "Y\n0\nN\n")
+    if status:
+      return status
+
+    status = runUtil(certutil, ["-L", "-d", tempDbDir, "-n", "pgo temporary ca", "-a", "-o", pgoCAPathSrc, "-f", pwfile.name])
+    if status:
+      return status
+
+    status = runUtil(pk12util, ["-o", pgoCAModulePathSrc, "-n", "pgo temporary ca", "-d", tempDbDir, "-w", pwfile.name, "-k", pwfile.name])
+    if status:
+      return status
+
+  shutil.rmtree(tempDbDir)
+  return 0
+
+
+def createSSLServerCertificate(build, srcDir):
+  certutil = build.get_binary_path(what="certutil")
+  pk12util = build.get_binary_path(what="pk12util")
+
+  with NamedTemporaryFile() as pwfile, NamedTemporaryFile() as rndfile:
+    pgoCAPath = os.path.join(srcDir, "pgoca.p12")
+
+    pwfile.write("\n")
+
+    if not dbFilesExist(srcDir):
+      # Make sure all DB files from src are really deleted
+      unlinkDbFiles(srcDir)
+
+      # Create certification database for ssltunnel
+      status = runUtil(certutil, ["-N", "-d", srcDir, "-f", pwfile.name])
+      if status:
+        return status
+
+      status = runUtil(pk12util, ["-i", pgoCAPath, "-w", pwfile.name, "-d", srcDir, "-k", pwfile.name])
+      if status:
+        return status
+
+    # Generate automatic certificate
+    locations = ServerLocations(os.path.join(build.topsrcdir,
+                                             "build", "pgo",
+                                             "server-locations.txt"))
+    iterator = iter(locations)
+
+    # Skips the first entry, I don't know why: bug 879740
+    iterator.next()
+
+    locationsParam = ""
+    firstLocation = ""
+    for loc in iterator:
+      if loc.scheme == "https" and "nocert" not in loc.options:
+        customCertOption = False
+        customCertRE = re.compile("^cert=(?:\w+)")
+        for option in loc.options:
+          match = customCertRE.match(option)
+          if match:
+            customCertOption = True
+            break
+
+        if not customCertOption:
+          if len(locationsParam) > 0:
+            locationsParam += ","
+          locationsParam += loc.host
+
+          if firstLocation == "":
+            firstLocation = loc.host
+
+    if not firstLocation:
+      print "Nothing to generate, no automatic secure hosts specified"
+    else:
+      createRandomFile(rndfile)
+
+      runUtil(certutil, ["-D", "-n", "pgo server certificate", "-d", srcDir, "-z", rndfile.name, "-f", pwfile.name])
+      # Ignore the result, the certificate may not be present when new database is being built
+
+      status = runUtil(certutil, ["-S", "-s", "CN=%s" % firstLocation, "-t", "Pu,,", "-c", "pgo temporary ca", "-m", "2", "-8", locationsParam, "-v", "120", "-n", "pgo server certificate", "-d", srcDir, "-z", rndfile.name, "-f", pwfile.name])
+      if status:
+        return status
+
+  return 0
+
+if len(sys.argv) == 1:
+  print "Specify --gen-server or --gen-ca"
+  sys.exit(1)
+
+build = MozbuildObject.from_environment()
+certdir = os.path.join(build.topsrcdir, "build", "pgo", "certs")
+if sys.argv[1] == "--gen-server":
+  certificateStatus = createSSLServerCertificate(build, certdir)
+  if certificateStatus:
+    print "TEST-UNEXPECTED-FAIL | SSL Server Certificate generation"
+
+  sys.exit(certificateStatus)
+
+if sys.argv[1] == "--gen-ca":
+  certificateStatus = createCertificateAuthority(build, certdir)
+  if certificateStatus:
+    print "TEST-UNEXPECTED-FAIL | Certificate Authority generation"
+  else:
+    print "\n\n"
+    print "==================================================="
+    print " IMPORTANT:"
+    print " To use this new certificate authority in tests"
+    print " run 'make' at testing/mochitest"
+    print "==================================================="
+
+  sys.exit(certificateStatus)
+
+print "Invalid option specified"
+sys.exit(1)
diff --git a/src/third_party/mozjs-45/build/pgo/index.html b/src/third_party/mozjs-45/build/pgo/index.html
new file mode 100644
index 0000000..ccfa00d
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/index.html
@@ -0,0 +1,64 @@
+<script>
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+ var list = 
+     [
+  "blueprint/sample.html",
+  "blueprint/forms.html",
+  "blueprint/grid.html",
+  "blueprint/elements.html",
+  "js-input/3d-thingy.html",
+  "js-input/crypto-otp.html",
+  "js-input/sunspider/3d-cube.html",
+  "js-input/sunspider/3d-morph.html",
+  "js-input/sunspider/3d-raytrace.html",
+  "js-input/sunspider/access-binary-trees.html",
+  "js-input/sunspider/access-fannkuch.html",
+  "js-input/sunspider/access-nbody.html",
+  "js-input/sunspider/access-nsieve.html",
+  "js-input/sunspider/bitops-3bit-bits-in-byte.html",
+  "js-input/sunspider/bitops-bits-in-byte.html",
+  "js-input/sunspider/bitops-bitwise-and.html",
+  "js-input/sunspider/bitops-nsieve-bits.html",
+  "js-input/sunspider/controlflow-recursive.html",
+  "js-input/sunspider/crypto-aes.html",
+  "js-input/sunspider/crypto-md5.html",
+  "js-input/sunspider/crypto-sha1.html",
+  "js-input/sunspider/date-format-tofte.html",
+  "js-input/sunspider/date-format-xparb.html",
+  "js-input/sunspider/math-cordic.html",
+  "js-input/sunspider/math-partial-sums.html",
+  "js-input/sunspider/math-spectral-norm.html",
+  "js-input/sunspider/regexp-dna.html",
+  "js-input/sunspider/string-base64.html",
+  "js-input/sunspider/string-fasta.html",
+  "js-input/sunspider/string-tagcloud.html",
+  "js-input/sunspider/string-unpack-code.html",
+  "js-input/sunspider/string-validate-input.html"
+     ];
+ var interval = 1000;
+ var idx = 0;
+ var w;
+ 
+ window.onload = function () {
+     w = window.open("about:blank");
+     window.setTimeout(loadURL, interval); 
+ };
+ function loadURL () {
+     w.close();
+     w = window.open(list[idx++]);
+     if (idx < list.length) {
+     window.setTimeout(loadURL, interval);
+     } else {
+         window.setTimeout(Quitter.quit, interval);
+     }
+ }
+ var i;
+ 
+ for(i=0; i < list.length;i++) {
+     document.write(list[i]);
+     document.write("<br>");
+ }
+  </script>
diff --git a/src/third_party/mozjs-45/build/pgo/js-input/3d-thingy.html b/src/third_party/mozjs-45/build/pgo/js-input/3d-thingy.html
new file mode 100644
index 0000000..9e54299
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/js-input/3d-thingy.html
@@ -0,0 +1,390 @@
+<html>
+<head>
+<title>3d thingy</title>
+<style type="text/css">
+div.z2 { position:absolute; z-index:2; }
+div.z1 { position:absolute; z-index:1; }
+</style>
+<script type="text/javascript">
+/**************************************************************************
+JavaScript Graphics Library 0.0.1, Updated Source Code at Scriptersoft.com
+Copyright (C) 2005  Kurt L. Whicher
+November,13,2005
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**************************************************************************/
+
+//________________________________________ global variables
+
+var S_piDoubled=Math.PI*2;
+var S_deg2Rad=Math.PI/180;
+
+//_______________________________________________ functions
+
+function S_matrix() {
+  return [1,0,0,0,
+          0,1,0,0,
+          0,0,1,0,
+          0,0,0,1];
+}
+function S_vec2D(x,y) { this.x=x; this.y=y; }
+function S_vec3D(x,y,z) { this.x=x; this.y=y; this.z=z; }
+function S_subVec2D(a,b) {
+  return new S_vec2D(a.x-b.x, a.y-b.y);
+}
+function S_subVec3D(a,b) {
+  return new S_vec3D(a.x-b.x, a.y-b.y, a.z-b.z);
+}
+function S_dotVec3D(a, b) { return a.x*b.x+a.y*b.y+a.z*b.z; }
+function S_cross(a,b) {
+  return new S_vec3D( a.y*b.z-a.z*b.y, a.z*b.x-a.x*b.z, a.x*b.y-a.y*b.x);
+}
+function S_lengthSquaredVec3D(v) { return S_dotVec3D(v,v); }
+function S_lengthVec3D(v) { return Math.sqrt(S_lengthSquaredVec3D(v)); }
+function S_normalizeVec3D(v) {
+  var l=S_lengthVec3D(v), nv=new S_vec3D(0,0,0);
+  if(l!=0) { nv.x=v.x/l; nv.y=v.y/l; nv.z=v.z/l; }
+  return nv;
+}
+function S_rotate(m,ax,a) { // transformation matrix, axis, angle
+  var i,j,ij=new Array(),v=new Array(),c=Math.cos(a),s=Math.sin(a);
+  if (ax=="x") ij=[1,2,5,6,9,10,13,14];
+  else if (ax=="y") ij=[2,0,6,4,10,8,14,12];
+  else if (ax=="z") ij=[0,1,4,5,8,9,12,13];
+  for (i=0;i<8;i++) v[i]=m[ij[i]];
+  for (i=0,j=1;i<8;i+=2,j+=2) {
+    m[ij[i]]=v[i]*c-v[j]*s;
+    m[ij[j]]=v[i]*s+v[j]*c
+  }
+}
+function S_checkBrowser() {
+  if (document.getElementById) return true; else return false;
+}
+function S_zIndex(e,z) { document.getElementById(e).style.zIndex=z; }
+function S_rgbColor(r,g,b) {
+  var i, c=[r,g,b];
+  for(i=0; i<3; i++) {
+    c[i]=Math.floor(c[i]);
+    if(c[i]<0) c[i]=0; else if(c[i]>255) c[i]=255;
+  }
+  return c;
+}
+function S_rgbColorString(c) {
+  return "rgb("+c[0]+","+c[1]+","+c[2]+")";
+}
+function S_vertice(x,y,z) {
+  this.x=x; this.y=y; this.z=z; this.w=1;
+  this.t=new S_vec3D(x,y,z); // transformed 3d
+  this.p=new S_vec2D(0,0); // projected 2d
+}
+function S_face(v0,v1,v2,c) { // 3 vertice faces
+  this.v=[v0,v1,v2]; this.c=c; this.b=0; // b:brightness
+  this.d=true; // display: true or false
+}
+// x coordinate, number of vertices, distance
+function S_verticeRing(x,nv,d) {
+  var i,a,v=new Array();
+  for(i=0;i<nv;i++) {
+    a=S_piDoubled*i/nv;
+    v[i]=new S_vertice(x,d*Math.sin(a),d*Math.cos(a));
+  }
+  return v;
+}
+function S_triangleRing(r1,r2,c,clr) { // rows 1 & 2, cols, color
+  var i,j,tr=new Array();
+  for(i=0,j=1;i<c;i++,j=++j%c) {
+    tr.push(new S_face(r1+i,r2+i,r2+j,clr));
+    tr.push(new S_face(r1+i,r2+j,r1+j,clr));
+  }
+  return tr;
+}
+function S_model(v,f) {
+  // vertice & face arrays, transformation matrix, display boolean
+  this.v=v; this.f=f, this.tm=S_matrix(), this.d=true;
+}
+S_model.prototype.S_rotateX=function(a) {
+  S_rotate(this.tm,"x",a*=S_deg2Rad);
+}
+S_model.prototype.S_rotateY=function(a) {
+  S_rotate(this.tm,"y",a*=S_deg2Rad);
+}
+S_model.prototype.S_rotateZ=function(a) {
+  S_rotate(this.tm,"z",a*=S_deg2Rad);
+}
+S_model.prototype.S_show=function() { this.d=true; }
+S_model.prototype.S_hide=function() { this.d=false; }
+function S_cube(d,c) { //distance & color
+  return new S_cone(d,d,Math.cos(Math.PI/4)*d*2,1,4,c);
+}
+function S_cylinder(w,h,r,c,clr,e) {
+  return new S_cone(w,w,h,r,c,clr,e);
+}
+// width, height, "rows", "columns", color, ends
+function S_cone(w1,w2,h,r,c,clr,e) {
+  var i,r1=0,r2=c,v=new Array(),t=new Array(),rxc=r*c;
+  for(i=0;i<=r;i++)
+    v=v.concat(S_verticeRing(h*(0.5-i/r),c,w1*i/r+w2*(r-i)/r));
+  for(i=0;i<r;i++,r1+=c,r2+=c)
+    t=t.concat(S_triangleRing(r1,r2,c,clr));
+  if (e!="hideEnds")
+    for(i=1;i<(c-1);i++) {
+      t.push(new S_face(0,i,i+1,clr));
+      t.push(new S_face(rxc,rxc+i+1,rxc+i,clr));
+    }
+  return new S_model(v,t);
+}
+function S_sphere(d,r,c,clr) {
+  // distance, "rows">=2, "columns">=3, color paramaters
+  var v=new Array(),t=new Array(),r_1xc=(r-1)*c,r_2xc=(r-2)*c;
+  var i,j,tmp,r1=0,r2=c;
+  for(i=1;i<r;i++) {
+    tmp=Math.PI*i/r;
+    v=v.concat(S_verticeRing(d*Math.cos(tmp),c,Math.sin(tmp)*d));
+  }
+  v.push(new S_vertice( d,0,0));
+  v.push(new S_vertice(-d,0,0));
+  for(i=0;i<(r-2);i++,r1+=c,r2+=c)
+    t=t.concat(S_triangleRing(r1,r2,c,clr));
+  for(i=0,j=1;i<c;i++,j=++j%c) {
+    t.push(new S_face(r_1xc,i,j,clr));
+    t.push(new S_face(r_1xc+1,r_2xc+j,r_2xc+i,clr));
+  }
+  return new S_model(v,t);
+}
+S_model.prototype.S_scale=function(x) { 
+  this.tm[0]*=x; this.tm[5]*=x; this.tm[10]*=x;
+}
+S_model.prototype.S_faceColor=function(i,c) { this.f[i].c=c; }
+S_model.prototype.S_scaleX=function(s) { this.tm[0]*=s; }
+S_model.prototype.S_scaleY=function(s) { this.tm[5]*=s; }
+S_model.prototype.S_scaleZ=function(s) { this.tm[10]*=s; }
+function S_scene(dv,l,t,w,h,cmra) { // left, top, width, height
+  this.dv=dv;
+  this.ps=1; // pixel size
+  this.l=l; this.t=t; this.w=w; this.h=h;
+  this.cx=l+w/2; this.cy=t+h/2; // center x, center y
+  this.dt="paint"; // output type
+  this.m=new Array(); // model array
+  this.lght=new S_light();
+  this.lc=S_rgbColor(255,255,255); // light color
+  this.cmra=-cmra; // camera on z axis
+  this.bfr=S_buffer(h,w);
+}
+function S_buffer(h,w) {
+  var i, j, b=new Array();
+  for(i=0;i<h;i++) {
+    b[i]=new Array();
+    for(j=0;j<w;j++) b[i][j]=new S_pixel();
+  }
+  return b;
+}
+function S_pixel() { // display boolean, color  
+  this.d=true; this.c=0;
+}
+S_pixel.prototype.S_setColor=function(c) {
+  this.d=true; this.c=c;
+}
+S_pixel.prototype.S_hide=function() { this.d=false; }
+S_scene.prototype.S_pixelSize=function(ps){ this.ps=ps; }
+S_scene.prototype.S_widthAndHeight=function(w,h){ this.w=w; this.h=h; }
+S_scene.prototype.S_center=function(cx,cy){ this.cx=cx; this.cy=cy; }
+S_scene.prototype.S_paint=function(){ this.dt="paint"; }
+S_scene.prototype.S_models=function() {
+  var i; this.m=new Array();
+  for(i=0;i<arguments.length;i++) this.m.push(arguments[i]);
+}
+S_scene.prototype.S_lightColor=function(c){ this.lc=c; }
+S_scene.prototype.S_project=function() {
+  var i, j, v, tm, d, m;
+  for(i=0;i<this.m.length;i++) {
+    m=this.m[i]; tm=this.m[i].tm;
+    for(j=0;j<m.v.length;j++) {
+      v=m.v[j];
+      v.t.x=v.x*tm[0]+v.y*tm[4]+v.z*tm[8]+v.w*tm[12];
+      v.t.y=v.x*tm[1]+v.y*tm[5]+v.z*tm[9]+v.w*tm[13];
+      v.t.z=v.x*tm[2]+v.y*tm[6]+v.z*tm[10]+v.w*tm[14];
+      d=(this.cmra-v.t.z/2);
+      if (d<0) {
+        v.p.x=(this.cmra*v.t.x/d)+this.cx;
+        v.p.y=-(this.cmra*v.t.y/d)+this.cy;
+      }
+    }
+  }
+}
+S_scene.prototype.S_display=function(disp){
+  var i, j, k, s="", ds, c, cnt=0; // ds:div start
+  this.tr=new Array(); // triangles ready to draw
+  this.S_project();
+  this.S_adjustLight();
+  this.S_clearBuffer();
+  for(i=0;i<this.m.length;i++) {
+    this.m[i].S_setupFaces(this.tr,this.lght.t);
+    for(j=0;j<this.tr.length;j++) { // loop through triangles
+      c=S_divColor(this.tr[j].c,this.lc,this.tr[j].b);
+      S_setupBuffer(this,this.tr[j].p,c);
+    }
+  }
+  for(i=0;i<this.h;i++) {
+    ds=-1;
+    for(j=0,k=1;j<this.w;j++,k++) {
+      if((this.bfr[i][j].d==true)&&(ds==-1)) ds=j;
+      if( (this.bfr[i][j].d==true)&&
+          ( (k==this.w)||
+            (this.bfr[i][k].d==false)||
+            (!S_sameColor(this.bfr[i][j].c, this.bfr[i][k].c)) ) ) {
+        s+=S_divString(S_rgbColorString(this.bfr[i][j].c),this.t+i*this.ps,this.l+ds*this.ps,this.ps,(k-ds)*this.ps);
+        ds=-1;
+        cnt++;
+      }
+    }
+  }
+  S_writeInnerHTML(this.dv,s);
+  if(disp=="ShowCount") alert(cnt);
+}
+S_scene.prototype.S_displayAndShowCount=function(){
+  this.S_display("ShowCount");
+}
+S_model.prototype.S_setupFaces=function(tr,lght) {
+  var i, j, fn, v, p=new Array(); // vertice & projection arrays
+  var z=new Array();
+  for(i=0;i<this.f.length;i++) { // loop through faces
+    v=this.f[i].v;
+    for(j=0;j<3;j++) { p[j]=this.v[v[j]].p; }
+    for(j=0;j<3;j++) { z[j]=this.v[v[j]].t.z; }
+    if (((p[1].x-p[0].x)*(p[2].y-p[0].y))<((p[2].x-p[0].x)*(p[1].y-p[0].y))) {
+      this.f[i].d=true;
+      fn=S_faceNormal(this.v[v[0]].t, this.v[v[1]].t, this.v[v[2]].t);
+      this.f[i].b=S_faceIntensity(fn,lght);
+      tr.push(new S_triangle(fn,this.f[i].b,p.slice(),this.f[i].c,z));
+    } else { this.f[i].d=false; }
+  }
+}
+// normal, brightness, array of 2D projection coordinates, and z depth
+function S_triangle(fn,b,p,c,z) {
+  this.fn=fn; this.b=b; this.p=p; this.z=z; this.c=c;
+}
+function S_faceNormal(a,b,c){
+  var cr=S_cross(S_subVec3D(b,a), S_subVec3D(b,c));
+  return S_normalizeVec3D(cr);
+}
+function S_faceIntensity(fn,lght) {
+  var i=S_dotVec3D(fn,lght); return (i>0)?i:0;
+}
+function S_divColor(c,lc,b) { // c:array of colors
+  var i, clr=new Array();
+  for(i=0;i<3;i++) clr[i]=Math.floor(c[i]+(lc[i]-c[i]+1)*b);
+  for(i=0;i<3;i++) if (clr[i]>lc[i]) { clr[i]=lc[i]; }
+  return S_rgbColor(clr[0],clr[1],clr[2]);
+}
+function S_sameColor(a,b) {
+  for(var i=0;i<3;i++) { if(a[i]!=b[i]) return false; }
+  return true;
+}
+function S_setupBuffer(scn,p,c) {
+  // temp, counters, min, max, scanline, vertice & slope arrays
+  var t,i,j,xmin=new Array(),xmax=new Array(),sl;
+  var v=new Array(), m=new Array();
+  p.sort(function(a,b) { return a.y-b.y; } );
+  for(i=0;i<3;i++) p[i].y=Math.floor(p[i].y);
+  v[0]=S_subVec2D(p[1],p[0]);
+  v[1]=S_subVec2D(p[2],p[0]);
+  v[2]=S_subVec2D(p[2],p[1]);
+  for(i=0;i<3;i++) { m[i]=(v[i].y!=0)?v[i].x/v[i].y:0; }
+  for(i=0,sl=scn.t;i<scn.h;i++,sl++) {
+    xmin[i]=1000;xmax[i]=0;
+    if((sl>=p[0].y)&&(sl<=p[2].y)) {
+      xmin[i]=xmax[i]=Math.floor(p[0].x+m[1]*(sl-p[0].y));
+    }
+    if((sl>=p[0].y)&&(sl<=p[1].y)) {
+      t=Math.floor(p[0].x+m[0]*(sl-p[0].y));
+      if(t<xmin[i]) xmin[i]=Math.floor(t);
+      else if(t>xmax[i]) xmax[i]=Math.floor(t);
+    }
+    if((sl>=p[1].y)&&(sl<=p[2].y)) {
+      t=Math.floor(p[1].x+m[2]*(sl-p[1].y));
+      if(t<xmin[i]) xmin[i]=Math.floor(t);
+      else if(t>xmax[i]) xmax[i]=Math.floor(t);
+    }
+    for(j=0;j<scn.w;j++)
+      if((j>=(xmin[i]-scn.l))&&(j<=(xmax[i]-scn.l))) {
+        scn.bfr[i][j].d=true; scn.bfr[i][j].c=c;          
+      }
+  }
+}
+function S_light() {
+  this.x=0; this.y=1; this.z=0; this.w=1; // original coordinates
+  this.t=new S_vec3D(0,1,0); // transformed coordinates
+  this.tm=new S_matrix();
+}
+S_scene.prototype.S_adjustLight=function() {
+  var m=this.lght.tm, l=this.lght;
+  l.t.x=l.x*m[0]+l.y*m[4]+ l.z*m[8]+l.w*m[12];
+  l.t.y=l.x*m[1]+l.y*m[5]+ l.z*m[9]+l.w*m[13];
+  l.t.z=l.x*m[2]+l.y*m[6]+ l.z*m[10]+l.w*m[14];
+  l.t=S_normalizeVec3D(l.t);
+}
+S_scene.prototype.S_lightRotateX=function(a) {
+  S_rotate(this.lght.tm,"x",a*=S_deg2Rad);
+}
+S_scene.prototype.S_lightRotateY=function(a) {
+  S_rotate(this.lght.tm,"y",a*=S_deg2Rad);
+}
+S_scene.prototype.S_lightRotateZ=function(a) {
+  S_rotate(this.lght.tm,"z",a*=S_deg2Rad);
+}
+S_scene.prototype.S_clearBuffer=function() {
+  for(var i=0;i<this.h;i++)
+    for(var j=0;j<this.w;j++) this.bfr[i][j].d=false;
+}
+function S_divString(b,t,l,h,w) {
+  var s='<div style="background-color:'+b+';position:absolute;';
+  s+='top:'+t+'px;left:'+l+'px;height:'+h+'px;width:'+w;
+  return s+'px;font-size:0;visibility:visible"></div>';
+}
+function S_writeInnerHTML(id,text) {
+  document.getElementById(id).innerHTML = text;
+}
+</script>
+</head>
+<body>
+<div class="z1" id="graphicsDiv">Text to be replaced with graphics.</div>
+<script type="text/javascript">
+if(S_checkBrowser()) {
+var intrvl;
+// Create a new scene with parameters for
+// div id, left, top, width, height, and camera distance
+var scn=new S_scene("graphicsDiv",75,25,100,100,300);
+scn.S_pixelSize(3); // set scene pixel size
+var c=S_rgbColor(0,0,127); // color
+var c2=S_rgbColor(0,127,127); // color
+var m=new S_cube(18,c); // model
+m.S_faceColor(4,c2);
+m.S_faceColor(5,c2);
+m.S_scaleX(2.5); // scale model along x axis
+scn.S_models(m); // add model(s) to scene
+scn.S_lightRotateX(-25); // adjust light
+function r(){ // rotation function
+m.S_rotateX(11); // rotate model around y axis
+m.S_rotateY(5); // rotate model around y axis
+m.S_rotateZ(7); // rotate model around z axis
+scn.S_display(); // display scene
+} // end rotation function
+intrvl=setInterval('r();',75);
+}
+</script>
+
+</body>
+</html>
+
diff --git a/src/third_party/mozjs-45/build/pgo/js-input/crypto-otp.html b/src/third_party/mozjs-45/build/pgo/js-input/crypto-otp.html
new file mode 100644
index 0000000..f6e1ca2
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/js-input/crypto-otp.html
@@ -0,0 +1,1344 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>One-Time Pad Generator</title>
+<meta name="description" content="JavaScript One-Time Pad Generator" />
+<meta name="author" content="John Walker" />
+<meta name="keywords" content="one, time, pad, generator, onetime, cryptography, JavaScript" />
+<style type="text/css">
+    a:link,  a:visited {
+	background-color: inherit;
+    	color: rgb(0%, 0%, 80%);
+	text-decoration: none;
+    }
+
+    a:hover  {
+    	background-color:  rgb(30%, 30%, 100%);
+    	color: rgb(100%, 100%, 100%);
+    }
+    
+    a:active {
+    	color: rgb(100%, 0%, 0%);
+    	background-color:  rgb(30%, 30%, 100%);
+    }
+    
+    a.i:link, a.i:visited, a.i:hover {
+    	background-color:  inherit;
+    	color: inherit;
+	text-decoration: none;
+    }
+    
+    body {
+        margin-left: 15%;
+        margin-right: 10%;
+	background-color: #FFFFFF;
+	color: #000000;
+    }
+    
+    body.jsgen {
+        margin-left: 5%;
+        margin-right: 5%;
+    }
+    
+    dt {
+    	margin-top: 0.5em;
+    }
+    
+    img.button {
+    	border: 0px;
+	vertical-align: middle;
+    }
+    
+    img.keyicon {
+	vertical-align: bottom;
+    }
+    
+    p, dd, li {
+    	text-align: justify;
+    }
+    
+    p.centre {
+    	text-align: center;
+    }
+    
+    table.r {
+   	float: right;
+    }
+    
+    table.c {
+    	background-color: #E0E0E0;
+	color: #000000;
+    	margin-left: auto;
+	margin-right: auto;
+    }
+
+    td.c {
+    	text-align: center;
+    }
+    
+    textarea {
+    	background-color: #FFFFD0;
+	color: #000000;
+    }
+</style>
+<script type="text/javascript">
+//<![CDATA[
+
+    loadTime = (new Date()).getTime();
+
+/*
+
+    L'Ecuyer's two-sequence generator with a Bays-Durham shuffle
+    on the back-end.  Schrage's algorithm is used to perform
+    64-bit modular arithmetic within the 32-bit constraints of
+    JavaScript.
+
+    Bays, C. and S. D. Durham.  ACM Trans. Math. Software: 2 (1976)
+        59-64.
+
+    L'Ecuyer, P.  Communications of the ACM: 31 (1968) 742-774.
+
+    Schrage, L.  ACM Trans. Math. Software: 5 (1979) 132-138.
+
+*/
+
+function uGen(old, a, q, r, m) {      // Schrage's modular multiplication algorithm
+    var t;
+
+    t = Math.floor(old / q);
+    t = a * (old - (t * q)) - (t * r);
+    return Math.round((t < 0) ? (t + m) : t);
+}
+
+function LEnext() {                   // Return next raw value
+    var i;
+
+    this.gen1 = uGen(this.gen1, 40014, 53668, 12211, 2147483563);
+    this.gen2 = uGen(this.gen2, 40692, 52774, 3791, 2147483399);
+
+    /* Extract shuffle table index from most significant part
+       of the previous result. */
+
+    i = Math.floor(this.state / 67108862);
+
+    // New state is sum of generators modulo one of their moduli
+
+    this.state = Math.round((this.shuffle[i] + this.gen2) % 2147483563);
+
+    // Replace value in shuffle table with generator 1 result
+
+    this.shuffle[i] = this.gen1;
+
+    return this.state;
+}
+
+//  Return next random integer between 0 and n inclusive
+
+function LEnint(n) {
+    return Math.floor(this.next() / (1 + 2147483562 / (n + 1)));
+}
+
+//  Constructor.  Called with seed value
+
+function LEcuyer(s) {
+    var i;
+
+    this.shuffle = new Array(32);
+    this.gen1 = this.gen2 = (s & 0x7FFFFFFF);
+    for (i = 0; i < 19; i++) {
+        this.gen1 = uGen(this.gen1, 40014, 53668, 12211, 2147483563);
+    }
+
+    // Fill the shuffle table with values
+
+    for (i = 0; i < 32; i++) {
+        this.gen1 = uGen(this.gen1, 40014, 53668, 12211, 2147483563);
+        this.shuffle[31 - i] = this.gen1;
+    }
+    this.state = this.shuffle[0];
+    this.next = LEnext;
+    this.nextInt = LEnint;
+}
+
+function sepchar() {
+    if (rsep) {
+        var seps = "!#$%&()*+,-./:;<=>?@[]^_{|}~";
+        return seps.charAt(sepran.nextInt(seps.length - 1));
+    }
+    return "-";
+}
+
+/*
+ *  md5.jvs 1.0b 27/06/96
+ *
+ * Javascript implementation of the RSA Data Security, Inc. MD5
+ * Message-Digest Algorithm.
+ *
+ * Copyright (c) 1996 Henri Torgemane. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purposes and without
+ * fee is hereby granted provided that this copyright notice
+ * appears in all copies. 
+ *
+ * Of course, this soft is provided "as is" without express or implied
+ * warranty of any kind.
+
+    This version contains some trivial reformatting modifications
+    by John Walker.
+
+ */
+
+function array(n) {
+    for (i = 0; i < n; i++) {
+        this[i] = 0;
+    }
+    this.length = n;
+}
+
+/* Some basic logical functions had to be rewritten because of a bug in
+ * Javascript.. Just try to compute 0xffffffff >> 4 with it..
+ * Of course, these functions are slower than the original would be, but
+ * at least, they work!
+ */
+
+function integer(n) {
+    return n % (0xffffffff + 1);
+}
+
+function shr(a, b) {
+    a = integer(a);
+    b = integer(b);
+    if (a - 0x80000000 >= 0) {
+        a = a % 0x80000000;
+        a >>= b;
+        a += 0x40000000 >> (b - 1);
+    } else {
+        a >>= b;
+    }
+    return a;
+}
+
+function shl1(a) {
+    a = a % 0x80000000;
+    if (a & 0x40000000 == 0x40000000) {
+        a -= 0x40000000;  
+        a *= 2;
+        a += 0x80000000;
+    } else {
+        a *= 2;
+    }
+    return a;
+}
+
+function shl(a, b) {
+    a = integer(a);
+    b = integer(b);
+    for (var i = 0; i < b; i++) {
+        a = shl1(a);
+    }
+    return a;
+}
+
+function and(a, b) {
+    a = integer(a);
+    b = integer(b);
+    var t1 = a - 0x80000000;
+    var t2 = b - 0x80000000;
+    if (t1 >= 0) {
+        if (t2 >= 0) {
+            return ((t1 & t2) + 0x80000000);
+        } else {
+            return (t1 & b);
+        }
+    } else {
+        if (t2 >= 0) {
+            return (a & t2);
+        } else {
+            return (a & b);  
+        }
+    }
+}
+
+function or(a, b) {
+    a = integer(a);
+    b = integer(b);
+    var t1 = a - 0x80000000;
+    var t2 = b - 0x80000000;
+    if (t1 >= 0) {
+        if (t2 >= 0) {
+            return ((t1 | t2) + 0x80000000);
+        } else {
+            return ((t1 | b) + 0x80000000);
+        }
+    } else {
+        if (t2 >= 0) {
+            return ((a | t2) + 0x80000000);
+        } else {
+            return (a | b);  
+        }
+    }
+}
+
+function xor(a, b) {
+    a = integer(a);
+    b = integer(b);
+    var t1 = a - 0x80000000;
+    var t2 = b - 0x80000000;
+    if (t1 >= 0) {
+        if (t2 >= 0) {
+            return (t1 ^ t2);
+        } else {
+            return ((t1 ^ b) + 0x80000000);
+        }
+    } else {
+        if (t2 >= 0) {
+            return ((a ^ t2) + 0x80000000);
+        } else {
+            return (a ^ b);  
+        }
+    }
+}
+
+function not(a) {
+    a = integer(a);
+    return 0xffffffff - a;
+}
+
+/* Here begin the real algorithm */
+
+var state = new array(4); 
+var count = new array(2);
+    count[0] = 0;
+    count[1] = 0;                     
+var buffer = new array(64); 
+var transformBuffer = new array(16); 
+var digestBits = new array(16);
+
+var S11 = 7;
+var S12 = 12;
+var S13 = 17;
+var S14 = 22;
+var S21 = 5;
+var S22 = 9;
+var S23 = 14;
+var S24 = 20;
+var S31 = 4;
+var S32 = 11;
+var S33 = 16;
+var S34 = 23;
+var S41 = 6;
+var S42 = 10;
+var S43 = 15;
+var S44 = 21;
+
+function F(x, y, z) {
+    return or(and(x, y), and(not(x), z));
+}
+
+function G(x, y, z) {
+    return or(and(x, z), and(y, not(z)));
+}
+
+function H(x, y, z) {
+    return xor(xor(x, y), z);
+}
+
+function I(x, y, z) {
+    return xor(y ,or(x , not(z)));
+}
+
+function rotateLeft(a, n) {
+    return or(shl(a, n), (shr(a, (32 - n))));
+}
+
+function FF(a, b, c, d, x, s, ac) {
+    a = a + F(b, c, d) + x + ac;
+    a = rotateLeft(a, s);
+    a = a + b;
+    return a;
+}
+
+function GG(a, b, c, d, x, s, ac) {
+    a = a + G(b, c, d) + x + ac;
+    a = rotateLeft(a, s);
+    a = a + b;
+    return a;
+}
+
+function HH(a, b, c, d, x, s, ac) {
+    a = a + H(b, c, d) + x + ac;
+    a = rotateLeft(a, s);
+    a = a + b;
+    return a;
+}
+
+function II(a, b, c, d, x, s, ac) {
+    a = a + I(b, c, d) + x + ac;
+    a = rotateLeft(a, s);
+    a = a + b;
+    return a;
+}
+
+function transform(buf, offset) { 
+    var a = 0, b = 0, c = 0, d = 0; 
+    var x = transformBuffer;
+    
+    a = state[0];
+    b = state[1];
+    c = state[2];
+    d = state[3];
+    
+    for (i = 0; i < 16; i++) {
+        x[i] = and(buf[i * 4 + offset], 0xFF);
+        for (j = 1; j < 4; j++) {
+            x[i] += shl(and(buf[i * 4 + j + offset] ,0xFF), j * 8);
+        }
+    }
+
+    /* Round 1 */
+    a = FF( a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
+    d = FF( d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
+    c = FF( c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
+    b = FF( b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
+    a = FF( a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
+    d = FF( d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
+    c = FF( c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
+    b = FF( b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
+    a = FF( a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
+    d = FF( d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
+    c = FF( c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
+    b = FF( b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
+    a = FF( a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
+    d = FF( d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
+    c = FF( c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
+    b = FF( b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
+
+    /* Round 2 */
+    a = GG( a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
+    d = GG( d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
+    c = GG( c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
+    b = GG( b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
+    a = GG( a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
+    d = GG( d, a, b, c, x[10], S22,  0x2441453); /* 22 */
+    c = GG( c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
+    b = GG( b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
+    a = GG( a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
+    d = GG( d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
+    c = GG( c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
+    b = GG( b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
+    a = GG( a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
+    d = GG( d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
+    c = GG( c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
+    b = GG( b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
+
+    /* Round 3 */
+    a = HH( a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
+    d = HH( d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
+    c = HH( c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
+    b = HH( b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
+    a = HH( a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
+    d = HH( d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
+    c = HH( c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
+    b = HH( b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
+    a = HH( a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
+    d = HH( d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
+    c = HH( c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
+    b = HH( b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
+    a = HH( a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
+    d = HH( d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
+    c = HH( c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
+    b = HH( b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
+
+    /* Round 4 */
+    a = II( a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
+    d = II( d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
+    c = II( c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
+    b = II( b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
+    a = II( a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
+    d = II( d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
+    c = II( c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
+    b = II( b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
+    a = II( a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
+    d = II( d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
+    c = II( c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
+    b = II( b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
+    a = II( a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
+    d = II( d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
+    c = II( c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
+    b = II( b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
+
+    state[0] += a;
+    state[1] += b;
+    state[2] += c;
+    state[3] += d;
+
+}
+
+function init() {
+    count[0] = count[1] = 0;
+    state[0] = 0x67452301;
+    state[1] = 0xefcdab89;
+    state[2] = 0x98badcfe;
+    state[3] = 0x10325476;
+    for (i = 0; i < digestBits.length; i++) {
+        digestBits[i] = 0;
+    }
+}
+
+function update(b) { 
+    var index, i;
+    
+    index = and(shr(count[0],3) , 0x3F);
+    if (count[0] < 0xFFFFFFFF - 7) {
+      count[0] += 8;
+    } else {
+      count[1]++;
+      count[0] -= 0xFFFFFFFF + 1;
+      count[0] += 8;
+    }
+    buffer[index] = and(b, 0xff);
+    if (index  >= 63) {
+        transform(buffer, 0);
+    }
+}
+
+function finish() {
+    var bits = new array(8);
+    var padding; 
+    var i = 0, index = 0, padLen = 0;
+
+    for (i = 0; i < 4; i++) {
+        bits[i] = and(shr(count[0], (i * 8)), 0xFF);
+    }
+    for (i = 0; i < 4; i++) {
+        bits[i + 4] = and(shr(count[1], (i * 8)), 0xFF);
+    }
+    index = and(shr(count[0], 3), 0x3F);
+    padLen = (index < 56) ? (56 - index) : (120 - index);
+    padding = new array(64); 
+    padding[0] = 0x80;
+    for (i = 0; i < padLen; i++) {
+      update(padding[i]);
+    }
+    for (i = 0; i < 8; i++) {
+      update(bits[i]);
+    }
+
+    for (i = 0; i < 4; i++) {
+        for (j = 0; j < 4; j++) {
+            digestBits[i * 4 + j] = and(shr(state[i], (j * 8)) , 0xFF);
+        }
+    } 
+}
+
+/* End of the MD5 algorithm */
+
+function gen() {
+    window.status = "Generating...";
+    document.getElementById('onetime').pad.value = "";
+
+    lower = document.getElementById('onetime').textcase.selectedIndex == 0;
+    upper = document.getElementById('onetime').textcase.selectedIndex == 1;
+    mixed = document.getElementById('onetime').textcase.selectedIndex == 2;
+    rsep = document.getElementById('onetime').rsep.checked;
+    if (!(numeric = document.getElementById('onetime').keytype[0].checked)) {
+        english = document.getElementById('onetime').keytype[1].checked;
+        gibberish = document.getElementById('onetime').keytype[3].checked;
+    }
+    clockseed = document.getElementById('onetime').seedy[0].checked
+    makesig = document.getElementById('onetime').dosig.checked;
+    npass = document.getElementById('onetime').nkeys.value;
+    pw_length = Math.round(document.getElementById('onetime').klength.value);
+    sep = document.getElementById('onetime').sep.value;
+    linelen = document.getElementById('onetime').linelen.value;
+//               01234567890123456789012345678901
+    charcodes = " " +
+                "!\"#$%&'()*+,-./0123456789:;<=>?" +
+                "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" +
+                "`abcdefghijklmnopqrstuvwxyz{|}~";
+
+    if (clockseed) {
+        var n, j, ran0;
+
+        /*  Obtain seed from the clock.  To reduce the likelihood
+            of the seed being guessed, we create the seed by combining
+            the time of the request with the time the page was loaded,
+            then use that composite value to seed an auxiliary generator
+            which is cycled between one and 32 times based on the time
+            derived initial seed, with the output of the generator fed
+            back into the seed we use to generate the pad.  */
+
+        seed = Math.round((new Date()).getTime() % Math.pow(2, 31));
+        ran0 = new LEcuyer((seed ^ Math.round(loadTime % Math.pow(2, 31))) & 0x7FFFFFFF);
+        for (j = 0; j < (5 + ((seed >> 3) & 0xF)); j++) {
+            n = ran0.nextInt(31);
+        }
+        while (n-- >= 0) {
+            seed = ((seed << 11) | (seed >>> (32 - 11))) ^ ran0.next();
+        }
+        seed &= 0x7FFFFFFF;
+        document.getElementById('onetime').seeder.value = seed;
+    } else {
+        var useed, seedNum;
+
+        /* Obtain seed from user specification.  If the seed is a
+           decimal number, use it as-is.  If it contains any
+           non-numeric characters, construct a hash code and
+           use that as the seed. */
+
+        useed = document.getElementById('onetime').seeder.value;
+        seedNum = true;
+        for (i = 0; i < useed.length; i++) {
+            if ("0123456789".indexOf(useed.charAt(i)) == -1) {
+                seedNum = false;
+                break;
+            }
+        }
+        if (seedNum) {
+            seed = Math.round(Math.floor(document.getElementById('onetime').seeder.value) % Math.pow(2, 31));
+            document.getElementById('onetime').seeder.value = seed;
+        } else {
+            var s, t, iso, hex;
+
+            iso = "";
+            hex = "0123456789ABCDEF";
+            for (i = 32; i < 256; i++) {
+                if (i < 127 || i >= 160) {
+                    // Why not "s = i.toString(16);"?  Doesn't work in Netscape 3.0
+                    iso += "%" + hex.charAt(i >> 4) + hex.charAt(i & 0xF);
+                }
+            }
+            iso = unescape(iso);
+            s = 0;
+            for (i = 0; i < useed.length; i++) {
+                t = iso.indexOf(useed.charAt(i));
+                if (t < 0) {
+                    t = 17;
+                }
+                s = 0x7FFFFFFF & (((s << 5) | (s >> (32 - 5))) ^ t);
+            }
+            seed = s;
+        }
+    }
+    ran1 = new LEcuyer(seed);
+    ran2 = new LEcuyer(seed);
+    if (rsep) {
+        /*  Use a separate random generator for separators
+            so that results are the same for a given seed
+            for both choices of separators.  */
+        sepran = new LEcuyer(seed);
+    }
+
+    ndig = 1;
+    j = 10;
+    while (npass >= j) {
+        ndig++;
+        j *= 10;
+    }
+    pw_item = pw_length + (sep > 0 ? (pw_length / sep) : 0);
+    pw_item += ndig + 5;
+    j = pw_item * 3;
+    if (j < 132) {
+        j = 132;
+    }
+    npline = Math.floor(linelen / pw_item);
+    if (npline < 1) {
+        npline = 0;
+    }
+    v = "";
+    md5v = "";
+    lineno = 0;
+    if (!numeric) {
+        letters = "abcdefghijklmnopqrstuvwxyz";
+        if (upper) {
+            letters = letters.toUpperCase();
+        }
+        if (english) {
+
+            // Frequency of English digraphs (from D. Edwards 1/27/66)
+
+            frequency = new Array( 
+                new Array(4, 20, 28, 52, 2, 11, 28, 4, 32, 4, 6, 62,
+                          23, 167, 2, 14, 0, 83, 76, 127, 7, 25, 8, 1,
+                          9, 1), /* aa - az */
+
+                new Array(13, 0, 0, 0, 55, 0, 0, 0, 8, 2, 0, 22, 0, 0,
+                          11, 0, 0, 15, 4, 2, 13, 0, 0, 0, 15, 0), /* ba - bz */
+
+                new Array(32, 0, 7, 1, 69, 0, 0, 33, 17, 0, 10, 9, 1,
+                          0, 50, 3, 0, 10, 0, 28, 11, 0, 0, 0, 3, 0), /* ca - cz */
+
+                new Array(40, 16, 9, 5, 65, 18, 3, 9, 56, 0, 1, 4, 15,
+                          6, 16, 4, 0, 21, 18, 53, 19, 5, 15, 0, 3, 0), /* da - dz */
+
+                new Array(84, 20, 55, 125, 51, 40, 19, 16, 50, 1, 4,
+                          55, 54, 146, 35, 37, 6, 191, 149, 65, 9, 26,
+                          21, 12, 5, 0), /* ea - ez */
+
+                new Array(19, 3, 5, 1, 19, 21, 1, 3, 30, 2, 0, 11, 1,
+                          0, 51, 0, 0, 26, 8, 47, 6, 3, 3, 0, 2, 0), /* fa - fz */
+
+                new Array(20, 4, 3, 2, 35, 1, 3, 15, 18, 0, 0, 5, 1,
+                          4, 21, 1, 1, 20, 9, 21, 9, 0, 5, 0, 1, 0), /* ga - gz */
+
+                new Array(101, 1, 3, 0, 270, 5, 1, 6, 57, 0, 0, 0, 3,
+                          2, 44, 1, 0, 3, 10, 18, 6, 0, 5, 0, 3, 0), /* ha - hz */
+
+                new Array(40, 7, 51, 23, 25, 9, 11, 3, 0, 0, 2, 38,
+                          25, 202, 56, 12, 1, 46, 79, 117, 1, 22, 0,
+                          4, 0, 3), /* ia - iz */
+
+                new Array(3, 0, 0, 0, 5, 0, 0, 0, 1, 0, 0, 0, 0, 0, 4,
+                          0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0), /* ja - jz */
+
+                new Array(1, 0, 0, 0, 11, 0, 0, 0, 13, 0, 0, 0, 0, 2,
+                          0, 0, 0, 0, 6, 2, 1, 0, 2, 0, 1, 0), /* ka - kz */
+
+                new Array(44, 2, 5, 12, 62, 7, 5, 2, 42, 1, 1, 53, 2,
+                          2, 25, 1, 1, 2, 16, 23, 9, 0, 1, 0, 33, 0), /* la - lz */
+
+                new Array(52, 14, 1, 0, 64, 0, 0, 3, 37, 0, 0, 0, 7,
+                          1, 17, 18, 1, 2, 12, 3, 8, 0, 1, 0, 2, 0), /* ma - mz */
+
+                new Array(42, 10, 47, 122, 63, 19, 106, 12, 30, 1, 6,
+                          6, 9, 7, 54, 7, 1, 7, 44, 124, 6, 1, 15, 0,
+                          12, 0), /* na - nz */
+
+                new Array(7, 12, 14, 17, 5, 95, 3, 5, 14, 0, 0, 19,
+                          41, 134, 13, 23, 0, 91, 23, 42, 55, 16, 28,
+                          0, 4, 1), /* oa - oz */
+
+                new Array(19, 1, 0, 0, 37, 0, 0, 4, 8, 0, 0, 15, 1, 0,
+                          27, 9, 0, 33, 14, 7, 6, 0, 0, 0, 0, 0), /* pa - pz */
+
+                new Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                          0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0), /* qa - qz */
+
+                new Array(83, 8, 16, 23, 169, 4, 8, 8, 77, 1, 10, 5,
+                          26, 16, 60, 4, 0, 24, 37, 55, 6, 11, 4, 0,
+                          28, 0), /* ra - rz */
+
+                new Array(65, 9, 17, 9, 73, 13, 1, 47, 75, 3, 0, 7,
+                          11, 12, 56, 17, 6, 9, 48, 116, 35, 1, 28, 0,
+                          4, 0), /* sa - sz */
+
+                new Array(57, 22, 3, 1, 76, 5, 2, 330, 126, 1, 0, 14,
+                          10, 6, 79, 7, 0, 49, 50, 56, 21, 2, 27, 0,
+                          24, 0), /* ta - tz */
+
+                new Array(11, 5, 9, 6, 9, 1, 6, 0, 9, 0, 1, 19, 5, 31,
+                          1, 15, 0, 47, 39, 31, 0, 3, 0, 0, 0, 0), /* ua - uz */
+
+                new Array(7, 0, 0, 0, 72, 0, 0, 0, 28, 0, 0, 0, 0, 0,
+                          5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0), /* va - vz */
+
+                new Array(36, 1, 1, 0, 38, 0, 0, 33, 36, 0, 0, 4, 1,
+                          8, 15, 0, 0, 0, 4, 2, 0, 0, 1, 0, 0, 0), /* wa - wz */
+
+                new Array(1, 0, 2, 0, 0, 1, 0, 0, 3, 0, 0, 0, 0, 0, 1,
+                          5, 0, 0, 0, 3, 0, 0, 1, 0, 0, 0), /* xa - xz */
+
+                new Array(14, 5, 4, 2, 7, 12, 12, 6, 10, 0, 0, 3, 7,
+                          5, 17, 3, 0, 4, 16, 30, 0, 0, 5, 0, 0, 0), /* ya - yz */
+
+                new Array(1, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) /* za - zz */ );
+
+            // This MUST be equal to the sum of the equivalent rows above.
+
+            row_sums = new Array(
+                796,   160,    284,    401,    1276,   262,    199,    539,    777,    
+                16,    39,     351,    243,    751,    662,    181,    17,     683,    
+                662,   968,    248,    115,    180,    17,     162,    5
+            );
+
+            // Frequencies of starting characters.
+
+            start_freq = new Array(
+                1299,  425,    725,    271,    375,    470,    93,     223,    1009,
+                24,    20,     355,    379,    319,    823,    618,    21,     317,
+                962,   1991,   271,    104,    516,    6,      16,     14
+            );
+
+            // This MUST be equal to the sum of all elements in the above array.
+
+            total_sum = 11646;
+        }
+        if (gibberish) {
+            gibber = "abcdefghijklmnopqrstuvwxyz" +
+                     "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
+                     "0123456789" +
+                     "!#$%&()*+,-./:;<=>?@[]^_{|}~";
+            if (upper) {
+                /*  Convert to upper case, leaving two copies of the
+                    alphabet for two reasons: first, to favour letters
+                    over gnarl, and second, to change only the letter case
+                    when the mode is selected.  */
+                gibber = gibber.toUpperCase();
+            } else if (lower) {
+	    	gibber = gibber.toLowerCase();
+	    }
+        }
+    }
+    for (line = 1; line <= npass; line++) {
+        password = "";
+        if (numeric) {
+            for (nchars = 0; nchars < pw_length; nchars++) {
+                if ((sep > 0) && ((nchars % sep) == 0) && (nchars > 0)) {
+                    password += sepchar();
+                }
+                password += ran1.nextInt(9);
+            }
+        } else if (!english) {
+            for (nchars = 0; nchars < pw_length; nchars++) {
+                if ((sep > 0) && ((nchars % sep) == 0) && (nchars > 0)) {
+                    password += sepchar();
+                }
+                if (gibberish) {
+                    password += gibber.charAt(ran1.nextInt(gibber.length - 1));
+                } else {
+                    password += letters.charAt(ran1.nextInt(25));
+                }
+            }
+        } else {
+            position = ran1.nextInt(total_sum - 1);
+            for (row_position = 0, j = 0; position >= row_position;
+                 row_position += start_freq[j], j++) {
+                continue;
+            }
+
+            password = letters.charAt(i = j - 1);
+            nch = 1;
+            for (nchars = pw_length - 1; nchars; --nchars) {
+
+                // Now find random position within the row.
+
+                position = ran1.nextInt(row_sums[i] - 1);
+                for (row_position = 0, j = 0;
+                     position >= row_position;
+                     row_position += frequency[i][j], j++) {
+                }
+
+                if ((sep > 0) && ((nch % sep) == 0)) {
+                    password += sepchar();
+                }
+                nch++;
+                password += letters.charAt(i = j - 1);
+            }
+        }
+	
+	if ((!numeric) && (!gibberish) && mixed) {
+	    var pwm = '';
+	    var j;
+	    for (j = 0; j < password.length; j++) {
+	    	pwm += ran2.nextInt(1) ? (password.charAt(j)) : (password.charAt(j).toUpperCase());
+	    }
+	    password = pwm;
+	}
+
+        /*  If requested, calculate the MD5 signature for this key and
+            and save for later appending to the results.  */
+
+        if (makesig) {
+            var n, m, hex = "0123456789ABCDEF";
+
+            init();
+            for (m = 0; m < password.length; m++) {
+                update(32 + charcodes.indexOf(password.charAt(m)));
+            }
+            finish();
+
+            for (n = 0; n < 16; n++) {
+                md5v += hex.charAt(digestBits[n] >> 4);
+                md5v += hex.charAt(digestBits[n] & 0xF);
+            }
+            md5v += "\n";
+        }
+
+        aline = "" + line;
+        while (aline.length < ndig) {
+            aline = " " + aline;
+        }
+        v += aline + ") " + password;
+
+        if ((++lineno) >= npline) {
+            v += "\n";
+            lineno = 0;
+        } else {
+            v += "  ";
+        }
+    }
+
+    if (makesig) {
+        v += "\n----------  MD5 Signatures  ----------\n" + md5v;
+    }
+
+    document.getElementById('onetime').pad.value = v;
+    window.status = "Done.";
+}
+
+function loadHandler() {
+    for (var i = 0; i < 25; i++) {
+	gen();
+    }
+};
+
+//]]>
+</script>
+
+</head>
+
+<body class="jsgen" onload="loadHandler();">
+
+<h1><img src="key.gif" class="keyicon" alt=""
+    	 width="40" height="40" /> &nbsp; One-Time Pad Generator</h1>
+
+<p>
+This page, which requires that your browser support JavaScript
+(see <a href="#why"><cite>Why JavaScript</cite></a> below),
+generates one-time pads or password lists in a variety of
+forms.  It is based a high-quality pseudorandom sequence
+generator, which can be seeded either from the current date
+and time, or from a seed you provide.  Fill in the form below
+to select the format of the pad and press &ldquo;Generate&rdquo; to
+create the pad in the text box.  You can then copy and paste
+the generated pad into another window to use as you wish.
+Each of the labels on the request form is linked to a description
+of that parameter.
+</p>
+
+<form id="onetime" action="#" onsubmit="return false;">
+
+<p class="centre">
+<b>Output:</b>
+<a href="#NumberOfKeys">Number of keys</a>: <input type="text" name="nkeys" value="20" size="4" maxlength="12" />
+<a href="#LineLength">Line length</a>: <input type="text" name="linelen" value="48" size="3" maxlength="12" />
+<br />
+<b>Format:</b>
+<a href="#KeyLength">Key length</a>: <input type="text" name="klength" value="8" size="3" maxlength="12" />
+<a href="#GroupLength">Group length</a>: <input type="text" name="sep" value="4" size="2" maxlength="12" />
+
+<br />
+<b>Composition:</b>
+<a href="#KeyText">Key text</a>: <input type="radio" name="keytype" /> Numeric
+<input type="radio" name="keytype" /> Word-like
+<input type="radio" name="keytype" checked="checked" /> Alphabetic
+<input type="radio" name="keytype" /> Gibberish
+<br />
+<a href="#LetterCase">Letters:</a>
+<select size="i" name="textcase">
+
+    <option value="1" selected="selected">Lower case</option>
+    <option value="2">Upper case</option>
+    <option value="3">Mixed case</option>
+</select>
+
+<input type="checkbox" name="rsep" /> <a href="#RandomSep">Random separators</a>
+<input type="checkbox" name="dosig" /> <a href="#Signatures">Include signatures</a>
+
+<br />
+<b><a href="#Seed">Seed:</a></b>
+<input type="radio" name="seedy" checked="checked" /> From clock
+<input type="radio" name="seedy" /> User-defined:
+<input type="text" name="seeder" value="" size="12" maxlength="128" 
+       onchange="document.getElementById('onetime').seedy[1].checked=true;" />
+<br />
+<input type="button" value=" Generate " onclick="gen();" />
+&nbsp;
+<input type="button" value=" Clear " onclick="document.getElementById('onetime').pad.value = '';" />
+&nbsp;
+<input type="button" value=" Select " onclick="document.getElementById('onetime').pad.select();" /><br />
+<textarea name="pad" rows="12" cols="72">
+
+Uh, oh.  It appears your browser either does not support
+JavaScript or that JavaScript has been disabled.  You'll
+have to replace your browser with one supporting JavaScript
+(or enable it, if that's the problem) before you can use
+this page.
+</textarea>
+</p>
+
+</form>
+
+<script type="text/javascript">
+//<![CDATA[
+    //  Clear out "sorry, no JavaScript" message from text box.
+    document.getElementById('onetime').pad.value = "";
+//]]>
+</script>
+
+<h2><a name="details">Details</a></h2>
+
+<p>
+Each of the fields in the one-time pad request form is described
+below.
+</p>
+
+<h3><a name="output">Output</a></h3>
+
+<h4><a name="NumberOfKeys">Number of keys</a></h4>
+
+<p>
+Enter the number of keys you'd like to generate.  If you generate
+more than fit in the results text box, you can use the scroll
+bar to view the additional lines.
+</p>
+
+<h4><a name="LineLength">Line length</a></h4>
+
+<p>
+Lines in the output will be limited to the given length (or contain
+only one key if the line length is less than required for a single
+key).  If the line length is greater than the width of the results
+box, you can use the horizontal scroll bar to view the rest of the
+line.  Enter <tt>0</tt> to force one key per line; this is handy
+when you're preparing a list of keys to be read by a computer program.
+</p>
+
+<h3><a name="format">Format</a></h3>
+
+<h4><a name="KeyLength">Key length</a></h4>
+
+<p>
+Each key will contain this number of characters, not counting
+separators between groups.
+</p>
+
+<h4><a name="GroupLength">Group length</a></h4>
+
+<p>
+If a nonzero value is entered in this field, the key will be broken
+into groups of the given number of characters by separators.  Humans
+find it easier to read and remember sequences of characters when
+divided into groups of five or fewer characters.
+</p>
+
+<h3><a name="composition">Composition</a></h3>
+
+<h4><a name="KeyText">Key text</a></h4>
+
+<p>
+This set of radio buttons lets you select the character set used in
+the keys.  The alternatives are listed in order of
+increasing security.
+</p>
+
+<blockquote>
+<dl>
+<dt><b>Numeric</b></dt>
+<dd>Keys contain only the decimal digits &ldquo;0&rdquo; through &ldquo;9&rdquo;.
+    <em>Least secure.</em></dd>
+
+<dt><b>Word-like</b></dt>
+<dd>Keys are composed of alphabetic characters which obey the
+    digraph statistics of English text.  Such keys contain
+    sequences of vowels and consonants familiar to speakers
+    of Western languages, and are therefore usually easier to
+    memorise but, for a given key length, are less secure than
+    purely random letters.</dd>
+
+<dt><b>Alphabetic</b></dt>
+<dd>Keys consist of letters of the alphabet chosen at random. 
+    Each character has an equal probability of being one of
+    the 26 letters.</dd>
+
+<dt><b>Gibberish</b></dt>
+<dd>Keys use most of the printable ASCII character set, excluding
+    only characters frequently used for quoting purposes.  This
+    option provides the greatest security for a given key length,
+    but most people find keys like this difficult to memorise or
+    even transcribe from a printed pad.  If a human is in the loop,
+    it's often better to use a longer alphabetic or word-like key.
+    <em>Most secure.</em></dd>
+</dl>
+
+</blockquote>
+
+<h4><a name="LetterCase">Letters</a></h4>
+
+<p>
+The case of letters in keys generated with Word-like, Alphabetic, and
+Gibberish key text will be as chosen.  Most people find it easier to
+read lower case letters than all capitals, but for some applications
+(for example, where keys must be scanned optically by hardware that
+only recognises capital letters), capitals are required.  Selecting
+&ldquo;Mixed&nbsp;case&rdquo; creates keys with a mix of upper- and
+lower-case letters; such keys are more secure than those with uniform
+letter case, but do not pass the &ldquo;telephone test&rdquo;: you
+can't read them across a (hopefully secure) voice link without having
+to indicate whether each letter is or is not a capital.
+</p>
+
+<h4><a name="RandomSep">Random separators</a></h4>
+
+<p>
+When the <a href="#KeyLength">Key length</a> is longer than
+a nonzero <a href="#GroupLength">Group length</a> specification,
+the key is divided into sequences of the given group length
+by separator characters.  By default, a hyphen, &ldquo;<tt>-</tt>&rdquo;, is used
+to separate groups.  If you check this box, separators will be
+chosen at random among punctuation marks generally acceptable
+for applications such as passwords.  If you're generating passwords
+for a computer system, random separators dramatically increase
+the difficulty of guessing passwords by exhaustive search.
+</p>
+
+<h4><a name="Signatures">Include signatures</a></h4>
+
+<p>
+
+When this box is checked, at the end of the list of keys, preceded by
+a line beginning with ten dashes &ldquo;<tt>-</tt>&rdquo;, the 128 bit MD5 signature of
+each key is given, one per line, with signatures expressed as 32
+hexadecimal digits.  Key signatures can be used to increase security
+when keys are used to control access to computer systems or databases.
+Instead of storing a copy of the keys, the computer stores their
+signatures.  When the user enters a key, its signature is computed
+with the same MD5 algorithm used to generate it initially, and the key
+is accepted only if the signature matches.  Since discovering
+a key which will generate a given signature is believed to be
+computationally prohibitive, even if the list of signatures stored on
+the computer is compromised, that information will not permit an
+intruder to deduce a valid key.
+</p>
+
+<p>
+Signature calculation is a computationally intense process for which
+JavaScript is not ideally suited; be patient while signatures are
+generated, especially if your computer has modest
+processing speed.
+</p>
+
+<p>
+For signature-based validation to be secure, it is essential
+the original keys be long enough to prohibit discovery of matching
+signatures by exhaustive search.  Suppose, for example, one used
+four digit numeric keys, as used for Personal Identification
+Numbers (PINs) by many credit card systems.  Since only 10,000
+different keys exist, one could simply compute the signatures of
+every possible key from 0000 through 9999, permitting an attacker who
+came into possession of the table of signatures to recover the
+keys by a simple lookup process.  For maximum security, keys must
+contain at least as much information as the 128 bit signatures
+computed from them.  This implies a minimum key length (not counting
+non-random separator characters) for the various key formats as
+follows:
+</p>
+
+<table class="c" border="border" cellpadding="4">
+<tr><th>Key Composition</th> <th>Minimum Characters</th></tr>
+
+<tr><td>Numeric</td> <td class="c">39</td></tr>
+<tr><td>Word-like</td> <td class="c">30</td></tr>
+<tr><td>Alphabetic</td> <td class="c">28</td></tr>
+<tr><td>Gibberish</td> <td class="c">20</td></tr>
+</table>
+
+<p>
+It should be noted that for many practical applications there is no
+need for anything approaching 128-bit security.  The guidelines above
+apply only in the case where maximum protection in the event of
+undetected compromise of key signatures occurs.  In many
+cases, much shorter keys are acceptable, especially when it is assumed
+that a compromise of the system's password or signature database would
+be only part of a much more serious subversion of all resources
+on the system.
+</p>
+
+<h3><a name="Seed">Seed</a></h3>
+
+<p>
+The <em>seed</em> is the starting value which determines all
+subsequent values in the pseudorandom sequence used to generate
+the one-time pad.  Given the seed, the pad can be reproduced.  The
+seed is a 31-bit number which can be derived from the date and
+time at which the one-time pad was requested, or from a
+user-defined seed value.  If the user-defined seed consists
+entirely of decimal digits, it is used directly as the seed,
+modulo 2<sup>31</sup>; if a string containing non-digit characters
+is entered, it is used to compute a <em>hash code</em> which is
+used to seed the generator.
+
+</p>
+
+<p>
+When the clock is used to create the seed, the seed value is entered
+in the User-defined box to allow you, by checking &ldquo;User-defined&rdquo;,
+to produce additional pads with the same seed.
+</p>
+
+<h2><a name="why">Why JavaScript?</a></h2>
+
+<p>
+At first glance, JavaScript may seem an odd choice for programming
+a page such as this.  The one-time pad generator program is rather
+large and complicated, and downloading it to your browser takes longer
+than would be required for a Java applet or to transfer a
+one-time pad generated by a CGI program on the Web server.  I chose
+JavaScript for two reasons: <em>security</em> and <em>transparency</em>.
+
+</p>
+
+<p>
+<b>Security.</b>
+The sole reason for the existence of one-time pads is to
+provide a source of information known only to people to whom
+they have been distributed in a secure manner.  This means
+the generation process cannot involve any link whose security
+is suspect.  If the pad were generated on a Web server and
+transmitted to you, it would have to pass over the
+Internet, where any intermediate site might make a copy
+of your pad before you even received it.  Even if some
+mechanism such as encryption could absolutely prevent the
+pad's being intercepted, you'd still have no way to be sure
+the site generating the pad didn't keep a copy
+in a file, conveniently tagged with your Internet address.
+</p>
+
+<p>
+In order to have any degree of security, it is essential
+that the pad be generated on <em>your</em> computer, without
+involving any transmission or interaction with other
+sites on the Internet.  A Web browser with JavaScript makes
+this possible, since the generation program embedded in this
+page runs entirely on your own computer and does not
+transmit anything over the Internet.  Its output appears
+only in the text box, allowing you to cut and paste it
+to another application.  From there on, its security is
+up to you.
+</p>
+
+<p>
+Security is never absolute.  A one-time pad generated with
+this page might be compromised in a variety of ways, including
+the following:
+
+</p>
+
+<ul>
+<li>    Your Web browser and/or JavaScript interpreter may
+        contain bugs or deliberate security violations
+        which report activity on your computer back to some
+        other Internet site.</li>
+
+<li>    Some other applet running on another page of your
+        browser, perhaps without your being aware of its
+        existence, is spying on other windows.</li>
+
+<li>    Some other application running on your computer
+        may have compromised your system's security and
+        be snooping on your activity.</li>
+
+<li>    Your Web browser may be keeping a &ldquo;history log&rdquo;
+
+        or &ldquo;cache&rdquo; of data you generate.  Somebody may
+        come along later and recover a copy of the pad
+        from that log.</li>
+
+<li>    The implementation of this page may contain a bug
+        or deliberate error which makes its output
+        predictable.  This is why <a href="#trans"><cite>transparency</cite></a>,
+        discussed below, is essential.</li>
+
+<li>    Your computer's security may have been compromised
+        physically; when's the last time you checked that a
+        bug that transmits your keystrokes and/or screen
+        contents to that white van parked down the street
+        wasn't lurking inside your computer cabinet?</li>
+</ul>
+
+<p>
+One can whip oneself into a fine fever of paranoia worrying about
+things like this.  One way to rule out the most probable risks
+is to download a copy of the generator page and run it
+from a &ldquo;<tt>file:</tt>&rdquo; URL on a computer which has no network
+connection whatsoever and is located in a secure location
+under your control.  And look very carefully at any files
+created by your Web browser.  You may find the most interesting
+things squirreled away there&hellip;.
+</p>
+
+<p>
+<b><a name="trans">Transparency</a>.</b>
+Any security-related tool is only as good as its design
+and implementation.  <em>Transparency</em> means that, in
+essence, all the moving parts are visible so you can judge
+for yourself whether the tool merits your confidence.  In
+the case of a program, this means that source code must
+be available, and that you can verify that the program
+you're running corresponds to the source code provided.
+
+</p>
+
+<p>
+The very nature of JavaScript achieves this transparency.
+The program is embedded into this actual Web page; to
+examine it you need only use your browser's &ldquo;View Source&rdquo;
+facility, or save the page into a file on your computer
+and read it with a text editor.  JavaScript's being
+an interpreted language eliminates the risk of your running
+a program different from the purported source code: with
+an interpreted language what you read is what you run.
+</p>
+
+<p>
+Transparency is important even if you don't know enough about
+programming or security to determine whether the program
+contains any flaws.  The very fact that it can be examined
+by anybody allows those with the required expertise to pass
+judgment, and you can form your own conclusions based on
+their analysis.
+</p>
+
+<h2>Credits</h2>
+
+<p>
+
+The pseudorandom sequence generator is based on L'Ecuyer's
+two-sequence generator as described in
+<cite>Communications of the ACM</cite>, Vol. 31 (1968), page 742.
+A Bays-Durham shuffle is used to guard against regularities
+lurking in L'Ecuyer's algorithm; see
+<cite>ACM Transactions on Mathematical Software</cite>, Vol. 2 (1976)
+pages 59&ndash;64 for details.
+</p>
+
+<p>
+The JavaScript implementation of the
+<a href="http://www.ietf.org/rfc/rfc1321.txt"><b>MD5 message-digest algorithm</b></a>
+was developed by Henri Torgemane; please view the source code of this
+page to examine the code, including the copyright notice and
+conditions of use.  The MD5 algorithm was developed by Ron Rivest.
+</p>
+
+<p />
+
+<hr />
+
+<p />
+
+<table class="r">
+<tr><td align="center">
+    <a class="i" href="http://validator.w3.org/check?uri=referer"><img
+       class="button"
+       src="valid-xhtml10.png"
+       alt="Valid XHTML 1.0" height="31" width="88" /></a>
+</td></tr>
+</table>
+
+<address>
+by <a href="/">John Walker</a><br />
+May 26, 1997<br />
+
+Updated: November 2006
+</address>
+
+<p class="centre">
+<em>This document is in the public domain.</em>
+</p>
+</body>
+</html>
+
diff --git a/src/third_party/mozjs-45/build/pgo/js-input/key.gif b/src/third_party/mozjs-45/build/pgo/js-input/key.gif
new file mode 100644
index 0000000..050311f
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/js-input/key.gif
Binary files differ
diff --git a/src/third_party/mozjs-45/build/pgo/js-input/sunspider/3d-cube.html b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/3d-cube.html
new file mode 100644
index 0000000..453167d
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/3d-cube.html
@@ -0,0 +1,387 @@
+<!DOCTYPE html>
+<head>
+<!--
+ Copyright (C) 2007 Apple Inc.  All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+-->
+
+<title>SunSpider 3d-cube</title>
+
+</head>
+
+<body>
+<h3>3d-cube</h3>
+<div id="console">
+</div>
+
+<script>
+
+var _sunSpiderStartDate = new Date();
+
+// 3D Cube Rotation
+// http://www.speich.net/computer/moztesting/3d.htm
+// Created by Simon Speich
+
+var Q = new Array();
+var MTrans = new Array();  // transformation matrix
+var MQube = new Array();  // position information of qube
+var I = new Array();      // entity matrix
+var Origin = new Object();
+var Testing = new Object();
+var LoopTimer;
+
+var DisplArea = new Object();
+DisplArea.Width = 300;
+DisplArea.Height = 300;
+
+function DrawLine(From, To) {
+  var x1 = From.V[0];
+  var x2 = To.V[0];
+  var y1 = From.V[1];
+  var y2 = To.V[1];
+  var dx = Math.abs(x2 - x1);
+  var dy = Math.abs(y2 - y1);
+  var x = x1;
+  var y = y1;
+  var IncX1, IncY1;
+  var IncX2, IncY2;  
+  var Den;
+  var Num;
+  var NumAdd;
+  var NumPix;
+
+  if (x2 >= x1) {  IncX1 = 1; IncX2 = 1;  }
+  else { IncX1 = -1; IncX2 = -1; }
+  if (y2 >= y1)  {  IncY1 = 1; IncY2 = 1; }
+  else { IncY1 = -1; IncY2 = -1; }
+  if (dx >= dy) {
+    IncX1 = 0;
+    IncY2 = 0;
+    Den = dx;
+    Num = dx / 2;
+    NumAdd = dy;
+    NumPix = dx;
+  }
+  else {
+    IncX2 = 0;
+    IncY1 = 0;
+    Den = dy;
+    Num = dy / 2;
+    NumAdd = dx;
+    NumPix = dy;
+  }
+
+  NumPix = Math.round(Q.LastPx + NumPix);
+
+  var i = Q.LastPx;
+  for (; i < NumPix; i++) {
+    Num += NumAdd;
+    if (Num >= Den) {
+      Num -= Den;
+      x += IncX1;
+      y += IncY1;
+    }
+    x += IncX2;
+    y += IncY2;
+  }
+  Q.LastPx = NumPix;
+}
+
+function CalcCross(V0, V1) {
+  var Cross = new Array();
+  Cross[0] = V0[1]*V1[2] - V0[2]*V1[1];
+  Cross[1] = V0[2]*V1[0] - V0[0]*V1[2];
+  Cross[2] = V0[0]*V1[1] - V0[1]*V1[0];
+  return Cross;
+}
+
+function CalcNormal(V0, V1, V2) {
+  var A = new Array();   var B = new Array(); 
+  for (var i = 0; i < 3; i++) {
+    A[i] = V0[i] - V1[i];
+    B[i] = V2[i] - V1[i];
+  }
+  A = CalcCross(A, B);
+  var Length = Math.sqrt(A[0]*A[0] + A[1]*A[1] + A[2]*A[2]); 
+  for (var i = 0; i < 3; i++) A[i] = A[i] / Length;
+  A[3] = 1;
+  return A;
+}
+
+function CreateP(X,Y,Z) {
+  this.V = [X,Y,Z,1];
+}
+
+// multiplies two matrices
+function MMulti(M1, M2) {
+  var M = [[],[],[],[]];
+  var i = 0;
+  var j = 0;
+  for (; i < 4; i++) {
+    j = 0;
+    for (; j < 4; j++) M[i][j] = M1[i][0] * M2[0][j] + M1[i][1] * M2[1][j] + M1[i][2] * M2[2][j] + M1[i][3] * M2[3][j];
+  }
+  return M;
+}
+
+//multiplies matrix with vector
+function VMulti(M, V) {
+  var Vect = new Array();
+  var i = 0;
+  for (;i < 4; i++) Vect[i] = M[i][0] * V[0] + M[i][1] * V[1] + M[i][2] * V[2] + M[i][3] * V[3];
+  return Vect;
+}
+
+function VMulti2(M, V) {
+  var Vect = new Array();
+  var i = 0;
+  for (;i < 3; i++) Vect[i] = M[i][0] * V[0] + M[i][1] * V[1] + M[i][2] * V[2];
+  return Vect;
+}
+
+// add to matrices
+function MAdd(M1, M2) {
+  var M = [[],[],[],[]];
+  var i = 0;
+  var j = 0;
+  for (; i < 4; i++) {
+    j = 0;
+    for (; j < 4; j++) M[i][j] = M1[i][j] + M2[i][j];
+  }
+  return M;
+}
+
+function Translate(M, Dx, Dy, Dz) {
+  var T = [
+  [1,0,0,Dx],
+  [0,1,0,Dy],
+  [0,0,1,Dz],
+  [0,0,0,1]
+  ];
+  return MMulti(T, M);
+}
+
+function RotateX(M, Phi) {
+  var a = Phi;
+  a *= Math.PI / 180;
+  var Cos = Math.cos(a);
+  var Sin = Math.sin(a);
+  var R = [
+  [1,0,0,0],
+  [0,Cos,-Sin,0],
+  [0,Sin,Cos,0],
+  [0,0,0,1]
+  ];
+  return MMulti(R, M);
+}
+
+function RotateY(M, Phi) {
+  var a = Phi;
+  a *= Math.PI / 180;
+  var Cos = Math.cos(a);
+  var Sin = Math.sin(a);
+  var R = [
+  [Cos,0,Sin,0],
+  [0,1,0,0],
+  [-Sin,0,Cos,0],
+  [0,0,0,1]
+  ];
+  return MMulti(R, M);
+}
+
+function RotateZ(M, Phi) {
+  var a = Phi;
+  a *= Math.PI / 180;
+  var Cos = Math.cos(a);
+  var Sin = Math.sin(a);
+  var R = [
+  [Cos,-Sin,0,0],
+  [Sin,Cos,0,0],
+  [0,0,1,0],   
+  [0,0,0,1]
+  ];
+  return MMulti(R, M);
+}
+
+function DrawQube() {
+  // calc current normals
+  var CurN = new Array();
+  var i = 5;
+  Q.LastPx = 0;
+  for (; i > -1; i--) CurN[i] = VMulti2(MQube, Q.Normal[i]);
+  if (CurN[0][2] < 0) {
+    if (!Q.Line[0]) { DrawLine(Q[0], Q[1]); Q.Line[0] = true; };
+    if (!Q.Line[1]) { DrawLine(Q[1], Q[2]); Q.Line[1] = true; };
+    if (!Q.Line[2]) { DrawLine(Q[2], Q[3]); Q.Line[2] = true; };
+    if (!Q.Line[3]) { DrawLine(Q[3], Q[0]); Q.Line[3] = true; };
+  }
+  if (CurN[1][2] < 0) {
+    if (!Q.Line[2]) { DrawLine(Q[3], Q[2]); Q.Line[2] = true; };
+    if (!Q.Line[9]) { DrawLine(Q[2], Q[6]); Q.Line[9] = true; };
+    if (!Q.Line[6]) { DrawLine(Q[6], Q[7]); Q.Line[6] = true; };
+    if (!Q.Line[10]) { DrawLine(Q[7], Q[3]); Q.Line[10] = true; };
+  }
+  if (CurN[2][2] < 0) {
+    if (!Q.Line[4]) { DrawLine(Q[4], Q[5]); Q.Line[4] = true; };
+    if (!Q.Line[5]) { DrawLine(Q[5], Q[6]); Q.Line[5] = true; };
+    if (!Q.Line[6]) { DrawLine(Q[6], Q[7]); Q.Line[6] = true; };
+    if (!Q.Line[7]) { DrawLine(Q[7], Q[4]); Q.Line[7] = true; };
+  }
+  if (CurN[3][2] < 0) {
+    if (!Q.Line[4]) { DrawLine(Q[4], Q[5]); Q.Line[4] = true; };
+    if (!Q.Line[8]) { DrawLine(Q[5], Q[1]); Q.Line[8] = true; };
+    if (!Q.Line[0]) { DrawLine(Q[1], Q[0]); Q.Line[0] = true; };
+    if (!Q.Line[11]) { DrawLine(Q[0], Q[4]); Q.Line[11] = true; };
+  }
+  if (CurN[4][2] < 0) {
+    if (!Q.Line[11]) { DrawLine(Q[4], Q[0]); Q.Line[11] = true; };
+    if (!Q.Line[3]) { DrawLine(Q[0], Q[3]); Q.Line[3] = true; };
+    if (!Q.Line[10]) { DrawLine(Q[3], Q[7]); Q.Line[10] = true; };
+    if (!Q.Line[7]) { DrawLine(Q[7], Q[4]); Q.Line[7] = true; };
+  }
+  if (CurN[5][2] < 0) {
+    if (!Q.Line[8]) { DrawLine(Q[1], Q[5]); Q.Line[8] = true; };
+    if (!Q.Line[5]) { DrawLine(Q[5], Q[6]); Q.Line[5] = true; };
+    if (!Q.Line[9]) { DrawLine(Q[6], Q[2]); Q.Line[9] = true; };
+    if (!Q.Line[1]) { DrawLine(Q[2], Q[1]); Q.Line[1] = true; };
+  }
+  Q.Line = [false,false,false,false,false,false,false,false,false,false,false,false];
+  Q.LastPx = 0;
+}
+
+function Loop() {
+  if (Testing.LoopCount > Testing.LoopMax) return;
+  var TestingStr = String(Testing.LoopCount);
+  while (TestingStr.length < 3) TestingStr = "0" + TestingStr;
+  MTrans = Translate(I, -Q[8].V[0], -Q[8].V[1], -Q[8].V[2]);
+  MTrans = RotateX(MTrans, 1);
+  MTrans = RotateY(MTrans, 3);
+  MTrans = RotateZ(MTrans, 5);
+  MTrans = Translate(MTrans, Q[8].V[0], Q[8].V[1], Q[8].V[2]);
+  MQube = MMulti(MTrans, MQube);
+  var i = 8;
+  for (; i > -1; i--) {
+    Q[i].V = VMulti(MTrans, Q[i].V);
+  }
+  DrawQube();
+  Testing.LoopCount++;
+  Loop();
+}
+
+function Init(CubeSize) {
+  // init/reset vars
+  Origin.V = [150,150,20,1];
+  Testing.LoopCount = 0;
+  Testing.LoopMax = 50;
+  Testing.TimeMax = 0;
+  Testing.TimeAvg = 0;
+  Testing.TimeMin = 0;
+  Testing.TimeTemp = 0;
+  Testing.TimeTotal = 0;
+  Testing.Init = false;
+
+  // transformation matrix
+  MTrans = [
+  [1,0,0,0],
+  [0,1,0,0],
+  [0,0,1,0],
+  [0,0,0,1]
+  ];
+  
+  // position information of qube
+  MQube = [
+  [1,0,0,0],
+  [0,1,0,0],
+  [0,0,1,0],
+  [0,0,0,1]
+  ];
+  
+  // entity matrix
+  I = [
+  [1,0,0,0],
+  [0,1,0,0],
+  [0,0,1,0],
+  [0,0,0,1]
+  ];
+  
+  // create qube
+  Q[0] = new CreateP(-CubeSize,-CubeSize, CubeSize);
+  Q[1] = new CreateP(-CubeSize, CubeSize, CubeSize);
+  Q[2] = new CreateP( CubeSize, CubeSize, CubeSize);
+  Q[3] = new CreateP( CubeSize,-CubeSize, CubeSize);
+  Q[4] = new CreateP(-CubeSize,-CubeSize,-CubeSize);
+  Q[5] = new CreateP(-CubeSize, CubeSize,-CubeSize);
+  Q[6] = new CreateP( CubeSize, CubeSize,-CubeSize);
+  Q[7] = new CreateP( CubeSize,-CubeSize,-CubeSize);
+  
+  // center of gravity
+  Q[8] = new CreateP(0, 0, 0);
+  
+  // anti-clockwise edge check
+  Q.Edge = [[0,1,2],[3,2,6],[7,6,5],[4,5,1],[4,0,3],[1,5,6]];
+  
+  // calculate squad normals
+  Q.Normal = new Array();
+  for (var i = 0; i < Q.Edge.length; i++) Q.Normal[i] = CalcNormal(Q[Q.Edge[i][0]].V, Q[Q.Edge[i][1]].V, Q[Q.Edge[i][2]].V);
+  
+  // line drawn ?
+  Q.Line = [false,false,false,false,false,false,false,false,false,false,false,false];
+  
+  // create line pixels
+  Q.NumPx = 9 * 2 * CubeSize;
+  for (var i = 0; i < Q.NumPx; i++) CreateP(0,0,0);
+  
+  MTrans = Translate(MTrans, Origin.V[0], Origin.V[1], Origin.V[2]);
+  MQube = MMulti(MTrans, MQube);
+
+  var i = 0;
+  for (; i < 9; i++) {
+    Q[i].V = VMulti(MTrans, Q[i].V);
+  }
+  DrawQube();
+  Testing.Init = true;
+  Loop();
+}
+
+for ( var i = 20; i <= 160; i *= 2 ) {
+  Init(i);
+}
+
+Q = null;
+MTrans = null;
+MQube = null;
+I = null;
+Origin = null;
+Testing = null;
+LoopTime = null;
+DisplArea = null;
+
+
+var _sunSpiderInterval = new Date() - _sunSpiderStartDate;
+
+document.getElementById("console").innerHTML = _sunSpiderInterval;
+</script>
+
+
+</body>
+</html>
diff --git a/src/third_party/mozjs-45/build/pgo/js-input/sunspider/3d-morph.html b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/3d-morph.html
new file mode 100644
index 0000000..aca991d
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/3d-morph.html
@@ -0,0 +1,104 @@
+<!DOCTYPE html>
+<head>
+<!--
+ Copyright (C) 2007 Apple Inc.  All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+-->
+
+<title>SunSpider 3d-morph</title>
+
+</head>
+
+<body>
+<h3>3d-morph</h3>
+<div id="console">
+</div>
+
+<script>
+
+var _sunSpiderStartDate = new Date();
+
+/*
+ * Copyright (C) 2007 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+var loops = 15
+var nx = 120
+var nz = 120
+
+function morph(a, f) {
+    var PI2nx = Math.PI * 8/nx
+    var sin = Math.sin
+    var f30 = -(50 * sin(f*Math.PI*2))
+    
+    for (var i = 0; i < nz; ++i) {
+        for (var j = 0; j < nx; ++j) {
+            a[3*(i*nx+j)+1]    = sin((j-1) * PI2nx ) * -f30
+        }
+    }
+}
+
+    
+var a = Array()
+for (var i=0; i < nx*nz*3; ++i) 
+    a[i] = 0
+
+for (var i = 0; i < loops; ++i) {
+    morph(a, i/loops)
+}
+
+testOutput = 0;
+for (var i = 0; i < nx; i++)
+    testOutput += a[3*(i*nx+i)+1];
+a = null;
+
+
+var _sunSpiderInterval = new Date() - _sunSpiderStartDate;
+
+document.getElementById("console").innerHTML = _sunSpiderInterval;
+</script>
+
+
+</body>
+</html>
diff --git a/src/third_party/mozjs-45/build/pgo/js-input/sunspider/3d-raytrace.html b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/3d-raytrace.html
new file mode 100644
index 0000000..2097d42
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/3d-raytrace.html
@@ -0,0 +1,490 @@
+<!DOCTYPE html>
+<head>
+<!--
+ Copyright (C) 2007 Apple Inc.  All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+-->
+
+<title>SunSpider 3d-raytrace</title>
+</head>
+
+<body>
+<h3>3d-raytrace</h3>
+<div id="console">
+</div>
+
+<script>
+
+var _sunSpiderStartDate = new Date();
+
+/*
+ * Copyright (C) 2007 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+function createVector(x,y,z) {
+    return new Array(x,y,z);
+}
+
+function sqrLengthVector(self) {
+    return self[0] * self[0] + self[1] * self[1] + self[2] * self[2];
+}
+
+function lengthVector(self) {
+    return Math.sqrt(self[0] * self[0] + self[1] * self[1] + self[2] * self[2]);
+}
+
+function addVector(self, v) {
+    self[0] += v[0];
+    self[1] += v[1];
+    self[2] += v[2];
+    return self;
+}
+
+function subVector(self, v) {
+    self[0] -= v[0];
+    self[1] -= v[1];
+    self[2] -= v[2];
+    return self;
+}
+
+function scaleVector(self, scale) {
+    self[0] *= scale;
+    self[1] *= scale;
+    self[2] *= scale;
+    return self;
+}
+
+function normaliseVector(self) {
+    var len = Math.sqrt(self[0] * self[0] + self[1] * self[1] + self[2] * self[2]);
+    self[0] /= len;
+    self[1] /= len;
+    self[2] /= len;
+    return self;
+}
+
+function add(v1, v2) {
+    return new Array(v1[0] + v2[0], v1[1] + v2[1], v1[2] + v2[2]);
+}
+
+function sub(v1, v2) {
+    return new Array(v1[0] - v2[0], v1[1] - v2[1], v1[2] - v2[2]);
+}
+
+function scalev(v1, v2) {
+    return new Array(v1[0] * v2[0], v1[1] * v2[1], v1[2] * v2[2]);
+}
+
+function dot(v1, v2) {
+    return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
+}
+
+function scale(v, scale) {
+    return [v[0] * scale, v[1] * scale, v[2] * scale];
+}
+
+function cross(v1, v2) {
+    return [v1[1] * v2[2] - v1[2] * v2[1], 
+            v1[2] * v2[0] - v1[0] * v2[2],
+            v1[0] * v2[1] - v1[1] * v2[0]];
+
+}
+
+function normalise(v) {
+    var len = lengthVector(v);
+    return [v[0] / len, v[1] / len, v[2] / len];
+}
+
+function transformMatrix(self, v) {
+    var vals = self;
+    var x  = vals[0] * v[0] + vals[1] * v[1] + vals[2] * v[2] + vals[3];
+    var y  = vals[4] * v[0] + vals[5] * v[1] + vals[6] * v[2] + vals[7];
+    var z  = vals[8] * v[0] + vals[9] * v[1] + vals[10] * v[2] + vals[11];
+    return [x, y, z];
+}
+
+function invertMatrix(self) {
+    var temp = new Array(16);
+    var tx = -self[3];
+    var ty = -self[7];
+    var tz = -self[11];
+    for (h = 0; h < 3; h++) 
+        for (v = 0; v < 3; v++) 
+            temp[h + v * 4] = self[v + h * 4];
+    for (i = 0; i < 11; i++)
+        self[i] = temp[i];
+    self[3] = tx * self[0] + ty * self[1] + tz * self[2];
+    self[7] = tx * self[4] + ty * self[5] + tz * self[6];
+    self[11] = tx * self[8] + ty * self[9] + tz * self[10];
+    return self;
+}
+
+
+// Triangle intersection using barycentric coord method
+function Triangle(p1, p2, p3) {
+    var edge1 = sub(p3, p1);
+    var edge2 = sub(p2, p1);
+    var normal = cross(edge1, edge2);
+    if (Math.abs(normal[0]) > Math.abs(normal[1]))
+        if (Math.abs(normal[0]) > Math.abs(normal[2]))
+            this.axis = 0; 
+        else 
+            this.axis = 2;
+    else
+        if (Math.abs(normal[1]) > Math.abs(normal[2])) 
+            this.axis = 1;
+        else 
+            this.axis = 2;
+    var u = (this.axis + 1) % 3;
+    var v = (this.axis + 2) % 3;
+    var u1 = edge1[u];
+    var v1 = edge1[v];
+    
+    var u2 = edge2[u];
+    var v2 = edge2[v];
+    this.normal = normalise(normal);
+    this.nu = normal[u] / normal[this.axis];
+    this.nv = normal[v] / normal[this.axis];
+    this.nd = dot(normal, p1) / normal[this.axis];
+    var det = u1 * v2 - v1 * u2;
+    this.eu = p1[u];
+    this.ev = p1[v]; 
+    this.nu1 = u1 / det;
+    this.nv1 = -v1 / det;
+    this.nu2 = v2 / det;
+    this.nv2 = -u2 / det; 
+    this.material = [0.7, 0.7, 0.7];
+}
+
+Triangle.prototype.intersect = function(orig, dir, near, far) {
+    var u = (this.axis + 1) % 3;
+    var v = (this.axis + 2) % 3;
+    var d = dir[this.axis] + this.nu * dir[u] + this.nv * dir[v];
+    var t = (this.nd - orig[this.axis] - this.nu * orig[u] - this.nv * orig[v]) / d;
+    if (t < near || t > far)
+        return null;
+    var Pu = orig[u] + t * dir[u] - this.eu;
+    var Pv = orig[v] + t * dir[v] - this.ev;
+    var a2 = Pv * this.nu1 + Pu * this.nv1;
+    if (a2 < 0) 
+        return null;
+    var a3 = Pu * this.nu2 + Pv * this.nv2;
+    if (a3 < 0) 
+        return null;
+
+    if ((a2 + a3) > 1) 
+        return null;
+    return t;
+}
+
+function Scene(a_triangles) {
+    this.triangles = a_triangles;
+    this.lights = [];
+    this.ambient = [0,0,0];
+    this.background = [0.8,0.8,1];
+}
+var zero = new Array(0,0,0);
+
+Scene.prototype.intersect = function(origin, dir, near, far) {
+    var closest = null;
+    for (i = 0; i < this.triangles.length; i++) {
+        var triangle = this.triangles[i];   
+        var d = triangle.intersect(origin, dir, near, far);
+        if (d == null || d > far || d < near)
+            continue;
+        far = d;
+        closest = triangle;
+    }
+    
+    if (!closest)
+        return [this.background[0],this.background[1],this.background[2]];
+        
+    var normal = closest.normal;
+    var hit = add(origin, scale(dir, far)); 
+    if (dot(dir, normal) > 0)
+        normal = [-normal[0], -normal[1], -normal[2]];
+    
+    var colour = null;
+    if (closest.shader) {
+        colour = closest.shader(closest, hit, dir);
+    } else {
+        colour = closest.material;
+    }
+    
+    // do reflection
+    var reflected = null;
+    if (colour.reflection > 0.001) {
+        var reflection = addVector(scale(normal, -2*dot(dir, normal)), dir);
+        reflected = this.intersect(hit, reflection, 0.0001, 1000000);
+        if (colour.reflection >= 0.999999)
+            return reflected;
+    }
+    
+    var l = [this.ambient[0], this.ambient[1], this.ambient[2]];
+    for (var i = 0; i < this.lights.length; i++) {
+        var light = this.lights[i];
+        var toLight = sub(light, hit);
+        var distance = lengthVector(toLight);
+        scaleVector(toLight, 1.0/distance);
+        distance -= 0.0001;
+        if (this.blocked(hit, toLight, distance))
+            continue;
+        var nl = dot(normal, toLight);
+        if (nl > 0)
+            addVector(l, scale(light.colour, nl));
+    }
+    l = scalev(l, colour);
+    if (reflected) {
+        l = addVector(scaleVector(l, 1 - colour.reflection), scaleVector(reflected, colour.reflection));
+    }
+    return l;
+}
+
+Scene.prototype.blocked = function(O, D, far) {
+    var near = 0.0001;
+    var closest = null;
+    for (i = 0; i < this.triangles.length; i++) {
+        var triangle = this.triangles[i];   
+        var d = triangle.intersect(O, D, near, far);
+        if (d == null || d > far || d < near)
+            continue;
+        return true;
+    }
+    
+    return false;
+}
+
+
+// this camera code is from notes i made ages ago, it is from *somewhere* -- i cannot remember where
+// that somewhere is
+function Camera(origin, lookat, up) {
+    var zaxis = normaliseVector(subVector(lookat, origin));
+    var xaxis = normaliseVector(cross(up, zaxis));
+    var yaxis = normaliseVector(cross(xaxis, subVector([0,0,0], zaxis)));
+    var m = new Array(16);
+    m[0] = xaxis[0]; m[1] = xaxis[1]; m[2] = xaxis[2];
+    m[4] = yaxis[0]; m[5] = yaxis[1]; m[6] = yaxis[2];
+    m[8] = zaxis[0]; m[9] = zaxis[1]; m[10] = zaxis[2];
+    invertMatrix(m);
+    m[3] = 0; m[7] = 0; m[11] = 0;
+    this.origin = origin;
+    this.directions = new Array(4);
+    this.directions[0] = normalise([-0.7,  0.7, 1]);
+    this.directions[1] = normalise([ 0.7,  0.7, 1]);
+    this.directions[2] = normalise([ 0.7, -0.7, 1]);
+    this.directions[3] = normalise([-0.7, -0.7, 1]);
+    this.directions[0] = transformMatrix(m, this.directions[0]);
+    this.directions[1] = transformMatrix(m, this.directions[1]);
+    this.directions[2] = transformMatrix(m, this.directions[2]);
+    this.directions[3] = transformMatrix(m, this.directions[3]);
+}
+
+Camera.prototype.generateRayPair = function(y) {
+    rays = new Array(new Object(), new Object());
+    rays[0].origin = this.origin;
+    rays[1].origin = this.origin;
+    rays[0].dir = addVector(scale(this.directions[0], y), scale(this.directions[3], 1 - y));
+    rays[1].dir = addVector(scale(this.directions[1], y), scale(this.directions[2], 1 - y));
+    return rays;
+}
+
+function renderRows(camera, scene, pixels, width, height, starty, stopy) {
+    for (var y = starty; y < stopy; y++) {
+        var rays = camera.generateRayPair(y / height);
+        for (var x = 0; x < width; x++) {
+            var xp = x / width;
+            var origin = addVector(scale(rays[0].origin, xp), scale(rays[1].origin, 1 - xp));
+            var dir = normaliseVector(addVector(scale(rays[0].dir, xp), scale(rays[1].dir, 1 - xp)));
+            var l = scene.intersect(origin, dir);
+            pixels[y][x] = l;
+        }
+    }
+}
+
+Camera.prototype.render = function(scene, pixels, width, height) {
+    var cam = this;
+    var row = 0;
+    renderRows(cam, scene, pixels, width, height, 0, height);
+}
+
+
+
+function raytraceScene()
+{
+    var startDate = new Date().getTime();
+    var numTriangles = 2 * 6;
+    var triangles = new Array();//numTriangles);
+    var tfl = createVector(-10,  10, -10);
+    var tfr = createVector( 10,  10, -10);
+    var tbl = createVector(-10,  10,  10);
+    var tbr = createVector( 10,  10,  10);
+    var bfl = createVector(-10, -10, -10);
+    var bfr = createVector( 10, -10, -10);
+    var bbl = createVector(-10, -10,  10);
+    var bbr = createVector( 10, -10,  10);
+    
+    // cube!!!
+    // front
+    var i = 0;
+    
+    triangles[i++] = new Triangle(tfl, tfr, bfr);
+    triangles[i++] = new Triangle(tfl, bfr, bfl);
+    // back
+    triangles[i++] = new Triangle(tbl, tbr, bbr);
+    triangles[i++] = new Triangle(tbl, bbr, bbl);
+    //        triangles[i-1].material = [0.7,0.2,0.2];
+    //            triangles[i-1].material.reflection = 0.8;
+    // left
+    triangles[i++] = new Triangle(tbl, tfl, bbl);
+    //            triangles[i-1].reflection = 0.6;
+    triangles[i++] = new Triangle(tfl, bfl, bbl);
+    //            triangles[i-1].reflection = 0.6;
+    // right
+    triangles[i++] = new Triangle(tbr, tfr, bbr);
+    triangles[i++] = new Triangle(tfr, bfr, bbr);
+    // top
+    triangles[i++] = new Triangle(tbl, tbr, tfr);
+    triangles[i++] = new Triangle(tbl, tfr, tfl);
+    // bottom
+    triangles[i++] = new Triangle(bbl, bbr, bfr);
+    triangles[i++] = new Triangle(bbl, bfr, bfl);
+    
+    //Floor!!!!
+    var green = createVector(0.0, 0.4, 0.0);
+    var grey = createVector(0.4, 0.4, 0.4);
+    grey.reflection = 1.0;
+    var floorShader = function(tri, pos, view) {
+        var x = ((pos[0]/32) % 2 + 2) % 2;
+        var z = ((pos[2]/32 + 0.3) % 2 + 2) % 2;
+        if (x < 1 != z < 1) {
+            //in the real world we use the fresnel term...
+            //    var angle = 1-dot(view, tri.normal);
+            //   angle *= angle;
+            //  angle *= angle;
+            // angle *= angle;
+            //grey.reflection = angle;
+            return grey;
+        } else 
+            return green;
+    }
+    var ffl = createVector(-1000, -30, -1000);
+    var ffr = createVector( 1000, -30, -1000);
+    var fbl = createVector(-1000, -30,  1000);
+    var fbr = createVector( 1000, -30,  1000);
+    triangles[i++] = new Triangle(fbl, fbr, ffr);
+    triangles[i-1].shader = floorShader;
+    triangles[i++] = new Triangle(fbl, ffr, ffl);
+    triangles[i-1].shader = floorShader;
+    
+    var _scene = new Scene(triangles);
+    _scene.lights[0] = createVector(20, 38, -22);
+    _scene.lights[0].colour = createVector(0.7, 0.3, 0.3);
+    _scene.lights[1] = createVector(-23, 40, 17);
+    _scene.lights[1].colour = createVector(0.7, 0.3, 0.3);
+    _scene.lights[2] = createVector(23, 20, 17);
+    _scene.lights[2].colour = createVector(0.7, 0.7, 0.7);
+    _scene.ambient = createVector(0.1, 0.1, 0.1);
+    //  _scene.background = createVector(0.7, 0.7, 1.0);
+    
+    var size = 30;
+    var pixels = new Array();
+    for (var y = 0; y < size; y++) {
+        pixels[y] = new Array();
+        for (var x = 0; x < size; x++) {
+            pixels[y][x] = 0;
+        }
+    }
+
+    var _camera = new Camera(createVector(-40, 40, 40), createVector(0, 0, 0), createVector(0, 1, 0));
+    _camera.render(_scene, pixels, size, size);
+
+    return pixels;
+}
+
+function arrayToCanvasCommands(pixels)
+{
+    var s = '<canvas id="renderCanvas" width="30px" height="30px"></canvas><scr' + 'ipt>\nvar pixels = [';
+    var size = 30;
+    for (var y = 0; y < size; y++) {
+        s += "[";
+        for (var x = 0; x < size; x++) {
+            s += "[" + pixels[y][x] + "],";
+        }
+        s+= "],";
+    }
+    s += '];\n    var canvas = document.getElementById("renderCanvas").getContext("2d");\n\
+\n\
+\n\
+    var size = 30;\n\
+    canvas.fillStyle = "red";\n\
+    canvas.fillRect(0, 0, size, size);\n\
+    canvas.scale(1, -1);\n\
+    canvas.translate(0, -size);\n\
+\n\
+    if (!canvas.setFillColor)\n\
+        canvas.setFillColor = function(r, g, b, a) {\n\
+            this.fillStyle = "rgb("+[Math.floor(r * 255), Math.floor(g * 255), Math.floor(b * 255)]+")";\n\
+    }\n\
+\n\
+for (var y = 0; y < size; y++) {\n\
+  for (var x = 0; x < size; x++) {\n\
+    var l = pixels[y][x];\n\
+    canvas.setFillColor(l[0], l[1], l[2], 1);\n\
+    canvas.fillRect(x, y, 1, 1);\n\
+  }\n\
+}</scr' + 'ipt>';
+
+    return s;
+}
+
+testOutput = arrayToCanvasCommands(raytraceScene());
+
+
+var _sunSpiderInterval = new Date() - _sunSpiderStartDate;
+
+document.getElementById("console").innerHTML = _sunSpiderInterval;
+</script>
+
+
+</body>
+</html>
diff --git a/src/third_party/mozjs-45/build/pgo/js-input/sunspider/access-binary-trees.html b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/access-binary-trees.html
new file mode 100644
index 0000000..c2c6cf3
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/access-binary-trees.html
@@ -0,0 +1,100 @@
+<!DOCTYPE html>
+<head>
+<!--
+ Copyright (C) 2007 Apple Inc.  All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+-->
+
+<title>SunSpider access-binary-trees</title>
+
+</head>
+
+<body>
+<h3>access-binary-trees</h3>
+<div id="console">
+</div>
+
+<script>
+
+var _sunSpiderStartDate = new Date();
+
+/* The Great Computer Language Shootout
+   http://shootout.alioth.debian.org/
+   contributed by Isaac Gouy */
+
+function TreeNode(left,right,item){
+   this.left = left;
+   this.right = right;
+   this.item = item;
+}
+
+TreeNode.prototype.itemCheck = function(){
+   if (this.left==null) return this.item;
+   else return this.item + this.left.itemCheck() - this.right.itemCheck();
+}
+
+function bottomUpTree(item,depth){
+   if (depth>0){
+      return new TreeNode(
+          bottomUpTree(2*item-1, depth-1)
+         ,bottomUpTree(2*item, depth-1)
+         ,item
+      );
+   }
+   else {
+      return new TreeNode(null,null,item);
+   }
+}
+
+var ret;
+
+for ( var n = 4; n <= 7; n += 1 ) {
+    var minDepth = 4;
+    var maxDepth = Math.max(minDepth + 2, n);
+    var stretchDepth = maxDepth + 1;
+    
+    var check = bottomUpTree(0,stretchDepth).itemCheck();
+    
+    var longLivedTree = bottomUpTree(0,maxDepth);
+    for (var depth=minDepth; depth<=maxDepth; depth+=2){
+        var iterations = 1 << (maxDepth - depth + minDepth);
+
+        check = 0;
+        for (var i=1; i<=iterations; i++){
+            check += bottomUpTree(i,depth).itemCheck();
+            check += bottomUpTree(-i,depth).itemCheck();
+        }
+    }
+
+    ret = longLivedTree.itemCheck();
+}
+
+
+var _sunSpiderInterval = new Date() - _sunSpiderStartDate;
+
+document.getElementById("console").innerHTML = _sunSpiderInterval;
+</script>
+
+
+</body>
+</html>
diff --git a/src/third_party/mozjs-45/build/pgo/js-input/sunspider/access-fannkuch.html b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/access-fannkuch.html
new file mode 100644
index 0000000..02b306f
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/access-fannkuch.html
@@ -0,0 +1,116 @@
+<!DOCTYPE html>
+<head>
+<!--
+ Copyright (C) 2007 Apple Inc.  All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+-->
+
+<title>SunSpider access-fannkuch</title>
+
+</head>
+
+<body>
+<h3>access-fannkuch</h3>
+<div id="console">
+</div>
+
+<script>
+
+var _sunSpiderStartDate = new Date();
+
+/* The Great Computer Language Shootout
+   http://shootout.alioth.debian.org/
+   contributed by Isaac Gouy */
+
+function fannkuch(n) {
+   var check = 0;
+   var perm = Array(n);
+   var perm1 = Array(n);
+   var count = Array(n);
+   var maxPerm = Array(n);
+   var maxFlipsCount = 0;
+   var m = n - 1;
+
+   for (var i = 0; i < n; i++) perm1[i] = i;
+   var r = n;
+
+   while (true) {
+      // write-out the first 30 permutations
+      if (check < 30){
+         var s = "";
+         for(var i=0; i<n; i++) s += (perm1[i]+1).toString();
+         check++;
+      }
+
+      while (r != 1) { count[r - 1] = r; r--; }
+      if (!(perm1[0] == 0 || perm1[m] == m)) {
+         for (var i = 0; i < n; i++) perm[i] = perm1[i];
+
+         var flipsCount = 0;
+         var k;
+
+         while (!((k = perm[0]) == 0)) {
+            var k2 = (k + 1) >> 1;
+            for (var i = 0; i < k2; i++) {
+               var temp = perm[i]; perm[i] = perm[k - i]; perm[k - i] = temp;
+            }
+            flipsCount++;
+         }
+
+         if (flipsCount > maxFlipsCount) {
+            maxFlipsCount = flipsCount;
+            for (var i = 0; i < n; i++) maxPerm[i] = perm1[i];
+         }
+      }
+
+      while (true) {
+         if (r == n) return maxFlipsCount;
+         var perm0 = perm1[0];
+         var i = 0;
+         while (i < r) {
+            var j = i + 1;
+            perm1[i] = perm1[j];
+            i = j;
+         }
+         perm1[r] = perm0;
+
+         count[r] = count[r] - 1;
+         if (count[r] > 0) break;
+         r++;
+      }
+   }
+}
+
+var n = 8;
+var ret = fannkuch(n);
+
+
+
+var _sunSpiderInterval = new Date() - _sunSpiderStartDate;
+
+document.getElementById("console").innerHTML = _sunSpiderInterval;
+</script>
+
+
+</body>
+</html>
diff --git a/src/third_party/mozjs-45/build/pgo/js-input/sunspider/access-nbody.html b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/access-nbody.html
new file mode 100644
index 0000000..4ef73c8
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/access-nbody.html
@@ -0,0 +1,219 @@
+<!DOCTYPE html>
+<head>
+<!--
+ Copyright (C) 2007 Apple Inc.  All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+-->
+
+<title>SunSpider access-nbody</title>
+
+</head>
+
+<body>
+<h3>access-nbody</h3>
+<div id="console">
+</div>
+
+<script>
+
+var _sunSpiderStartDate = new Date();
+
+/* The Great Computer Language Shootout
+   http://shootout.alioth.debian.org/
+   contributed by Isaac Gouy */
+
+var PI = 3.141592653589793;
+var SOLAR_MASS = 4 * PI * PI;
+var DAYS_PER_YEAR = 365.24;
+
+function Body(x,y,z,vx,vy,vz,mass){
+   this.x = x;
+   this.y = y;
+   this.z = z;
+   this.vx = vx;
+   this.vy = vy;
+   this.vz = vz;
+   this.mass = mass;
+}
+
+Body.prototype.offsetMomentum = function(px,py,pz) {
+   this.vx = -px / SOLAR_MASS;
+   this.vy = -py / SOLAR_MASS;
+   this.vz = -pz / SOLAR_MASS;
+   return this;
+}
+
+function Jupiter(){
+   return new Body(
+      4.84143144246472090e+00,
+      -1.16032004402742839e+00,
+      -1.03622044471123109e-01,
+      1.66007664274403694e-03 * DAYS_PER_YEAR,
+      7.69901118419740425e-03 * DAYS_PER_YEAR,
+      -6.90460016972063023e-05 * DAYS_PER_YEAR,
+      9.54791938424326609e-04 * SOLAR_MASS
+   );
+}
+
+function Saturn(){
+   return new Body(
+      8.34336671824457987e+00,
+      4.12479856412430479e+00,
+      -4.03523417114321381e-01,
+      -2.76742510726862411e-03 * DAYS_PER_YEAR,
+      4.99852801234917238e-03 * DAYS_PER_YEAR,
+      2.30417297573763929e-05 * DAYS_PER_YEAR,
+      2.85885980666130812e-04 * SOLAR_MASS
+   );
+}
+
+function Uranus(){
+   return new Body(
+      1.28943695621391310e+01,
+      -1.51111514016986312e+01,
+      -2.23307578892655734e-01,
+      2.96460137564761618e-03 * DAYS_PER_YEAR,
+      2.37847173959480950e-03 * DAYS_PER_YEAR,
+      -2.96589568540237556e-05 * DAYS_PER_YEAR,
+      4.36624404335156298e-05 * SOLAR_MASS
+   );
+}
+
+function Neptune(){
+   return new Body(
+      1.53796971148509165e+01,
+      -2.59193146099879641e+01,
+      1.79258772950371181e-01,
+      2.68067772490389322e-03 * DAYS_PER_YEAR,
+      1.62824170038242295e-03 * DAYS_PER_YEAR,
+      -9.51592254519715870e-05 * DAYS_PER_YEAR,
+      5.15138902046611451e-05 * SOLAR_MASS
+   );
+}
+
+function Sun(){
+   return new Body(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, SOLAR_MASS);
+}
+
+
+function NBodySystem(bodies){
+   this.bodies = bodies;
+   var px = 0.0;
+   var py = 0.0;
+   var pz = 0.0;
+   var size = this.bodies.length;
+   for (var i=0; i<size; i++){
+      var b = this.bodies[i];
+      var m = b.mass;
+      px += b.vx * m;
+      py += b.vy * m;
+      pz += b.vz * m;
+   }
+   this.bodies[0].offsetMomentum(px,py,pz);
+}
+
+NBodySystem.prototype.advance = function(dt){
+   var dx, dy, dz, distance, mag;
+   var size = this.bodies.length;
+
+   for (var i=0; i<size; i++) {
+      var bodyi = this.bodies[i];
+      for (var j=i+1; j<size; j++) {
+         var bodyj = this.bodies[j];
+         dx = bodyi.x - bodyj.x;
+         dy = bodyi.y - bodyj.y;
+         dz = bodyi.z - bodyj.z;
+
+         distance = Math.sqrt(dx*dx + dy*dy + dz*dz);
+         mag = dt / (distance * distance * distance);
+
+         bodyi.vx -= dx * bodyj.mass * mag;
+         bodyi.vy -= dy * bodyj.mass * mag;
+         bodyi.vz -= dz * bodyj.mass * mag;
+
+         bodyj.vx += dx * bodyi.mass * mag;
+         bodyj.vy += dy * bodyi.mass * mag;
+         bodyj.vz += dz * bodyi.mass * mag;
+      }
+   }
+
+   for (var i=0; i<size; i++) {
+      var body = this.bodies[i];
+      body.x += dt * body.vx;
+      body.y += dt * body.vy;
+      body.z += dt * body.vz;
+   }
+}
+
+NBodySystem.prototype.energy = function(){
+   var dx, dy, dz, distance;
+   var e = 0.0;
+   var size = this.bodies.length;
+
+   for (var i=0; i<size; i++) {
+      var bodyi = this.bodies[i];
+
+      e += 0.5 * bodyi.mass *
+         ( bodyi.vx * bodyi.vx
+         + bodyi.vy * bodyi.vy
+         + bodyi.vz * bodyi.vz );
+
+      for (var j=i+1; j<size; j++) {
+         var bodyj = this.bodies[j];
+         dx = bodyi.x - bodyj.x;
+         dy = bodyi.y - bodyj.y;
+         dz = bodyi.z - bodyj.z;
+
+         distance = Math.sqrt(dx*dx + dy*dy + dz*dz);
+         e -= (bodyi.mass * bodyj.mass) / distance;
+      }
+   }
+   return e;
+}
+
+var ret;
+
+for ( var n = 3; n <= 24; n *= 2 ) {
+    (function(){
+        var bodies = new NBodySystem( Array(
+           Sun(),Jupiter(),Saturn(),Uranus(),Neptune()
+        ));
+        var max = n * 100;
+        
+        ret = bodies.energy();
+        for (var i=0; i<max; i++){
+            bodies.advance(0.01);
+        }
+        ret = bodies.energy();
+    })();
+}
+
+
+var _sunSpiderInterval = new Date() - _sunSpiderStartDate;
+
+document.getElementById("console").innerHTML = _sunSpiderInterval;
+</script>
+
+
+</body>
+</html>
diff --git a/src/third_party/mozjs-45/build/pgo/js-input/sunspider/access-nsieve.html b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/access-nsieve.html
new file mode 100644
index 0000000..c3ed067
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/access-nsieve.html
@@ -0,0 +1,88 @@
+<!DOCTYPE html>
+<head>
+<!--
+ Copyright (C) 2007 Apple Inc.  All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+-->
+
+<title>SunSpider access-nsieve</title>
+
+</head>
+
+<body>
+<h3>access-nsieve</h3>
+<div id="console">
+</div>
+
+<script>
+
+var _sunSpiderStartDate = new Date();
+
+// The Great Computer Language Shootout
+// http://shootout.alioth.debian.org/
+//
+// modified by Isaac Gouy
+
+function pad(number,width){
+   var s = number.toString();
+   var prefixWidth = width - s.length;
+   if (prefixWidth>0){
+      for (var i=1; i<=prefixWidth; i++) s = " " + s;
+   }
+   return s;
+}
+
+function nsieve(m, isPrime){
+   var i, k, count;
+
+   for (i=2; i<=m; i++) { isPrime[i] = true; }
+   count = 0;
+
+   for (i=2; i<=m; i++){
+      if (isPrime[i]) {
+         for (k=i+i; k<=m; k+=i) isPrime[k] = false;
+         count++;
+      }
+   }
+   return count;
+}
+
+function sieve() {
+    for (var i = 1; i <= 3; i++ ) {
+        var m = (1<<i)*10000;
+        var flags = Array(m+1);
+        nsieve(m, flags);
+    }
+}
+
+sieve();
+
+
+var _sunSpiderInterval = new Date() - _sunSpiderStartDate;
+
+document.getElementById("console").innerHTML = _sunSpiderInterval;
+</script>
+
+
+</body>
+</html>
diff --git a/src/third_party/mozjs-45/build/pgo/js-input/sunspider/bitops-3bit-bits-in-byte.html b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/bitops-3bit-bits-in-byte.html
new file mode 100644
index 0000000..c40be94
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/bitops-3bit-bits-in-byte.html
@@ -0,0 +1,82 @@
+<!DOCTYPE html>
+<head>
+<!--
+ Copyright (C) 2007 Apple Inc.  All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+-->
+
+<title>SunSpider bitops-3bit-bits-in-byte</title>
+
+</head>
+
+<body>
+<h3>bitops-3bit-bits-in-byte</h3>
+<div id="console">
+</div>
+
+<script>
+
+var _sunSpiderStartDate = new Date();
+
+// Copyright (c) 2004 by Arthur Langereis (arthur_ext at domain xfinitegames, tld com
+
+// 1 op = 6 ANDs, 3 SHRs, 3 SHLs, 4 assigns, 2 ADDs
+// O(1)
+function fast3bitlookup(b) {
+var c, bi3b = 0xE994; // 0b1110 1001 1001 0100; // 3 2 2 1  2 1 1 0
+c  = 3 & (bi3b >> ((b << 1) & 14));
+c += 3 & (bi3b >> ((b >> 2) & 14));
+c += 3 & (bi3b >> ((b >> 5) & 6));
+return c;
+
+/*
+lir4,0xE994; 9 instructions, no memory access, minimal register dependence, 6 shifts, 2 adds, 1 inline assign
+rlwinmr5,r3,1,28,30
+rlwinmr6,r3,30,28,30
+rlwinmr7,r3,27,29,30
+rlwnmr8,r4,r5,30,31
+rlwnmr9,r4,r6,30,31
+rlwnmr10,r4,r7,30,31
+addr3,r8,r9
+addr3,r3,r10
+*/
+}
+
+
+function TimeFunc(func) {
+var x, y, t;
+for(var x=0; x<500; x++)
+for(var y=0; y<256; y++) func(y);
+}
+
+TimeFunc(fast3bitlookup);
+
+
+var _sunSpiderInterval = new Date() - _sunSpiderStartDate;
+
+document.getElementById("console").innerHTML = _sunSpiderInterval;
+</script>
+
+
+</body>
+</html>
diff --git a/src/third_party/mozjs-45/build/pgo/js-input/sunspider/bitops-bits-in-byte.html b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/bitops-bits-in-byte.html
new file mode 100644
index 0000000..4022c77
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/bitops-bits-in-byte.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<head>
+<!--
+ Copyright (C) 2007 Apple Inc.  All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+-->
+
+<title>SunSpider bitops-bits-in-byte</title>
+
+</head>
+
+<body>
+<h3>bitops-bits-in-byte</h3>
+<div id="console">
+</div>
+
+<script>
+
+var _sunSpiderStartDate = new Date();
+
+// Copyright (c) 2004 by Arthur Langereis (arthur_ext at domain xfinitegames, tld com)
+
+
+// 1 op = 2 assigns, 16 compare/branches, 8 ANDs, (0-8) ADDs, 8 SHLs
+// O(n)
+function bitsinbyte(b) {
+var m = 1, c = 0;
+while(m<0x100) {
+if(b & m) c++;
+m <<= 1;
+}
+return c;
+}
+
+function TimeFunc(func) {
+var x, y, t;
+for(var x=0; x<350; x++)
+for(var y=0; y<256; y++) func(y);
+}
+
+TimeFunc(bitsinbyte);
+
+
+var _sunSpiderInterval = new Date() - _sunSpiderStartDate;
+
+
+document.getElementById("console").innerHTML = _sunSpiderInterval;
+</script>
+
+
+</body>
+</html>
diff --git a/src/third_party/mozjs-45/build/pgo/js-input/sunspider/bitops-bitwise-and.html b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/bitops-bitwise-and.html
new file mode 100644
index 0000000..cca5130
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/bitops-bitwise-and.html
@@ -0,0 +1,78 @@
+<!DOCTYPE html>
+<head>
+<!--
+ Copyright (C) 2007 Apple Inc.  All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+-->
+
+<title>SunSpider bitops-bitwise-and</title>
+
+</head>
+
+<body>
+<h3>bitops-bitwise-and</h3>
+<div id="console">
+</div>
+
+<script>
+
+var _sunSpiderStartDate = new Date();
+
+/*
+ * Copyright (C) 2007 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+bitwiseAndValue = 4294967296;
+for (var i = 0; i < 600000; i++)
+    bitwiseAndValue = bitwiseAndValue & i;
+
+
+var _sunSpiderInterval = new Date() - _sunSpiderStartDate;
+
+document.getElementById("console").innerHTML = _sunSpiderInterval;
+</script>
+
+
+</body>
+</html>
diff --git a/src/third_party/mozjs-45/build/pgo/js-input/sunspider/bitops-nsieve-bits.html b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/bitops-nsieve-bits.html
new file mode 100644
index 0000000..1849f9d
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/bitops-nsieve-bits.html
@@ -0,0 +1,82 @@
+<!DOCTYPE html>
+<head>
+<!--
+ Copyright (C) 2007 Apple Inc.  All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+-->
+
+<title>SunSpider bitops-nsieve-bits</title>
+
+</head>
+
+<body>
+<h3>bitops-nsieve-bits</h3>
+<div id="console">
+</div>
+
+<script>
+
+var _sunSpiderStartDate = new Date();
+
+// The Great Computer Language Shootout
+//  http://shootout.alioth.debian.org
+//
+//  Contributed by Ian Osgood
+
+function pad(n,width) {
+  var s = n.toString();
+  while (s.length < width) s = ' ' + s;
+  return s;
+}
+
+function primes(isPrime, n) {
+  var i, count = 0, m = 10000<<n, size = m+31>>5;
+
+  for (i=0; i<size; i++) isPrime[i] = 0xffffffff;
+
+  for (i=2; i<m; i++)
+    if (isPrime[i>>5] & 1<<(i&31)) {
+      for (var j=i+i; j<m; j+=i)
+        isPrime[j>>5] &= ~(1<<(j&31));
+      count++;
+    }
+}
+
+function sieve() {
+    for (var i = 4; i <= 4; i++) {
+        var isPrime = new Array((10000<<i)+31>>5);
+        primes(isPrime, i);
+    }
+}
+
+sieve();
+
+
+var _sunSpiderInterval = new Date() - _sunSpiderStartDate;
+
+document.getElementById("console").innerHTML = _sunSpiderInterval;
+</script>
+
+
+</body>
+</html>
diff --git a/src/third_party/mozjs-45/build/pgo/js-input/sunspider/controlflow-recursive.html b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/controlflow-recursive.html
new file mode 100644
index 0000000..9a9651d
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/controlflow-recursive.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<head>
+<!--
+ Copyright (C) 2007 Apple Inc.  All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+-->
+
+<title>SunSpider controlflow-recursive</title>
+
+</head>
+
+<body>
+<h3>controlflow-recursive</h3>
+<div id="console">
+</div>
+
+<script>
+
+var _sunSpiderStartDate = new Date();
+
+// The Computer Language Shootout
+// http://shootout.alioth.debian.org/
+// contributed by Isaac Gouy
+
+function ack(m,n){
+   if (m==0) { return n+1; }
+   if (n==0) { return ack(m-1,1); }
+   return ack(m-1, ack(m,n-1) );
+}
+
+function fib(n) {
+    if (n < 2){ return 1; }
+    return fib(n-2) + fib(n-1);
+}
+
+function tak(x,y,z) {
+    if (y >= x) return z;
+    return tak(tak(x-1,y,z), tak(y-1,z,x), tak(z-1,x,y));
+}
+
+for ( var i = 3; i <= 5; i++ ) {
+    ack(3,i);
+    fib(17.0+i);
+    tak(3*i+3,2*i+2,i+1);
+}
+
+
+var _sunSpiderInterval = new Date() - _sunSpiderStartDate;
+
+document.getElementById("console").innerHTML = _sunSpiderInterval;
+</script>
+
+
+</body>
+</html>
diff --git a/src/third_party/mozjs-45/build/pgo/js-input/sunspider/crypto-aes.html b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/crypto-aes.html
new file mode 100644
index 0000000..12f26b2
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/crypto-aes.html
@@ -0,0 +1,472 @@
+<!DOCTYPE html>
+<head>
+<!--
+ Copyright (C) 2007 Apple Inc.  All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+-->
+
+<title>SunSpider crypto-aes</title>
+
+</head>
+
+<body>
+<h3>crypto-aes</h3>
+<div id="console">
+</div>
+
+<script>
+
+var _sunSpiderStartDate = new Date();
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
+
+/*
+ * AES Cipher function: encrypt 'input' with Rijndael algorithm
+ *
+ *   takes   byte-array 'input' (16 bytes)
+ *           2D byte-array key schedule 'w' (Nr+1 x Nb bytes)
+ *
+ *   applies Nr rounds (10/12/14) using key schedule w for 'add round key' stage
+ *
+ *   returns byte-array encrypted value (16 bytes)
+ */
+function Cipher(input, w) {    // main Cipher function [§5.1]
+  var Nb = 4;               // block size (in words): no of columns in state (fixed at 4 for AES)
+  var Nr = w.length/Nb - 1; // no of rounds: 10/12/14 for 128/192/256-bit keys
+
+  var state = [[],[],[],[]];  // initialise 4xNb byte-array 'state' with input [§3.4]
+  for (var i=0; i<4*Nb; i++) state[i%4][Math.floor(i/4)] = input[i];
+
+  state = AddRoundKey(state, w, 0, Nb);
+
+  for (var round=1; round<Nr; round++) {
+    state = SubBytes(state, Nb);
+    state = ShiftRows(state, Nb);
+    state = MixColumns(state, Nb);
+    state = AddRoundKey(state, w, round, Nb);
+  }
+
+  state = SubBytes(state, Nb);
+  state = ShiftRows(state, Nb);
+  state = AddRoundKey(state, w, Nr, Nb);
+
+  var output = new Array(4*Nb);  // convert state to 1-d array before returning [§3.4]
+  for (var i=0; i<4*Nb; i++) output[i] = state[i%4][Math.floor(i/4)];
+  return output;
+}
+
+
+function SubBytes(s, Nb) {    // apply SBox to state S [§5.1.1]
+  for (var r=0; r<4; r++) {
+    for (var c=0; c<Nb; c++) s[r][c] = Sbox[s[r][c]];
+  }
+  return s;
+}
+
+
+function ShiftRows(s, Nb) {    // shift row r of state S left by r bytes [§5.1.2]
+  var t = new Array(4);
+  for (var r=1; r<4; r++) {
+    for (var c=0; c<4; c++) t[c] = s[r][(c+r)%Nb];  // shift into temp copy
+    for (var c=0; c<4; c++) s[r][c] = t[c];         // and copy back
+  }          // note that this will work for Nb=4,5,6, but not 7,8 (always 4 for AES):
+  return s;  // see fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.311.pdf 
+}
+
+
+function MixColumns(s, Nb) {   // combine bytes of each col of state S [§5.1.3]
+  for (var c=0; c<4; c++) {
+    var a = new Array(4);  // 'a' is a copy of the current column from 's'
+    var b = new Array(4);  // 'b' is a•{02} in GF(2^8)
+    for (var i=0; i<4; i++) {
+      a[i] = s[i][c];
+      b[i] = s[i][c]&0x80 ? s[i][c]<<1 ^ 0x011b : s[i][c]<<1;
+    }
+    // a[n] ^ b[n] is a•{03} in GF(2^8)
+    s[0][c] = b[0] ^ a[1] ^ b[1] ^ a[2] ^ a[3]; // 2*a0 + 3*a1 + a2 + a3
+    s[1][c] = a[0] ^ b[1] ^ a[2] ^ b[2] ^ a[3]; // a0 * 2*a1 + 3*a2 + a3
+    s[2][c] = a[0] ^ a[1] ^ b[2] ^ a[3] ^ b[3]; // a0 + a1 + 2*a2 + 3*a3
+    s[3][c] = a[0] ^ b[0] ^ a[1] ^ a[2] ^ b[3]; // 3*a0 + a1 + a2 + 2*a3
+  }
+  return s;
+}
+
+
+function AddRoundKey(state, w, rnd, Nb) {  // xor Round Key into state S [§5.1.4]
+  for (var r=0; r<4; r++) {
+    for (var c=0; c<Nb; c++) state[r][c] ^= w[rnd*4+c][r];
+  }
+  return state;
+}
+
+
+function KeyExpansion(key) {  // generate Key Schedule (byte-array Nr+1 x Nb) from Key [§5.2]
+  var Nb = 4;            // block size (in words): no of columns in state (fixed at 4 for AES)
+  var Nk = key.length/4  // key length (in words): 4/6/8 for 128/192/256-bit keys
+  var Nr = Nk + 6;       // no of rounds: 10/12/14 for 128/192/256-bit keys
+
+  var w = new Array(Nb*(Nr+1));
+  var temp = new Array(4);
+
+  for (var i=0; i<Nk; i++) {
+    var r = [key[4*i], key[4*i+1], key[4*i+2], key[4*i+3]];
+    w[i] = r;
+  }
+
+  for (var i=Nk; i<(Nb*(Nr+1)); i++) {
+    w[i] = new Array(4);
+    for (var t=0; t<4; t++) temp[t] = w[i-1][t];
+    if (i % Nk == 0) {
+      temp = SubWord(RotWord(temp));
+      for (var t=0; t<4; t++) temp[t] ^= Rcon[i/Nk][t];
+    } else if (Nk > 6 && i%Nk == 4) {
+      temp = SubWord(temp);
+    }
+    for (var t=0; t<4; t++) w[i][t] = w[i-Nk][t] ^ temp[t];
+  }
+
+  return w;
+}
+
+function SubWord(w) {    // apply SBox to 4-byte word w
+  for (var i=0; i<4; i++) w[i] = Sbox[w[i]];
+  return w;
+}
+
+function RotWord(w) {    // rotate 4-byte word w left by one byte
+  w[4] = w[0];
+  for (var i=0; i<4; i++) w[i] = w[i+1];
+  return w;
+}
+
+
+// Sbox is pre-computed multiplicative inverse in GF(2^8) used in SubBytes and KeyExpansion [§5.1.1]
+var Sbox =  [0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,
+             0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,
+             0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,
+             0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,
+             0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,
+             0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,
+             0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,
+             0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,
+             0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,
+             0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,
+             0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,
+             0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,
+             0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,
+             0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,
+             0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,
+             0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16];
+
+// Rcon is Round Constant used for the Key Expansion [1st col is 2^(r-1) in GF(2^8)] [§5.2]
+var Rcon = [ [0x00, 0x00, 0x00, 0x00],
+             [0x01, 0x00, 0x00, 0x00],
+             [0x02, 0x00, 0x00, 0x00],
+             [0x04, 0x00, 0x00, 0x00],
+             [0x08, 0x00, 0x00, 0x00],
+             [0x10, 0x00, 0x00, 0x00],
+             [0x20, 0x00, 0x00, 0x00],
+             [0x40, 0x00, 0x00, 0x00],
+             [0x80, 0x00, 0x00, 0x00],
+             [0x1b, 0x00, 0x00, 0x00],
+             [0x36, 0x00, 0x00, 0x00] ]; 
+
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
+
+/* 
+ * Use AES to encrypt 'plaintext' with 'password' using 'nBits' key, in 'Counter' mode of operation
+ *                           - see http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
+ *   for each block
+ *   - outputblock = cipher(counter, key)
+ *   - cipherblock = plaintext xor outputblock
+ */
+function AESEncryptCtr(plaintext, password, nBits) {
+  if (!(nBits==128 || nBits==192 || nBits==256)) return '';  // standard allows 128/192/256 bit keys
+
+  // for this example script, generate the key by applying Cipher to 1st 16/24/32 chars of password; 
+  // for real-world applications, a more secure approach would be to hash the password e.g. with SHA-1
+  var nBytes = nBits/8;  // no bytes in key
+  var pwBytes = new Array(nBytes);
+  for (var i=0; i<nBytes; i++) pwBytes[i] = password.charCodeAt(i) & 0xff;
+  var key = Cipher(pwBytes, KeyExpansion(pwBytes));
+  key = key.concat(key.slice(0, nBytes-16));  // key is now 16/24/32 bytes long
+
+  // initialise counter block (NIST SP800-38A §B.2): millisecond time-stamp for nonce in 1st 8 bytes,
+  // block counter in 2nd 8 bytes
+  var blockSize = 16;  // block size fixed at 16 bytes / 128 bits (Nb=4) for AES
+  var counterBlock = new Array(blockSize);  // block size fixed at 16 bytes / 128 bits (Nb=4) for AES
+  var nonce = (new Date()).getTime();  // milliseconds since 1-Jan-1970
+
+  // encode nonce in two stages to cater for JavaScript 32-bit limit on bitwise ops
+  for (var i=0; i<4; i++) counterBlock[i] = (nonce >>> i*8) & 0xff;
+  for (var i=0; i<4; i++) counterBlock[i+4] = (nonce/0x100000000 >>> i*8) & 0xff; 
+
+  // generate key schedule - an expansion of the key into distinct Key Rounds for each round
+  var keySchedule = KeyExpansion(key);
+
+  var blockCount = Math.ceil(plaintext.length/blockSize);
+  var ciphertext = new Array(blockCount);  // ciphertext as array of strings
+  
+  for (var b=0; b<blockCount; b++) {
+    // set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes)
+    // again done in two stages for 32-bit ops
+    for (var c=0; c<4; c++) counterBlock[15-c] = (b >>> c*8) & 0xff;
+    for (var c=0; c<4; c++) counterBlock[15-c-4] = (b/0x100000000 >>> c*8)
+
+    var cipherCntr = Cipher(counterBlock, keySchedule);  // -- encrypt counter block --
+    
+    // calculate length of final block:
+    var blockLength = b<blockCount-1 ? blockSize : (plaintext.length-1)%blockSize+1;
+
+    var ct = '';
+    for (var i=0; i<blockLength; i++) {  // -- xor plaintext with ciphered counter byte-by-byte --
+      var plaintextByte = plaintext.charCodeAt(b*blockSize+i);
+      var cipherByte = plaintextByte ^ cipherCntr[i];
+      ct += String.fromCharCode(cipherByte);
+    }
+    // ct is now ciphertext for this block
+
+    ciphertext[b] = escCtrlChars(ct);  // escape troublesome characters in ciphertext
+  }
+
+  // convert the nonce to a string to go on the front of the ciphertext
+  var ctrTxt = '';
+  for (var i=0; i<8; i++) ctrTxt += String.fromCharCode(counterBlock[i]);
+  ctrTxt = escCtrlChars(ctrTxt);
+
+  // use '-' to separate blocks, use Array.join to concatenate arrays of strings for efficiency
+  return ctrTxt + '-' + ciphertext.join('-');
+}
+
+
+/* 
+ * Use AES to decrypt 'ciphertext' with 'password' using 'nBits' key, in Counter mode of operation
+ *
+ *   for each block
+ *   - outputblock = cipher(counter, key)
+ *   - cipherblock = plaintext xor outputblock
+ */
+function AESDecryptCtr(ciphertext, password, nBits) {
+  if (!(nBits==128 || nBits==192 || nBits==256)) return '';  // standard allows 128/192/256 bit keys
+
+  var nBytes = nBits/8;  // no bytes in key
+  var pwBytes = new Array(nBytes);
+  for (var i=0; i<nBytes; i++) pwBytes[i] = password.charCodeAt(i) & 0xff;
+  var pwKeySchedule = KeyExpansion(pwBytes);
+  var key = Cipher(pwBytes, pwKeySchedule);
+  key = key.concat(key.slice(0, nBytes-16));  // key is now 16/24/32 bytes long
+
+  var keySchedule = KeyExpansion(key);
+
+  ciphertext = ciphertext.split('-');  // split ciphertext into array of block-length strings 
+
+  // recover nonce from 1st element of ciphertext
+  var blockSize = 16;  // block size fixed at 16 bytes / 128 bits (Nb=4) for AES
+  var counterBlock = new Array(blockSize);
+  var ctrTxt = unescCtrlChars(ciphertext[0]);
+  for (var i=0; i<8; i++) counterBlock[i] = ctrTxt.charCodeAt(i);
+
+  var plaintext = new Array(ciphertext.length-1);
+
+  for (var b=1; b<ciphertext.length; b++) {
+    // set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes)
+    for (var c=0; c<4; c++) counterBlock[15-c] = ((b-1) >>> c*8) & 0xff;
+    for (var c=0; c<4; c++) counterBlock[15-c-4] = ((b/0x100000000-1) >>> c*8) & 0xff;
+
+    var cipherCntr = Cipher(counterBlock, keySchedule);  // encrypt counter block
+
+    ciphertext[b] = unescCtrlChars(ciphertext[b]);
+
+    var pt = '';
+    for (var i=0; i<ciphertext[b].length; i++) {
+      // -- xor plaintext with ciphered counter byte-by-byte --
+      var ciphertextByte = ciphertext[b].charCodeAt(i);
+      var plaintextByte = ciphertextByte ^ cipherCntr[i];
+      pt += String.fromCharCode(plaintextByte);
+    }
+    // pt is now plaintext for this block
+
+    plaintext[b-1] = pt;  // b-1 'cos no initial nonce block in plaintext
+  }
+
+  return plaintext.join('');
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
+
+function escCtrlChars(str) {  // escape control chars which might cause problems handling ciphertext
+  return str.replace(/[\0\t\n\v\f\r\xa0'"!-]/g, function(c) { return '!' + c.charCodeAt(0) + '!'; });
+}  // \xa0 to cater for bug in Firefox; include '-' to leave it free for use as a block marker
+
+function unescCtrlChars(str) {  // unescape potentially problematic control characters
+  return str.replace(/!\d\d?\d?!/g, function(c) { return String.fromCharCode(c.slice(1,-1)); });
+}
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
+
+/*
+ * if escCtrlChars()/unescCtrlChars() still gives problems, use encodeBase64()/decodeBase64() instead
+ */
+var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
+
+function encodeBase64(str) {  // http://tools.ietf.org/html/rfc4648
+   var o1, o2, o3, h1, h2, h3, h4, bits, i=0, enc='';
+   
+   str = encodeUTF8(str);  // encode multi-byte chars into UTF-8 for byte-array
+
+   do {  // pack three octets into four hexets
+      o1 = str.charCodeAt(i++);
+      o2 = str.charCodeAt(i++);
+      o3 = str.charCodeAt(i++);
+      
+      bits = o1<<16 | o2<<8 | o3;
+      
+      h1 = bits>>18 & 0x3f;
+      h2 = bits>>12 & 0x3f;
+      h3 = bits>>6 & 0x3f;
+      h4 = bits & 0x3f;
+      
+      // end of string? index to '=' in b64
+      if (isNaN(o3)) h4 = 64;
+      if (isNaN(o2)) h3 = 64;
+      
+      // use hexets to index into b64, and append result to encoded string
+      enc += b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4);
+   } while (i < str.length);
+   
+   return enc;
+}
+
+function decodeBase64(str) {
+   var o1, o2, o3, h1, h2, h3, h4, bits, i=0, enc='';
+
+   do {  // unpack four hexets into three octets using index points in b64
+      h1 = b64.indexOf(str.charAt(i++));
+      h2 = b64.indexOf(str.charAt(i++));
+      h3 = b64.indexOf(str.charAt(i++));
+      h4 = b64.indexOf(str.charAt(i++));
+      
+      bits = h1<<18 | h2<<12 | h3<<6 | h4;
+      
+      o1 = bits>>16 & 0xff;
+      o2 = bits>>8 & 0xff;
+      o3 = bits & 0xff;
+      
+      if (h3 == 64)      enc += String.fromCharCode(o1);
+      else if (h4 == 64) enc += String.fromCharCode(o1, o2);
+      else               enc += String.fromCharCode(o1, o2, o3);
+   } while (i < str.length);
+
+   return decodeUTF8(enc);  // decode UTF-8 byte-array back to Unicode
+}
+
+function encodeUTF8(str) {  // encode multi-byte string into utf-8 multiple single-byte characters 
+  str = str.replace(
+      /[\u0080-\u07ff]/g,  // U+0080 - U+07FF = 2-byte chars
+      function(c) { 
+        var cc = c.charCodeAt(0);
+        return String.fromCharCode(0xc0 | cc>>6, 0x80 | cc&0x3f); }
+    );
+  str = str.replace(
+      /[\u0800-\uffff]/g,  // U+0800 - U+FFFF = 3-byte chars
+      function(c) { 
+        var cc = c.charCodeAt(0); 
+        return String.fromCharCode(0xe0 | cc>>12, 0x80 | cc>>6&0x3F, 0x80 | cc&0x3f); }
+    );
+  return str;
+}
+
+function decodeUTF8(str) {  // decode utf-8 encoded string back into multi-byte characters
+  str = str.replace(
+      /[\u00c0-\u00df][\u0080-\u00bf]/g,                 // 2-byte chars
+      function(c) { 
+        var cc = (c.charCodeAt(0)&0x1f)<<6 | c.charCodeAt(1)&0x3f;
+        return String.fromCharCode(cc); }
+    );
+  str = str.replace(
+      /[\u00e0-\u00ef][\u0080-\u00bf][\u0080-\u00bf]/g,  // 3-byte chars
+      function(c) { 
+        var cc = (c.charCodeAt(0)&0x0f)<<12 | (c.charCodeAt(1)&0x3f<<6) | c.charCodeAt(2)&0x3f; 
+        return String.fromCharCode(cc); }
+    );
+  return str;
+}
+
+
+function byteArrayToHexStr(b) {  // convert byte array to hex string for displaying test vectors
+  var s = '';
+  for (var i=0; i<b.length; i++) s += b[i].toString(16) + ' ';
+  return s;
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
+
+
+var plainText = "ROMEO: But, soft! what light through yonder window breaks?\n\
+It is the east, and Juliet is the sun.\n\
+Arise, fair sun, and kill the envious moon,\n\
+Who is already sick and pale with grief,\n\
+That thou her maid art far more fair than she:\n\
+Be not her maid, since she is envious;\n\
+Her vestal livery is but sick and green\n\
+And none but fools do wear it; cast it off.\n\
+It is my lady, O, it is my love!\n\
+O, that she knew she were!\n\
+She speaks yet she says nothing: what of that?\n\
+Her eye discourses; I will answer it.\n\
+I am too bold, 'tis not to me she speaks:\n\
+Two of the fairest stars in all the heaven,\n\
+Having some business, do entreat her eyes\n\
+To twinkle in their spheres till they return.\n\
+What if her eyes were there, they in her head?\n\
+The brightness of her cheek would shame those stars,\n\
+As daylight doth a lamp; her eyes in heaven\n\
+Would through the airy region stream so bright\n\
+That birds would sing and think it were not night.\n\
+See, how she leans her cheek upon her hand!\n\
+O, that I were a glove upon that hand,\n\
+That I might touch that cheek!\n\
+JULIET: Ay me!\n\
+ROMEO: She speaks:\n\
+O, speak again, bright angel! for thou art\n\
+As glorious to this night, being o'er my head\n\
+As is a winged messenger of heaven\n\
+Unto the white-upturned wondering eyes\n\
+Of mortals that fall back to gaze on him\n\
+When he bestrides the lazy-pacing clouds\n\
+And sails upon the bosom of the air.";
+
+var password = "O Romeo, Romeo! wherefore art thou Romeo?";
+
+var cipherText = AESEncryptCtr(plainText, password, 256);
+var decryptedText = AESDecryptCtr(cipherText, password, 256);
+
+
+var _sunSpiderInterval = new Date() - _sunSpiderStartDate;
+
+document.getElementById("console").innerHTML = _sunSpiderInterval;
+</script>
+
+
+</body>
+</html>
diff --git a/src/third_party/mozjs-45/build/pgo/js-input/sunspider/crypto-md5.html b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/crypto-md5.html
new file mode 100644
index 0000000..8395107
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/crypto-md5.html
@@ -0,0 +1,336 @@
+<!DOCTYPE html>
+<head>
+<!--
+ Copyright (C) 2007 Apple Inc.  All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+-->
+
+<title>SunSpider crypto-md5</title>
+
+</head>
+
+<body>
+<h3>crypto-md5</h3>
+<div id="console">
+</div>
+
+<script>
+
+var _sunSpiderStartDate = new Date();
+
+/*
+ * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
+ * Digest Algorithm, as defined in RFC 1321.
+ * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
+ * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
+ * Distributed under the BSD License
+ * See http://pajhome.org.uk/crypt/md5 for more info.
+ */
+
+/*
+ * Configurable variables. You may need to tweak these to be compatible with
+ * the server-side, but the defaults work in most cases.
+ */
+var hexcase = 0;  /* hex output format. 0 - lowercase; 1 - uppercase        */
+var b64pad  = ""; /* base-64 pad character. "=" for strict RFC compliance   */
+var chrsz   = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode      */
+
+/*
+ * These are the functions you'll usually want to call
+ * They take string arguments and return either hex or base-64 encoded strings
+ */
+function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));}
+function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));}
+function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));}
+function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); }
+function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); }
+function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); }
+
+/*
+ * Perform a simple self-test to see if the VM is working
+ */
+function md5_vm_test()
+{
+  return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72";
+}
+
+/*
+ * Calculate the MD5 of an array of little-endian words, and a bit length
+ */
+function core_md5(x, len)
+{
+  /* append padding */
+  x[len >> 5] |= 0x80 << ((len) % 32);
+  x[(((len + 64) >>> 9) << 4) + 14] = len;
+
+  var a =  1732584193;
+  var b = -271733879;
+  var c = -1732584194;
+  var d =  271733878;
+
+  for(var i = 0; i < x.length; i += 16)
+  {
+    var olda = a;
+    var oldb = b;
+    var oldc = c;
+    var oldd = d;
+
+    a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
+    d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
+    c = md5_ff(c, d, a, b, x[i+ 2], 17,  606105819);
+    b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
+    a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
+    d = md5_ff(d, a, b, c, x[i+ 5], 12,  1200080426);
+    c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
+    b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
+    a = md5_ff(a, b, c, d, x[i+ 8], 7 ,  1770035416);
+    d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
+    c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
+    b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
+    a = md5_ff(a, b, c, d, x[i+12], 7 ,  1804603682);
+    d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
+    c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
+    b = md5_ff(b, c, d, a, x[i+15], 22,  1236535329);
+
+    a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
+    d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
+    c = md5_gg(c, d, a, b, x[i+11], 14,  643717713);
+    b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
+    a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
+    d = md5_gg(d, a, b, c, x[i+10], 9 ,  38016083);
+    c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
+    b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
+    a = md5_gg(a, b, c, d, x[i+ 9], 5 ,  568446438);
+    d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
+    c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
+    b = md5_gg(b, c, d, a, x[i+ 8], 20,  1163531501);
+    a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
+    d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
+    c = md5_gg(c, d, a, b, x[i+ 7], 14,  1735328473);
+    b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
+
+    a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
+    d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
+    c = md5_hh(c, d, a, b, x[i+11], 16,  1839030562);
+    b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
+    a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
+    d = md5_hh(d, a, b, c, x[i+ 4], 11,  1272893353);
+    c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
+    b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
+    a = md5_hh(a, b, c, d, x[i+13], 4 ,  681279174);
+    d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
+    c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
+    b = md5_hh(b, c, d, a, x[i+ 6], 23,  76029189);
+    a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
+    d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
+    c = md5_hh(c, d, a, b, x[i+15], 16,  530742520);
+    b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
+
+    a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
+    d = md5_ii(d, a, b, c, x[i+ 7], 10,  1126891415);
+    c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
+    b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
+    a = md5_ii(a, b, c, d, x[i+12], 6 ,  1700485571);
+    d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
+    c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
+    b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
+    a = md5_ii(a, b, c, d, x[i+ 8], 6 ,  1873313359);
+    d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
+    c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
+    b = md5_ii(b, c, d, a, x[i+13], 21,  1309151649);
+    a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
+    d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
+    c = md5_ii(c, d, a, b, x[i+ 2], 15,  718787259);
+    b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
+
+    a = safe_add(a, olda);
+    b = safe_add(b, oldb);
+    c = safe_add(c, oldc);
+    d = safe_add(d, oldd);
+  }
+  return Array(a, b, c, d);
+
+}
+
+/*
+ * These functions implement the four basic operations the algorithm uses.
+ */
+function md5_cmn(q, a, b, x, s, t)
+{
+  return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
+}
+function md5_ff(a, b, c, d, x, s, t)
+{
+  return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
+}
+function md5_gg(a, b, c, d, x, s, t)
+{
+  return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
+}
+function md5_hh(a, b, c, d, x, s, t)
+{
+  return md5_cmn(b ^ c ^ d, a, b, x, s, t);
+}
+function md5_ii(a, b, c, d, x, s, t)
+{
+  return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
+}
+
+/*
+ * Calculate the HMAC-MD5, of a key and some data
+ */
+function core_hmac_md5(key, data)
+{
+  var bkey = str2binl(key);
+  if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz);
+
+  var ipad = Array(16), opad = Array(16);
+  for(var i = 0; i < 16; i++)
+  {
+    ipad[i] = bkey[i] ^ 0x36363636;
+    opad[i] = bkey[i] ^ 0x5C5C5C5C;
+  }
+
+  var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz);
+  return core_md5(opad.concat(hash), 512 + 128);
+}
+
+/*
+ * Add integers, wrapping at 2^32. This uses 16-bit operations internally
+ * to work around bugs in some JS interpreters.
+ */
+function safe_add(x, y)
+{
+  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
+  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
+  return (msw << 16) | (lsw & 0xFFFF);
+}
+
+/*
+ * Bitwise rotate a 32-bit number to the left.
+ */
+function bit_rol(num, cnt)
+{
+  return (num << cnt) | (num >>> (32 - cnt));
+}
+
+/*
+ * Convert a string to an array of little-endian words
+ * If chrsz is ASCII, characters >255 have their hi-byte silently ignored.
+ */
+function str2binl(str)
+{
+  var bin = Array();
+  var mask = (1 << chrsz) - 1;
+  for(var i = 0; i < str.length * chrsz; i += chrsz)
+    bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
+  return bin;
+}
+
+/*
+ * Convert an array of little-endian words to a string
+ */
+function binl2str(bin)
+{
+  var str = "";
+  var mask = (1 << chrsz) - 1;
+  for(var i = 0; i < bin.length * 32; i += chrsz)
+    str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask);
+  return str;
+}
+
+/*
+ * Convert an array of little-endian words to a hex string.
+ */
+function binl2hex(binarray)
+{
+  var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
+  var str = "";
+  for(var i = 0; i < binarray.length * 4; i++)
+  {
+    str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
+           hex_tab.charAt((binarray[i>>2] >> ((i%4)*8  )) & 0xF);
+  }
+  return str;
+}
+
+/*
+ * Convert an array of little-endian words to a base-64 string
+ */
+function binl2b64(binarray)
+{
+  var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+  var str = "";
+  for(var i = 0; i < binarray.length * 4; i += 3)
+  {
+    var triplet = (((binarray[i   >> 2] >> 8 * ( i   %4)) & 0xFF) << 16)
+                | (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 )
+                |  ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF);
+    for(var j = 0; j < 4; j++)
+    {
+      if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
+      else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
+    }
+  }
+  return str;
+}
+
+var plainText = "Rebellious subjects, enemies to peace,\n\
+Profaners of this neighbour-stained steel,--\n\
+Will they not hear? What, ho! you men, you beasts,\n\
+That quench the fire of your pernicious rage\n\
+With purple fountains issuing from your veins,\n\
+On pain of torture, from those bloody hands\n\
+Throw your mistemper'd weapons to the ground,\n\
+And hear the sentence of your moved prince.\n\
+Three civil brawls, bred of an airy word,\n\
+By thee, old Capulet, and Montague,\n\
+Have thrice disturb'd the quiet of our streets,\n\
+And made Verona's ancient citizens\n\
+Cast by their grave beseeming ornaments,\n\
+To wield old partisans, in hands as old,\n\
+Canker'd with peace, to part your canker'd hate:\n\
+If ever you disturb our streets again,\n\
+Your lives shall pay the forfeit of the peace.\n\
+For this time, all the rest depart away:\n\
+You Capulet; shall go along with me:\n\
+And, Montague, come you this afternoon,\n\
+To know our further pleasure in this case,\n\
+To old Free-town, our common judgment-place.\n\
+Once more, on pain of death, all men depart."
+
+for (var i = 0; i <4; i++) {
+    plainText += plainText;
+}
+
+var md5Output = hex_md5(plainText);
+
+
+var _sunSpiderInterval = new Date() - _sunSpiderStartDate;
+
+document.getElementById("console").innerHTML = _sunSpiderInterval;
+</script>
+
+
+</body>
+</html>
diff --git a/src/third_party/mozjs-45/build/pgo/js-input/sunspider/crypto-sha1.html b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/crypto-sha1.html
new file mode 100644
index 0000000..01d0b56
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/crypto-sha1.html
@@ -0,0 +1,274 @@
+<!DOCTYPE html>
+<head>
+<!--
+ Copyright (C) 2007 Apple Inc.  All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+-->
+
+<title>SunSpider crypto-sha1</title>
+
+</head>
+
+<body>
+<h3>crypto-sha1</h3>
+<div id="console">
+</div>
+
+<script>
+
+var _sunSpiderStartDate = new Date();
+
+/*
+ * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
+ * in FIPS PUB 180-1
+ * Version 2.1a Copyright Paul Johnston 2000 - 2002.
+ * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
+ * Distributed under the BSD License
+ * See http://pajhome.org.uk/crypt/md5 for details.
+ */
+
+/*
+ * Configurable variables. You may need to tweak these to be compatible with
+ * the server-side, but the defaults work in most cases.
+ */
+var hexcase = 0;  /* hex output format. 0 - lowercase; 1 - uppercase        */
+var b64pad  = ""; /* base-64 pad character. "=" for strict RFC compliance   */
+var chrsz   = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode      */
+
+/*
+ * These are the functions you'll usually want to call
+ * They take string arguments and return either hex or base-64 encoded strings
+ */
+function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));}
+function b64_sha1(s){return binb2b64(core_sha1(str2binb(s),s.length * chrsz));}
+function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length * chrsz));}
+function hex_hmac_sha1(key, data){ return binb2hex(core_hmac_sha1(key, data));}
+function b64_hmac_sha1(key, data){ return binb2b64(core_hmac_sha1(key, data));}
+function str_hmac_sha1(key, data){ return binb2str(core_hmac_sha1(key, data));}
+
+/*
+ * Perform a simple self-test to see if the VM is working
+ */
+function sha1_vm_test()
+{
+  return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d";
+}
+
+/*
+ * Calculate the SHA-1 of an array of big-endian words, and a bit length
+ */
+function core_sha1(x, len)
+{
+  /* append padding */
+  x[len >> 5] |= 0x80 << (24 - len % 32);
+  x[((len + 64 >> 9) << 4) + 15] = len;
+
+  var w = Array(80);
+  var a =  1732584193;
+  var b = -271733879;
+  var c = -1732584194;
+  var d =  271733878;
+  var e = -1009589776;
+
+  for(var i = 0; i < x.length; i += 16)
+  {
+    var olda = a;
+    var oldb = b;
+    var oldc = c;
+    var oldd = d;
+    var olde = e;
+
+    for(var j = 0; j < 80; j++)
+    {
+      if(j < 16) w[j] = x[i + j];
+      else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
+      var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)),
+                       safe_add(safe_add(e, w[j]), sha1_kt(j)));
+      e = d;
+      d = c;
+      c = rol(b, 30);
+      b = a;
+      a = t;
+    }
+
+    a = safe_add(a, olda);
+    b = safe_add(b, oldb);
+    c = safe_add(c, oldc);
+    d = safe_add(d, oldd);
+    e = safe_add(e, olde);
+  }
+  return Array(a, b, c, d, e);
+
+}
+
+/*
+ * Perform the appropriate triplet combination function for the current
+ * iteration
+ */
+function sha1_ft(t, b, c, d)
+{
+  if(t < 20) return (b & c) | ((~b) & d);
+  if(t < 40) return b ^ c ^ d;
+  if(t < 60) return (b & c) | (b & d) | (c & d);
+  return b ^ c ^ d;
+}
+
+/*
+ * Determine the appropriate additive constant for the current iteration
+ */
+function sha1_kt(t)
+{
+  return (t < 20) ?  1518500249 : (t < 40) ?  1859775393 :
+         (t < 60) ? -1894007588 : -899497514;
+}
+
+/*
+ * Calculate the HMAC-SHA1 of a key and some data
+ */
+function core_hmac_sha1(key, data)
+{
+  var bkey = str2binb(key);
+  if(bkey.length > 16) bkey = core_sha1(bkey, key.length * chrsz);
+
+  var ipad = Array(16), opad = Array(16);
+  for(var i = 0; i < 16; i++)
+  {
+    ipad[i] = bkey[i] ^ 0x36363636;
+    opad[i] = bkey[i] ^ 0x5C5C5C5C;
+  }
+
+  var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz);
+  return core_sha1(opad.concat(hash), 512 + 160);
+}
+
+/*
+ * Add integers, wrapping at 2^32. This uses 16-bit operations internally
+ * to work around bugs in some JS interpreters.
+ */
+function safe_add(x, y)
+{
+  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
+  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
+  return (msw << 16) | (lsw & 0xFFFF);
+}
+
+/*
+ * Bitwise rotate a 32-bit number to the left.
+ */
+function rol(num, cnt)
+{
+  return (num << cnt) | (num >>> (32 - cnt));
+}
+
+/*
+ * Convert an 8-bit or 16-bit string to an array of big-endian words
+ * In 8-bit function, characters >255 have their hi-byte silently ignored.
+ */
+function str2binb(str)
+{
+  var bin = Array();
+  var mask = (1 << chrsz) - 1;
+  for(var i = 0; i < str.length * chrsz; i += chrsz)
+    bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32);
+  return bin;
+}
+
+/*
+ * Convert an array of big-endian words to a string
+ */
+function binb2str(bin)
+{
+  var str = "";
+  var mask = (1 << chrsz) - 1;
+  for(var i = 0; i < bin.length * 32; i += chrsz)
+    str += String.fromCharCode((bin[i>>5] >>> (32 - chrsz - i%32)) & mask);
+  return str;
+}
+
+/*
+ * Convert an array of big-endian words to a hex string.
+ */
+function binb2hex(binarray)
+{
+  var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
+  var str = "";
+  for(var i = 0; i < binarray.length * 4; i++)
+  {
+    str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) +
+           hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8  )) & 0xF);
+  }
+  return str;
+}
+
+/*
+ * Convert an array of big-endian words to a base-64 string
+ */
+function binb2b64(binarray)
+{
+  var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+  var str = "";
+  for(var i = 0; i < binarray.length * 4; i += 3)
+  {
+    var triplet = (((binarray[i   >> 2] >> 8 * (3 -  i   %4)) & 0xFF) << 16)
+                | (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 )
+                |  ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF);
+    for(var j = 0; j < 4; j++)
+    {
+      if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
+      else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
+    }
+  }
+  return str;
+}
+
+
+var plainText = "Two households, both alike in dignity,\n\
+In fair Verona, where we lay our scene,\n\
+From ancient grudge break to new mutiny,\n\
+Where civil blood makes civil hands unclean.\n\
+From forth the fatal loins of these two foes\n\
+A pair of star-cross'd lovers take their life;\n\
+Whole misadventured piteous overthrows\n\
+Do with their death bury their parents' strife.\n\
+The fearful passage of their death-mark'd love,\n\
+And the continuance of their parents' rage,\n\
+Which, but their children's end, nought could remove,\n\
+Is now the two hours' traffic of our stage;\n\
+The which if you with patient ears attend,\n\
+What here shall miss, our toil shall strive to mend.";
+
+for (var i = 0; i <4; i++) {
+    plainText += plainText;
+}
+
+var sha1Output = hex_sha1(plainText);
+
+
+var _sunSpiderInterval = new Date() - _sunSpiderStartDate;
+
+document.getElementById("console").innerHTML = _sunSpiderInterval;
+</script>
+
+
+</body>
+</html>
diff --git a/src/third_party/mozjs-45/build/pgo/js-input/sunspider/date-format-tofte.html b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/date-format-tofte.html
new file mode 100644
index 0000000..b8e4773
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/date-format-tofte.html
@@ -0,0 +1,349 @@
+<!DOCTYPE html>
+<head>
+<!--
+ Copyright (C) 2007 Apple Inc.  All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+-->
+
+<title>SunSpider date-format-tofte</title>
+
+</head>
+
+<body>
+<h3>date-format-tofte</h3>
+<div id="console">
+</div>
+
+<script>
+
+var _sunSpiderStartDate = new Date();
+
+function arrayExists(array, x) {
+    for (var i = 0; i < array.length; i++) {
+        if (array[i] == x) return true;
+    }
+    return false;
+}
+
+Date.prototype.formatDate = function (input,time) {
+    // formatDate :
+    // a PHP date like function, for formatting date strings
+    // See: http://www.php.net/date
+    //
+    // input : format string
+    // time : epoch time (seconds, and optional)
+    //
+    // if time is not passed, formatting is based on 
+    // the current "this" date object's set time.
+    //
+    // supported:
+    // a, A, B, d, D, F, g, G, h, H, i, j, l (lowercase L), L, 
+    // m, M, n, O, r, s, S, t, U, w, W, y, Y, z
+    //
+    // unsupported:
+    // I (capital i), T, Z    
+
+    var switches =    ["a", "A", "B", "d", "D", "F", "g", "G", "h", "H", 
+                       "i", "j", "l", "L", "m", "M", "n", "O", "r", "s", 
+                       "S", "t", "U", "w", "W", "y", "Y", "z"];
+    var daysLong =    ["Sunday", "Monday", "Tuesday", "Wednesday", 
+                       "Thursday", "Friday", "Saturday"];
+    var daysShort =   ["Sun", "Mon", "Tue", "Wed", 
+                       "Thu", "Fri", "Sat"];
+    var monthsShort = ["Jan", "Feb", "Mar", "Apr",
+                       "May", "Jun", "Jul", "Aug", "Sep",
+                       "Oct", "Nov", "Dec"];
+    var monthsLong =  ["January", "February", "March", "April",
+                       "May", "June", "July", "August", "September",
+                       "October", "November", "December"];
+    var daysSuffix = ["st", "nd", "rd", "th", "th", "th", "th", // 1st - 7th
+                      "th", "th", "th", "th", "th", "th", "th", // 8th - 14th
+                      "th", "th", "th", "th", "th", "th", "st", // 15th - 21st
+                      "nd", "rd", "th", "th", "th", "th", "th", // 22nd - 28th
+                      "th", "th", "st"];                        // 29th - 31st
+
+    function a() {
+        // Lowercase Ante meridiem and Post meridiem
+        return self.getHours() > 11? "pm" : "am";
+    }
+    function A() {
+        // Uppercase Ante meridiem and Post meridiem
+        return self.getHours() > 11? "PM" : "AM";
+    }
+
+    function B(){
+        // Swatch internet time. code simply grabbed from ppk,
+        // since I was feeling lazy:
+        // http://www.xs4all.nl/~ppk/js/beat.html
+        var off = (self.getTimezoneOffset() + 60)*60;
+        var theSeconds = (self.getHours() * 3600) + 
+                         (self.getMinutes() * 60) + 
+                          self.getSeconds() + off;
+        var beat = Math.floor(theSeconds/86.4);
+        if (beat > 1000) beat -= 1000;
+        if (beat < 0) beat += 1000;
+        if ((""+beat).length == 1) beat = "00"+beat;
+        if ((""+beat).length == 2) beat = "0"+beat;
+        return beat;
+    }
+    
+    function d() {
+        // Day of the month, 2 digits with leading zeros
+        return new String(self.getDate()).length == 1?
+        "0"+self.getDate() : self.getDate();
+    }
+    function D() {
+        // A textual representation of a day, three letters
+        return daysShort[self.getDay()];
+    }
+    function F() {
+        // A full textual representation of a month
+        return monthsLong[self.getMonth()];
+    }
+    function g() {
+        // 12-hour format of an hour without leading zeros
+        return self.getHours() > 12? self.getHours()-12 : self.getHours();
+    }
+    function G() {
+        // 24-hour format of an hour without leading zeros
+        return self.getHours();
+    }
+    function h() {
+        // 12-hour format of an hour with leading zeros
+        if (self.getHours() > 12) {
+          var s = new String(self.getHours()-12);
+          return s.length == 1?
+          "0"+ (self.getHours()-12) : self.getHours()-12;
+        } else { 
+          var s = new String(self.getHours());
+          return s.length == 1?
+          "0"+self.getHours() : self.getHours();
+        }  
+    }
+    function H() {
+        // 24-hour format of an hour with leading zeros
+        return new String(self.getHours()).length == 1?
+        "0"+self.getHours() : self.getHours();
+    }
+    function i() {
+        // Minutes with leading zeros
+        return new String(self.getMinutes()).length == 1? 
+        "0"+self.getMinutes() : self.getMinutes(); 
+    }
+    function j() {
+        // Day of the month without leading zeros
+        return self.getDate();
+    }    
+    function l() {
+        // A full textual representation of the day of the week
+        return daysLong[self.getDay()];
+    }
+    function L() {
+        // leap year or not. 1 if leap year, 0 if not.
+        // the logic should match iso's 8601 standard.
+        var y_ = Y();
+        if (         
+            (y_ % 4 == 0 && y_ % 100 != 0) ||
+            (y_ % 4 == 0 && y_ % 100 == 0 && y_ % 400 == 0)
+            ) {
+            return 1;
+        } else {
+            return 0;
+        }
+    }
+    function m() {
+        // Numeric representation of a month, with leading zeros
+        return self.getMonth() < 9?
+        "0"+(self.getMonth()+1) : 
+        self.getMonth()+1;
+    }
+    function M() {
+        // A short textual representation of a month, three letters
+        return monthsShort[self.getMonth()];
+    }
+    function n() {
+        // Numeric representation of a month, without leading zeros
+        return self.getMonth()+1;
+    }
+    function O() {
+        // Difference to Greenwich time (GMT) in hours
+        var os = Math.abs(self.getTimezoneOffset());
+        var h = ""+Math.floor(os/60);
+        var m = ""+(os%60);
+        h.length == 1? h = "0"+h:1;
+        m.length == 1? m = "0"+m:1;
+        return self.getTimezoneOffset() < 0 ? "+"+h+m : "-"+h+m;
+    }
+    function r() {
+        // RFC 822 formatted date
+        var r; // result
+        //  Thu    ,     21          Dec         2000
+        r = D() + ", " + j() + " " + M() + " " + Y() +
+        //        16     :    01     :    07          +0200
+            " " + H() + ":" + i() + ":" + s() + " " + O();
+        return r;
+    }
+    function S() {
+        // English ordinal suffix for the day of the month, 2 characters
+        return daysSuffix[self.getDate()-1];
+    }
+    function s() {
+        // Seconds, with leading zeros
+        return new String(self.getSeconds()).length == 1?
+        "0"+self.getSeconds() : self.getSeconds();
+    }
+    function t() {
+
+        // thanks to Matt Bannon for some much needed code-fixes here!
+        var daysinmonths = [null,31,28,31,30,31,30,31,31,30,31,30,31];
+        if (L()==1 && n()==2) return 29; // leap day
+        return daysinmonths[n()];
+    }
+    function U() {
+        // Seconds since the Unix Epoch (January 1 1970 00:00:00 GMT)
+        return Math.round(self.getTime()/1000);
+    }
+    function W() {
+        // Weeknumber, as per ISO specification:
+        // http://www.cl.cam.ac.uk/~mgk25/iso-time.html
+        
+        // if the day is three days before newyears eve,
+        // there's a chance it's "week 1" of next year.
+        // here we check for that.
+        var beforeNY = 364+L() - z();
+        var afterNY  = z();
+        var weekday = w()!=0?w()-1:6; // makes sunday (0), into 6.
+        if (beforeNY <= 2 && weekday <= 2-beforeNY) {
+            return 1;
+        }
+        // similarly, if the day is within threedays of newyears
+        // there's a chance it belongs in the old year.
+        var ny = new Date("January 1 " + Y() + " 00:00:00");
+        var nyDay = ny.getDay()!=0?ny.getDay()-1:6;
+        if (
+            (afterNY <= 2) && 
+            (nyDay >=4)  && 
+            (afterNY >= (6-nyDay))
+            ) {
+            // Since I'm not sure we can just always return 53,
+            // i call the function here again, using the last day
+            // of the previous year, as the date, and then just
+            // return that week.
+            var prevNY = new Date("December 31 " + (Y()-1) + " 00:00:00");
+            return prevNY.formatDate("W");
+        }
+        
+        // week 1, is the week that has the first thursday in it.
+        // note that this value is not zero index.
+        if (nyDay <= 3) {
+            // first day of the year fell on a thursday, or earlier.
+            return 1 + Math.floor( ( z() + nyDay ) / 7 );
+        } else {
+            // first day of the year fell on a friday, or later.
+            return 1 + Math.floor( ( z() - ( 7 - nyDay ) ) / 7 );
+        }
+    }
+    function w() {
+        // Numeric representation of the day of the week
+        return self.getDay();
+    }
+    
+    function Y() {
+        // A full numeric representation of a year, 4 digits
+
+        // we first check, if getFullYear is supported. if it
+        // is, we just use that. ppks code is nice, but wont
+        // work with dates outside 1900-2038, or something like that
+        if (self.getFullYear) {
+            var newDate = new Date("January 1 2001 00:00:00 +0000");
+            var x = newDate .getFullYear();
+            if (x == 2001) {              
+                // i trust the method now
+                return self.getFullYear();
+            }
+        }
+        // else, do this:
+        // codes thanks to ppk:
+        // http://www.xs4all.nl/~ppk/js/introdate.html
+        var x = self.getYear();
+        var y = x % 100;
+        y += (y < 38) ? 2000 : 1900;
+        return y;
+    }
+    function y() {
+        // A two-digit representation of a year
+        var y = Y()+"";
+        return y.substring(y.length-2,y.length);
+    }
+    function z() {
+        // The day of the year, zero indexed! 0 through 366
+        var t = new Date("January 1 " + Y() + " 00:00:00");
+        var diff = self.getTime() - t.getTime();
+        return Math.floor(diff/1000/60/60/24);
+    }
+        
+    var self = this;
+    if (time) {
+        // save time
+        var prevTime = self.getTime();
+        self.setTime(time);
+    }
+    
+    var ia = input.split("");
+    var ij = 0;
+    while (ia[ij]) {
+        if (ia[ij] == "\\") {
+            // this is our way of allowing users to escape stuff
+            ia.splice(ij,1);
+        } else {
+            if (arrayExists(switches,ia[ij])) {
+                ia[ij] = eval(ia[ij] + "()");
+            }
+        }
+        ij++;
+    }
+    // reset time, back to what it was
+    if (prevTime) {
+        self.setTime(prevTime);
+    }
+    return ia.join("");
+}
+
+var date = new Date("1/1/2007 1:11:11");
+
+for (i = 0; i < 500; ++i) {
+    var shortFormat = date.formatDate("Y-m-d");
+    var longFormat = date.formatDate("l, F d, Y g:i:s A");
+    date.setTime(date.getTime() + 84266956);
+}
+
+
+
+var _sunSpiderInterval = new Date() - _sunSpiderStartDate;
+
+document.getElementById("console").innerHTML = _sunSpiderInterval;
+</script>
+
+
+</body>
+</html>
diff --git a/src/third_party/mozjs-45/build/pgo/js-input/sunspider/date-format-xparb.html b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/date-format-xparb.html
new file mode 100644
index 0000000..dd35713
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/date-format-xparb.html
@@ -0,0 +1,467 @@
+<!DOCTYPE html>
+<head>
+<!--
+ Copyright (C) 2007 Apple Inc.  All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+-->
+
+<title>SunSpider date-format-xparb</title>
+
+</head>
+
+<body>
+<h3>date-format-xparb</h3>
+<div id="console">
+</div>
+
+<script>
+
+var _sunSpiderStartDate = new Date();
+
+/*
+ * Copyright (C) 2004 Baron Schwartz <baron at sequent dot org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation, version 2.1.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+ * details.
+ */
+
+Date.parseFunctions = {count:0};
+Date.parseRegexes = [];
+Date.formatFunctions = {count:0};
+
+Date.prototype.dateFormat = function(format) {
+    if (Date.formatFunctions[format] == null) {
+        Date.createNewFormat(format);
+    }
+    var func = Date.formatFunctions[format];
+    return this[func]();
+}
+
+Date.createNewFormat = function(format) {
+    var funcName = "format" + Date.formatFunctions.count++;
+    Date.formatFunctions[format] = funcName;
+    var code = "Date.prototype." + funcName + " = function(){return ";
+    var special = false;
+    var ch = '';
+    for (var i = 0; i < format.length; ++i) {
+        ch = format.charAt(i);
+        if (!special && ch == "\\") {
+            special = true;
+        }
+        else if (special) {
+            special = false;
+            code += "'" + String.escape(ch) + "' + ";
+        }
+        else {
+            code += Date.getFormatCode(ch);
+        }
+    }
+    eval(code.substring(0, code.length - 3) + ";}");
+}
+
+Date.getFormatCode = function(character) {
+    switch (character) {
+    case "d":
+        return "String.leftPad(this.getDate(), 2, '0') + ";
+    case "D":
+        return "Date.dayNames[this.getDay()].substring(0, 3) + ";
+    case "j":
+        return "this.getDate() + ";
+    case "l":
+        return "Date.dayNames[this.getDay()] + ";
+    case "S":
+        return "this.getSuffix() + ";
+    case "w":
+        return "this.getDay() + ";
+    case "z":
+        return "this.getDayOfYear() + ";
+    case "W":
+        return "this.getWeekOfYear() + ";
+    case "F":
+        return "Date.monthNames[this.getMonth()] + ";
+    case "m":
+        return "String.leftPad(this.getMonth() + 1, 2, '0') + ";
+    case "M":
+        return "Date.monthNames[this.getMonth()].substring(0, 3) + ";
+    case "n":
+        return "(this.getMonth() + 1) + ";
+    case "t":
+        return "this.getDaysInMonth() + ";
+    case "L":
+        return "(this.isLeapYear() ? 1 : 0) + ";
+    case "Y":
+        return "this.getFullYear() + ";
+    case "y":
+        return "('' + this.getFullYear()).substring(2, 4) + ";
+    case "a":
+        return "(this.getHours() < 12 ? 'am' : 'pm') + ";
+    case "A":
+        return "(this.getHours() < 12 ? 'AM' : 'PM') + ";
+    case "g":
+        return "((this.getHours() %12) ? this.getHours() % 12 : 12) + ";
+    case "G":
+        return "this.getHours() + ";
+    case "h":
+        return "String.leftPad((this.getHours() %12) ? this.getHours() % 12 : 12, 2, '0') + ";
+    case "H":
+        return "String.leftPad(this.getHours(), 2, '0') + ";
+    case "i":
+        return "String.leftPad(this.getMinutes(), 2, '0') + ";
+    case "s":
+        return "String.leftPad(this.getSeconds(), 2, '0') + ";
+    case "O":
+        return "this.getGMTOffset() + ";
+    case "T":
+        return "this.getTimezone() + ";
+    case "Z":
+        return "(this.getTimezoneOffset() * -60) + ";
+    default:
+        return "'" + String.escape(character) + "' + ";
+    }
+}
+
+Date.parseDate = function(input, format) {
+    if (Date.parseFunctions[format] == null) {
+        Date.createParser(format);
+    }
+    var func = Date.parseFunctions[format];
+    return Date[func](input);
+}
+
+Date.createParser = function(format) {
+    var funcName = "parse" + Date.parseFunctions.count++;
+    var regexNum = Date.parseRegexes.length;
+    var currentGroup = 1;
+    Date.parseFunctions[format] = funcName;
+
+    var code = "Date." + funcName + " = function(input){\n"
+        + "var y = -1, m = -1, d = -1, h = -1, i = -1, s = -1;\n"
+        + "var d = new Date();\n"
+        + "y = d.getFullYear();\n"
+        + "m = d.getMonth();\n"
+        + "d = d.getDate();\n"
+        + "var results = input.match(Date.parseRegexes[" + regexNum + "]);\n"
+        + "if (results && results.length > 0) {"
+    var regex = "";
+
+    var special = false;
+    var ch = '';
+    for (var i = 0; i < format.length; ++i) {
+        ch = format.charAt(i);
+        if (!special && ch == "\\") {
+            special = true;
+        }
+        else if (special) {
+            special = false;
+            regex += String.escape(ch);
+        }
+        else {
+            obj = Date.formatCodeToRegex(ch, currentGroup);
+            currentGroup += obj.g;
+            regex += obj.s;
+            if (obj.g && obj.c) {
+                code += obj.c;
+            }
+        }
+    }
+
+    code += "if (y > 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0)\n"
+        + "{return new Date(y, m, d, h, i, s);}\n"
+        + "else if (y > 0 && m >= 0 && d > 0 && h >= 0 && i >= 0)\n"
+        + "{return new Date(y, m, d, h, i);}\n"
+        + "else if (y > 0 && m >= 0 && d > 0 && h >= 0)\n"
+        + "{return new Date(y, m, d, h);}\n"
+        + "else if (y > 0 && m >= 0 && d > 0)\n"
+        + "{return new Date(y, m, d);}\n"
+        + "else if (y > 0 && m >= 0)\n"
+        + "{return new Date(y, m);}\n"
+        + "else if (y > 0)\n"
+        + "{return new Date(y);}\n"
+        + "}return null;}";
+
+    Date.parseRegexes[regexNum] = new RegExp("^" + regex + "$");
+    eval(code);
+}
+
+Date.formatCodeToRegex = function(character, currentGroup) {
+    switch (character) {
+    case "D":
+        return {g:0,
+        c:null,
+        s:"(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)"};
+    case "j":
+    case "d":
+        return {g:1,
+            c:"d = parseInt(results[" + currentGroup + "], 10);\n",
+            s:"(\\d{1,2})"};
+    case "l":
+        return {g:0,
+            c:null,
+            s:"(?:" + Date.dayNames.join("|") + ")"};
+    case "S":
+        return {g:0,
+            c:null,
+            s:"(?:st|nd|rd|th)"};
+    case "w":
+        return {g:0,
+            c:null,
+            s:"\\d"};
+    case "z":
+        return {g:0,
+            c:null,
+            s:"(?:\\d{1,3})"};
+    case "W":
+        return {g:0,
+            c:null,
+            s:"(?:\\d{2})"};
+    case "F":
+        return {g:1,
+            c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "].substring(0, 3)], 10);\n",
+            s:"(" + Date.monthNames.join("|") + ")"};
+    case "M":
+        return {g:1,
+            c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "]], 10);\n",
+            s:"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)"};
+    case "n":
+    case "m":
+        return {g:1,
+            c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
+            s:"(\\d{1,2})"};
+    case "t":
+        return {g:0,
+            c:null,
+            s:"\\d{1,2}"};
+    case "L":
+        return {g:0,
+            c:null,
+            s:"(?:1|0)"};
+    case "Y":
+        return {g:1,
+            c:"y = parseInt(results[" + currentGroup + "], 10);\n",
+            s:"(\\d{4})"};
+    case "y":
+        return {g:1,
+            c:"var ty = parseInt(results[" + currentGroup + "], 10);\n"
+                + "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n",
+            s:"(\\d{1,2})"};
+    case "a":
+        return {g:1,
+            c:"if (results[" + currentGroup + "] == 'am') {\n"
+                + "if (h == 12) { h = 0; }\n"
+                + "} else { if (h < 12) { h += 12; }}",
+            s:"(am|pm)"};
+    case "A":
+        return {g:1,
+            c:"if (results[" + currentGroup + "] == 'AM') {\n"
+                + "if (h == 12) { h = 0; }\n"
+                + "} else { if (h < 12) { h += 12; }}",
+            s:"(AM|PM)"};
+    case "g":
+    case "G":
+    case "h":
+    case "H":
+        return {g:1,
+            c:"h = parseInt(results[" + currentGroup + "], 10);\n",
+            s:"(\\d{1,2})"};
+    case "i":
+        return {g:1,
+            c:"i = parseInt(results[" + currentGroup + "], 10);\n",
+            s:"(\\d{2})"};
+    case "s":
+        return {g:1,
+            c:"s = parseInt(results[" + currentGroup + "], 10);\n",
+            s:"(\\d{2})"};
+    case "O":
+        return {g:0,
+            c:null,
+            s:"[+-]\\d{4}"};
+    case "T":
+        return {g:0,
+            c:null,
+            s:"[A-Z]{3}"};
+    case "Z":
+        return {g:0,
+            c:null,
+            s:"[+-]\\d{1,5}"};
+    default:
+        return {g:0,
+            c:null,
+            s:String.escape(character)};
+    }
+}
+
+Date.prototype.getTimezone = function() {
+    return this.toString().replace(
+        /^.*? ([A-Z]{3}) [0-9]{4}.*$/, "$1").replace(
+        /^.*?\(([A-Z])[a-z]+ ([A-Z])[a-z]+ ([A-Z])[a-z]+\)$/, "$1$2$3");
+}
+
+Date.prototype.getGMTOffset = function() {
+    return (this.getTimezoneOffset() > 0 ? "-" : "+")
+        + String.leftPad(Math.floor(this.getTimezoneOffset() / 60), 2, "0")
+        + String.leftPad(this.getTimezoneOffset() % 60, 2, "0");
+}
+
+Date.prototype.getDayOfYear = function() {
+    var num = 0;
+    Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
+    for (var i = 0; i < this.getMonth(); ++i) {
+        num += Date.daysInMonth[i];
+    }
+    return num + this.getDate() - 1;
+}
+
+Date.prototype.getWeekOfYear = function() {
+    // Skip to Thursday of this week
+    var now = this.getDayOfYear() + (4 - this.getDay());
+    // Find the first Thursday of the year
+    var jan1 = new Date(this.getFullYear(), 0, 1);
+    var then = (7 - jan1.getDay() + 4);
+    document.write(then);
+    return String.leftPad(((now - then) / 7) + 1, 2, "0");
+}
+
+Date.prototype.isLeapYear = function() {
+    var year = this.getFullYear();
+    return ((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
+}
+
+Date.prototype.getFirstDayOfMonth = function() {
+    var day = (this.getDay() - (this.getDate() - 1)) % 7;
+    return (day < 0) ? (day + 7) : day;
+}
+
+Date.prototype.getLastDayOfMonth = function() {
+    var day = (this.getDay() + (Date.daysInMonth[this.getMonth()] - this.getDate())) % 7;
+    return (day < 0) ? (day + 7) : day;
+}
+
+Date.prototype.getDaysInMonth = function() {
+    Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
+    return Date.daysInMonth[this.getMonth()];
+}
+
+Date.prototype.getSuffix = function() {
+    switch (this.getDate()) {
+        case 1:
+        case 21:
+        case 31:
+            return "st";
+        case 2:
+        case 22:
+            return "nd";
+        case 3:
+        case 23:
+            return "rd";
+        default:
+            return "th";
+    }
+}
+
+String.escape = function(string) {
+    return string.replace(/('|\\)/g, "\\$1");
+}
+
+String.leftPad = function (val, size, ch) {
+    var result = new String(val);
+    if (ch == null) {
+        ch = " ";
+    }
+    while (result.length < size) {
+        result = ch + result;
+    }
+    return result;
+}
+
+Date.daysInMonth = [31,28,31,30,31,30,31,31,30,31,30,31];
+Date.monthNames =
+   ["January",
+    "February",
+    "March",
+    "April",
+    "May",
+    "June",
+    "July",
+    "August",
+    "September",
+    "October",
+    "November",
+    "December"];
+Date.dayNames =
+   ["Sunday",
+    "Monday",
+    "Tuesday",
+    "Wednesday",
+    "Thursday",
+    "Friday",
+    "Saturday"];
+Date.y2kYear = 50;
+Date.monthNumbers = {
+    Jan:0,
+    Feb:1,
+    Mar:2,
+    Apr:3,
+    May:4,
+    Jun:5,
+    Jul:6,
+    Aug:7,
+    Sep:8,
+    Oct:9,
+    Nov:10,
+    Dec:11};
+Date.patterns = {
+    ISO8601LongPattern:"Y-m-d H:i:s",
+    ISO8601ShortPattern:"Y-m-d",
+    ShortDatePattern: "n/j/Y",
+    LongDatePattern: "l, F d, Y",
+    FullDateTimePattern: "l, F d, Y g:i:s A",
+    MonthDayPattern: "F d",
+    ShortTimePattern: "g:i A",
+    LongTimePattern: "g:i:s A",
+    SortableDateTimePattern: "Y-m-d\\TH:i:s",
+    UniversalSortableDateTimePattern: "Y-m-d H:i:sO",
+    YearMonthPattern: "F, Y"};
+
+var date = new Date("1/1/2007 1:11:11");
+
+for (i = 0; i < 4000; ++i) {
+    var shortFormat = date.dateFormat("Y-m-d");
+    var longFormat = date.dateFormat("l, F d, Y g:i:s A");
+    date.setTime(date.getTime() + 84266956);
+}
+
+
+var _sunSpiderInterval = new Date() - _sunSpiderStartDate;
+
+document.getElementById("console").innerHTML = _sunSpiderInterval;
+</script>
+
+
+</body>
+</html>
diff --git a/src/third_party/mozjs-45/build/pgo/js-input/sunspider/math-cordic.html b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/math-cordic.html
new file mode 100644
index 0000000..ec28f9d
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/math-cordic.html
@@ -0,0 +1,145 @@
+<!DOCTYPE html>
+<head>
+<!--
+ Copyright (C) 2007 Apple Inc.  All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+-->
+
+<title>SunSpider math-cordic</title>
+
+</head>
+
+<body>
+<h3>math-cordic</h3>
+<div id="console">
+</div>
+
+<script>
+
+var _sunSpiderStartDate = new Date();
+
+/*
+ * Copyright (C) Rich Moore.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+/////. Start CORDIC
+
+var AG_CONST = 0.6072529350;
+
+function FIXED(X)
+{
+  return X * 65536.0;
+}
+
+function FLOAT(X)
+{
+  return X / 65536.0;
+}
+
+function DEG2RAD(X)
+{
+  return 0.017453 * (X);
+}
+
+var Angles = [
+  FIXED(45.0), FIXED(26.565), FIXED(14.0362), FIXED(7.12502),
+  FIXED(3.57633), FIXED(1.78991), FIXED(0.895174), FIXED(0.447614),
+  FIXED(0.223811), FIXED(0.111906), FIXED(0.055953),
+  FIXED(0.027977) 
+              ];
+
+
+function cordicsincos() {
+    var X;
+    var Y;
+    var TargetAngle;
+    var CurrAngle;
+    var Step;
+ 
+    X = FIXED(AG_CONST);         /* AG_CONST * cos(0) */
+    Y = 0;                       /* AG_CONST * sin(0) */
+
+    TargetAngle = FIXED(28.027);
+    CurrAngle = 0;
+    for (Step = 0; Step < 12; Step++) {
+        var NewX;
+        if (TargetAngle > CurrAngle) {
+            NewX = X - (Y >> Step);
+            Y = (X >> Step) + Y;
+            X = NewX;
+            CurrAngle += Angles[Step];
+        } else {
+            NewX = X + (Y >> Step);
+            Y = -(X >> Step) + Y;
+            X = NewX;
+            CurrAngle -= Angles[Step];
+        }
+    }
+}
+
+///// End CORDIC
+
+function cordic( runs ) {
+  var start = new Date();
+
+  for ( var i = 0 ; i < runs ; i++ ) {
+      cordicsincos();
+  }
+
+  var end = new Date();
+
+  return end.getTime() - start.getTime();
+}
+
+cordic(25000);
+
+
+var _sunSpiderInterval = new Date() - _sunSpiderStartDate;
+
+document.getElementById("console").innerHTML = _sunSpiderInterval;
+</script>
+
+
+</body>
+</html>
diff --git a/src/third_party/mozjs-45/build/pgo/js-input/sunspider/math-partial-sums.html b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/math-partial-sums.html
new file mode 100644
index 0000000..b78b962
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/math-partial-sums.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<head>
+<!--
+ Copyright (C) 2007 Apple Inc.  All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+-->
+
+<title>SunSpider math-partial-sums</title>
+
+</head>
+
+<body>
+<h3>math-partial-sums</h3>
+<div id="console">
+</div>
+
+<script>
+
+var _sunSpiderStartDate = new Date();
+
+// The Computer Language Shootout
+// http://shootout.alioth.debian.org/
+// contributed by Isaac Gouy
+
+function partial(n){
+    var a1 = a2 = a3 = a4 = a5 = a6 = a7 = a8 = a9 = 0.0;
+    var twothirds = 2.0/3.0;
+    var alt = -1.0;
+    var k2 = k3 = sk = ck = 0.0;
+    
+    for (var k = 1; k <= n; k++){
+        k2 = k*k;
+        k3 = k2*k;
+        sk = Math.sin(k);
+        ck = Math.cos(k);
+        alt = -alt;
+        
+        a1 += Math.pow(twothirds,k-1);
+        a2 += Math.pow(k,-0.5);
+        a3 += 1.0/(k*(k+1.0));
+        a4 += 1.0/(k3 * sk*sk);
+        a5 += 1.0/(k3 * ck*ck);
+        a6 += 1.0/k;
+        a7 += 1.0/k2;
+        a8 += alt/k;
+        a9 += alt/(2*k -1);
+    }
+}
+
+for (var i = 1024; i <= 16384; i *= 2) {
+    partial(i);
+}
+
+
+
+var _sunSpiderInterval = new Date() - _sunSpiderStartDate;
+
+document.getElementById("console").innerHTML = _sunSpiderInterval;
+</script>
+
+
+</body>
+</html>
diff --git a/src/third_party/mozjs-45/build/pgo/js-input/sunspider/math-spectral-norm.html b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/math-spectral-norm.html
new file mode 100644
index 0000000..2949f9d
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/math-spectral-norm.html
@@ -0,0 +1,101 @@
+<!DOCTYPE html>
+<head>
+<!--
+ Copyright (C) 2007 Apple Inc.  All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+-->
+
+<title>SunSpider math-spectral-norm</title>
+
+</head>
+
+<body>
+<h3>math-spectral-norm</h3>
+<div id="console">
+</div>
+
+<script>
+
+var _sunSpiderStartDate = new Date();
+
+// The Great Computer Language Shootout
+// http://shootout.alioth.debian.org/
+//
+// contributed by Ian Osgood
+
+function A(i,j) {
+  return 1/((i+j)*(i+j+1)/2+i+1);
+}
+
+function Au(u,v) {
+  for (var i=0; i<u.length; ++i) {
+    var t = 0;
+    for (var j=0; j<u.length; ++j)
+      t += A(i,j) * u[j];
+    v[i] = t;
+  }
+}
+
+function Atu(u,v) {
+  for (var i=0; i<u.length; ++i) {
+    var t = 0;
+    for (var j=0; j<u.length; ++j)
+      t += A(j,i) * u[j];
+    v[i] = t;
+  }
+}
+
+function AtAu(u,v,w) {
+  Au(u,w);
+  Atu(w,v);
+}
+
+function spectralnorm(n) {
+  var i, u=[], v=[], w=[], vv=0, vBv=0;
+  for (i=0; i<n; ++i) {
+    u[i] = 1; v[i] = w[i] = 0;
+  }
+  for (i=0; i<10; ++i) {
+    AtAu(u,v,w);
+    AtAu(v,u,w);
+  }
+  for (i=0; i<n; ++i) {
+    vBv += u[i]*v[i];
+    vv  += v[i]*v[i];
+  }
+  return Math.sqrt(vBv/vv);
+}
+
+for (var i = 6; i <= 48; i *= 2) {
+    spectralnorm(i);
+}
+
+
+var _sunSpiderInterval = new Date() - _sunSpiderStartDate;
+
+document.getElementById("console").innerHTML = _sunSpiderInterval;
+</script>
+
+
+</body>
+</html>
diff --git a/src/third_party/mozjs-45/build/pgo/js-input/sunspider/regexp-dna.html b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/regexp-dna.html
new file mode 100644
index 0000000..4a00399
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/regexp-dna.html
@@ -0,0 +1,1762 @@
+<!DOCTYPE html>
+<head>
+<!--
+ Copyright (C) 2007 Apple Inc.  All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+-->
+
+<title>SunSpider regexp-dna</title>
+
+</head>
+
+<body>
+<h3>regexp-dna</h3>
+<div id="console">
+</div>
+
+<script>
+
+var _sunSpiderStartDate = new Date();
+
+// The Computer Language Shootout
+// http://shootout.alioth.debian.org/
+//
+// contributed by Jesse Millikan
+// Base on the Ruby version by jose fco. gonzalez
+
+var l;
+var dnaInput = ">ONE Homo sapiens alu\n\
+GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGA\n\
+TCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACT\n\
+AAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAG\n\
+GCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCG\n\
+CCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGT\n\
+GGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCA\n\
+GGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAA\n\
+TTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAG\n\
+AATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCA\n\
+GCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGT\n\
+AATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACC\n\
+AGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTG\n\
+GTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACC\n\
+CGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAG\n\
+AGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTT\n\
+TGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACA\n\
+TGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCT\n\
+GTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGG\n\
+TTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGT\n\
+CTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGG\n\
+CGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCG\n\
+TCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTA\n\
+CTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCG\n\
+AGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCG\n\
+GGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACC\n\
+TGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAA\n\
+TACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGA\n\
+GGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACT\n\
+GCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTC\n\
+ACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGT\n\
+TCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGC\n\
+CGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCG\n\
+CTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTG\n\
+GGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCC\n\
+CAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCT\n\
+GGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGC\n\
+GCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGA\n\
+GGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGA\n\
+GACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGA\n\
+GGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTG\n\
+AAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAAT\n\
+CCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCA\n\
+GTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAA\n\
+AAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGC\n\
+GGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCT\n\
+ACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGG\n\
+GAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATC\n\
+GCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGC\n\
+GGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGG\n\
+TCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAA\n\
+AAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAG\n\
+GAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACT\n\
+CCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCC\n\
+TGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAG\n\
+ACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGC\n\
+GTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGA\n\
+ACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGA\n\
+CAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCA\n\
+CTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCA\n\
+ACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCG\n\
+CCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGG\n\
+AGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTC\n\
+CGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCG\n\
+AGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACC\n\
+CCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAG\n\
+CTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAG\n\
+CCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGG\n\
+CCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATC\n\
+ACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAA\n\
+AAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGC\n\
+TGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCC\n\
+ACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGG\n\
+CTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGG\n\
+AGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATT\n\
+AGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAA\n\
+TCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGC\n\
+CTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAA\n\
+TCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAG\n\
+CCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGT\n\
+GGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCG\n\
+GGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAG\n\
+CGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTG\n\
+GGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATG\n\
+GTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGT\n\
+AATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTT\n\
+GCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCT\n\
+CAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCG\n\
+GGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTC\n\
+TCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACT\n\
+CGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAG\n\
+ATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGG\n\
+CGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTG\n\
+AGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATA\n\
+CAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGG\n\
+CAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGC\n\
+ACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCAC\n\
+GCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTC\n\
+GAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCG\n\
+GGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCT\n\
+TGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGG\n\
+CGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCA\n\
+GCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGG\n\
+CCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGC\n\
+GCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGG\n\
+CGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGA\n\
+CTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGG\n\
+CCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAA\n\
+ACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCC\n\
+CAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGT\n\
+GAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAA\n\
+AGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGG\n\
+ATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTAC\n\
+TAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGA\n\
+GGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGC\n\
+GCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGG\n\
+TGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTC\n\
+AGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAA\n\
+ATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGA\n\
+GAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC\n\
+AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTG\n\
+TAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGAC\n\
+CAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGT\n\
+GGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAAC\n\
+CCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACA\n\
+GAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACT\n\
+TTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAAC\n\
+ATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCC\n\
+TGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAG\n\
+GTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCG\n\
+TCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAG\n\
+GCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCC\n\
+GTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCT\n\
+ACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCC\n\
+GAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCC\n\
+GGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCAC\n\
+CTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAA\n\
+ATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTG\n\
+AGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCAC\n\
+TGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCT\n\
+CACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAG\n\
+TTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAG\n\
+CCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATC\n\
+GCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCT\n\
+GGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATC\n\
+CCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCC\n\
+TGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGG\n\
+CGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG\n\
+AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCG\n\
+AGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGG\n\
+AGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGT\n\
+GAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAA\n\
+TCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGC\n\
+AGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCA\n\
+AAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGG\n\
+CGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTC\n\
+TACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCG\n\
+GGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGAT\n\
+CGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCG\n\
+CGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAG\n\
+GTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACA\n\
+AAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCA\n\
+GGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCAC\n\
+TCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGC\n\
+CTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGA\n\
+GACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGG\n\
+CGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTG\n\
+AACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCG\n\
+ACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGC\n\
+ACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCC\n\
+AACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGC\n\
+GCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCG\n\
+GAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACT\n\
+CCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCC\n\
+GAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAAC\n\
+CCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA\n\
+GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGA\n\
+GCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAG\n\
+GCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGAT\n\
+CACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTA\n\
+AAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGG\n\
+CTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGC\n\
+CACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTG\n\
+GCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAG\n\
+GAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAAT\n\
+TAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGA\n\
+ATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAG\n\
+CCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTA\n\
+ATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCA\n\
+GCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGG\n\
+TGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCC\n\
+GGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGA\n\
+GCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTT\n\
+GGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACAT\n\
+GGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTG\n\
+TAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGT\n\
+TGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTC\n\
+TCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGC\n\
+GGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGT\n\
+CTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTAC\n\
+TCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGA\n\
+GATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGG\n\
+GCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCT\n\
+GAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT\n\
+ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAG\n\
+GCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTG\n\
+CACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCA\n\
+CGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTT\n\
+CGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCC\n\
+GGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGC\n\
+TTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGG\n\
+GCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCC\n\
+AGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTG\n\
+GCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCG\n\
+CGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAG\n\
+GCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAG\n\
+ACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAG\n\
+GCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGA\n\
+AACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATC\n\
+CCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAG\n\
+TGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAA\n\
+AAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCG\n\
+GATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTA\n\
+CTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGG\n\
+AGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCG\n\
+CGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCG\n\
+GTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGT\n\
+CAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAA\n\
+AATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGG\n\
+AGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTC\n\
+CAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCT\n\
+GTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA\n\
+CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCG\n\
+TGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAA\n\
+CCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGAC\n\
+AGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCAC\n\
+TTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAA\n\
+CATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGC\n\
+CTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGA\n\
+GGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCC\n\
+GTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGA\n\
+GGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCC\n\
+CGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGC\n\
+TACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGC\n\
+CGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGC\n\
+CGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCA\n\
+CCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAA\n\
+AATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCT\n\
+GAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCA\n\
+CTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGC\n\
+TCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGA\n\
+GTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTA\n\
+GCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAAT\n\
+CGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCC\n\
+TGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAAT\n\
+CCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGC\n\
+CTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTG\n\
+GCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGG\n\
+GAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGC\n\
+GAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG\n\
+GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGG\n\
+TGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTA\n\
+ATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTG\n\
+CAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTC\n\
+AAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGG\n\
+GCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCT\n\
+CTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTC\n\
+GGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGA\n\
+TCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGC\n\
+GCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGA\n\
+GGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATAC\n\
+AAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGC\n\
+AGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCA\n\
+CTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACG\n\
+CCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCG\n\
+AGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGG\n\
+GCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTT\n\
+GAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGC\n\
+GACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAG\n\
+CACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGC\n\
+CAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCG\n\
+CGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGC\n\
+GGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGAC\n\
+TCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGC\n\
+CGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAA\n\
+CCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCC\n\
+AGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTG\n\
+AGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA\n\
+GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGA\n\
+TCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACT\n\
+AAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAG\n\
+GCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCG\n\
+CCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGT\n\
+GGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCA\n\
+GGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAA\n\
+TTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAG\n\
+AATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCA\n\
+GCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGT\n\
+AATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACC\n\
+AGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTG\n\
+GTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACC\n\
+CGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAG\n\
+AGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTT\n\
+TGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACA\n\
+TGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCT\n\
+GTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGG\n\
+TTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGT\n\
+CTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGG\n\
+CGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCG\n\
+TCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTA\n\
+CTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCG\n\
+AGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCG\n\
+GGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACC\n\
+TGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAA\n\
+TACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGA\n\
+GGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACT\n\
+GCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTC\n\
+ACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGT\n\
+TCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGC\n\
+CGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCG\n\
+CTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTG\n\
+GGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCC\n\
+CAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCT\n\
+GGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGC\n\
+GCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGA\n\
+GGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGA\n\
+GACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGA\n\
+GGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTG\n\
+AAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAAT\n\
+CCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCA\n\
+GTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAA\n\
+AAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGC\n\
+GGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCT\n\
+ACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGG\n\
+GAGGCTGAGGCAGGAGAATC\n\
+>TWO IUB ambiguity codes\n\
+cttBtatcatatgctaKggNcataaaSatgtaaaDcDRtBggDtctttataattcBgtcg\n\
+tactDtDagcctatttSVHtHttKtgtHMaSattgWaHKHttttagacatWatgtRgaaa\n\
+NtactMcSMtYtcMgRtacttctWBacgaaatatagScDtttgaagacacatagtVgYgt\n\
+cattHWtMMWcStgttaggKtSgaYaaccWStcgBttgcgaMttBYatcWtgacaYcaga\n\
+gtaBDtRacttttcWatMttDBcatWtatcttactaBgaYtcttgttttttttYaaScYa\n\
+HgtgttNtSatcMtcVaaaStccRcctDaataataStcYtRDSaMtDttgttSagtRRca\n\
+tttHatSttMtWgtcgtatSSagactYaaattcaMtWatttaSgYttaRgKaRtccactt\n\
+tattRggaMcDaWaWagttttgacatgttctacaaaRaatataataaMttcgDacgaSSt\n\
+acaStYRctVaNMtMgtaggcKatcttttattaaaaagVWaHKYagtttttatttaacct\n\
+tacgtVtcVaattVMBcttaMtttaStgacttagattWWacVtgWYagWVRctDattBYt\n\
+gtttaagaagattattgacVatMaacattVctgtBSgaVtgWWggaKHaatKWcBScSWa\n\
+accRVacacaaactaccScattRatatKVtactatatttHttaagtttSKtRtacaaagt\n\
+RDttcaaaaWgcacatWaDgtDKacgaacaattacaRNWaatHtttStgttattaaMtgt\n\
+tgDcgtMgcatBtgcttcgcgaDWgagctgcgaggggVtaaScNatttacttaatgacag\n\
+cccccacatYScaMgtaggtYaNgttctgaMaacNaMRaacaaacaKctacatagYWctg\n\
+ttWaaataaaataRattagHacacaagcgKatacBttRttaagtatttccgatctHSaat\n\
+actcNttMaagtattMtgRtgaMgcataatHcMtaBSaRattagttgatHtMttaaKagg\n\
+YtaaBataSaVatactWtataVWgKgttaaaacagtgcgRatatacatVtHRtVYataSa\n\
+KtWaStVcNKHKttactatccctcatgWHatWaRcttactaggatctataDtDHBttata\n\
+aaaHgtacVtagaYttYaKcctattcttcttaataNDaaggaaaDYgcggctaaWSctBa\n\
+aNtgctggMBaKctaMVKagBaactaWaDaMaccYVtNtaHtVWtKgRtcaaNtYaNacg\n\
+gtttNattgVtttctgtBaWgtaattcaagtcaVWtactNggattctttaYtaaagccgc\n\
+tcttagHVggaYtgtNcDaVagctctctKgacgtatagYcctRYHDtgBattDaaDgccK\n\
+tcHaaStttMcctagtattgcRgWBaVatHaaaataYtgtttagMDMRtaataaggatMt\n\
+ttctWgtNtgtgaaaaMaatatRtttMtDgHHtgtcattttcWattRSHcVagaagtacg\n\
+ggtaKVattKYagactNaatgtttgKMMgYNtcccgSKttctaStatatNVataYHgtNa\n\
+BKRgNacaactgatttcctttaNcgatttctctataScaHtataRagtcRVttacDSDtt\n\
+aRtSatacHgtSKacYagttMHtWataggatgactNtatSaNctataVtttRNKtgRacc\n\
+tttYtatgttactttttcctttaaacatacaHactMacacggtWataMtBVacRaSaatc\n\
+cgtaBVttccagccBcttaRKtgtgcctttttRtgtcagcRttKtaaacKtaaatctcac\n\
+aattgcaNtSBaaccgggttattaaBcKatDagttactcttcattVtttHaaggctKKga\n\
+tacatcBggScagtVcacattttgaHaDSgHatRMaHWggtatatRgccDttcgtatcga\n\
+aacaHtaagttaRatgaVacttagattVKtaaYttaaatcaNatccRttRRaMScNaaaD\n\
+gttVHWgtcHaaHgacVaWtgttScactaagSgttatcttagggDtaccagWattWtRtg\n\
+ttHWHacgattBtgVcaYatcggttgagKcWtKKcaVtgaYgWctgYggVctgtHgaNcV\n\
+taBtWaaYatcDRaaRtSctgaHaYRttagatMatgcatttNattaDttaattgttctaa\n\
+ccctcccctagaWBtttHtBccttagaVaatMcBHagaVcWcagBVttcBtaYMccagat\n\
+gaaaaHctctaacgttagNWRtcggattNatcRaNHttcagtKttttgWatWttcSaNgg\n\
+gaWtactKKMaacatKatacNattgctWtatctaVgagctatgtRaHtYcWcttagccaa\n\
+tYttWttaWSSttaHcaaaaagVacVgtaVaRMgattaVcDactttcHHggHRtgNcctt\n\
+tYatcatKgctcctctatVcaaaaKaaaagtatatctgMtWtaaaacaStttMtcgactt\n\
+taSatcgDataaactaaacaagtaaVctaggaSccaatMVtaaSKNVattttgHccatca\n\
+cBVctgcaVatVttRtactgtVcaattHgtaaattaaattttYtatattaaRSgYtgBag\n\
+aHSBDgtagcacRHtYcBgtcacttacactaYcgctWtattgSHtSatcataaatataHt\n\
+cgtYaaMNgBaatttaRgaMaatatttBtttaaaHHKaatctgatWatYaacttMctctt\n\
+ttVctagctDaaagtaVaKaKRtaacBgtatccaaccactHHaagaagaaggaNaaatBW\n\
+attccgStaMSaMatBttgcatgRSacgttVVtaaDMtcSgVatWcaSatcttttVatag\n\
+ttactttacgatcaccNtaDVgSRcgVcgtgaacgaNtaNatatagtHtMgtHcMtagaa\n\
+attBgtataRaaaacaYKgtRccYtatgaagtaataKgtaaMttgaaRVatgcagaKStc\n\
+tHNaaatctBBtcttaYaBWHgtVtgacagcaRcataWctcaBcYacYgatDgtDHccta\n\
+aagacYRcaggattHaYgtKtaatgcVcaataMYacccatatcacgWDBtgaatcBaata\n\
+cKcttRaRtgatgaBDacggtaattaaYtataStgVHDtDctgactcaaatKtacaatgc\n\
+gYatBtRaDatHaactgtttatatDttttaaaKVccYcaaccNcBcgHaaVcattHctcg\n\
+attaaatBtatgcaaaaatYMctSactHatacgaWacattacMBgHttcgaatVaaaaca\n\
+BatatVtctgaaaaWtctRacgBMaatSgRgtgtcgactatcRtattaScctaStagKga\n\
+DcWgtYtDDWKRgRtHatRtggtcgaHgggcgtattaMgtcagccaBggWVcWctVaaat\n\
+tcgNaatcKWagcNaHtgaaaSaaagctcYctttRVtaaaatNtataaccKtaRgtttaM\n\
+tgtKaBtRtNaggaSattHatatWactcagtgtactaKctatttgRYYatKatgtccgtR\n\
+tttttatttaatatVgKtttgtatgtNtataRatWYNgtRtHggtaaKaYtKSDcatcKg\n\
+taaYatcSRctaVtSMWtVtRWHatttagataDtVggacagVcgKWagBgatBtaaagNc\n\
+aRtagcataBggactaacacRctKgttaatcctHgDgttKHHagttgttaatgHBtatHc\n\
+DaagtVaBaRccctVgtgDtacRHSctaagagcggWYaBtSaKtHBtaaactYacgNKBa\n\
+VYgtaacttagtVttcttaatgtBtatMtMtttaattaatBWccatRtttcatagVgMMt\n\
+agctStKctaMactacDNYgKYHgaWcgaHgagattacVgtttgtRaSttaWaVgataat\n\
+gtgtYtaStattattMtNgWtgttKaccaatagNYttattcgtatHcWtctaaaNVYKKt\n\
+tWtggcDtcgaagtNcagatacgcattaagaccWctgcagcttggNSgaNcHggatgtVt\n\
+catNtRaaBNcHVagagaaBtaaSggDaatWaatRccaVgggStctDaacataKttKatt\n\
+tggacYtattcSatcttagcaatgaVBMcttDattctYaaRgatgcattttNgVHtKcYR\n\
+aatRKctgtaaacRatVSagctgtWacBtKVatctgttttKcgtctaaDcaagtatcSat\n\
+aWVgcKKataWaYttcccSaatgaaaacccWgcRctWatNcWtBRttYaattataaNgac\n\
+acaatagtttVNtataNaYtaatRaVWKtBatKagtaatataDaNaaaaataMtaagaaS\n\
+tccBcaatNgaataWtHaNactgtcDtRcYaaVaaaaaDgtttRatctatgHtgttKtga\n\
+aNSgatactttcgagWaaatctKaaDaRttgtggKKagcDgataaattgSaacWaVtaNM\n\
+acKtcaDaaatttctRaaVcagNacaScRBatatctRatcctaNatWgRtcDcSaWSgtt\n\
+RtKaRtMtKaatgttBHcYaaBtgatSgaSWaScMgatNtctcctatttctYtatMatMt\n\
+RRtSaattaMtagaaaaStcgVgRttSVaScagtgDtttatcatcatacRcatatDctta\n\
+tcatVRtttataaHtattcYtcaaaatactttgVctagtaaYttagatagtSYacKaaac\n\
+gaaKtaaatagataatSatatgaaatSgKtaatVtttatcctgKHaatHattagaaccgt\n\
+YaaHactRcggSBNgtgctaaBagBttgtRttaaattYtVRaaaattgtaatVatttctc\n\
+ttcatgBcVgtgKgaHaaatattYatagWacNctgaaMcgaattStagWaSgtaaKagtt\n\
+ttaagaDgatKcctgtaHtcatggKttVDatcaaggtYcgccagNgtgcVttttagagat\n\
+gctaccacggggtNttttaSHaNtatNcctcatSaaVgtactgBHtagcaYggYVKNgta\n\
+KBcRttgaWatgaatVtagtcgattYgatgtaatttacDacSctgctaaaStttaWMagD\n\
+aaatcaVYctccgggcgaVtaaWtStaKMgDtttcaaMtVgBaatccagNaaatcYRMBg\n\
+gttWtaaScKttMWtYataRaDBMaDataatHBcacDaaKDactaMgagttDattaHatH\n\
+taYatDtattDcRNStgaatattSDttggtattaaNSYacttcDMgYgBatWtaMagact\n\
+VWttctttgYMaYaacRgHWaattgRtaagcattctMKVStatactacHVtatgatcBtV\n\
+NataaBttYtSttacKgggWgYDtgaVtYgatDaacattYgatggtRDaVDttNactaSa\n\
+MtgNttaacaaSaBStcDctaccacagacgcaHatMataWKYtaYattMcaMtgSttDag\n\
+cHacgatcaHttYaKHggagttccgatYcaatgatRaVRcaagatcagtatggScctata\n\
+ttaNtagcgacgtgKaaWaactSgagtMYtcttccaKtStaacggMtaagNttattatcg\n\
+tctaRcactctctDtaacWYtgaYaSaagaWtNtatttRacatgNaatgttattgWDDcN\n\
+aHcctgaaHacSgaataaRaataMHttatMtgaSDSKatatHHaNtacagtccaYatWtc\n\
+actaactatKDacSaStcggataHgYatagKtaatKagStaNgtatactatggRHacttg\n\
+tattatgtDVagDVaRctacMYattDgtttYgtctatggtKaRSttRccRtaaccttaga\n\
+gRatagSaaMaacgcaNtatgaaatcaRaagataatagatactcHaaYKBctccaagaRa\n\
+BaStNagataggcgaatgaMtagaatgtcaKttaaatgtaWcaBttaatRcggtgNcaca\n\
+aKtttScRtWtgcatagtttWYaagBttDKgcctttatMggNttattBtctagVtacata\n\
+aaYttacacaaRttcYtWttgHcaYYtaMgBaBatctNgcDtNttacgacDcgataaSat\n\
+YaSttWtcctatKaatgcagHaVaacgctgcatDtgttaSataaaaYSNttatagtaNYt\n\
+aDaaaNtggggacttaBggcHgcgtNtaaMcctggtVtaKcgNacNtatVaSWctWtgaW\n\
+cggNaBagctctgaYataMgaagatBSttctatacttgtgtKtaattttRagtDtacata\n\
+tatatgatNHVgBMtKtaKaNttDHaagatactHaccHtcatttaaagttVaMcNgHata\n\
+tKtaNtgYMccttatcaaNagctggacStttcNtggcaVtattactHaSttatgNMVatt\n\
+MMDtMactattattgWMSgtHBttStStgatatRaDaagattttctatMtaaaaaggtac\n\
+taaVttaSacNaatactgMttgacHaHRttgMacaaaatagttaatatWKRgacDgaRta\n\
+tatttattatcYttaWtgtBRtWatgHaaattHataagtVaDtWaVaWtgStcgtMSgaS\n\
+RgMKtaaataVacataatgtaSaatttagtcgaaHtaKaatgcacatcggRaggSKctDc\n\
+agtcSttcccStYtccRtctctYtcaaKcgagtaMttttcRaYDttgttatctaatcata\n\
+NctctgctatcaMatactataggDaHaaSttMtaDtcNatataattctMcStaaBYtaNa\n\
+gatgtaatHagagSttgWHVcttatKaYgDctcttggtgttMcRaVgSgggtagacaata\n\
+aDtaattSaDaNaHaBctattgNtaccaaRgaVtKNtaaYggHtaKKgHcatctWtctDt\n\
+ttctttggSDtNtaStagttataaacaattgcaBaBWggHgcaaaBtYgctaatgaaatW\n\
+cDcttHtcMtWWattBHatcatcaaatctKMagtDNatttWaBtHaaaNgMttaaStagt\n\
+tctctaatDtcRVaYttgttMtRtgtcaSaaYVgSWDRtaatagctcagDgcWWaaaBaa\n\
+RaBctgVgggNgDWStNaNBKcBctaaKtttDcttBaaggBttgaccatgaaaNgttttt\n\
+tttatctatgttataccaaDRaaSagtaVtDtcaWatBtacattaWacttaSgtattggD\n\
+gKaaatScaattacgWcagKHaaccaYcRcaRttaDttRtttHgaHVggcttBaRgtccc\n\
+tDatKaVtKtcRgYtaKttacgtatBtStaagcaattaagaRgBagSaattccSWYttta\n\
+ttVaataNctgHgttaaNBgcVYgtRtcccagWNaaaacaDNaBcaaaaRVtcWMgBagM\n\
+tttattacgDacttBtactatcattggaaatVccggttRttcatagttVYcatYaSHaHc\n\
+ttaaagcNWaHataaaRWtctVtRYtagHtaaaYMataHYtNBctNtKaatattStgaMc\n\
+BtRgctaKtgcScSttDgYatcVtggaaKtaagatWccHccgKYctaNNctacaWctttt\n\
+gcRtgtVcgaKttcMRHgctaHtVaataaDtatgKDcttatBtDttggNtacttttMtga\n\
+acRattaaNagaactcaaaBBVtcDtcgaStaDctgaaaSgttMaDtcgttcaccaaaag\n\
+gWtcKcgSMtcDtatgtttStaaBtatagDcatYatWtaaaBacaKgcaDatgRggaaYc\n\
+taRtccagattDaWtttggacBaVcHtHtaacDacYgtaatataMagaatgHMatcttat\n\
+acgtatttttatattacHactgttataMgStYaattYaccaattgagtcaaattaYtgta\n\
+tcatgMcaDcgggtcttDtKgcatgWRtataatatRacacNRBttcHtBgcRttgtgcgt\n\
+catacMtttBctatctBaatcattMttMYgattaaVYatgDaatVagtattDacaacDMa\n\
+tcMtHcccataagatgBggaccattVWtRtSacatgctcaaggggYtttDtaaNgNtaaB\n\
+atggaatgtctRtaBgBtcNYatatNRtagaacMgagSaSDDSaDcctRagtVWSHtVSR\n\
+ggaacaBVaccgtttaStagaacaMtactccagtttVctaaRaaHttNcttagcaattta\n\
+ttaatRtaaaatctaacDaBttggSagagctacHtaaRWgattcaaBtctRtSHaNtgta\n\
+cattVcaHaNaagtataccacaWtaRtaaVKgMYaWgttaKggKMtKcgWatcaDatYtK\n\
+SttgtacgaccNctSaattcDcatcttcaaaDKttacHtggttHggRRaRcaWacaMtBW\n\
+VHSHgaaMcKattgtaRWttScNattBBatYtaNRgcggaagacHSaattRtttcYgacc\n\
+BRccMacccKgatgaacttcgDgHcaaaaaRtatatDtatYVtttttHgSHaSaatagct\n\
+NYtaHYaVYttattNtttgaaaYtaKttWtctaNtgagaaaNctNDctaaHgttagDcRt\n\
+tatagccBaacgcaRBtRctRtggtaMYYttWtgataatcgaataattattataVaaaaa\n\
+ttacNRVYcaaMacNatRttcKatMctgaagactaattataaYgcKcaSYaatMNctcaa\n\
+cgtgatttttBacNtgatDccaattattKWWcattttatatatgatBcDtaaaagttgaa\n\
+VtaHtaHHtBtataRBgtgDtaataMttRtDgDcttattNtggtctatctaaBcatctaR\n\
+atgNacWtaatgaagtcMNaacNgHttatactaWgcNtaStaRgttaaHacccgaYStac\n\
+aaaatWggaYaWgaattattcMaactcBKaaaRVNcaNRDcYcgaBctKaacaaaaaSgc\n\
+tccYBBHYaVagaatagaaaacagYtctVccaMtcgtttVatcaatttDRtgWctagtac\n\
+RttMctgtDctttcKtWttttataaatgVttgBKtgtKWDaWagMtaaagaaattDVtag\n\
+gttacatcatttatgtcgMHaVcttaBtVRtcgtaYgBRHatttHgaBcKaYWaatcNSc\n\
+tagtaaaaatttacaatcactSWacgtaatgKttWattagttttNaggtctcaagtcact\n\
+attcttctaagKggaataMgtttcataagataaaaatagattatDgcBVHWgaBKttDgc\n\
+atRHaagcaYcRaattattatgtMatatattgHDtcaDtcaaaHctStattaatHaccga\n\
+cNattgatatattttgtgtDtRatagSacaMtcRtcattcccgacacSattgttKaWatt\n\
+NHcaacttccgtttSRtgtctgDcgctcaaMagVtBctBMcMcWtgtaacgactctcttR\n\
+ggRKSttgYtYatDccagttDgaKccacgVatWcataVaaagaataMgtgataaKYaaat\n\
+cHDaacgataYctRtcYatcgcaMgtNttaBttttgatttaRtStgcaacaaaataccVg\n\
+aaDgtVgDcStctatatttattaaaaRKDatagaaagaKaaYYcaYSgKStctccSttac\n\
+agtcNactttDVttagaaagMHttRaNcSaRaMgBttattggtttaRMggatggcKDgWR\n\
+tNaataataWKKacttcKWaaagNaBttaBatMHtccattaacttccccYtcBcYRtaga\n\
+ttaagctaaYBDttaNtgaaaccHcaRMtKtaaHMcNBttaNaNcVcgVttWNtDaBatg\n\
+ataaVtcWKcttRggWatcattgaRagHgaattNtatttctctattaattaatgaDaaMa\n\
+tacgttgggcHaYVaaNaDDttHtcaaHtcVVDgBVagcMacgtgttaaBRNtatRtcag\n\
+taagaggtttaagacaVaaggttaWatctccgtVtaDtcDatttccVatgtacNtttccg\n\
+tHttatKgScBatgtVgHtYcWagcaKtaMYaaHgtaattaSaHcgcagtWNaatNccNN\n\
+YcacgVaagaRacttctcattcccRtgtgtaattagcSttaaStWaMtctNNcSMacatt\n\
+ataaactaDgtatWgtagtttaagaaaattgtagtNagtcaataaatttgatMMYactaa\n\
+tatcggBWDtVcYttcDHtVttatacYaRgaMaacaStaatcRttttVtagaDtcacWat\n\
+ttWtgaaaagaaagNRacDtttStVatBaDNtaactatatcBSMcccaSttccggaMatg\n\
+attaaWatKMaBaBatttgataNctgttKtVaagtcagScgaaaDggaWgtgttttKtWt\n\
+atttHaatgtagttcactaaKMagttSYBtKtaYgaactcagagRtatagtVtatcaaaW\n\
+YagcgNtaDagtacNSaaYDgatBgtcgataacYDtaaactacagWDcYKaagtttatta\n\
+gcatcgagttKcatDaattgattatDtcagRtWSKtcgNtMaaaaacaMttKcaWcaaSV\n\
+MaaaccagMVtaMaDtMaHaBgaacataBBVtaatVYaNSWcSgNtDNaaKacacBttta\n\
+tKtgtttcaaHaMctcagtaacgtcgYtactDcgcctaNgagagcYgatattttaaattt\n\
+ccattttacatttDaaRctattttWctttacgtDatYtttcagacgcaaVttagtaaKaa\n\
+aRtgVtccataBggacttatttgtttaWNtgttVWtaWNVDaattgtatttBaagcBtaa\n\
+BttaaVatcHcaVgacattccNggtcgacKttaaaRtagRtctWagaYggtgMtataatM\n\
+tgaaRttattttgWcttNtDRRgMDKacagaaaaggaaaRStcccagtYccVattaNaaK\n\
+StNWtgacaVtagaagcttSaaDtcacaacgDYacWDYtgtttKatcVtgcMaDaSKStV\n\
+cgtagaaWaKaagtttcHaHgMgMtctataagBtKaaaKKcactggagRRttaagaBaaN\n\
+atVVcgRcKSttDaactagtSttSattgttgaaRYatggttVttaataaHttccaagDtg\n\
+atNWtaagHtgcYtaactRgcaatgMgtgtRaatRaNaacHKtagactactggaatttcg\n\
+ccataacgMctRgatgttaccctaHgtgWaYcactcacYaattcttaBtgacttaaacct\n\
+gYgaWatgBttcttVttcgttWttMcNYgtaaaatctYgMgaaattacNgaHgaacDVVM\n\
+tttggtHtctaaRgtacagacgHtVtaBMNBgattagcttaRcttacaHcRctgttcaaD\n\
+BggttKaacatgKtttYataVaNattccgMcgcgtagtRaVVaattaKaatggttRgaMc\n\
+agtatcWBttNtHagctaatctagaaNaaacaYBctatcgcVctBtgcaaagDgttVtga\n\
+HtactSNYtaaNccatgtgDacgaVtDcgKaRtacDcttgctaagggcagMDagggtBWR\n\
+tttSgccttttttaacgtcHctaVtVDtagatcaNMaVtcVacatHctDWNaataRgcgt\n\
+aVHaggtaaaaSgtttMtattDgBtctgatSgtRagagYtctSaKWaataMgattRKtaa\n\
+catttYcgtaacacattRWtBtcggtaaatMtaaacBatttctKagtcDtttgcBtKYYB\n\
+aKttctVttgttaDtgattttcttccacttgSaaacggaaaNDaattcYNNaWcgaaYat\n\
+tttMgcBtcatRtgtaaagatgaWtgaccaYBHgaatagataVVtHtttVgYBtMctaMt\n\
+cctgaDcYttgtccaaaRNtacagcMctKaaaggatttacatgtttaaWSaYaKttBtag\n\
+DacactagctMtttNaKtctttcNcSattNacttggaacaatDagtattRtgSHaataat\n\
+gccVgacccgatactatccctgtRctttgagaSgatcatatcgDcagWaaHSgctYYWta\n\
+tHttggttctttatVattatcgactaagtgtagcatVgtgHMtttgtttcgttaKattcM\n\
+atttgtttWcaaStNatgtHcaaaDtaagBaKBtRgaBgDtSagtatMtaacYaatYtVc\n\
+KatgtgcaacVaaaatactKcRgtaYtgtNgBBNcKtcttaccttKgaRaYcaNKtactt\n\
+tgagSBtgtRagaNgcaaaNcacagtVtttHWatgttaNatBgtttaatNgVtctgaata\n\
+tcaRtattcttttttttRaaKcRStctcggDgKagattaMaaaKtcaHacttaataataK\n\
+taRgDtKVBttttcgtKaggHHcatgttagHggttNctcgtatKKagVagRaaaggaaBt\n\
+NatttVKcRttaHctaHtcaaatgtaggHccaBataNaNaggttgcWaatctgatYcaaa\n\
+HaatWtaVgaaBttagtaagaKKtaaaKtRHatMaDBtBctagcatWtatttgWttVaaa\n\
+ScMNattRactttgtYtttaaaagtaagtMtaMaSttMBtatgaBtttaKtgaatgagYg\n\
+tNNacMtcNRacMMHcttWtgtRtctttaacaacattattcYaMagBaacYttMatcttK\n\
+cRMtgMNccattaRttNatHaHNaSaaHMacacaVaatacaKaSttHatattMtVatWga\n\
+ttttttaYctttKttHgScWaacgHtttcaVaaMgaacagNatcgttaacaaaaagtaca\n\
+HBNaattgttKtcttVttaaBtctgctacgBgcWtttcaggacacatMgacatcccagcg\n\
+gMgaVKaBattgacttaatgacacacaaaaaatRKaaBctacgtRaDcgtagcVBaacDS\n\
+BHaaaaSacatatacagacRNatcttNaaVtaaaataHattagtaaaaSWccgtatWatg\n\
+gDttaactattgcccatcttHaSgYataBttBaactattBtcHtgatcaataSttaBtat\n\
+KSHYttWggtcYtttBttaataccRgVatStaHaKagaatNtagRMNgtcttYaaSaact\n\
+cagDSgagaaYtMttDtMRVgWKWtgMaKtKaDttttgactatacataatcNtatNaHat\n\
+tVagacgYgatatatttttgtStWaaatctWaMgagaRttRatacgStgattcttaagaD\n\
+taWccaaatRcagcagaaNKagtaaDggcgccBtYtagSBMtactaaataMataBSacRM\n\
+gDgattMMgtcHtcaYDtRaDaacggttDaggcMtttatgttaNctaattaVacgaaMMt\n\
+aatDccSgtattgaRtWWaccaccgagtactMcgVNgctDctaMScatagcgtcaactat\n\
+acRacgHRttgctatttaatgaattataYKttgtaagWgtYttgcHgMtaMattWaWVta\n\
+RgcttgYgttBHtYataSccStBtgtagMgtDtggcVaaSBaatagDttgBgtctttctc\n\
+attttaNagtHKtaMWcYactVcgcgtatMVtttRacVagDaatcttgctBBcRDgcaac\n\
+KttgatSKtYtagBMagaRtcgBattHcBWcaactgatttaatttWDccatttatcgagS\n\
+KaWttataHactaHMttaatHtggaHtHagaatgtKtaaRactgtttMatacgatcaagD\n\
+gatKaDctataMggtHDtggHacctttRtatcttYattttgacttgaaSaataaatYcgB\n\
+aaaaccgNatVBttMacHaKaataagtatKgtcaagactcttaHttcggaattgttDtct\n\
+aaccHttttWaaatgaaatataaaWattccYDtKtaaaacggtgaggWVtctattagtga\n\
+ctattaagtMgtttaagcatttgSgaaatatccHaaggMaaaattttcWtatKctagDtY\n\
+tMcctagagHcactttactatacaaacattaacttaHatcVMYattYgVgtMttaaRtga\n\
+aataaDatcaHgtHHatKcDYaatcttMtNcgatYatgSaMaNtcttKcWataScKggta\n\
+tcttacgcttWaaagNatgMgHtctttNtaacVtgttcMaaRatccggggactcMtttaY\n\
+MtcWRgNctgNccKatcttgYDcMgattNYaRagatHaaHgKctcataRDttacatBatc\n\
+cattgDWttatttaWgtcggagaaaaatacaatacSNtgggtttccttacSMaagBatta\n\
+caMaNcactMttatgaRBacYcYtcaaaWtagctSaacttWgDMHgaggatgBVgcHaDt\n\
+ggaactttggtcNatNgtaKaBcccaNtaagttBaacagtatacDYttcctNgWgcgSMc\n\
+acatStctHatgRcNcgtacacaatRttMggaNKKggataaaSaYcMVcMgtaMaHtgat\n\
+tYMatYcggtcttcctHtcDccgtgRatcattgcgccgatatMaaYaataaYSggatagc\n\
+gcBtNtaaaScaKgttBgagVagttaKagagtatVaactaSacWactSaKatWccaKaaa\n\
+atBKgaaKtDMattttgtaaatcRctMatcaaMagMttDgVatggMaaWgttcgaWatga\n\
+aatttgRtYtattaWHKcRgctacatKttctaccaaHttRatctaYattaaWatVNccat\n\
+NgagtcKttKataStRaatatattcctRWatDctVagttYDgSBaatYgttttgtVaatt\n\
+taatagcagMatRaacttBctattgtMagagattaaactaMatVtHtaaatctRgaaaaa\n\
+aaatttWacaacaYccYDSaattMatgaccKtaBKWBattgtcaagcHKaagttMMtaat\n\
+ttcKcMagNaaKagattggMagaggtaatttYacatcWaaDgatMgKHacMacgcVaaca\n\
+DtaDatatYggttBcgtatgWgaSatttgtagaHYRVacaRtctHaaRtatgaactaata\n\
+tctSSBgggaaHMWtcaagatKgagtDaSatagttgattVRatNtctMtcSaagaSHaat\n\
+aNataataRaaRgattctttaataaagWaRHcYgcatgtWRcttgaaggaMcaataBRaa\n\
+ccagStaaacNtttcaatataYtaatatgHaDgcStcWttaacctaRgtYaRtataKtgM\n\
+ttttatgactaaaatttacYatcccRWtttHRtattaaatgtttatatttgttYaatMca\n\
+RcSVaaDatcgtaYMcatgtagacatgaaattgRtcaaYaaYtRBatKacttataccaNa\n\
+aattVaBtctggacaagKaaYaaatatWtMtatcYaaVNtcgHaactBaagKcHgtctac\n\
+aatWtaDtSgtaHcataHtactgataNctRgttMtDcDttatHtcgtacatcccaggStt\n\
+aBgtcacacWtccNMcNatMVaVgtccDYStatMaccDatggYaRKaaagataRatttHK\n\
+tSaaatDgataaacttaHgttgVBtcttVttHgDacgaKatgtatatNYataactctSat\n\
+atatattgcHRRYttStggaactHgttttYtttaWtatMcttttctatctDtagVHYgMR\n\
+BgtHttcctaatYRttKtaagatggaVRataKDctaMtKBNtMtHNtWtttYcVtattMc\n\
+gRaacMcctNSctcatttaaagDcaHtYccSgatgcaatYaaaaDcttcgtaWtaattct\n\
+cgttttScttggtaatctttYgtctaactKataHacctMctcttacHtKataacacagcN\n\
+RatgKatttttSaaatRYcgDttaMRcgaaattactMtgcgtaagcgttatBtttttaat\n\
+taagtNacatHgttcRgacKcBBtVgatKttcgaBaatactDRgtRtgaNacWtcacYtt\n\
+aaKcgttctHaKttaNaMgWgWaggtctRgaKgWttSttBtDcNtgtttacaaatYcDRt\n\
+gVtgcctattcNtctaaaDMNttttNtggctgagaVctDaacVtWccaagtaacacaNct\n\
+gaScattccDHcVBatcgatgtMtaatBgHaatDctMYgagaatgYWKcctaatNaStHa\n\
+aaKccgHgcgtYaaYtattgtStgtgcaaRtattaKatattagaWVtcaMtBagttatta\n\
+gNaWHcVgcaattttDcMtgtaRHVYtHtctgtaaaaHVtMKacatcgNaatttMatatg\n\
+ttgttactagWYtaRacgataKagYNKcattataNaRtgaacKaYgcaaYYacaNccHat\n\
+MatDcNgtHttRaWttagaaDcaaaaaatagggtKDtStaDaRtaVtHWKNtgtattVct\n\
+SVgRgataDaRaWataBgaagaaKtaataaYgDcaStaNgtaDaaggtattHaRaWMYaY\n\
+aWtggttHYgagVtgtgcttttcaaDKcagVcgttagacNaaWtagtaataDttctggtt\n\
+VcatcataaagtgKaaaNaMtaBBaattaatWaattgctHaVKaSgDaaVKaHtatatat\n\
+HatcatSBagNgHtatcHYMHgttDgtaHtBttWatcgtttaRaattgStKgSKNWKatc\n\
+agDtctcagatttctRtYtBatBgHHtKaWtgYBgacVVWaKtacKcDttKMaKaVcggt\n\
+gttataagaataaHaatattagtataatMHgttYgaRttagtaRtcaaVatacggtcMcg\n\
+agtaaRttacWgactKRYataaaagSattYaWgagatYagKagatgSaagKgttaatMgg\n\
+tataatgttWYttatgagaaacctNVataatHcccKtDctcctaatactggctHggaSag\n\
+gRtKHaWaattcgSatMatttagaggcYtctaMcgctcataSatatgRagacNaaDagga\n\
+VBagaYttKtacNaKgtSYtagttggaWcatcWttaatctatgaVtcgtgtMtatcaYcg\n\
+tRccaaYgDctgcMgtgtWgacWtgataacacgcgctBtgttaKtYDtatDcatcagKaV\n\
+MctaatcttgVcaaRgcRMtDcgattaHttcaNatgaatMtactacVgtRgatggaWttt\n\
+actaaKatgagSaaKggtaNtactVaYtaaKRagaacccacaMtaaMtKtatBcttgtaa\n\
+WBtMctaataaVcDaaYtcRHBtcgttNtaaHatttBNgRStVDattBatVtaagttaYa\n\
+tVattaagaBcacggtSgtVtatttaRattgatgtaHDKgcaatattKtggcctatgaWD\n\
+KRYcggattgRctatNgatacaatMNttctgtcRBYRaaaHctNYattcHtaWcaattct\n\
+BtMKtVgYataatMgYtcagcttMDataVtggRtKtgaatgccNcRttcaMtRgattaac\n\
+attRcagcctHtWMtgtDRagaKaBtgDttYaaaaKatKgatctVaaYaacWcgcatagB\n\
+VtaNtRtYRaggBaaBtgKgttacataagagcatgtRattccacttaccatRaaatgWgD\n\
+aMHaYVgVtaSctatcgKaatatattaDgacccYagtgtaYNaaatKcagtBRgagtcca\n\
+tgKgaaaccBgaagBtgSttWtacgatWHaYatcgatttRaaNRgcaNaKVacaNtDgat\n\
+tgHVaatcDaagcgtatgcNttaDataatcSataaKcaataaHWataBtttatBtcaKtK\n\
+tatagttaDgSaYctacaRatNtaWctSaatatttYaKaKtaccWtatcRagacttaYtt\n\
+VcKgSDcgagaagatccHtaattctSttatggtKYgtMaHagVaBRatttctgtRgtcta\n\
+tgggtaHKgtHacHtSYacgtacacHatacKaaBaVaccaDtatcSaataaHaagagaat\n\
+ScagactataaRttagcaaVcaHataKgDacatWccccaagcaBgagWatctaYttgaaa\n\
+tctVNcYtttWagHcgcgcDcVaaatgttKcHtNtcaatagtgtNRaactttttcaatgg\n\
+WgBcgDtgVgtttctacMtaaataaaRggaaacWaHttaRtNtgctaaRRtVBctYtVta\n\
+tDcattDtgaccYatagatYRKatNYKttNgcctagtaWtgaactaMVaacctgaStttc\n\
+tgaKVtaaVaRKDttVtVctaDNtataaaDtccccaagtWtcgatcactDgYaBcatcct\n\
+MtVtacDaaBtYtMaKNatNtcaNacgDatYcatcgcaRatWBgaacWttKttagYtaat\n\
+tcggttgSWttttDWctttacYtatatWtcatDtMgtBttgRtVDggttaacYtacgtac\n\
+atgaattgaaWcttMStaDgtatattgaDtcRBcattSgaaVBRgagccaaKtttcDgcg\n\
+aSMtatgWattaKttWtgDBMaggBBttBaatWttRtgcNtHcgttttHtKtcWtagHSt\n\
+aacagttgatatBtaWSaWggtaataaMttaKacDaatactcBttcaatatHttcBaaSa\n\
+aatYggtaRtatNtHcaatcaHtagVtgtattataNggaMtcttHtNagctaaaggtaga\n\
+YctMattNaMVNtcKtactBKcaHHcBttaSagaKacataYgctaKaYgttYcgacWVtt\n\
+WtSagcaacatcccHaccKtcttaacgaKttcacKtNtacHtatatRtaaatacactaBt\n\
+ttgaHaRttggttWtatYagcatYDatcggagagcWBataagRtacctataRKgtBgatg\n\
+aDatataSttagBaHtaatNtaDWcWtgtaattacagKttcNtMagtattaNgtctcgtc\n\
+ctcttBaHaKcKccgtRcaaYagSattaagtKataDatatatagtcDtaacaWHcaKttD\n\
+gaaRcgtgYttgtcatatNtatttttatggccHtgDtYHtWgttatYaacaattcaWtat\n\
+NgctcaaaSttRgctaatcaaatNatcgtttaBtNNVtgttataagcaaagattBacgtD\n\
+atttNatttaaaDcBgtaSKgacgtagataatttcHMVNttgttBtDtgtaWKaaRMcKM\n\
+tHtaVtagataWctccNNaSWtVaHatctcMgggDgtNHtDaDttatatVWttgttattt\n\
+aacctttcacaaggaSaDcggttttttatatVtctgVtaacaStDVaKactaMtttaSNa\n\
+gtgaaattaNacttSKctattcctctaSagKcaVttaagNaVcttaVaaRNaHaaHttat\n\
+gtHttgtgatMccaggtaDcgaccgtWgtWMtttaHcRtattgScctatttKtaaccaag\n\
+tYagaHgtWcHaatgccKNRtttagtMYSgaDatctgtgaWDtccMNcgHgcaaacNDaa\n\
+aRaStDWtcaaaaHKtaNBctagBtgtattaactaattttVctagaatggcWSatMaccc\n\
+ttHttaSgSgtgMRcatRVKtatctgaaaccDNatYgaaVHNgatMgHRtacttaaaRta\n\
+tStRtDtatDttYatattHggaBcttHgcgattgaKcKtttcRataMtcgaVttWacatN\n\
+catacctRataDDatVaWNcggttgaHtgtMacVtttaBHtgagVttMaataattatgtt\n\
+cttagtttgtgcDtSatttgBtcaacHattaaBagVWcgcaSYttMgcttacYKtVtatc\n\
+aYaKctgBatgcgggcYcaaaaacgNtctagKBtattatctttKtaVttatagtaYtRag\n\
+NtaYataaVtgaatatcHgcaaRataHtacacatgtaNtgtcgYatWMatttgaactacR\n\
+ctaWtWtatacaatctBatatgYtaagtatgtgtatSttactVatcttYtaBcKgRaSgg\n\
+RaaaaatgcagtaaaWgtaRgcgataatcBaataccgtatttttccatcNHtatWYgatH\n\
+SaaaDHttgctgtccHtggggcctaataatttttctatattYWtcattBtgBRcVttaVM\n\
+RSgctaatMagtYtttaaaaatBRtcBttcaaVtaacagctccSaaSttKNtHtKYcagc\n\
+agaaaccccRtttttaaDcDtaStatccaagcgctHtatcttaDRYgatDHtWcaaaBcW\n\
+gKWHttHataagHacgMNKttMKHccaYcatMVaacgttaKgYcaVaaBtacgcaacttt\n\
+MctaaHaatgtBatgagaSatgtatgSRgHgWaVWgataaatatttccKagVgataattW\n\
+aHNcYggaaatgctHtKtaDtctaaagtMaatVDVactWtSaaWaaMtaHtaSKtcBRaN\n\
+cttStggtBttacNagcatagRgtKtgcgaacaacBcgKaatgataagatgaaaattgta\n\
+ctgcgggtccHHWHaaNacaBttNKtKtcaaBatatgctaHNgtKcDWgtttatNgVDHg\n\
+accaacWctKaaggHttgaRgYaatHcaBacaatgagcaaattactgtaVaaYaDtagat\n\
+tgagNKggtggtgKtWKaatacagDRtatRaMRtgattDggtcaaYRtatttNtagaDtc\n\
+acaaSDctDtataatcgtactaHttatacaatYaacaaHttHatHtgcgatRRttNgcat\n\
+SVtacWWgaaggagtatVMaVaaattScDDKNcaYBYaDatHgtctatBagcaacaagaa\n\
+tgagaaRcataaKNaRtBDatcaaacgcattttttaaBtcSgtacaRggatgtMNaattg\n\
+gatatWtgagtattaaaVctgcaYMtatgatttttYgaHtgtcttaagWBttHttgtctt\n\
+attDtcgtatWtataataSgctaHagcDVcNtaatcaagtaBDaWaDgtttagYctaNcc\n\
+DtaKtaHcttaataacccaRKtacaVaatNgcWRaMgaattatgaBaaagattVYaHMDc\n\
+aDHtcRcgYtcttaaaWaaaVKgatacRtttRRKYgaatacaWVacVcRtatMacaBtac\n\
+tggMataaattttHggNagSctacHgtBagcgtcgtgattNtttgatSaaggMttctttc\n\
+ttNtYNagBtaaacaaatttMgaccttacataattgYtcgacBtVMctgStgMDtagtaR\n\
+ctHtatgttcatatVRNWataDKatWcgaaaaagttaaaagcacgHNacgtaatctttMR\n\
+tgacttttDacctataaacgaaatatgattagaactccSYtaBctttaataacWgaaaYa\n\
+tagatgWttcatKtNgatttttcaagHtaYgaaRaDaagtaggagcttatVtagtctttc\n\
+attaaaatcgKtattaRttacagVaDatgcatVgattgggtctttHVtagKaaRBtaHta\n\
+aggccccaaaaKatggtttaMWgtBtaaacttcactttKHtcgatctccctaYaBacMgt\n\
+cttBaBaNgcgaaacaatctagtHccHtKttcRtRVttccVctttcatacYagMVtMcag\n\
+aMaaacaataBctgYtaatRaaagattaaccatVRatHtaRagcgcaBcgDttStttttc\n\
+VtttaDtKgcaaWaaaaatSccMcVatgtKgtaKgcgatatgtagtSaaaDttatacaaa\n\
+catYaRRcVRHctKtcgacKttaaVctaDaatgttMggRcWaacttttHaDaKaDaBctg\n\
+taggcgtttaHBccatccattcNHtDaYtaataMttacggctNVaacDattgatatttta\n\
+cVttSaattacaaRtataNDgacVtgaacataVRttttaDtcaaacataYDBtttaatBa\n\
+DtttYDaDaMccMttNBttatatgagaaMgaNtattHccNataattcaHagtgaaggDga\n\
+tgtatatatgYatgaStcataaBStWacgtcccataRMaaDattggttaaattcMKtctM\n\
+acaBSactcggaatDDgatDgcWctaacaccgggaVcacWKVacggtaNatatacctMta\n\
+tgatagtgcaKagggVaDtgtaacttggagtcKatatcgMcttRaMagcattaBRaStct\n\
+YSggaHYtacaactMBaagDcaBDRaaacMYacaHaattagcattaaaHgcgctaaggSc\n\
+cKtgaaKtNaBtatDDcKBSaVtgatVYaagVtctSgMctacgttaacWaaattctSgtD\n\
+actaaStaaattgcagBBRVctaatatacctNttMcRggctttMttagacRaHcaBaacV\n\
+KgaataHttttMgYgattcYaNRgttMgcVaaacaVVcDHaatttgKtMYgtatBtVVct\n\
+WgVtatHtacaaHttcacgatagcagtaaNattBatatatttcVgaDagcggttMaagtc\n\
+ScHagaaatgcYNggcgtttttMtStggtRatctacttaaatVVtBacttHNttttaRca\n\
+aatcacagHgagagtMgatcSWaNRacagDtatactaaDKaSRtgattctccatSaaRtt\n\
+aaYctacacNtaRtaactggatgaccYtacactttaattaattgattYgttcagDtNKtt\n\
+agDttaaaaaaaBtttaaNaYWKMBaaaacVcBMtatWtgBatatgaacVtattMtYatM\n\
+NYDKNcKgDttDaVtaaaatgggatttctgtaaatWtctcWgtVVagtcgRgacttcccc\n\
+taDcacagcRcagagtgtWSatgtacatgttaaSttgtaaHcgatgggMagtgaacttat\n\
+RtttaVcaccaWaMgtactaatSSaHtcMgaaYtatcgaaggYgggcgtgaNDtgttMNg\n\
+aNDMtaattcgVttttaacatgVatgtWVMatatcaKgaaattcaBcctccWcttgaaWH\n\
+tWgHtcgNWgaRgctcBgSgaattgcaaHtgattgtgNagtDttHHgBttaaWcaaWagc\n\
+aSaHHtaaaVctRaaMagtaDaatHtDMtcVaWMtagSagcttHSattaacaaagtRacM\n\
+tRtctgttagcMtcaBatVKtKtKacgagaSNatSactgtatatcBctgagVtYactgta\n\
+aattaaaggcYgDHgtaacatSRDatMMccHatKgttaacgactKtgKagtcttcaaHRV\n\
+tccttKgtSataatttacaactggatDNgaacttcaRtVaagDcaWatcBctctHYatHa\n\
+DaaatttagYatSatccaWtttagaaatVaacBatHcatcgtacaatatcgcNYRcaata\n\
+YaRaYtgattVttgaatgaVaactcRcaNStgtgtattMtgaggtNttBaDRcgaaaagc\n\
+tNgBcWaWgtSaDcVtgVaatMKBtttcgtttctaaHctaaagYactgMtatBDtcStga\n\
+ccgtSDattYaataHctgggaYYttcggttaWaatctggtRagWMaDagtaacBccacta\n\
+cgHWMKaatgatWatcctgHcaBaSctVtcMtgtDttacctaVgatYcWaDRaaaaRtag\n\
+atcgaMagtggaRaWctctgMgcWttaagKBRtaaDaaWtctgtaagYMttactaHtaat\n\
+cttcataacggcacBtSgcgttNHtgtHccatgttttaaagtatcgaKtMttVcataYBB\n\
+aKtaMVaVgtattNDSataHcagtWMtaggtaSaaKgttgBtVtttgttatcatKcgHac\n\
+acRtctHatNVagSBgatgHtgaRaSgttRcctaacaaattDNttgacctaaYtBgaaaa\n\
+tagttattactcttttgatgtNNtVtgtatMgtcttRttcatttgatgacacttcHSaaa\n\
+ccaWWDtWagtaRDDVNacVaRatgttBccttaatHtgtaaacStcVNtcacaSRttcYa\n\
+gacagaMMttttgMcNttBcgWBtactgVtaRttctccaaYHBtaaagaBattaYacgat\n\
+ttacatctgtaaMKaRYtttttactaaVatWgctBtttDVttctggcDaHaggDaagtcg\n\
+aWcaagtagtWttHtgKtVataStccaMcWcaagataagatcactctHatgtcYgaKcat\n\
+cagatactaagNSStHcctRRNtattgtccttagttagMVgtatagactaactctVcaat\n\
+MctgtttgtgttgccttatWgtaBVtttctggMcaaKgDWtcgtaaYStgSactatttHg\n\
+atctgKagtagBtVacRaagRtMctatgggcaaaKaaaatacttcHctaRtgtDcttDat\n\
+taggaaatttcYHaRaaBttaatggcacKtgctHVcaDcaaaVDaaaVcgMttgtNagcg\n\
+taDWgtcgttaatDgKgagcSatatcSHtagtagttggtgtHaWtaHKtatagctgtVga\n\
+ttaBVaatgaataagtaatVatSttaHctttKtttgtagttaccttaatcgtagtcctgB\n\
+cgactatttVcMacHaaaggaatgDatggKtaHtgStatattaaSagctWcctccRtata\n\
+BaDYcgttgcNaagaggatRaaaYtaWgNtSMcaatttactaacatttaaWttHtatBat\n\
+tgtcgacaatNgattgcNgtMaaaKaBDattHacttggtRtttaYaacgVactBtaBaKt\n\
+gBttatgVttgtVttcaatcWcNctDBaaBgaDHacBttattNtgtDtatttVSaaacag\n\
+gatgcRatSgtaSaNtgBatagttcHBgcBBaaattaHgtDattatDaKaatBaaYaaMa\n\
+ataaataKtttYtagtBgMatNcatgtttgaNagtgttgtgKaNaSagtttgaSMaYBca\n\
+aaacDStagttVacaaaaactaaWttBaagtctgtgcgtMgtaattctcctacctcaNtt\n\
+taaccaaaaVtBcacataacaccccBcWMtatVtggaatgaWtcaaWaaaaaaaaWtDta\n\
+atatRcctDWtcctaccMtVVatKttaWaaKaaatataaagScHBagaggBaSMtaWaVt\n\
+atattactSaaaKNaactatNatccttgaYctattcaaaVgatttYHcRagattttaSat\n\
+aggttattcVtaaagaKgtattattKtRttNcggcRgtgtgtWYtaacHgKatKgatYta\n\
+cYagDtWcHBDctctgRaYKaYagcactKcacSaRtBttttBHKcMtNtcBatttatttt\n\
+tgSatVgaaagaWtcDtagDatatgMacaacRgatatatgtttgtKtNRaatatNatgYc\n\
+aHtgHataacKtgagtagtaacYttaNccaaatHcacaacaVDtagtaYtccagcattNt\n\
+acKtBtactaaagaBatVtKaaHBctgStgtBgtatgaSNtgDataaccctgtagcaBgt\n\
+gatcttaDataStgaMaccaSBBgWagtacKcgattgaDgNNaaaacacagtSatBacKD\n\
+gcgtataBKcatacactaSaatYtYcDaactHttcatRtttaatcaattataRtttgtaa\n\
+gMcgNttcatcBtYBagtNWNMtSHcattcRctttttRWgaKacKttgggagBcgttcgc\n\
+MaWHtaatactgtctctatttataVgtttaBScttttaBMaNaatMacactYtBMggtHa\n\
+cMagtaRtctgcatttaHtcaaaatttgagKtgNtactBacaHtcgtatttctMaSRagc\n\
+agttaatgtNtaaattgagagWcKtaNttagVtacgatttgaatttcgRtgtWcVatcgt\n\
+taaDVctgtttBWgaccagaaagtcSgtVtatagaBccttttcctaaattgHtatcggRa\n\
+ttttcaaggcYSKaagWaWtRactaaaacccBatMtttBaatYtaagaactSttcgaaSc\n\
+aatagtattgaccaagtgttttctaacatgtttNVaatcaaagagaaaNattaaRtttta\n\
+VaaaccgcaggNMtatattVctcaagaggaacgBgtttaacaagttcKcYaatatactaa\n\
+ccBaaaSggttcNtattctagttRtBacgScVctcaatttaatYtaaaaaaatgSaatga\n\
+tagaMBRatgRcMcgttgaWHtcaVYgaatYtaatctttYttatRaWtctgBtDcgatNa\n\
+tcKaBaDgatgtaNatWKctccgatattaacattNaaacDatgBgttctgtDtaaaMggt\n\
+gaBaSHataacgccSctaBtttaRBtcNHcDatcDcctagagtcRtaBgWttDRVHagat\n\
+tYatgtatcWtaHtttYcattWtaaagtctNgtStggRNcgcggagSSaaagaaaatYcH\n\
+DtcgctttaatgYcKBVSgtattRaYBaDaaatBgtatgaHtaaRaRgcaSWNtagatHa\n\
+acttNctBtcaccatctMcatattccaSatttgcgaDagDgtatYtaaaVDtaagtttWV\n\
+aagtagYatRttaagDcNgacKBcScagHtattatcDaDactaaaaaYgHttBcgaDttg\n\
+gataaaKSRcBMaBcgaBSttcWtgNBatRaccgattcatttataacggHVtaattcaca\n\
+agagVttaaRaatVVRKcgWtVgacctgDgYaaHaWtctttcacMagggatVgactagMa\n\
+aataKaaNWagKatagNaaWtaaaatttgaattttatttgctaaVgaHatBatcaaBWcB\n\
+gttcMatcgBaaNgttcgSNaggSaRtttgHtRtattaNttcDcatSaVttttcgaaaaa\n\
+ttgHatctaRaggSaNatMDaaatDcacgattttagaHgHaWtYgattaatHNSttatMS\n\
+gggNtcKtYatRggtttgtMWVtttaYtagcagBagHaYagttatatggtBacYcattaR\n\
+SataBatMtttaaatctHcaaaSaaaagttNSaaWcWRccRtKaagtBWtcaaattSttM\n\
+tattggaaaccttaacgttBtWatttatatWcDaatagattcctScacctaagggRaaYt\n\
+aNaatgVtBcttaaBaacaMVaaattatStYgRcctgtactatcMcVKatttcgSgatRH\n\
+MaaaHtagtaaHtVgcaaataatatcgKKtgccaatBNgaaWcVttgagttaKatagttc\n\
+aggKDatDtattgaKaVcaKtaataDataataHSaHcattagttaatRVYcNaHtaRcaa\n\
+ggtNHcgtcaaccaBaaagYtHWaaaRcKgaYaaDttgcWYtataRgaatatgtYtgcKt\n\
+aNttWacatYHctRaDtYtattcBttttatcSataYaYgttWaRagcacHMgtttHtYtt\n\
+YaatcggtatStttcgtRSattaaDaKMaatatactaNBaWgctacacYtgaYVgtgHta\n\
+aaRaaRgHtagtWattataaaSDaaWtgMattatcgaaaagtaYRSaWtSgNtBgagcRY\n\
+aMDtactaacttaWgtatctagacaagNtattHggataatYttYatcataDcgHgttBtt\n\
+ctttVttgccgaaWtaaaacgKgtatctaaaaaNtccDtaDatBMaMggaatNKtatBaa\n\
+atVtccRaHtaSacataHattgtttKVYattcataVaattWtcgtgMttcttKtgtctaa\n\
+cVtatctatatBRataactcgKatStatattcatHHRttKtccaacgtgggtgRgtgaMt\n\
+attattggctatcgtgacMtRcBDtcttgtactaatRHttttaagatcgVMDStattatY\n\
+BtttDttgtBtNttgRcMtYtgBacHaWaBaatDKctaagtgaaactaatgRaaKgatcc\n\
+aagNaaaatattaggWNtaagtatacttttKcgtcggSYtcttgRctataYcttatataa\n\
+agtatattaatttataVaacacaDHatctatttttKYVatHRactttaBHccaWagtact\n\
+BtcacgaVgcgttRtttttttSVgtSagtBaaattctgaHgactcttgMcattttagVta\n\
+agaattHctHtcaDaaNtaacRggWatagttcgtSttgaDatcNgNagctagDgatcNtt\n\
+KgttgtaDtctttRaaYStRatDtgMggactSttaDtagSaVtBDttgtDgccatcacaM\n\
+attaaaMtNacaVcgSWcVaaDatcaHaatgaattaMtatccVtctBtaattgtWattat\n\
+BRcWcaatgNNtactWYtDaKttaaatcactcagtRaaRgatggtKgcgccaaHgaggat\n\
+StattYcaNMtcaBttacttatgagDaNtaMgaaWtgtttcttctaHtMNgttatctaWW\n\
+atMtBtaaatagDVatgtBYtatcggcttaagacMRtaHScgatatYgRDtcattatSDa\n\
+HggaaataNgaWSRRaaaBaatagBattaDctttgHWNttacaataaaaaaatacggttt\n\
+gHgVtaHtWMttNtBtctagtMcgKMgHgYtataHaNagWtcaacYattaataYRgtaWK\n\
+gaBctataaccgatttaHaNBRaRaMtccggtNgacMtctcatttgcaattcWgMactta\n\
+caaDaaNtactWatVtttagccttMaatcagVaagtctVaaDaBtattaattaYtNaYtg\n\
+gattaKtaKctYaMtattYgatattataatKtVgDcttatatNBtcgttgtStttttMag\n\
+aggttaHYSttcKgtcKtDNtataagttataagSgttatDtRttattgttttSNggRtca\n\
+aKMNatgaatattgtBWtaMacctgggYgaSgaagYataagattacgagaatBtggtRcV\n\
+HtgYggaDgaYaKagWagctatagacgaaHgtWaNgacttHRatVaWacKYtgRVNgVcS\n\
+gRWctacatcKSactctgWYtBggtataagcttNRttVtgRcaWaaatDMatYattaact\n\
+ttcgaagRatSctgccttgcRKaccHtttSNVagtagHagBagttagaccaRtataBcca\n\
+taatSHatRtcHagacBWatagcaMtacaRtgtgaaBatctKRtScttccaNaatcNgta\n\
+atatWtcaMgactctBtWtaaNactHaaaaRctcgcatggctMcaaNtcagaaaaacaca\n\
+gtggggWttRttagtaagaVctVMtcgaatcttcMaaaHcaHBttcgattatgtcaDagc\n\
+YRtBtYcgacMgtDcagcgaNgttaataatagcagKYYtcgtaBtYctMaRtaRtDagaa\n\
+aacacatgYaBttgattattcgaaNttBctSataaMataWRgaHtttccgtDgaYtatgg\n\
+tDgHKgMtatttVtMtVagttaRatMattRagataaccctKctMtSttgaHagtcStcta\n\
+tttccSagatgttccacgaggYNttHRacgattcDatatDcataaaatBBttatcgaHtN\n\
+HaaatatDNaggctgaNcaaggagttBttMgRagVatBcRtaWgatgBtSgaKtcgHttt\n\
+gaatcaaDaHttcSBgHcagtVaaSttDcagccgttNBtgttHagYtattctttRWaaVt\n\
+SttcatatKaaRaaaNacaVtVctMtSDtDtRHRcgtaatgctcttaaatSacacaatcg\n\
+HattcaWcttaaaatHaaatcNctWttaNMcMtaKctVtcctaagYgatgatcYaaaRac\n\
+tctaRDaYagtaacgtDgaggaaatctcaaacatcaScttcKttNtaccatNtaNataca\n\
+tttHaaDHgcaDatMWaaBttcRggctMaagctVYcacgatcaDttatYtaatcKatWat\n\
+caatVYtNagatttgattgaYttttYgacttVtcKaRagaaaHVgDtaMatKYagagttN\n\
+atWttaccNtYtcDWgSatgaRgtMatgKtcgacaagWtacttaagtcgKtgatccttNc\n\
+ttatagMatHVggtagcgHctatagccctYttggtaattKNaacgaaYatatVctaataM\n\
+aaaYtgVtcKaYtaataacagaatHcacVagatYWHttagaaSMaatWtYtgtaaagNaa\n\
+acaVgaWtcacNWgataNttcaSagctMDaRttgNactaccgataMaaatgtttattDtc\n\
+aagacgctDHYYatggttcaagccNctccttcMctttagacBtaaWtaWVHggaaaaNat\n\
+ttaDtDtgctaaHHtMtatNtMtagtcatttgcaaaRatacagRHtatDNtgtDgaatVg\n\
+tVNtcaaatYBMaaaagcaKgtgatgatMgWWMaHttttMgMagatDtataaattaacca\n\
+actMtacataaattgRataatacgBtKtaataattRgtatDagDtcRDacctatRcagag\n\
+cSHatNtcaScNtttggacNtaaggaccgtgKNttgttNcttgaaRgYgRtNtcagttBc\n\
+ttttcHtKtgcttYaaNgYagtaaatgaatggWaMattBHtatctatSgtcYtgcHtaat\n\
+tHgaaMtHcagaaSatggtatgccaHBtYtcNattWtgtNgctttaggtttgtWatNtgH\n\
+tgcDttactttttttgcNtactKtWRaVcttcatagtgSNKaNccgaataaBttataata\n\
+YtSagctttaaatSttggctaaKSaatRccgWHgagDttaaatcatgagMtcgagtVtaD\n\
+ggaBtatttgDacataaacgtagYRagBWtgDStKDgatgaagttcattatttaKWcata\n\
+aatWRgatataRgttRacaaNKttNtKagaaYaStaactScattattaacgatttaaatg\n\
+DtaattagatHgaYataaactatggggatVHtgccgtNgatNYcaStRtagaccacWcaM\n\
+tatRagHgVactYtWHtcttcatgatWgagaKggagtatgaWtDtVtNaNtcgYYgtaaa\n\
+ctttaDtBactagtaDctatagtaatatttatatataacgHaaaRagKattSagttYtSt\n\
+>THREE Homo sapiens frequency\n\
+agagagacgatgaaaattaatcgtcaatacgctggcgaacactgagggggacccaatgct\n\
+cttctcggtctaaaaaggaatgtgtcagaaattggtcagttcaaaagtagaccggatctt\n\
+tgcggagaacaattcacggaacgtagcgttgggaaatatcctttctaccacacatcggat\n\
+tttcgccctctcccattatttattgtgttctcacatagaattattgtttagacatccctc\n\
+gttgtatggagagttgcccgagcgtaaaggcataatccatataccgccgggtgagtgacc\n\
+tgaaattgtttttagttgggatttcgctatggattagcttacacgaagagattctaatgg\n\
+tactataggataattataatgctgcgtggcgcagtacaccgttacaaacgtcgttcgcat\n\
+atgtggctaacacggtgaaaatacctacatcgtatttgcaatttcggtcgtttcatagag\n\
+cgcattgaattactcaaaaattatatatgttgattatttgattagactgcgtggaaagaa\n\
+ggggtactcaagccatttgtaaaagctgcatctcgcttaagtttgagagcttacattagt\n\
+ctatttcagtcttctaggaaatgtctgtgtgagtggttgtcgtccataggtcactggcat\n\
+atgcgattcatgacatgctaaactaagaaagtagattactattaccggcatgcctaatgc\n\
+gattgcactgctatgaaggtgcggacgtcgcgcccatgtagccctgataataccaatact\n\
+tacatttggtcagcaattctgacattatacctagcacccataaatttactcagacttgag\n\
+gacaggctcttggagtcgatcttctgtttgtatgcatgtgatcatatagatgaataagcg\n\
+atgcgactagttagggcatagtatagatctgtgtatacagttcagctgaacgtccgcgag\n\
+tggaagtacagctgagatctatcctaaaatgcaaccatatcgttcacacatgatatgaac\n\
+ccagggggaaacattgagttcagttaaattggcagcgaatcccccaagaagaaggcggag\n\
+tgacgttgaacgggcttatggtttttcagtacttcctccgtataagttgagcgaaatgta\n\
+aacagaataatcgttgtgttaacaacattaaaatcgcggaatatgatgagaatacacagt\n\
+gtgagcatttcacttgtaaaatatctttggtagaacttactttgctttaaatatgttaaa\n\
+ccgatctaataatctacaaaacggtagattttgcctagcacattgcgtccttctctattc\n\
+agatagaggcaatactcagaaggttttatccaaagcactgtgttgactaacctaagtttt\n\
+agtctaataatcatgattgattataggtgccgtggactacatgactcgtccacaaataat\n\
+acttagcagatcagcaattggccaagcacccgacttttatttaatggttgtgcaatagtc\n\
+cagattcgtattcgggactctttcaaataatagtttcctggcatctaagtaagaaaagct\n\
+cataaggaagcgatattatgacacgctcttccgccgctgttttgaaacttgagtattgct\n\
+cgtccgaaattgagggtcacttcaaaatttactgagaagacgaagatcgactaaagttaa\n\
+aatgctagtccacagttggtcaagttgaattcatccacgagttatatagctattttaatt\n\
+tatagtcgagtgtacaaaaaacatccacaataagatttatcttagaataacaacccccgt\n\
+atcatcgaaatcctccgttatggcctgactcctcgagcttatagcatttgtgctggcgct\n\
+cttgccaggaacttgctcgcgaggtggtgacgagtgagatgatcagtttcattatgatga\n\
+tacgattttatcgcgactagttaatcatcatagcaagtaaaatttgaattatgtcattat\n\
+catgctccattaacaggttatttaattgatactgacgaaattttttcacaatgggttttc\n\
+tagaatttaatatcagtaattgaagccttcataggggtcctactagtatcctacacgacg\n\
+caggtccgcagtatcctggagggacgtgttactgattaaaagggtcaaaggaatgaaggc\n\
+tcacaatgttacctgcttcaccatagtgagccgatgagttttacattagtactaaatccc\n\
+aaatcatactttacgatgaggcttgctagcgctaaagagaatacatacaccaccacatag\n\
+aattgttagcgatgatatcaaatagactcctggaagtgtcagggggaaactgttcaatat\n\
+ttcgtccacaggactgaccaggcatggaaaagactgacgttggaaactataccatctcac\n\
+gcccgacgcttcactaattgatgatccaaaaaatatagcccggattcctgattagcaaag\n\
+ggttcacagagaaagatattatcgacgtatatcccaaaaaacagacgtaatgtgcatctt\n\
+cgaatcgggatgaatacttgtatcataaaaatgtgacctctagtatacaggttaatgtta\n\
+gtgatacacaatactcgtgggccatgggttctcaaataaaatgtaatattgcgtcgatca\n\
+ctcacccacgtatttggtctaattatgttttatttagtgacaatccaatagataaccggt\n\
+cctattaagggctatatttttagcgaccacgcgtttaaacaaaggattgtatgtagatgg\n\
+taccagtttaattgccagtgggcaatcctaagcaaaatgagattctatcctaaagtttgg\n\
+gcttgatataagatttcggatgtatgggttttataatcgttggagagctcaatcatgagc\n\
+taatacatggatttcgctacctcaccgagagaccttgcatgaagaattctaaccaaaagt\n\
+ttaataggccggattggattgagttaattaagaccttgttcagtcatagtaaaaaccctt\n\
+aaattttaccgattgacaaagtgagcagtcgcaataccctatgcgaaacgcctcgatagt\n\
+gactaggtatacaaggtttttgagttcctttgaaatagttaactaatttaaaattaatta\n\
+acgacatggaaatcacagaacctaatgctttgtaggagttatttatgctgtttactgcct\n\
+ctacaaccctaataaagcagtcctaagaatgaaacgcatcttttagttcagaaagtggta\n\
+tccagggtggtcaatttaataaattcaacatcgggtctcaggatattcggtcatataatt\n\
+tattaagggctcttcgagtcttactctgagtgaaattggaaacagtcatccttttcgttg\n\
+tgaggcatcttacaccgctatcgatatacaatgcattccaccgcggtgtcccgtacacaa\n\
+ggaaacttgttaccttggggatataagaaaactcacacgtctcattattaaactgagtac\n\
+aatttttgcacgagaaagtaatgcaatacaatatgatgaaagccagctaatgaaaaggga\n\
+tggaacgcacctcggatctgttgcactggattaaaatccgattatttttaaaaatattca\n\
+gtgctagagcatatcaggtctacttttttatctggtatgtaaagcccacggagcgatagt\n\
+gagatccttacgactcaacgaaaagttataacataactcccgttagccaaagcccaatcc\n\
+cgattactgccctaccctaacgtctgccatctaaatatcgaacttgttatgatcaatgtg\n\
+actacctcccaccctttccccttcatttgttccactggggataagctagcgttttcagaa\n\
+tcaatgcaataagaatagccaattgtctcacttcatcagagctcttggcaattccaggcg\n\
+ctacgtggttctggaatatattcatttttcaaatagtaatacgtttagtgttgctattgt\n\
+ctacacgtttggatattacgttatgtgagcggacatcaatagttgtctaactctttagta\n\
+agccagagatagcactcttagcgaatggataccatcttccataagtttagttaatagtcc\n\
+gaaacaactgcttcgagcatatttgaacctccttgtaggcaaatagcctcttcaaagcaa\n\
+tcttactaatagatagagtttgttttaagggactactagaaatgggacaatcttaatagt\n\
+atgacctaaactgacatttaaagatatatccaggtggcaagcataaagatcattgcgcca\n\
+cctccaccgtgggattacttatcagtcgatatcctatatgctaagtttgcgacggcagaa\n\
+tacaaactaagctgagttgatgctaaccttacctatgataccccattggaccggttaaca\n\
+gccctacttattccaaataaaagaacttttatgctgtagaagctattatagtgatgcctg\n\
+gtaacttcagtatattaaaatgacacacatacgccatatagagctcctggaactttgaat\n\
+aatgagcgaacttcgaagttgaagagcaagaaaccatatgtcacggttgcctaaagcccg\n\
+gtaaccagacatgtgctatcattgatcattatcgaggttttcataaccttgacccattat\n\
+cggctgtgcgcggacaagtacttaaatcactagtttcttcacctgcttatcggtaagaaa\n\
+taaggttggcaaagaatcgcataagacggacgtagagccgcagcgttgtgcgagtccagg\n\
+tgcatgcgcagcaataggattttaaattttgttccatttttaatttagccgtaaggatgt\n\
+ccgtaaatgattgaaaattggattcaatctttgggcctatgctactggaacctgatcgac\n\
+aaaatttcaaacatacgttaactccgaaagaccgtatttttgcggctagaatagtcagtc\n\
+gcttggagccatataccttaccacttaaacgacgtgctcctgtagttgaaatataaacag\n\
+aacacaaagactaccgatcatatcaactgaagatctttgtaactttgaggcgaagcaccc\n\
+tcttcgagacaactaagagtaaagtaccgggcgccgcaaggagtcgattgggaccctaaa\n\
+tcttgacgaattgctaagaggctcagagctaccactgtaatttctctagagcccataata\n\
+aatgaacgatacatccgtaggtagcacctaagggattataatggaagccaaatgcagtta\n\
+ataatattatatactggcgtacacgattcgacggatctctcacatagtgattcacgaccc\n\
+ccccctttgattgacacagcgtcagcattttgcaagaacgatcttctgcatagggtgcgc\n\
+caccgtaaggatgacgtcgaagctacaactgggtataatttaccatgcttccctgatgct\n\
+gagtgcaatacactaagaatgagtttttaccccatatcaccagtatttgttctgttattg\n\
+cgaagaaatggctatgctgagttggcgactaaagtcacccatcctttttattaggtaacc\n\
+ccctcccttaaactaactgatttgctggagctgccctgcatacatatactttatcattta\n\
+tggacgtccgtgacgcttattatccaccatagtcgatatgctacacggattcattaatgg\n\
+atcgtaggagtttaagttatatttactaagatcggtctcggctactatcccgccttaccc\n\
+ggcgctatttacggccatttttaatatattgacggtaattattcctatggtttcgaccgc\n\
+acgtccttggacaagaaagaatggcaaaaaaaatgtaaaagaaaaaaaatattgagtccc\n\
+taccatcatataaaaaatatgtgatgagtaacttgacgaaatgttagtggttattaaaga\n\
+ctatctattacaccttttgttttctgtcgtagtatattaaagtctagaagccttacagga\n\
+aaatcagggttatacagccgatactccgcagcatgaatcatcgaggaggtgtcctaccat\n\
+cgcgccttgtaatcttgtctgtgtatactgtatttagaccttttatacaaagtaaatatc\n\
+tcggctttatgtgattgggaggggcctactcaaacatgatgacttgacctaataatcact\n\
+gtgcgggcgtcttatgactagctattccttgaaatccaccaccaaatggttaatatgtaa\n\
+aaactttgacgatgaaacaaggtgaatgtgtagttactttgtgtaattagctgcgtcgag\n\
+cattgcttgtaaaaccgtcaatcgcacacgttacttccataaaatttctacgaatacacc\n\
+cttcttaaaaaaaacgtaggaattcacgagtttaacaaacgataactgtataaagtggaa\n\
+gtccgaagaaagcagatgcccgaactactcgaagatgtttcgttttcttaaccatagggg\n\
+cttcttaatggcccactacgcacattttgttcaagcccgagagggacatccccattacgg\n\
+gagtattactaaaactgttccgtaatacgttcagcaagggatgaaaaaggccactgctca\n\
+agttattgacgtgggagtattacatcggaagcctgaatcccacactatgatggtctgtac\n\
+aggcctagggactgcgtctagacggtattaccggcttctaatcatacgatcgtgagtctt\n\
+aacgggaagtaaggctcacacctaccccaaaccatttatctatgtaagtataaaattgtg\n\
+cgtaagtgttcaaagtggacaataaagacgtggcaaaaacccccgcacataagccgcttt\n\
+agatttcacaaataccaatgcggttaaaaacatccttgagtcgtacatacaccatactcg\n\
+cgttaaacggatataacagaagataataaatccggatgtggagtcggtgtaactatagaa\n\
+agccaagtgaaataatgcttaccagtcatttagctatacggctttcatttcatgtcaaga\n\
+gggtggagtttgacctgtacagttgatatatcaccgatacttagaactcacctaaagcta\n\
+aaattgctcgcagcgtgtaatccgcatattacaaacaatagatgggattcattatacata\n\
+agacacgatgatctgctttttcaggttgcgagatgttgcctatcgtcaatcgagtcctgc\n\
+cttacaccacttaaacaaaagtattgacagggaacctattttcgaggtattatatagtcc\n\
+agcttgaatatcaatttgacagttaacctagtgaaaatcagtaagaggaaatacgccaca\n\
+ttctccagtgaaattctacgggttatcgtctagtccaactatcaattataactcacgaga\n\
+tataagtaaattctcgtacttggcctgatttttattatactttggatccttagtaaacag\n\
+gaagggagaaaccttcaacgaaaaacactggattttgttttactctcaaagctcttatat\n\
+gacggaaataccctgtcaagtcttaactttattactagactaatgaaatgggcttggggt\n\
+ggccagaatcatagtacaatttagcggatacactattcggactttcctatcggctgtctg\n\
+gttggataagtatggggactaataggctagacatacctatacttaaactatacaggcgtc\n\
+atctatctctgcaactttggagttccctgatgttctcccgccctttgggttcacatcttc\n\
+tataccgacacccctaataacgattagtttgtgggttagagtaaattaatacggttaata\n\
+ttaatgtatcgttgaaaagctggtgtcgccaataaggtaaccggctaggcagagtatatg\n\
+tcacgaagtataactaccctaatgataagctgtaggaataaaattaatgctgtctctaag\n\
+cgaagagatatttccgactctgttttaatgacgaatctcattacttctgacttgcaaatg\n\
+ttcaatatggcacggtttcacggcacctttgtgacgcatataatgaacttagaagattat\n\
+aacgacggaactttatatgataatccgttacgattaaagaatctgttaaatatcataatg\n\
+gcattcagttctagaccgtgcatcatggtaaacttactttctctgcatggcgacatacat\n\
+ttcgctattcaaattcgcgtgtggttacacccactcgcacctttggaatattaagagaag\n\
+atgatcagaaaatccattcgctcaatttttctgacgtacgtctaatttatcctaggagac\n\
+aaatcgttttatgtctctcacatttttgaagaaaggttcgagagacaatactcaggtcct\n\
+gaactgctagaagatactcggtggagcgtggcaacaatgaaaaactcgtgacataaatga\n\
+atgatacttttccaagttcagttaagtgaatatgtttaacatacccggcttttcgatctt\n\
+aagctgacgctggacgtgcgagtaatgtcagtctcttacatacactagtgactccaagtt\n\
+tcgtcaaaaacgccccctcccttctcgagcccactcacgctatgtattgacgcgaacttg\n\
+ttcgggatcagacttttcaggagttcggtcgcgtgtccctatgtgctaatatataagtta\n\
+gatcgcattagatgctaatctgaatacttatagacgaccttcaacgagaacgggtaccac\n\
+cttgaggctagagttaggtgtgaaacgacaggtagggacatataaaatttgagtgcggct\n\
+ttagttaagggtttaattacctactcaaacatcacgctcgcgcccttcgtacgtaatcga\n\
+ccatctagaggctaaggggactgtactaggtagtgattaatgatatcctagacgcacgtg\n\
+ccttagatcttcagactctgatggtccgcgatcaccgtaattgtagtcctccaactcgat\n\
+cactttgttggcgtcaaagaaattacgatatctaaatacttataatacaataaccaagga\n\
+tgagaatgactcatcgcgttggagttatattgcttgaagttctatggaatgaaagcacgt\n\
+tatctgccgtcccaatatctccagtgagctaattcattggacggtccactttgatcaatc\n\
+cccgaggagatgttcggacactttagtctgtaacacttagcgttgagaccacgaacaatt\n\
+gattactcagtcttgaaggtgttttccaaagttcattttaaataagactacgataggcct\n\
+ttcctattgatataaactacccggctctgttgttcgtgtgagtcgtacttctctgtgttt\n\
+ttctgattatagcaagattcgattcttagtgtaaacagcgatttttatttgacccgtcaa\n\
+tgagaagcgcataggatctaagcaaaattatcaagttgtgccacaaggtaagatctttcc\n\
+agttattgcaggtaggatgtatcccacgttgatagtatgaggtctgacgtcaactgtcta\n\
+ggagagttgaccgcgtgcgggtacaccggatttgcatcgatgttgagaacgcagaactcc\n\
+cactgtcgtggcggcgttcctgatatttagcaagaggcgttgataaagccctcatcatct\n\
+agatctcgacctcatctgccctcttgctccatcattttctacacagactactttcctatc\n\
+tacgttagtataattgctttctatcttagtatcatttagagcttctccgtcaacaggttc\n\
+gtgctattaaagttagtacgaaagggacaacttgtagcaacgcatttaatcggttttcga\n\
+ctacttcgcacaaaatcagataaagaagtttgtcattctattagacattgaattgcgcaa\n\
+ttgacttgtaccacttatgatcgaacactgaatcaagactgtgattaactaaaatagaca\n\
+agccactatatcaactaataaaaacgcccctggtggtcgaacatagttgactacaggata\n\
+attaattggactggagccattacattctctacaatcgtatcacttcccaagtagacaact\n\
+ttgaccttgtagtttcatgtacaaaaaaatgctttcgcaggagcacattggtagttcaat\n\
+agtttcatgggaacctcttgagccgtcttctgtgggtgtgttcggatagtaggtactgat\n\
+aaagtcgtgtcgctttcgatgagagggaattcaccggaaaacaccttggttaacaggata\n\
+gtctatgtaaacttcgagacatgtttaagagttaccagcttaatccacggtgctctacta\n\
+gtatcatcagctgtcttgcctcgcctagaaatatgcattctatcgttatcctatcaacgg\n\
+ttgccgtactgagcagccttattgtggaagagtaatatataaatgtagtcttgtctttac\n\
+gaagcagacgtaagtaataatgacttggaataccaaaactaaacatagtggattatcata\n\
+ctcaagaactctccagataaataacagtttttacgatacgtcaccaatgagcttaaagat\n\
+taggatcctcaaaactgatacaaacgctaattcatttgttattggatccagtatcagtta\n\
+aactgaatggagtgaagattgtagaatgttgttctggcctcgcatggggtctaggtgata\n\
+tacaatttctcatacttacacggtagtggaaatctgattctagcttcgtagctgactata\n\
+ctcaaggaaccactgctcaaggtaggagactagttccgaccctacagtcaaagtggccga\n\
+agcttaaactatagactagttgttaaatgctgatttcaagatatcatctatatacagttt\n\
+ggacaattatgtgtgcgaaactaaaattcatgctattcagatggatttcacttatgcctt\n\
+agaaacagatattgcccgagctcaatcaacagttttagccggaaacaatcgaagcatagg\n\
+gacaatgtatcttttcctaaattgccatgtgcagatttctgagtgtcacgaagcgcataa\n\
+tagaatcttgtgttgcctcaactcgttgaaaagtttaaaacaatcgcagcagtctttttg\n\
+gggtctactgtgtgtttgcaaaataactgaaagaaacgcttgaacaactctgaagtagct\n\
+cgagtactcattaaagtgtaacacattagtgaatatcggccaatgaaccaaacgcttccc\n\
+ggtacgctatctctctcatcgggaggcgatgtgcaggttatctacgaaagcatcccttta\n\
+cgttgagagtgtcgatgcatgaacctcattgtaacaatagcccagcaaattctcatacgt\n\
+gcctcagggtccgggcgtactcctccatggaagggcgcgcatctagtgttataccaactc\n\
+gctttttaactactatgctgtagttctacaggcatagtggccagtattttctaacttctc\n\
+tggatagatgctctcactcctcatccatcacggcttcagtttacgtcttacttgcttgtt\n\
+cagcaacggatggaggcattaagtatcttcactgttccctaaaattgctgttcaatatca\n\
+aagtaaggacgatacagggaaagctcaagcacactcattgaatactgccccagttgcaac\n\
+ctcacttaatctgacaaaaataatgactactctaagtgttgcggaagcagtctcttccac\n\
+gagcttgtctgtatcacttcgtataggcatgtaactcgatagacacgaacaccgagtgag\n\
+aaactatattcttgcttccgtgtgtgtgacaccaggtaattgatgcggatataagctgga\n\
+gatcactcacgcccacacaaggcgctgctacctctttattccaatgtgtaagaatttgct\n\
+aacttcatttctagaccgcagctttgcggtcataatttcacggtacggacccttgggtta\n\
+gagacttgataacacacttcgcagtttccaccgcgcacatgttttagtggcttctaacat\n\
+agaatttttgttgtgacataaagagtgcgtgggagacttgcccgaccgttaagccataat\n\
+caattgaaagccccgtgagtcacatctaattggttgtactgcgcatttagctatccttta\n\
+gctgactcgaagagattcgattcctaatataggttaattagatggctgccgcgcgaagta\n\
+aaacgtgaaaaacgtagtgcgcagatctgcataactcgcgcttaattacttatgagtagt\n\
+tccaagttcgctacgttatgagagagattggaattaagcaaatatgttttatggtgattt\n\
+tgggatgagaaggactgctaagtacggctactaaacaaatttctaaaaccgccatctacc\n\
+ttatcttggagacatttaagttgtatatgtcactagtctagcttttgtctgtgggacgcg\n\
+ttctcggaatgagggaaatgcaagagccgattcatcaaatgcttatctaagaaagtagtg\n\
+gactattacaccaagcacgaatgccagggaactgctttcttgctcaggacctcgcgacaa\n\
+ggtaccccgcataagtcctagaattacatttggtcagcaatgctgacatttgaccgtgaa\n\
+aacataattttaatcagaaggcagctcacccgcttgctctagatcttatctttgtatgaa\n\
+tgtcagaatttactgcaatatccgttccgaatagtgagggcttagtatagttctctgtat\n\
+acaggtcacatcaaactccccctgtcctagtacagctctgagctttaattaattgcatac\n\
+atttccttcaatcatcagatgaaaacaccgcgaatcatgctcttctcgtatagggcaaga\n\
+gaagcaacaaacaactagcccgactcacgttcatccgccgtatccttgttcagttcttac\n\
+tccgtattaggtcagcgaaatctaatcagaataatcggtcgcgtatcaaaattaaaatcc\n\
+cgcttgaggttgacaattaaaacgctgagcagttatcggctattagatagtggggtgaaa\n\
+gtaattggctggaattatgttaaaacgtgatattaagctaaaatacgctacttgttgccg\n\
+acctaattcagtcattcgatattcagttagagccaagaataacaagcttgtataaattga\n\
+acggggtgcactaaacgatgtgttactctaatattcagcttggagtatacctgaaggcga\n\
+attcatgtatcggccaataataagacgttgaagatcacaatttggactagcaaaagaagg\n\
+tgatttatgcgtggggattgagtccactgtacgagtacggtctctggaaaattataggtt\n\
+cagggaatataaggaagtaaagataattaccaagagatttttggtatcgctatgacccag\n\
+aggtgttctaacgtctgttttgatccgcagaatttctgcctcaatgcatatttgacggac\n\
+ttgaactagagcctctaaagttaaatggcgacgcaactgttcctaaacttcaattattac\n\
+tactctttttttcctagggtattgtagaggccagtggacaaaataaatcaaatttaagat\n\
+gtttcggacattaacatcccccgtagcatagaaatcatcagttatccaatctctcatcga\n\
+gcttttacaatttctgctggcgctatggacagcatatgccgcgagacctccgcaagactc\n\
+acttgatcactgtaagtatcttcattagaggttagagcctatagttaagctgctgaccta\n\
+gtaaaattggtattttctaattttattgctcaagttaaaggttagtgaagggataatgac\n\
+gttatttttgaacaatgggttgtattcaattttatatcacgaatggaacccttcattccc\n\
+ggcataatactagacgacacgaacaagctccgatctatcagccaggcacgtgttaaggtt\n\
+taattccggcaaaccaatgaagcatcaaaaggtgacctgatgcaacttagggtcacgatg\n\
+agtttttcaggactacttattacctattaataagttaacatgagccttcataccccgtaa\n\
+gacaatacatactccaccaattagaattctgagccatcttatctttttgtatcatcgaag\n\
+ggtatggccgaataggttaattagttactcctaacgtctctacaggcatgcatttgacgc\n\
+accttcgaaaatagtcaatctctcgccacacgcgtctagtatgcagcatcaaaaatatag\n\
+tccacggtttccggattaccaaacgcggcaaagagaaacattgtatcgacggagataact\n\
+taatacagaaggaaggggcatcttcgaatacggatgaataattctatctgtttattctga\n\
+catcttgttttcaggttaatcttacgcattcaaatgacgcctgccccatgcgtgcgcaat\n\
+tattttctaatattgacgagagcaatctcactccttttgggtctatttatgttttattga\n\
+ggcacaagcctatacagaacaggtactattaaggccgtgagtgtgagactcaaaccgtgg\n\
+aaacaaaggatgggttgttcttggtacaagttttagtgcatgtgggcaatccttaccaaa\n\
+atcagatgctatccttaactttgggctgcatttaagatggcggttggaggcctgtgagaa\n\
+tcctgcgtgtcatctttaatgaccgaattcatccatgtagattcagatcacacactcatt\n\
+ccttgatgttgtctaaacaaaagttgttgtggacgcattggagggagttaagtaacaact\n\
+tgggatcgcatacttataaaaattatatgttaaactttcacaaacgctgaagtccaaagt\n\
+aactagcccaaacgcctcgagagtcactaggtattaatggtgtttgagttcctgtgaaat\n\
+agtgttcgaaggtaaaatttatgtaccaaatcgaaagaacacttaataaggcttgcttgc\n\
+acggaggtatgatgtttactgactctacaaccctaattttccagtacgtacattcattcc\n\
+aataggttagttctcaaagtgctatacaggctcctcaattgatgatatgcttcagccgct\n\
+ctatggatattagctcattttatttaggaagcccgcttagaggcttactatgagggaaat\n\
+gccaaaatgtcatacttttcggtgtgtcccatatgacaccgctttacatagaatttgaat\n\
+taaaacgcgctctcccgttcactaccatacttggtaccgtgcgcatattacatatagata\n\
+taggatcattttttaaagctgtactaggtttgatcgacaatcttatgctatactatatga\n\
+tgtaaccctcataatcaataccgatcgtacgatcctagcataggtggcaagcgattttat\n\
+gccgattattgtgttaaatagtctgtgagtgtgattatcagggctacgttggtagagggg\n\
+ttgtatagacctcgcacacattgtgacatacttaacaatatacgaaaactgatataataa\n\
+atccccttacccaaacaccaatcccgttgaatcaactaccataacgtctcccatataaat\n\
+tgcctacttgtttgcataaatctgaatacataacaccattgcaccttcttgtgttccaat\n\
+cccgttaagattgccttgtcagatgatatgcaagaacaatagcatttgctagcaattatt\n\
+aacagctcttcgaattgcctccacataacgcgggagggtatattttaatttggcaaatac\n\
+taagtactgttggcgtcatatgctattaacggttggatattaagttatgtcagccgtaag\n\
+caagagtgggcgaaatattttgttacccagtgagagcactcttagagtttggatacaata\n\
+ggccatatgttgacttaagaggacgtaactacgccgtacaccattgttcaaccgacttct\n\
+tggcaaatagaatcgtattagcaatcttaagaatagagacacgttcgtgttagggtatac\n\
+tacaaatccgaaaatcttaagaggatcacctaaactgaaatttatacatatttcaacgtg\n\
+gatagatttaacataattcagccacctccaacctgggagtaattttcagtagatttacta\n\
+gatgattagtggcccaacgcacttgactatataagatctggggatcctaacctgacctat\n\
+gagacaaaattggaaacgttaacagcccttatgtgtacaaagaaaagtaagttgttgctg\n\
+ttcaacagatgatagtcatgacgcgtaacttcactatagtaaattgaaacaaatacgcaa\n\
+tttagacagaatggtacggtcatgaatgacagtaattcgaagtgctagaccaacttaaaa\n\
+taggtaaacgtgcccgaaaccccccttaacagaaagctgctatcatggtgcagtatcgac\n\
+gtgttcagaaacttgtaacttttgagcaggtccgagcacatggaagtatatcacgtgttt\n\
+ctgaaccggcttatccctaagatatatccgtcgcaaactttcgatttagtcccacgtaga\n\
+gcccaagcgttgtgcgactccacgtgcatgcccagaaatacgagtttaaatttggttaca\n\
+tggttaattttgaccgaagcatcgcactttatgattgataattggattcaatatgtcgcc\n\
+ctatgcgaatgcaacatgatccacaatttggctataagacgtttaatccgtatcacactt\n\
+tgtttgcggctagtatagtaacgcccgtgcaccaagagtcagtaacaattataagtactc\n\
+cgcaggtacttcaaatataaaaactaatcaaacacgacccatatgatcatctgaagatat\n\
+ttggaactttctcgacaaccaccctcgtactcaatacttacactaatcgacaggcacacg\n\
+caacgtgtacagtcgcaccatattgagtcaagatttgcttagtggcgatgagcgtacacg\n\
+cttatttctctagtcacaattagttatctacgagacatcacgagggagcaaataagcgat\n\
+gttatggctacacataggcacgtatgaatatgatataagccagttaaacagtcgaaccat\n\
+cgagcaaattctcatgcaccaacccacacgttgaggcacaaagagtaagctgtttgaatg\n\
+taacttcttctgctgagcgggccccaacgtaaggatcaactagaagagaaaactcggtat\n\
+tagtttaaatgcgtcacggagcatgagtgcatttcactaagaatgtctgtgtaaccaata\n\
+taacatctatttgttatctgattgcctacttatggctttgcggtcgtggcgactaatgtc\n\
+tccaatccttttgaggtcggtaccaactccctttaaattacgctgtgcaggctcatgcac\n\
+tgcatacatatacggtagcaggtagggacctcacgcacccttattataatcaatagtagt\n\
+tatcagtcaacgaggcaggaatgctgaggtcgaggtgttggtatattttctatgtgccgt\n\
+ctaggcgactatcacgcattaccaggcgagatttaagccaattttgaatatagtcaacgt\n\
+aatttttactatgggttccaccgaaacgccttgcacaactaagaatcccataaaatatcg\n\
+atatcaaataaaagattgtgtcaataccttcatatatattttttcggttgactaacgtga\n\
+actaaggttaggggttttgtatgtctatataggaaacagtttcttttctgtcctacttta\n\
+gtaaagtcttcaagccttactccaaaatcacggtgattaagccgttactcagcagcatga\n\
+ttctgcctgctcgggtcctaaaatccagccttgtaagagtcgctgtgtattagctaggga\n\
+gacctttgttaaaaaggatatatcgcggcgggatgtgagtgcgtggcgcatactcaatct\n\
+tcagctcgtgtcattataatatctctcccccacgcttttcactagatatgccgtgtaagc\n\
+aaacaccttatgcttaatttcgaaaatattggtacttgaaaaaagctgtaggggtactta\n\
+atgtctggtaggagatcaggagagaattgagtgtaaaaccgtaaagccctcacctgactt\n\
+catgtaaatggcttagaagactccatgatttaataaatactacgaaggaaagactggatc\n\
+taaagataactctagtaaggccaactcccttcaatgctgttgccagttataatccaagag\n\
+ctgtccttttctgaaccatagcggcttctgaagcgaactagaagcaaagttggttctagc\n\
+cagacagccacataccctgtacgggtgtattactaaaactggtccggtattagttcacca\n\
+agggaggaattaggcaaaggatctaggtatgcaagtcggagtattacatccctaccctga\n\
+atccatcaataggttcctctgtactggccttcgcaatgagtattcaaggttgtacagccg\n\
+tataataataagatagtgactatgaacgggaagtaacccgctcaccttccccaaaacatt\n\
+gttatatctaagtattaaagtctgccgtagtgttaatactcgaaaataaacaactggcaa\n\
+attacaccgcacttaagccgcttttgatttatatttttccaatgcgcttttaaaaataat\n\
+tcagtcctacatactaattaagacccttaaacggagatatcacaagttaagttttaacca\n\
+tctcgactaggtggaactatagatacccaactcaatttatcattacctgtaatgttccta\n\
+gaaggattgcatttcatgtcaagacggtggagtttcacagcgaaacttcagtgtgaacag\n\
+attctgagaaatcacctaaacctattagtcagagcacccggttagaaccagttgtcaaaa\n\
+aatagagcggttgcatgagacagaagtaacgatgagatccgttgtaacgttgagacatct\n\
+ggcctatcgtcaatacagtcctcccttaaaaatatttttaaatactaggcaaacccaaca\n\
+taggttagtcctatgtgatacgccacatggtatatcattttgtaacgttacctagggata\n\
+atcaggaagtggaattacgcaaaagtagacagtgaaatgcttagggttatagtctagtcc\n\
+aaagataaaggataaagcacgtcagagaactatattagccgaatgggaatcattgttagg\n\
+agactgtggatcatgtctaaaaagcaacgcagaaacagtcatcgaaaaaatctcgttttt\n\
+gtttgaatctaaaagagctttgatgaccgatagtacctgtatactagttactgtattacg\n\
+tgtctaatgatttcggattggggtccccagaatcagacgtcattgtagacgattcaagtt\n\
+taccaatttaatttcccagctctccttggagaactatcgccaataattgcagtcactttc\n\
+cttttctgaaacgataaagccgtcagagttctctgcaacgttggacttacctgaggttct\n\
+aacccactttcggttctaatagtagttaacgacacaacgaataacctttactgtggggct\n\
+ttcacgatattttttcgcttattattaatggttacgtcataagctggtgtccaaattaag\n\
+gttaccggcttcgcagagtagttgtatccaagtataacttccctaatcataagatcgagg\n\
+tagaaaattaatgctgtctctaaccgaacagatatgtcccactatgtggtatggacgttg\n\
+ctaattacttctgaagggaaattggtcattatggatacgtgtctaccatcaggtcggacg\n\
+cagatatggttctgtcttcagttgatccaccgttctttataggataataactgacgatta\n\
+aagattatggtaaatagattaagccaattctcttcttgtcagtgaagcatccttaactga\n\
+cttgctctgcagcccctcatacatttagctattcaaagtaccggctcgtttcaaactctc\n\
+ccacctttggaagaggttgtcaacttgataagtatatcatttacagcattttttcggacg\n\
+tacctctaatgtttcattgcagaaaattagttttttctatcgcacattttgcaagtaacg\n\
+ttagagacacaattatctgcgaatgaactgctagatctgacgaccgggagcctcgcaaat\n\
+atcaaaaaagactgacatatatcaaggagtcgttgacaagtgctggtaagtcaattggtt\n\
+tatctgtcccggcgtttcgatcttaagctgaccatgcacggcagagtaatgtcactctcg\n\
+ttcttacaagtctgtctccaagggtcggcaaaaaagacccctccattctcgagcccactc\n\
+acgatatgtagggacgacaacttgtgcggcttatgaattgtctggactgcgggcgagggt\n\
+ccatatctccgaagttagaagggacatacctttagatgataagatcaattcttattgacg\n\
+aaattcatccacaacggggaacaacttcaccctagacttacgtctgaaaagacacctagc\n\
+gtcttataaaaggtcagtgccccgtttcgtaaggctggaattacctacgcaaacttaaac\n\
+ctcgcgcccttccttacgtatcgacaagatagaggctatcgcgaatgtactacggaggca\n\
+tgaatcatatactagaaccaagtgcctgtgatattaacaagatgatccgacgcgagcacc\n\
+gtaattctaggcataaaactccagcaatttgggggccgaaaacaaatgacgttagctaat\n\
+taattatatgacatgatcaaaggaggtcaatcacgcatcgagttcgacgtatattcattg\n\
+aacttcgtgcgtttgaaagaaacttttatgaaggcaaaattgatcctgtctcctatttca\n\
+tgcgtacctcctagttgataattccccgagcagtggttaggacacttttgtcggtatcaa\n\
+gttccggtctcaaaacgtaaaattctgtaatctgtatggatggtctgtgaattagttaat\n\
+ttttatgaagtcgtcgagacgcagttcctattgatttattctaaacggagatgtgcttcg\n\
+tgggactcggaagtagatctgtgtttatgattattgctactttagatgctgactgttaac\n\
+tccgtgttgtttttcaaccgtatatcacaaccgaattggatagaacctatagtttcaagt\n\
+tctgccacaaggtatcatatttacagttagtgctggttgcttctttcaaacgtggtgagt\n\
+ttgtgctatcacgtcaacggtagagctcagtggaccgagtgcgcgttcaaccctgttcca\n\
+gagagggtgtgatagcacatataccacgctcgtcgaggcgttcatgatagtttgcaagag\n\
+ccggtgttaaacacatattattattgttatccaactaatcggacctatgcataaagcatt\n\
+gtctaaacagaataattgcctatatacggtagttttagtgatttatatcttagtatcagt\n\
+tagagcttcgaactcttcaggttcctcatatttaacgttcttcgaaagcgaaaacttcta\n\
+caaacgaatgtaagcggttttccaagtagtacctataaatcacagaaagatctgtctcag\n\
+tatagttgaaatggtattcagctagtgacgtgtaccaattatcatagttcactcaagcaa\n\
+gacgctcattaacgaatatagacaagacactatatcatataataaaaaagaacatggtgc\n\
+tcgaacatagttgaattcaccatattgaaggggaatgctgacatgtaattcgctactaga\n\
+cgatcaattccctacttgtcaaagttgaactggtacgttcttggaattaaatatgattgc\n\
+gctggaccaaattgcgacttcttgagtttcagggcaaacgattgagccggaggatgtccg\n\
+tctcttacctttcttgcttatgataaacgacggtccctgtacatcactgggaattctcag\n\
+caaaaataattgggtaaatcgagactcgatgtattcggccacaaaggtgttagacgttaa\n\
+agattattcaacggggcgataataggatcataaccggtatgcaagcgcattgaaagagcc\n\
+atgagatccttatccgataaacgctgcacggtatgtgcagccttattgtcgatcacgaat\n\
+ttataaatgtagtctgggctgtaagttgaagacctaagttataatgaagtgcaataccaa\n\
+atcgattcatagtggattatcagactcaagatatctcctgataaattacagttgttaaga\n\
+tacggataaaatgagatttaagattagcagcctctaatctgtttcaatcccgttggaatg\n\
+tggtatgcgatcaaggttaagttaaaatcaagcctgtcttcagtcttgattcttgttctg\n\
+ccatcgcatgcggtctacgtgagttaatatgtagcttacgttctagcttgtgctaatctg\n\
+agtatagattcgtagaggaatattatcaagcttccacgcctcaacgtacgtgtattggtc\n\
+acacaagacactaaaagtggaagtagcgtaaactatagtctagttgttaaatgctcagtt\n\
+cttgttatattcgatatactcttggctaatttatgtctgagtatataaaattaatgatat\n\
+taacttgcatttcacggatcccttagaaaaagattttgaccgagcgcattataaacggtt\n\
+acaccgaatcaatagaagcatacccaatagctttctttgaatttattgcctgcgcaactt\n\
+ggctgactctctagatccgaataattctatatggtcgtgacgaaactagttcattactgt\n\
+ttaaaatgccaacatgtcttttgggccgataatggctctttgcaaaattactcaatgata\n\
+cgattgatcaaagcggtagttgctagtggtagcatgtaagtctatcaaatgtctgattat\n\
+ccgaaaatcttccaaaagagtccacgtaccatatctatctcatagcgacgcgaggggaac\n\
+cttatctaactatcattccatttaccgggtgactctcgatgcaggatccgattgggataa\n\
+attgcccagaaatggctcattcctgactaagggtaaggccgttctcagcaagggaacccc\n\
+gcgaatctaggcttataccatctagattgttaactacttgcctgtagttctacagccata\n\
+ctggacagttgtttctaaatgatcgggattcatgctagcactcctctgaatgcaccgcgt\n\
+aagtttaactattacgtccgtgggcagataaggatggaggctgtatgtatcttaactgtt\n\
+acctaatatggctggtaattatcaaagtaaggaccttaatgccatagcgctagcaatcgc\n\
+tttgtatactgaccatgtgccaacctctcttaatctgtaaaatataatgtcttagctaac\n\
+tgtggacgatcatgtctctgcctagagcttcgctgtatcaattcctatagccagcgtact\n\
+agtgacacaacaacaccgtgtgagaaaagatattagtccttacgtctgtctctctacagc\n\
+ttattgatgaggattgaacatggacatatagctccccctcaaaagcagatgctacctctt\n\
+tattccattctcgaacatttgccgaacttaatttcgacaaacctgaggtcacgtcttaat\n\
+ttatcggtaacgtcacgtccctttgagactggataaatatattaccaggggccaacgagc\n\
+aattgttggaggcgcttctataatacaaggtgtcttgtcaaagaaagacggcgtgcgtct\n\
+cgtgcaactcacttaaccaatattaatgtgaaacccccctctctcacatcttatgcggtg\n\
+tactgccctggtacatttcctgtacaggactccaacagtgtagattcctaagatagctgt\n\
+tggagttgcctcacgccagatcgaaaaactgaataaactagtgagctgagctgcagaaat\n\
+accgcttaattacttatgactagttcaaagggacctacgtgatgtcagacattgcaagga\n\
+agaaattaggtttgtgcgtcattttggctggactagcactccttacttcccctactattc\n\
+aaatgtcgtaaacagcatgagacaggatcgtgctgacatttaaggtctattgggaacgag\n\
+gctacctttggtcgcgcgctcgcgttctccgaatgaccgaaatgcatgagcacagtatgc\n\
+aattgcttatagatctaaggtctggtcgttgaaaccaagcacgtaggcctgggaaatcag\n\
+ttcttcctcagcaactacacaaaagcgtccaagcattagtacttgtagtaaatgtccgaa\n\
+cctatgcgctcatttgaaagtcaaaaaatatttttaagcagtaggcacctaacccgattc\n\
+ctctacttagtagctttctttgattctcagaattgactgcaatatcactgcacaattctg\n\
+tgccattactagacttctctgtattaacgtctcatcttactaacactcgcctaggacaca\n\
+tctgagagtgaagtatttcaatacatttactgaaatcttcagttctaaaatccccgaata\n\
+aggctcttatcggtttggccaacacaagaaaaaaacttcttgcaccactcaccttcatac\n\
+gcaggagcctggggaacttagtaataactatttcggcagacaaagcttataacaagttgc\n\
+cggcgcgtataatatttaaaagaccccttgagctgctcaattaaaacgctcacctggtat\n\
+aggctattagatagtgccgtcttagtaaggggcgggaattatcggataaactgatatttt\n\
+gataaaataaccgacttgttcacgacataagtcactaaggagattttatctttctccaaa\n\
+gtatatcttccttggataatttcaaagcgctgcaatttaagttctgttactagtttatgc\n\
+tgctgggaggtgaccggaaggcgtagtaatctagaggcaaattataagaagttcatcata\n\
+tcattttcgactacaaaaacaaggtgttgtatgccggcgcattgtgtaaactggacgagt\n\
+accctagatggaaaattatacgttaagccaagatttcgatgtaatgataattacctacac\n\
+atttttgctatccataggaacaagagctgttctataggctcgtggcatacgaacatttgc\n\
+tgccgctatgaatattggaagctcttcaactacagactctattcttaattgccgtcgaaa\n\
+atgggccgaatcggctattattaatactcggtttttccgaggggattgttgtcgacagtc\n\
+gtaattattattaatattgatgttggtgaggtcatttaaatacaaccttgcagacaatga\n\
+ataagggatccaatctctcatactccttttacaattgctcatgcccctatgcaaacctta\n\
+tgccgccacacctccgcaactctctcttctgaactgtaagtagcttcattactggtttga\n\
+gactatactgaagctgatgacattctaaaatggctattttcgaatgtgattcataatgtt\n\
+tatcgtttgggatggcagaatcacgttatttttgatatagcccgggtattctattgtata\n\
+gaacgtatgctacaagtcattccccgaagaagactagaagtaaacaacatgcgaccatcg\n\
+ttaagccacgcaaggctgtagctttatttcccgataacctatcttccataaatagcggac\n\
+agcaggatactgacgctcaacatcagtggttatggtctaatttttaacttttaataaggt\n\
+aacttcagcaggcatacacagtaactctttaatttataatcaaattagaagtctgacact\n\
+tcttatatttttctatcatccaacgcgatcgcccattagcttattgtgttactaataacg\n\
+tatctaaaccaatccttttcaagctactgcctatattgtcaatatatacaaacaacagga\n\
+tagtaggctgcttaaaaaatattgtcaaccgtgtacgctttacaatacccggaaatcaca\n\
+aactttgtagacaacgagtgaaatttatacactacgaagggccagcgtacaagacccatg\n\
+aattaggcgatatgtttattctgacatattggtttatccttaatctgtcgctgtaaaatg\n\
+aagccgcccccatccctgcgaattttttttcgaagattcacgactgaaatataaatacgt\n\
+ttggctatatttatgttggagggaggcaatagcctttactgttaaccgaagatttagcca\n\
+gtgagtgtgacactaaaacactggaataaatgcaggcgttcttctgggtaaaaggtttag\n\
+tcaatctcgcctataagttcatatagctctggatataattatctggcccatgcatttatc\n\
+atggcgcttggtgccctgtgtgaagccggcctctcatattgaaggtccgaagtattccat\n\
+gtacattaagatcactctctcattcatgcatcttggcttaacaaatctggttgtccaagc\n\
+tttccaggcacgtatggtacaaattcggatcgaatacttataaaaatgatatgttaaact\n\
+gtctaaaacgctcatctacaaagtaaagtgcactaaccaatagagtctcaagaccgtgta\n\
+atgctggtgcactgaatgtgtaatacggttagaagggattagttatgttacaaatccatt\n\
+gaaaacttaagaagcattgcgtgctcggagggtgcatcttttatcaagagactaacatta\n\
+ttttcaacgacgtacatgctttacaatagggtacttatcaaacgccgagaaacgcgccta\n\
+tagtgatgttatgattatgacccgatatccattggaccgaattttatgtaggttcccagc\n\
+gtactcgcgtaatatctcggtattgccataatgtaatacttgtcggtctctcccagatga\n\
+aaaagcgttacagagtatttcaatgaaaaacagcgcgcaacgtcaatacctttaggggta\n\
+acggccgctgatttcatatagatatacgataagttggtatagctctactaggtggcatcc\n\
+acaatcgttgcatttactatagctggttacaatcataatctataccgttccttacatact\n\
+accatagcgggatagcgtttttttgccgttgattgggtttaagaggatgtcagtctcatt\n\
+atatccgattcggtgggagagccgttgttttcaaatcgcacactttgtgacataatgtac\n\
+aagataacaaaactgatataagatataaactgtcaatatcaccttgacacttgaatcaaa\n\
+gtaaattaactcgcaaatataatttgactaattgggtgcagatttctcaattaataaaaa\n\
+aatggcaccggatgggcttacaagccccttatcattcacttgtatcatgatttccaagaa\n\
+caatagaatttgctagcaagtatgaacagagattcgaattgcatccacagtacgccggag\n\
+cgtttattttaatgtggatatgacgatgtactgttggcggcatttgctagtaaccggtcc\n\
+ttatttacgtagcgcacacgtaagcatgtctgggagaaatatggtggtacaatctcagag\n\
+aaagattacagtttggtttaaataggacttatcgggtcggaagtggaacttaataagcag\n\
+tacacaattgggcaacagacgtcttgcctattacaataggattacaatgcgttagatttc\n\
+agacacgttcgtgtttggctattcgtcaattccctaaatagttagacgatcaactattat\n\
+caaagtgattctttgttcatcctccattcatgtaacagatggcacactacgcataacgcc\n\
+gaggaattttaacgagatttaagagagcagttcgggcacaacccacttgactttataaca\n\
+gctcggcagcataaacggtaatatgtgacaaatttccaaacgttataagaacgtatgtgt\n\
+acttagaaaactaagtggttcatgttcaacagatgtgacgcagcaagcctaacttatcta\n\
+ttggttttgctataaaagaacaaagttacacagaatcctaagggcttgtttcacacttat\n\
+gcctagtgcttcaccatcttaaaatagcgaaaccggcacgaatcaaaccttaaaacaatg\n\
+cgcagatattggtgatggtgactccgggtatgataatggtaactgttgaccagcgcccac\n\
+ctcatcgaagtatagaaagtggttaggataaggatgagaccgaacttatttccggccata\n\
+actttagattttctacctagtacacaacatcagggcggacacgaaaccgccatcacatca\n\
+tataccaggtttaatttgcttaatgggggaagtgtcaacgaaccttcgaactttagcagg\n\
+catatggccattatatatggccccagagcagaatgctacagcagacaaaatttggattta\n\
+tgtagtttaatacctatcaaacttggtgtgaccatacttgtctaacgacagtgcacaaag\n\
+tgtaagttacaattattactactcagcagcttctgcaatgataaaatcttatcatacacg\n\
+tcacatatgataatatctacttagggggaacgggctccacaacctacatagtactcaata\n\
+cttacactattcgacaggcacaccaaacctgtacagtcccaaaagattgagtcaactttg\n\
+cagtactgcagatcacagtaatagcttagttagcgagtcaaaattagttttctacgagac\n\
+tgcacgaccgtgcaaatttccgatgtgttggctacaaatagcaacgtatgaatttgtttg\n\
+aagccacgtaaactgtacaaccttagagataagtctcaggctactaaaaacacgttgtgg\n\
+cactaacaggatcatggttgattcttacttattcggctgaccggcccaataagtaacctt\n\
+caactagaacagaataatcgggagtagtttaattcagtcaaggtgcaggtctcattgtaa\n\
+ctaacaagctctgtgtaaccaagttaaaatcgttttcttagcggattccctacttatgga\n\
+tttgagctcgtccacaatattcgatacaagaagtttgtggtccgtaacaacgaaatttta\n\
+attacgctgtgcagcctcatccaaggaattaatagaaggttgatggtaggctccgaacgc\n\
+tccatgattataatcaagtggactgtgcagtaaacgaggaaggtatcctgacgtcgtggt\n\
+gttcgtttttgttatttgtgccctatacgagtagataaaccatgaacagcacagtgtgaa\n\
+cccatggttgattttaggctaccttatttttaatttccgttacacagaaacgaattccac\n\
+aactaacatgccattaatttttcgatatcttataaaagatggtcgaaattcattcattta\n\
+ttttttttcggttctcgaaagtcaactaagctgtcgcgttttgtttctctttagaggtaa\n\
+aagtggctttgatctcctacgtttggatactagtcaaccattactccatttgatccgtga\n\
+gtatcacctgtctaacatccagcattatgactcctcggcgaagaaaagacacacttctta\n\
+gagtcgatgtgtattagctagggacacagttgtttaatacgatagtgagcccagggaggg\n\
+cagtgcgtcccccagtagatttattcagctagtgtaagtataagatatctcacccacgag\n\
+gttcaagtgatatgcagtcttagaataatacttatcctgaatttcgatattatgggtact\n\
+tcaataatccgctagcgctactttatgtctcgttggacagcaggacacatggcagtctta\n\
+aacactaaagacatcacctgaatgaatgtaatgggattacaagaatcaatgaggtattat\n\
+atacgacgtaggaaactctggatatatacagtaatctagttacgccatcgcacttcattc\n\
+ctctggaaacttagaagacatcagctgtacgtggaggaaccagacccccgtatgtagcca\n\
+aatagaaccaaagttgcttatacaaacacacccaatgacaatggaccgctggagttcgta\n\
+aactcggaacgtagtactgcacaaacccagcatttagcaataggagctacgtatgcaact\n\
+cccacgtggtaataccttcaagctatcaatatataggtgcctagctaatcgcattcgcaa\n\
+gcagtattcaagcttgtaaaccagtataataattacagaggctctatgaaacccaacttt\n\
+ccagctaaaagtcccaattaaatggttatttcgtacttttaaagtcgcccgttctgttat\n\
+tacgcgaattgattctactccaaaattaaacacaaattatcaaccgtttcatttatattt\n\
+gtcaatgcagctgtttaaaataaggctctactaaattataattaagacacttattaccag\n\
+atttctctagttaagtttgaaccagctcgactaccgcgaaagatacattcccttctctat\n\
+ttttcagttcatctatgggtcagagaagcattgaatttattctattcaccctcgtcgttc\n\
+acagcgaatcgtcagtgtgatcagtgtatgagaaatatcctaaaccgtttagtcagacca\n\
+cacgcttagaacaagtggtctaaaaagactgccctggaaggagtaagaagtatacagctg\n\
+atccggtgtatccttcagtcatctgccctatactaattacacgacgcaaggaaaaatagg\n\
+tttattttctaggcaaacccttcataggtgactccgatgtgttacgaatcatgcttgaga\n\
+atgtgctatcgttaccgacggataataacgatctccaatgaaccaaatgtagaatgtcta\n\
+ttgattacccttttactattcgacttagagataggagatagaacctcagtgtactttttt\n\
+agccgaatgggaatctttgggaggtgaatggccataaggtcgtaaatccaaccctcttaa\n\
+agtcttccatattatatcgttgttcgtggaatcgataacagatttgttgacccatagtaa\n\
+atgtatactagtttatgttgtaagtgtagattgttttccgattgccgtccaaactttatg\n\
+tcgtaattgtagaccagtaaagttgaccaaggtaagtgcccagcgatcctgcgagatcga\n\
+tcgccaatttttccagtcactgtaagtgtaggtttagataaagccgtatgagttatatca\n\
+taagggcctcggaaagcagcttcgaaccaaagttcccttataatagtagtttaactataa\n\
+aagtatatactggtctgtcgccctttcacgatttgttttaccggtttatgaagcgttacg\n\
+tcattagagcggctccaatttaaggttaacggcttccatgtgtagttgtatacaaggata\n\
+acttaaagtatctgttcagcgagctagttaagttatcctcgatagaacacaactcagagg\n\
+tcccaagatcgggtttgcaacttgctaatttattctcaaggcaaattgggaattatcgat\n\
+acctgtataccataaggtcgctcgatgtgatgcttatgtcttctggtgatcctaccttag\n\
+ttagtgctgattaacggaacattaatgtttatcgttttgagatttagccaattctctgat\n\
+tctaactcaagatgccttatctgacgtgctatgcagcccctaagtattttacattgtaat\n\
+aggacacgctcctttaaaactcgccaaaaggtcgttgtggttctctactggttaactata\n\
+taatttacagctttgttgagctagttcctctttggtttaagtcctcaatattagttggtt\n\
+cgagcgataagttggctagttaccttagtcactatattagatccgaatgttatgcttcat\n\
+ctgaagaccgccaccctccaaaatttcttttaagactcacttattgcaaggtgtaggtga\n\
+attcggctcgtttctcaagtggtgtatctgtacacgagtttccatattttcatcaacagc\n\
+caccgcacacttatgtcactctaggtattaaaagtcgctctacaaggggacgcaattaag\n\
+aaacagacatgctagtcaaaaataaacatagcgaggcaccactaattcggccgcttatca\n\
+atgggatgctctgcgcgagacgcgccagagctcagtagttagttcggacatacatttact\n\
+tcagatgatcaattagttttctacaaatgcttactctaccccgaaaaaagtcaccagact\n\
+cttacgtctctttagtatccttccgtcttatataaggtcagtcccccgtttcggtaccct\n\
+ggaatttactaagaataatgaaacagcccccaaggacgtacgtttacaaatgatagacca\n\
+gatcgcctagcttattccgacgcatgttgcatagaattgaaccaacggaatgtgagagta\n\
+actagatgagccgaccacagcacccgtttgcgtcgcagaatacgcctgatagttcggcca\n\
+cgaaatcatatgtcctttgagtattaagtatttgtaatgatcaatcgagctcaagcaagc\n\
+ttacacttcctcggatattcagggaacttagtgcctttgaaagatacgttgatcaacgaa\n\
+aaattgataatggctcatatggaatgcctacctcatagtgctgaattaacacagcactgc\n\
+ggacctaacttttcgaggtttcaagttcacgtctcaaaacctaataggctggaatatgta\n\
+gggatcctcggtgaatttgtgattgggtttgttgtagtactgaccaagtgaatattcttt\n\
+ttttctaaaagcagatctgctgccgggcactacgaaggagatctctgtgtatcattattg\n\
+cttcttgacatgatgactcttaaatcactgtgggtgtgcaaaacgatagcacaacccaat\n\
+tcgatagtacatattgttgatacttcgcactaaaccgttcatatttaaaggttgtgctcc\n\
+ttccttcgttaaatactggtgacttggtcctatctactattagctagacctctggggaac\n\
+cacgcccccgtaaaacctgtgcaagagagggggtcatacatcttagacatcgcgcctcca\n\
+ccagggaagcattgggtgattgaccaggtgtgtaacaaatatgattattcttatactaat\n\
+attagcaaagatgcataatgatttgtattaaatgtataattgaattgataagggtctttt\n\
+agtcagtgatagagtagtataaggtagacattagaactcttaaccggacgcagatttttc\n\
+ggtcttagtaagccaattagtcgacaaaacaaggtaagagcggttactagtagtacctat\n\
+aatgcactgaatcttcggtcgaagtatagttctaatgctatgcagattgtgacggcgaca\n\
+aatgttcagacttatatcatgaaacaagctcttgtaagtattgacaaatgaaaagattga\n\
+atatttttaaatacaaaatgcgcctacttattaggggaattaaccagattgaaggccaat\n\
+cctcacatgtaatgagataatagacgataaatgaaattcttgtaatagttgaactgctac\n\
+gtgatgggtattatatatgattgagatcctccaattgccgacgtcttgtcttgatgccca\n\
+aaagattgtcaacgaggagctccctcgcgtacctgtcgtccgtatcataaacgacgcgac\n\
+atgtacagcactccgaagtataagcaataataatgcgggtaatccagactagatcttttc\n\
+ggactcaatgcggtttcacggtaaacatgattaataccggagagtagtcgagcttatcag\n\
+cgatgcaagcgaattcattgtgccaggagatacgttgcagataaaaccggcaacgtatgt\n\
+caacaagttttggcgatctcgttgtttgtattcgacgaggcgcgggaacttcaagaacta\n\
+tcgtatattcaagtccattaccttttagtttcagactggtggagctgactaaagttatat\n\
+catcattttgtacactggtttagttaacgataatttcagatttaacatgaccagacgata\n\
+atcgctgtatatccagttggaatgtggtttgccagaaaggttaacttataatcaagcctc\n\
+tcttcagtcttgattcgtcgtatcccatccattgcgctatacctcagtgtatttggagct\n\
+gtagttataccgtgtgctaagatcagtagacatgacgagagcaatattatctaccttaca\n\
+agcatcaacggacgtctagtcggaacaaaagactctaaaactcgaacttcaggttaatat\n\
+actatagttctgtattcagcagttattcttatattcgatattatcttgcctattggatgt\n\
+ctgactttagtatattaatcatagtatctgccatgtaaaggtgccagtactaaatctgtt\n\
+tcacagtgcgaattataaacggttacaaccattaaagacaacaagaccctatagctttat\n\
+ttgaattttgtcaatgcgcaacttggagctcgcgatacatcccaattagtctatagggtc\n\
+gggacgattctacggcatttctggttataatgacaacatggattgtggcccgagaatcgc\n\
+tctttcattaattaagcaatcattacagtcttataagcgctacttccgagtggtagcagg\n\
+taactcgatataaggtcgcatgagccgaatagcttaaaaaacaggccaccgaacattgat\n\
+agagaataccgaccacagcgcaacctttgattactttcattaaattgtacggctcactcg\n\
+acatcaagcttaagattgcgataatgtgaactcaaatggatcagtactgaagaaccgtaa\n\
+cccacttcgcagaaagcgtacccagagaagatacgctgttacaatatacagggtgaaatt\n\
+attgcctgttcttcgtaaccatttcgccaaacttggttagaaatgatagccattcatgat\n\
+agaaataagctgaatgataccagtatctttaactatgtagtcagggggaagataacgatg\n\
+gtccatgtatgtttctgatatgtgacagtattggccgcgtaatttgctaacgaagctact\n\
+taatgcctttgagcttcatatagatttctttaatcaaaatcggcaaaaagatagtatgag\n\
+ctataatatatgctagtagagaactctggaccatcatctatatgaatactgattcgagcg\n\
+tgcaattactttagcctgcgtactactgactctacaaaacactctgagataagtttgtag\n\
+tcagtaagtcgctctctataaaccttttggatgaccattgtacagccacttatagatccc\n\
+aataaatagcacaggagacagagtttttcaatgctcgatcatttgccgatagtattttcg\n\
+tctaacctcagggcacctattatttgatacctaacctaacggccctttcacaatggagaa\n\
+atatatgacatcgggacaaacacaaatggtgggtggccaggagatatgacatggtggcgt\n\
+ctctaagaaacacggactccctctaggcaaactcacgtaaccaattttaatgtcaaacaa\n\
+aacgctcgaaaagattttgccgtgtaatgacctggtacattgactggtcaggaatacatc\n\
+actgtagttgccgtagtgtcctgttggtgttccatcaagacacatcgtataacgcaattt\n\
+acgacggacatcagatcaagttatacagattatttaagtatcacgtgtgcattgggacat\n\
+aagggatctcacacatgccttggaacatttttgctttgtgccgctttttcgctgcactac\n\
+caatccttacttaccagtatattcaaaggtcgttaacagaatgagaaaggttagggctct\n\
+aagttatcgtcgattgggatagacgagacatttgcgagcgccctccacggatacgaatct\n\
+cccatatcaatgtgaactggatgctatgcagtttagttcttacgtctcctagtggtaaaa\n\
+atcaaagtagcactcgcatagcagttattcagaacctaatacacaaaaccgtcaaacatt\n\
+ttctaattctaggtatgggccgatcataggagctaaggtgaaactcataaatgttttgtt\n\
+agatctagcatcctaaaaagatgcatatactgagtagctggcgtgcattctctcaattgt\n\
+atcctttttaactgaactagtcggtcccatttcgtgactgagatctattaaccgataaga\n\
+ttaataacactcgcattcgtatcagctcagagtgaagtttttcaataatttgactgatat\n\
+attaacttctaaaataaccctttaagcctcggatccgtttcccaatcacatcaaaaattc\n\
+ttattccaactatctacggattaacaacgtgcatggggatcgtagtaagaacttgttccg\n\
+atcactttgagtatatcaagttgacggcccggttattattgaatagaaacattcacctgc\n\
+taaattaaataccgcacatcggatacccgatttcagagggccgtcttactaagggcaggc\n\
+tttgttcggtttaactgagatgttcattattttacagtatgcttcaactaatatgtaacg\n\
+aaggacagtggatctgtctccatagtagatcttcagtcgtgaatttcataccgctcctat\n\
+ttaagttcgcgttcgagttgttgatcatggcacgtgaaagcaacccctagtattctagac\n\
+gaaaattttttctagttcatctgataatttgccaattcaaaaacaaccgctggtttcccg\n\
+gcgcattctctaaaatggaagtcgaacctagagccattatttgtcggtaacccatgagtt\n\
+ccttcttttcagaagttaatacactgtggtcctatacagaggaaaaacagcggttatata\n\
+cgatcgtggcataacaacattggatcaagatagcaatttggctacctattctaattctca\n\
+ctagattcggtattccactacaatatcggcagattaggattggatgaataatcggtgttt\n\
+aagtccggttgcgtctccaatctcctaatttttattaatattgatcttggtgacctattg\n\
+taaataaaaacttcaagactttgaataacggtgaaaagatagaagactcatttgaaaatg\n\
+gatcatccacagatccaaacattagcaagacactaatccccaactagctattctgatcgc\n\
+gatcgtgctgcagtactcctgtcacaatagtctgttcatgatctaattctttttgggctt\n\
+tgttcgatggtgattcagaatctttatccggtcgcttccctgtagctactttgtggggat\n\
+attgcccggggattatagggttgagatcgtttcctaaaagtatttaaaccaagtagactt\n\
+caactaaactacatcagaacatcgtgaagacaccatacgcggtacctttatttaccgata\n\
+acatttcttcaagaaataccggtaagcagcataatgaccctaaacagctcggggtatcgt\n\
+cgtagttttaaattttatttaggttactgctcaaggaataaaaactaactatttaattta\n\
+taataatattacaaggctcacactgattagatttgtctataagacttcgcgatcccccat\n\
+taccggattgtcttaagaataaactagataaaccatgcattttctagataaggcctttag\n\
+tctaattagatacaaaaaacacgatagttgcatccttaatttattgtgtcaaacctggaa\n\
+ccttttaattacccgcaaatcactttatgtcgagactacctctgaaatttattatctacc\n\
+taccgcatgaggacttgaaccatcttgtaggagttatgtttattagctaagattcgttta\n\
+tcctgtagcggtccatgtatattcaacaagcaaaaagcactcagaattgtttttagttga\n\
+gtcaagactgatatataaataagtttccctagttttttcgtggtgggacgatattgaatt\n\
+gaatcttaaccgaagagtttcccactctgtcgcacaataatacacgccaatatttccagc\n\
+cctgcttatgccttaatcggttactcaatctcccattgaagttcattttgatctgcatag\n\
+aagtttcgggcccagccttttttctgccaccttcctccaagctctgtagacgcactctaa\n\
+gattgatgctcacatgtattaattctacattaacataaatatataagtcatgcatcttcg\n\
+agtaaaatatctggttctccaacatgtcctggcacgtatcgttataatgcccatacatgt\n\
+agtattaaaatgattgggttaactggatattaagatcatcgaaattgtaaagtcaaatta\n\
+acaatactgtctcaagaccgtgtattcctcgtgctcggaagggctattacgcttacttcc\n\
+gttttggtatcttaatatgactttcaaaaattaagttgcagtgagtcctacctgcgtgca\n\
+tcggttagcaagagtataaaagttgtttaaacgaactacttgctttacaataccggtcgt\n\
+atatatcgccgtgaatccagaagattgtcttctttggattatcaaccgagatcctgtgga\n\
+ccgatgttttgggaccttcacagaggactccaggtagagctcgcttttgcattaatctaa\n\
+gaattgtacctctctaaaagatctaaaacagtgaatgtgtatttcatggaaaaacacaga\n\
+gaaacgtaaattactttaggccgaaaggcacatgagttattatacatatacgagatggtg\n\
+gtatacatcgaattcggggcatacactatagttgcattgtatttagctgctttaaataat\n\
+atgatattaccttccttacataagacattaccggcataccctggttttcaacttgtgggg\n\
+ctttttgacgatcgcactctcatttgatccgagtagggcggtgacccctgcttttcaaat\n\
+acaaaaatttcgctatgaaggtaatagattacttttcgctgttatgatagaaacggtaaa\n\
+tttaaaattgaaacttctagaaaagtaaagtaacgagaaatgattttgtgaataatgcgg\n\
+tcatgattgcgcaagtaagaaaaaaaggcaaaaggatgcgcggaatagaaacttatcagt\n\
+cacgggtatcttgatttcattcttcttgtcaattgccgacataggatgaaatcagattcc\n\
+aatgcaatacacagtaacccccacccttgattgtaatgtcgatttgaagttgtacgcgtc\n\
+gacgaagtggatagtatacgggccttttgtacggtgcgatcaactatgaatctcggcgag\n\
+ttagatggtcgtacaatctcacacatagaggtcacttgcctgtaatgacgaattttcggc\n\
+taggtactcgaactttattagaagtaaaaatgtgggcaaaagaaggattccattttacaa\n\
+gacgattacaatgagttacatgtctctcaacgtagtctttccctagtagtctttgaacta\n\
+tttaggtactccagaaaattttagcaaagggtttctgtgtgaatccgccattcatgttta\n\
+tgatggaacaataagaataacgccctcgtatgttatcgacagtgaagtcagcagttcggc\n\
+caaaaacatattcaatttagtacagatccccagaagttaagctaagtgctctaaaatggc\n\
+ctaaacggttatcaaagtaggtctaattactatactaacgggtgcatcgtaataactgct\n\
+gtcgatgcaacactatatgatagtgtcgttttgctatatatgtacaatgtgacaaagaag\n\
+ccttagcgattcttgcaaacttaggacttcggattctcaatcttaaatgtccgaaaacgc\n\
+aaagattcaaaaatttaatctatgagcagatatgcctgatggtgactacgcgtatgttaa\n\
+ggctaaatgttgacaaccgcacacataatcgaactattgatagtcgggagcataaccagg\n\
+tgaacgtactttgttcacgacatttattgacatgttctaaatacgtctcaaaatcacggc\n\
+gcactagaaaacgcaatcaaatcattgtcctggtttaagggccgtaatgccggtagtgtc\n\
+aaacttcatgagaactttagctggcttttggccagtatttagggaccaagagcactagcc\n\
+ttaagctgaatattttgccatttatctactgttataactttaaaacttggtggcaccaga\n\
+cttgtcgatacacacgcatcaatctgtaacgtaaaaggtttactaagaacaagcgtagga\n\
+attgagtttatattatatttaaactaaaagatgatattagcttctgagggcgatagggct\n\
+ccaaatcataaagaggaatatattattacacgattagaaacccacaacatacctcgaatc\n\
+gcccaaaagtttgacgaaacttggcagtactccacatctcagtaatacagttgggagagt\n\
+ctcaaatgttgttttattactcaatgaaccaccctcataatttcactgctgttccattaa\n\
+atttgcaaacgatcatttgctttgaagaaacgtaaaatcgacaaaattacagataagtag\n\
+atgcataataaaaaaaactgctcgctataacacgatcatcgtgcattcttacttaggagc\n\
+atcacccgcacaataacgtaccttaaactacaacactattagaccgagtactgtaattca\n\
+cgaaagctcaagctcgcattgtaaagaacttgctctctcgtaaaatgtgataatagtttg\n\
+cggagaggattcaattattttccattgcacctactccactagattcgataaaagaaggtg\n\
+gtcctcccttaaaaagaaatgttaagtaacatcggaaccataagcaaagcatgtaagtga\n\
+accgtcatccttccctaagaaacataaaggtttttaataatgtcgactgtgaactataac\n\
+tgcatcctttcctgacctactccggttccttgttgttatttctgaacgagaccagtagat\n\
+aaacaatgtaaaccacagtgggtaccaatggtgcatgtgacgctaccgttgttttaagtg\n\
+cccgtacaaacataagaagtcataatcttacttgaaattaattttgccttttattttttt\n\
+tcaggctcgaaattaatgatttgttttttttgaccttctagttacgctaatatgcggtcg\n\
+cctgtggtttctattgagtcctataacgggatgggatctaatacgtttggttactagtaa\n\
+acaaggtataaatttgataccggagtatcaactgtataacatcaagctttatgactcata\n\
+cgcgaagtaatgacacaaggctttcaggagatcgcgagtacagagccactaaggggtgta\n\
+ttacgatagtgacaccaccgagcgcactcactccccaagtagatttatgatcctacgcta\n\
+agtattagatatataaccaaagaggttctagtcagtgcaactcttagaataataattagc\n\
+cggttttgcctttttaggcctaatgcaatattcagctagcccttatgtatctcgcgttcc\n\
+acagcaccactcatggcacgcgtttaaactaatcaaatataatctatgaatgttatgcca\n\
+gtacttgaataaatcaggttttttataagtccttgcatactctcgttatatactgttaga\n\
+gtcttaccccatagaaattctttcatctgcaaacttagaagaattctcagctacggggag\n\
+cataaagtccccaggatgttgacaaatacaacaaatgtggcttatacaaacactccatat\n\
+gaaaatcgaaccctcgtggtagttttagccgaaccttgtacggataaatccctccatttt\n\
+ccaatagcagatacctatcctactacctcgtggtattaaattaaagcttgaaatatagag\n\
+ctgcatagcttatccaattcccaagcacgagtctaccgtcgtaaccacgatttgatttac\n\
+agacgctagagcaaacccatctttaaacatataagtaaaaattaaagggtgagtgcgtac\n\
+gtgtttactagcaacttcgcttattaagacaattgtttataagccataattaaaaacata\n\
+tgttcaacaggttcattgatatttgtaattgcacaggtttttaataaggatctacgtaag\n\
+tataatgaacaaactttttaccagagttatattctgtactttgaaaatgctcctctaccg\n\
+ccttagagactttcaattagattttttgcagttaatctatgcgtaagtgaaccatgcaag\n\
+ggatgcgattcaaccgcctcgtgctaaccctatcgtctgtctcataactgtaggtctaat\n\
+ataattttcagttttcgaacacataaccctttgaaaatctgctatttaatgtctcacctg\n\
+catgcactatcttctatactgctcagaacggctatacgtcactatgctccaagtgacgat\n\
+ttaaacgaagcaaggaataataggtttattttagtgcaaaacaattaagtgcggactacg\n\
+tgctctttacaataagccttgtgattgggctataggttaagtcccatattaacgatctcc\n\
+aatgtacaaaatcgacaatcgctttgcattacccggttactagtcgaattacagatagct\n\
+gttagatactcactctaattttggacaacaatcccaatcttggggtcgtctatcgcctga\n\
+agctcgtaaatccttccatcttaaacgattacatattatagacttgttcggggtagagat\n\
+atcacagttgtgcaaacattgtaaatcgatactagtttatgttggtagtctagttgcttt\n\
+taccattccccgaaaaacttgatctactatttcgacaacagtaaacttgaactaggtaag\n\
+tgaaaacagagaatgcctcatagtgccactatttgtccactatatgtaagtgtagcttta\n\
+cataatccactatgactgagatcattacggcctaggaaagcagcgtagaaaaaaagggcc\n\
+cggatattacgactgtaactataaaactagttactggtagcgcgccatgtatagatttgt\n\
+tttaccggttgtggttgcgttaacgaatttcagccgcgaaaattgatccgttaaccagtc\n\
+catctcgacttctataaaacgataaagtaaagttgatgttcagcctccttcttatggttg\n\
+catcgagagtacactactcagtgggaaatagatcggggttcctacttcagattgtattat\n\
+ctaggcaattgccgattgtgccatacctggataaaataagctacctacatgtgatgctta\n\
+tctattatcgtcatactaccttagggtgtcctgttgaacgctacattaatctttagccgt\n\
+ttgagatgttccaatggataggagtctaacgcatgatgaagtttaggaaggcagagcatc\n\
+ccactaagtatgtgacagtgtatttcgaaacgagacgttataaatagaaaaaaggtcctt\n\
+ctggttctattctgctgaactattgaatggaaagattggttgacctacgtactatttgct\n\
+tgaagtcatcaatttgacggggtgagagacatatggtgcatactttacggactctatatt\n\
+ttagatcagaagcttagcagtcttctctacaccccctcacgacataattgcttttaagaa\n\
+tctatgtttgattcctctacgggaattcggatccgttcgcatgtgcggtttatctaaacc\n\
+aggggacatatgttcagctaaagcatacgaacactttgctaactagacgtatgtatagta\n\
+gctataaatcccgacgatatttacaaaaagaaatgagactcaaatatatacatagcgacc\n\
+ctacacttattcgcaccctgatctaggcgatcctagcacccacacccgaaagtgagcact\n\
+agtgtcttccgtattaaatttactgcagttgagattttagttgtctactaaggattactc\n\
+taacccgtaataaggatcaagactcggtactagctttactatcattccctatgtgttttc\n\
+ctaactcacaagggtacgtaccagcctatgtaattacaataatgataaagacacaaagga\n\
+agtaactttacaaatgagtctccagttacactagcttagtccctcccatcttgctttgaa\n\
+gtctaaatacgcaatctctgaggatatacagcagaagaacactcataacgttggagtcca\n\
+agaattagactcatagggcccccaacatttaatatgtactgtgagtttgaaggtgttcta\n\
+ttgttaattcctgctcttgatacatgacacgtactccgtgtttaaggcttcggactgact\n\
+ttctttcataagttgagcaacgaaaatttcagaatcgataagttggattcactaactaat\n\
+acggctgattgaaaactccactccggacctatatggtcgacctttatacgtaaccgatat\n\
+aaaacttataggctggtatatcgagccttcctagcgcaatttcggatggggtttcttcta\n\
+ctactcaacaacggaatagtctttgtttagtaaaccagagctcaggacgcccaatacgta\n\
+ggagagcgctgtggagcatgtgtcattatggactggagcactcttaaatcactctgcgtg\n\
+tgctaaacgatagatcataacatgtcctgagtaaattttcttgatacgtcgcaatatacc\n\
+gttattagttaaacgttctcatccgtcatgcgtgaaatacggctgtcgtgctcagatata\n\
+ctattagcgactcatctcgcctaacacgcacacgtataaactcggaatgactgccgctct\n\
+tacatattagaaatacagactacaccacggaagcattgggtcattctcaaccgctgtata\n\
+aaagatgattagtcttataataagattaccaaagaggcagaatcatgggtagtaaatcta\n\
+ttattcaagtgattaccgtcgtgtaggcagggagtgaggacgagatggtactcaggacaa\n\
+atattaaccggacgaagtggtttacgtcgtactttcactattagtagtaaatacaaggta\n\
+acaccggggaatagtactaaatataatgatatctatcttcgggagaacgagtcgtctatt\n\
+gctttgaacattctcaaggcgtaaaatgtgctgacttatagcatgatacaaccgattgtt\n\
+acttttgtctattcaaaagattgaatagttttttatacaaaagccgcatacttatgacgg\n\
+ctagtatacagtttcatcccctagcatcaatgctatggacagtattgaacttataggaaa\n\
+ttcttctaatagggcaaatccgtcgtgatgcctattttttttcagtcacatcctcaaatg\n\
+gcactagtattgtcgggatcccattaacaggctcaaccacgagctcacgcgaggacatgt\n\
+agtccgtatctttaacgaagcgacagcgacagaactcccatggataaccaattataaggc\n\
+ccgtaatcctctagacatcgtttaccaataaatccgctttctccgtaatcatgttgaata\n\
+ccccagagtagtccagatgataaccgatgaaacacaagtctttctcaatgcacttacggt\n\
+gaacttattaccgccaacgtagctcatcaaggttgcgacatctagttgtgtgtttgcgac\n\
+gagcccagcgaacttcatcaactttcgtatattcaacgccttgtaattttactttaagac\n\
+gcctggtgatgtagattcttagataatcagtttgttatcggctgtactttaccataattt\n\
+cacaggtttcaggtcaagaagattatagctgtatatacagttccatgctcggtgcacaga\n\
+aacgtgatcggataataatcaatcgcttatgtcgtctttaggcgtatccaatacatgccc\n\
+cgataccgcagtgtatttcgacatgtaggtataccgtcgcatttgagctcgagtcaggac\n\
+gtcagctagattagattccttaatagaatataccgacctctagtccgaactaaactatag\n\
+ataacgccaacttcaggttaattgtctagtcgtctgtttgcagatgggattcttagatga\n\
+gtgagtatcggccatattggttcgagcactttagtttttgatgcataggatatgcaatgt\n\
+atagctgaaagtactttatctgtttcaaactcacattgattaaaccggtaaacctttaaa\n\
+gactacaagaaaatattcagtgagggcaattttgtcaatcacaatcttccagctagagat\n\
+acttcacaatttgtcttgaggctacgcaacattagacggattttcgcgttttattgaaat\n\
+aatcgaggggcccaagagtatccatagttcattttgtaagatttctttacaggcttatta\n\
+cagcttcttcagactcctacatgcttacgagttatatgctagcatgtgaacaatagatta\n\
+atatacaggaaaacgtacattgagagagatgaccctacacagcgcaaccgttgagtactt\n\
+tcattaaagggtaacgctctcgagacagcatccttaagatggccttattgtcaaatcatt\n\
+tgcagaagtacgcaagatccctaaccaacgtagaagaatccctacaaacacatgagacgc\n\
+ggtgaaaatagacagggtgttagtattcaatcttcggagtatcaatttcgccaatcttgg\n\
+tgagaaagcataccctttcttcagagaaagaagatcaatcataacactatctttaacgag\n\
+gtacgcacgcgcatcattacctgcctccatggatctttaggatagcggaaagtattggca\n\
+gcgtattgtgatttcgttcctactttatcaatttcacattcatatacatgtcttttatca\n\
+aaatcgccaataagataggatgagctatattagatgctagtagagttcgcgccaacatca\n\
+tcgataggaatactcaggacagcgtgataggacttttcaatccctaatactctctataat\n\
+tataactctctcttaagtttggaggcagtaacgcgctctatataatcagtttgctgcacc\n\
+attcttcagcctctgatacatacaaataaattccacagcagtaagagggtttaattgaga\n\
+catcttgggaacttaggattttactctaacatcaccgaaacgattattggataccgtacc\n\
+taaacgaactttctcaaggcagtaatataggacatccgcaataacacaaatgctgcctcc\n\
+ccaggagttatgtcttcctggaggctatatcttacacccactcactataggcaaactaaa\n\
+gtttaaatgttgattgtctaaaaaaaagatagataagagttggccggcgtagcacatgcg\n\
+aaagtgaatcgtaagctataattctctggacttgaagttctgtcctgttcctctgcaaga\n\
+aacaaacttcctttaaagctatttacgacgcacatctcagcaagttataaacatgttgga\n\
+agtttctagtcggaattcccaaagaacggatctatctaatgcattcctacatttttcctg\n\
+tctgccgatggtgccatcctattcaaagaatttcttaaaagtagattaaatgggactttt\n\
+aacaatgagtaaccttacgcctctaagggttcctcgagtgccatacaccagtcaggtccg\n\
+agccacatacacggagaacattctaacatagcattctcaactcgatcatttgcaggttac\n\
+ttctttcctatcctagtgctaaaaatcatacttgcaatcccatagcacggattaagaacc\n\
+taagaaacaattcagtaaaacatgttcgaattcttggtatgggaacatcattgcagctat\n\
+ggtctaacgcattaatgtttgggtacatcttccatcatataaacaggaagagtctgacga\n\
+cagggagtgcttgcgatcatgtctatcattgtgaaatcaaattgtagctcacatgtcgtc\n\
+tatgagagcgtgtatccgataagatttagaaaaatagaagtcgtataagatctcactgaa\n\
+cttttgaatgaatgtgaagcatatatgatctgctttaataaaactttatccataggatac\n\
+gtttccaaatcaattcaataattattagtcaaaatagataaggatgaacaacctgaaggc\n\
+cgatcggacgtagaaagtggtcccatcactttgagttgatattgttgaaccacacgttat\n\
+tatggttttcaaacagtctcaggatattgtatatacagataatccgataccagttgtctg\n\
+acgcccctcttacgtaccccaccctttgtgacgtttaaagcagttgttcagtattttaaa\n\
+ctaggcggcaactaatttggaaagaagcacagtggatatgtctaaattcttgttattcag\n\
+gcctgaatttaatacaccgcatagttaacttcgcggtagagttgttcatcatgcctcctc\n\
+taagctaccacttctatgatacaccaatagttgttctacggaatctgataattggccaag\n\
+tcataaacttccgctgcgttcaacccccttgctcgaatatccaactcgaaaagacagcct\n\
+tttggtgtccggaacaaatcagttacttcttttctgatgttaattctctgtggtcagata\n\
+cagaccaaaaactccgcggatttaccatcctccaagaacaaatttgcatcaacatagcat\n\
+tttggctacatattctaagtctcaatagtttaggttttcaactacattatcccaacatta\n\
+ggattggaggaataatagctgggtaagtccccttgcgtctacaatcgactattttttatg\n\
+aatatgcttctgccgcacctatggttattaaaaaagtcatgactttgaagaaccctgaaa\n\
+agatagatgaatcaggtgtaatggcagcagccaaagagcatataattagcaacactctaa\n\
+gaacattatagatatgatgatagcgatcgtcatgatgttatccggtcacaatagtagctt\n\
+catcagctaattcgttttgccagtggtgacttgcgctggaagaatcgttatacggtccct\n\
+tccctcttgatacggtgggggcttattcaaccgcgtggattgggttgtcatacttgcatt\n\
+aaacgatgtaaaccatctagtagtcaactatactaaatcacaaaatagtgatcaatacat\n\
+acccgcttcatggttttaaccatttaattgattaaagatattccgctaagaaccattatc\n\
+tacctaaactgatcgccgtatcctagtagtttgaaatttgatgtaccgtaatgatcaacg\n\
+aagtaaaacgttatattgtatgtagaataataggtcttggagctaaatgatgtgattggt\n\
+agtgaagacttacccttacaactttaccggtttctcggaagaatatactagagaatcaat\n\
+gcatgggctacataagcactttagtctaatgagataaaaaatacacgagtcttccatcat\n\
+gaattttttgtcgaaaaactcgaacctggtaatttaaaccatatatctttatgtcgtcaa\n\
+taactctcatatgttttatataacttcccaatcacgacttgtaactgcttgttcgactga\n\
+gctgtttgagctatgaggccgggatccggttgagctacatctatttgctacaagaaaaat\n\
+gaaagcacatttgttgggagttctggctacactcatagagaaataagtggcccgagtggg\n\
+tgcggcctgcctccatattcaagtgtatcttaaaccaagtggttccaacgctcgcgctaa\n\
+agaattaaagcctttatttcctccacggagtagcccgtaatccggttcgaaagagaccat\n\
+tgaagttaattttcatatccagtgaagtttaggcacaagcatgtgttctgccacatgcct\n\
+caaagcgctcttcaaccaagatatgattcatcctaacttcgatgaatgcgtctgtaacat\n\
+aaatatagaaggaatgattcggcgagttaattttcgccttctccaacatggcatccctac\n\
+gttcgttataaggaccatacatgtaggttttaaaggtttgcggttaatcgatatttacat\n\
+catagaaattctatagtcaaatttacaagactctagatactcactcgttgcagccggcta\n\
+ggaagcgctttgtaccttacttcccttttcgttgcgtaatatgaatttcatatagtaagt\n\
+tcaaggcactcatacctccgtgaagagggtagatagactattaaagttgtttaatagtac\n\
+gtattgatggaaatgacccgtaggagatttaccactcaatccacaagattcgctgctgtg\n\
+cattatcaaaacagtgcatgtcgaaacatgggttgggtccttcaaacacgaatccaggta\n\
+gagatacctttgcaattttt\n";
+
+dnaInput = dnaInput + dnaInput + dnaInput;
+
+var ilen, clen,
+ seqs = [
+  /agggtaaa|tttaccct/ig,
+  /[cgt]gggtaaa|tttaccc[acg]/ig,
+  /a[act]ggtaaa|tttacc[agt]t/ig,
+  /ag[act]gtaaa|tttac[agt]ct/ig,
+  /agg[act]taaa|ttta[agt]cct/ig,
+  /aggg[acg]aaa|ttt[cgt]ccct/ig,
+  /agggt[cgt]aa|tt[acg]accct/ig,
+  /agggta[cgt]a|t[acg]taccct/ig,
+  /agggtaa[cgt]|[acg]ttaccct/ig],
+ subs = {
+  B: '(c|g|t)', D: '(a|g|t)', H: '(a|c|t)', K: '(g|t)',
+  M: '(a|c)', N: '(a|c|g|t)', R: '(a|g)', S: '(c|t)',
+  V: '(a|c|g)', W: '(a|t)', Y: '(c|t)' }
+
+ilen = dnaInput.length;
+
+// There is no in-place substitution
+dnaInput = dnaInput.replace(/>.*\n|\n/g,"")
+clen = dnaInput.length
+
+var dnaOutputString = "";
+
+for(i in seqs)
+    dnaOutputString += seqs[i].source + " " + (dnaInput.match(seqs[i]) || []).length + "\n";
+ // match returns null if no matches, so replace with empty
+
+for(k in subs)
+ dnaInput = dnaInput.replace(k, subs[k]) // FIXME: Would like this to be a global substitution in a future version of SunSpider.
+ // search string, replacement string, flags
+
+
+var _sunSpiderInterval = new Date() - _sunSpiderStartDate;
+
+document.getElementById("console").innerHTML = _sunSpiderInterval;
+</script>
+
+
+</body>
+</html>
diff --git a/src/third_party/mozjs-45/build/pgo/js-input/sunspider/string-base64.html b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/string-base64.html
new file mode 100644
index 0000000..53280ef
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/string-base64.html
@@ -0,0 +1,151 @@
+<!DOCTYPE html>
+<head>
+<!--
+ Copyright (C) 2007 Apple Inc.  All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+-->
+
+<title>SunSpider string-base64</title>
+
+</head>
+
+<body>
+<h3>string-base64</h3>
+<div id="console">
+</div>
+
+<script>
+
+var _sunSpiderStartDate = new Date();
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// From: http://lxr.mozilla.org/mozilla/source/extensions/xml-rpc/src/nsXmlRpcClient.js#956
+
+/* Convert data (an array of integers) to a Base64 string. */
+var toBase64Table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
+var base64Pad = '=';
+
+function toBase64(data) {
+    var result = '';
+    var length = data.length;
+    var i;
+    // Convert every three bytes to 4 ascii characters.
+    for (i = 0; i < (length - 2); i += 3) {
+        result += toBase64Table[data[i] >> 2];
+        result += toBase64Table[((data[i] & 0x03) << 4) + (data[i+1] >> 4)];
+        result += toBase64Table[((data[i+1] & 0x0f) << 2) + (data[i+2] >> 6)];
+        result += toBase64Table[data[i+2] & 0x3f];
+    }
+
+    // Convert the remaining 1 or 2 bytes, pad out to 4 characters.
+    if (length%3) {
+        i = length - (length%3);
+        result += toBase64Table[data[i] >> 2];
+        if ((length%3) == 2) {
+            result += toBase64Table[((data[i] & 0x03) << 4) + (data[i+1] >> 4)];
+            result += toBase64Table[(data[i+1] & 0x0f) << 2];
+            result += base64Pad;
+        } else {
+            result += toBase64Table[(data[i] & 0x03) << 4];
+            result += base64Pad + base64Pad;
+        }
+    }
+
+    return result;
+}
+
+/* Convert Base64 data to a string */
+var toBinaryTable = [
+    -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
+    -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
+    -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63,
+    52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1, 0,-1,-1,
+    -1, 0, 1, 2,  3, 4, 5, 6,  7, 8, 9,10, 11,12,13,14,
+    15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1,
+    -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
+    41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1
+];
+
+function base64ToString(data) {
+    var result = '';
+    var leftbits = 0; // number of bits decoded, but yet to be appended
+    var leftdata = 0; // bits decoded, but yet to be appended
+
+    // Convert one by one.
+    for (var i = 0; i < data.length; i++) {
+        var c = toBinaryTable[data.charCodeAt(i) & 0x7f];
+        var padding = (data[i] == base64Pad);
+        // Skip illegal characters and whitespace
+        if (c == -1) continue;
+        
+        // Collect data into leftdata, update bitcount
+        leftdata = (leftdata << 6) | c;
+        leftbits += 6;
+
+        // If we have 8 or more bits, append 8 bits to the result
+        if (leftbits >= 8) {
+            leftbits -= 8;
+            // Append if not padding.
+            if (!padding)
+                result += String.fromCharCode((leftdata >> leftbits) & 0xff);
+            leftdata &= (1 << leftbits) - 1;
+        }
+    }
+
+    // If there are any bits left, the base64 string was corrupted
+    if (leftbits)
+        throw Components.Exception('Corrupted base64 string');
+
+    return result;
+}
+
+var str = "";
+
+for ( var i = 0; i < 8192; i++ )
+        str += String.fromCharCode( (25 * Math.random()) + 97 );
+
+for ( var i = 8192; i <= 16384; i *= 2 ) {
+
+    var base64;
+
+    base64 = toBase64(str);
+    base64ToString(base64);
+
+    // Double the string
+    str += str;
+}
+
+toBinaryTable = null;
+
+
+var _sunSpiderInterval = new Date() - _sunSpiderStartDate;
+
+document.getElementById("console").innerHTML = _sunSpiderInterval;
+</script>
+
+
+</body>
+</html>
diff --git a/src/third_party/mozjs-45/build/pgo/js-input/sunspider/string-fasta.html b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/string-fasta.html
new file mode 100644
index 0000000..240e601
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/string-fasta.html
@@ -0,0 +1,135 @@
+<!DOCTYPE html>
+<head>
+<!--
+ Copyright (C) 2007 Apple Inc.  All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+-->
+
+<title>SunSpider string-fasta</title>
+
+</head>
+
+<body>
+<h3>string-fasta</h3>
+<div id="console">
+</div>
+
+<script>
+
+var _sunSpiderStartDate = new Date();
+
+// The Great Computer Language Shootout
+//  http://shootout.alioth.debian.org
+//
+//  Contributed by Ian Osgood
+
+var last = 42, A = 3877, C = 29573, M = 139968;
+
+function rand(max) {
+  last = (last * A + C) % M;
+  return max * last / M;
+}
+
+var ALU =
+  "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG" +
+  "GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA" +
+  "CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT" +
+  "ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA" +
+  "GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG" +
+  "AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC" +
+  "AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA";
+
+var IUB = {
+  a:0.27, c:0.12, g:0.12, t:0.27,
+  B:0.02, D:0.02, H:0.02, K:0.02,
+  M:0.02, N:0.02, R:0.02, S:0.02,
+  V:0.02, W:0.02, Y:0.02
+}
+
+var HomoSap = {
+  a: 0.3029549426680,
+  c: 0.1979883004921,
+  g: 0.1975473066391,
+  t: 0.3015094502008
+}
+
+function makeCumulative(table) {
+  var last = null;
+  for (var c in table) {
+    if (last) table[c] += table[last];
+    last = c;
+  }
+}
+
+function fastaRepeat(n, seq) {
+  var seqi = 0, lenOut = 60;
+  while (n>0) {
+    if (n<lenOut) lenOut = n;
+    if (seqi + lenOut < seq.length) {
+      ret = seq.substring(seqi, seqi+lenOut);
+      seqi += lenOut;
+    } else {
+      var s = seq.substring(seqi);
+      seqi = lenOut - s.length;
+      ret = s + seq.substring(0, seqi);
+    }
+    n -= lenOut;
+  }
+}
+
+function fastaRandom(n, table) {
+  var line = new Array(60);
+  makeCumulative(table);
+  while (n>0) {
+    if (n<line.length) line = new Array(n);
+    for (var i=0; i<line.length; i++) {
+      var r = rand(1);
+      for (var c in table) {
+        if (r < table[c]) {
+          line[i] = c;
+          break;
+        }
+      }
+    }
+    ret = line.join('');
+    n -= line.length;
+  }
+}
+
+var ret;
+
+var count = 7;
+ret = fastaRepeat(2*count*100000, ALU);
+ret = fastaRandom(3*count*1000, IUB);
+ret = fastaRandom(5*count*1000, HomoSap);
+
+
+
+var _sunSpiderInterval = new Date() - _sunSpiderStartDate;
+
+document.getElementById("console").innerHTML = _sunSpiderInterval;
+</script>
+
+
+</body>
+</html>
diff --git a/src/third_party/mozjs-45/build/pgo/js-input/sunspider/string-tagcloud.html b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/string-tagcloud.html
new file mode 100644
index 0000000..893a927
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/string-tagcloud.html
@@ -0,0 +1,315 @@
+<!DOCTYPE html>
+<head>
+<!--
+ Copyright (C) 2007 Apple Inc.  All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+-->
+
+<title>SunSpider string-tagcloud</title>
+
+</head>
+
+<body>
+<h3>string-tagcloud</h3>
+<div id="console">
+</div>
+
+<script>
+
+var _sunSpiderStartDate = new Date();
+
+
+/*
+ * Copyright (C) 2007 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+/*
+    Portions from:
+    json.js
+    2007-10-10
+
+    Public Domain
+*/
+
+// This test parses a JSON string giving tag names and popularity, and
+// generates html markup for a "tagcloud" view.
+
+if (!Object.prototype.toJSONString) {
+
+    Array.prototype.toJSONString = function (w) {
+        var a = [],     // The array holding the partial texts.
+            i,          // Loop counter.
+            l = this.length,
+            v;          // The value to be stringified.
+
+        for (i = 0; i < l; i += 1) {
+            v = this[i];
+            switch (typeof v) {
+            case 'object':
+
+                if (v && typeof v.toJSONString === 'function') {
+                    a.push(v.toJSONString(w));
+                } else {
+                    a.push('null');
+                }
+                break;
+
+            case 'string':
+            case 'number':
+            case 'boolean':
+                a.push(v.toJSONString());
+                break;
+            default:
+                a.push('null');
+            }
+        }
+
+        return '[' + a.join(',') + ']';
+    };
+
+
+    Boolean.prototype.toJSONString = function () {
+        return String(this);
+    };
+
+
+    Date.prototype.toJSONString = function () {
+
+        function f(n) {
+
+            return n < 10 ? '0' + n : n;
+        }
+
+        return '"' + this.getUTCFullYear()   + '-' +
+                   f(this.getUTCMonth() + 1) + '-' +
+                   f(this.getUTCDate())      + 'T' +
+                   f(this.getUTCHours())     + ':' +
+                   f(this.getUTCMinutes())   + ':' +
+                   f(this.getUTCSeconds())   + 'Z"';
+    };
+
+
+    Number.prototype.toJSONString = function () {
+
+        return isFinite(this) ? String(this) : 'null';
+    };
+
+
+    Object.prototype.toJSONString = function (w) {
+        var a = [],     // The array holding the partial texts.
+            k,          // The current key.
+            i,          // The loop counter.
+            v;          // The current value.
+
+        if (w) {
+            for (i = 0; i < w.length; i += 1) {
+                k = w[i];
+                if (typeof k === 'string') {
+                    v = this[k];
+                    switch (typeof v) {
+                    case 'object':
+
+                        if (v) {
+                            if (typeof v.toJSONString === 'function') {
+                                a.push(k.toJSONString() + ':' +
+                                       v.toJSONString(w));
+                            }
+                        } else {
+                            a.push(k.toJSONString() + ':null');
+                        }
+                        break;
+
+                    case 'string':
+                    case 'number':
+                    case 'boolean':
+                        a.push(k.toJSONString() + ':' + v.toJSONString());
+
+                    }
+                }
+            }
+        } else {
+
+            for (k in this) {
+                if (typeof k === 'string' &&
+                        Object.prototype.hasOwnProperty.apply(this, [k])) {
+                    v = this[k];
+                    switch (typeof v) {
+                    case 'object':
+
+                        if (v) {
+                            if (typeof v.toJSONString === 'function') {
+                                a.push(k.toJSONString() + ':' +
+                                       v.toJSONString());
+                            }
+                        } else {
+                            a.push(k.toJSONString() + ':null');
+                        }
+                        break;
+
+                    case 'string':
+                    case 'number':
+                    case 'boolean':
+                        a.push(k.toJSONString() + ':' + v.toJSONString());
+
+                    }
+                }
+            }
+        }
+
+        return '{' + a.join(',') + '}';
+    };
+
+
+    (function (s) {
+
+        var m = {
+            '\b': '\\b',
+            '\t': '\\t',
+            '\n': '\\n',
+            '\f': '\\f',
+            '\r': '\\r',
+            '"' : '\\"',
+            '\\': '\\\\'
+        };
+
+
+        s.parseJSON = function (filter) {
+            var j;
+
+            function walk(k, v) {
+                var i, n;
+                if (v && typeof v === 'object') {
+                    for (i in v) {
+                        if (Object.prototype.hasOwnProperty.apply(v, [i])) {
+                            n = walk(i, v[i]);
+                            if (n !== undefined) {
+                                v[i] = n;
+                            }
+                        }
+                    }
+                }
+                return filter(k, v);
+            }
+
+            if (/^[\],:{}\s]*$/.test(this.replace(/\\./g, '@').
+                    replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(:?[eE][+\-]?\d+)?/g, ']').
+                    replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
+
+                j = eval('(' + this + ')');
+
+                return typeof filter === 'function' ? walk('', j) : j;
+            }
+
+            throw new SyntaxError('parseJSON');
+        };
+
+
+        s.toJSONString = function () {
+
+            if (/["\\\x00-\x1f]/.test(this)) {
+                return '"' + this.replace(/[\x00-\x1f\\"]/g, function (a) {
+                    var c = m[a];
+                    if (c) {
+                        return c;
+                    }
+                    c = a.charCodeAt();
+                    return '\\u00' + Math.floor(c / 16).toString(16) +
+                                               (c % 16).toString(16);
+                }) + '"';
+            }
+            return '"' + this + '"';
+        };
+    })(String.prototype);
+}
+
+var tagInfoJSON = '[\n  {\n    \"tag\": "titillation",\n    \"popularity\": 4294967296\n  },\n  {\n    \"tag\": "foamless",\n    \"popularity\": 1257718401\n  },\n  {\n    \"tag\": "snarler",\n    \"popularity\": 613166183\n  },\n  {\n    \"tag\": "multangularness",\n    \"popularity\": 368304452\n  },\n  {\n    \"tag\": "Fesapo unventurous",\n    \"popularity\": 248026512\n  },\n  {\n    \"tag\": "esthesioblast",\n    \"popularity\": 179556755\n  },\n  {\n    \"tag\": "echeneidoid",\n    \"popularity\": 136641578\n  },\n  {\n    \"tag\": "embryoctony",\n    \"popularity\": 107852576\n  },\n  {\n    \"tag\": "undilatory",\n    \"popularity\": 87537981\n  },\n  {\n    \"tag\": "predisregard",\n    \"popularity\": 72630939\n  },\n  {\n    \"tag\": "allergenic",\n    \"popularity\": 61345190\n  },\n  {\n    \"tag\": "uncloudy",\n    \"popularity\": 52580571\n  },\n  {\n    \"tag\": "unforeseeably",\n    \"popularity\": 45628109\n  },\n  {\n    \"tag\": "sturniform",\n    \"popularity\": 40013489\n  },\n  {\n    \"tag\": "anesthetize",\n    \"popularity\": 35409226\n  },\n  {\n    \"tag\": "ametabolia",\n    \"popularity\": 31583050\n  },\n  {\n    \"tag\": "angiopathy",\n    \"popularity\": 28366350\n  },\n  {\n    \"tag\": "sultanaship",\n    \"popularity\": 25634218\n  },\n  {\n    \"tag\": "Frenchwise",\n    \"popularity\": 23292461\n  },\n  {\n    \"tag\": "cerviconasal",\n    \"popularity\": 21268909\n  },\n  {\n    \"tag\": "mercurialness",\n    \"popularity\": 19507481\n  },\n  {\n    \"tag\": "glutelin venditate",\n    \"popularity\": 17964042\n  },\n  {\n    \"tag\": "acred overblack",\n    \"popularity\": 16603454\n  },\n  {\n    \"tag\": "Atik",\n    \"popularity\": 15397451\n  },\n  {\n    \"tag\": "puncturer",\n    \"popularity\": 14323077\n  },\n  {\n    \"tag\": "pukatea",\n    \"popularity\": 13361525\n  },\n  {\n    \"tag\": "suberize",\n    \"popularity\": 12497261\n  },\n  {\n    \"tag\": "Godfrey",\n    \"popularity\": 11717365\n  },\n  {\n    \"tag\": "tetraptote",\n    \"popularity\": 11011011\n  },\n  {\n    \"tag\": "lucidness",\n    \"popularity\": 10369074\n  },\n  {\n    \"tag\": "tartness",\n    \"popularity\": 9783815\n  },\n  {\n    \"tag\": "axfetch",\n    \"popularity\": 9248634\n  },\n  {\n    \"tag\": "preacquittal",\n    \"popularity\": 8757877\n  },\n  {\n    \"tag\": "matris",\n    \"popularity\": 8306671\n  },\n  {\n    \"tag\": "hyphenate",\n    \"popularity\": 7890801\n  },\n  {\n    \"tag\": "semifabulous",\n    \"popularity\": 7506606\n  },\n  {\n    \"tag\": "oppressiveness",\n    \"popularity\": 7150890\n  },\n  {\n    \"tag\": "Protococcales",\n    \"popularity\": 6820856\n  },\n  {\n    \"tag\": "unpreventive",\n    \"popularity\": 6514045\n  },\n  {\n    \"tag\": "Cordia",\n    \"popularity\": 6228289\n  },\n  {\n    \"tag\": "Wakamba leaflike",\n    \"popularity\": 5961668\n  },\n  {\n    \"tag\": "dacryoma",\n    \"popularity\": 5712480\n  },\n  {\n    \"tag\": "inguinal",\n    \"popularity\": 5479211\n  },\n  {\n    \"tag\": "responseless",\n    \"popularity\": 5260507\n  },\n  {\n    \"tag\": "supplementarily",\n    \"popularity\": 5055158\n  },\n  {\n    \"tag\": "emu",\n    \"popularity\": 4862079\n  },\n  {\n    \"tag\": "countermeet",\n    \"popularity\": 4680292\n  },\n  {\n    \"tag\": "purrer",\n    \"popularity\": 4508918\n  },\n  {\n    \"tag\": "Corallinaceae",\n    \"popularity\": 4347162\n  },\n  {\n    \"tag\": "speculum",\n    \"popularity\": 4194304\n  },\n  {\n    \"tag\": "crimpness",\n    \"popularity\": 4049690\n  },\n  {\n    \"tag\": "antidetonant",\n    \"popularity\": 3912727\n  },\n  {\n    \"tag\": "topeewallah",\n    \"popularity\": 3782875\n  },\n  {\n    \"tag\": "fidalgo ballant",\n    \"popularity\": 3659640\n  },\n  {\n    \"tag\": "utriculose",\n    \"popularity\": 3542572\n  },\n  {\n    \"tag\": "testata",\n    \"popularity\": 3431259\n  },\n  {\n    \"tag\": "beltmaking",\n    \"popularity\": 3325322\n  },\n  {\n    \"tag\": "necrotype",\n    \"popularity\": 3224413\n  },\n  {\n    \"tag\": "ovistic",\n    \"popularity\": 3128215\n  },\n  {\n    \"tag\": "swindlership",\n    \"popularity\": 3036431\n  },\n  {\n    \"tag\": "augustal",\n    \"popularity\": 2948792\n  },\n  {\n    \"tag\": "Titoist",\n    \"popularity\": 2865047\n  },\n  {\n    \"tag\": "trisoctahedral",\n    \"popularity\": 2784963\n  },\n  {\n    \"tag\": "sequestrator",\n    \"popularity\": 2708327\n  },\n  {\n    \"tag\": "sideburns",\n    \"popularity\": 2634939\n  },\n  {\n    \"tag\": "paraphrasia",\n    \"popularity\": 2564616\n  },\n  {\n    \"tag\": "graminology unbay",\n    \"popularity\": 2497185\n  },\n  {\n    \"tag\": "acaridomatium emargination",\n    \"popularity\": 2432487\n  },\n  {\n    \"tag\": "roofward",\n    \"popularity\": 2370373\n  },\n  {\n    \"tag\": "lauder",\n    \"popularity\": 2310705\n  },\n  {\n    \"tag\": "subjunctive",\n    \"popularity\": 2253354\n  },\n  {\n    \"tag\": "subelongate",\n    \"popularity\": 2198199\n  },\n  {\n    \"tag\": "guacimo",\n    \"popularity\": 2145128\n  },\n  {\n    \"tag\": "cockade",\n    \"popularity\": 2094033\n  },\n  {\n    \"tag\": "misgauge",\n    \"popularity\": 2044818\n  },\n  {\n    \"tag\": "unexpensive",\n    \"popularity\": 1997388\n  },\n  {\n    \"tag\": "chebel",\n    \"popularity\": 1951657\n  },\n  {\n    \"tag\": "unpursuing",\n    \"popularity\": 1907543\n  },\n  {\n    \"tag\": "kilobar",\n    \"popularity\": 1864969\n  },\n  {\n    \"tag\": "obsecration",\n    \"popularity\": 1823863\n  },\n  {\n    \"tag\": "nacarine",\n    \"popularity\": 1784157\n  },\n  {\n    \"tag\": "spirituosity",\n    \"popularity\": 1745787\n  },\n  {\n    \"tag\": "movableness deity",\n    \"popularity\": 1708692\n  },\n  {\n    \"tag\": "exostracism",\n    \"popularity\": 1672816\n  },\n  {\n    \"tag\": "archipterygium",\n    \"popularity\": 1638104\n  },\n  {\n    \"tag\": "monostrophic",\n    \"popularity\": 1604506\n  },\n  {\n    \"tag\": "gynecide",\n    \"popularity\": 1571974\n  },\n  {\n    \"tag\": "gladden",\n    \"popularity\": 1540462\n  },\n  {\n    \"tag\": "throughbred",\n    \"popularity\": 1509927\n  },\n  {\n    \"tag\": "groper",\n    \"popularity\": 1480329\n  },\n  {\n    \"tag\": "Xenosaurus",\n    \"popularity\": 1451628\n  },\n  {\n    \"tag\": "photoetcher",\n    \"popularity\": 1423788\n  },\n  {\n    \"tag\": "glucosid",\n    \"popularity\": 1396775\n  },\n  {\n    \"tag\": "Galtonian",\n    \"popularity\": 1370555\n  },\n  {\n    \"tag\": "mesosporic",\n    \"popularity\": 1345097\n  },\n  {\n    \"tag\": "theody",\n    \"popularity\": 1320370\n  },\n  {\n    \"tag\": "zaffer",\n    \"popularity\": 1296348\n  },\n  {\n    \"tag\": "probiology",\n    \"popularity\": 1273003\n  },\n  {\n    \"tag\": "rhizomic",\n    \"popularity\": 1250308\n  },\n  {\n    \"tag\": "superphosphate",\n    \"popularity\": 1228240\n  },\n  {\n    \"tag\": "Hippolytan",\n    \"popularity\": 1206776\n  },\n  {\n    \"tag\": "garget",\n    \"popularity\": 1185892\n  },\n  {\n    \"tag\": "diploplacula",\n    \"popularity\": 1165568\n  },\n  {\n    \"tag\": "orohydrographical",\n    \"popularity\": 1145785\n  },\n  {\n    \"tag\": "enhypostatize",\n    \"popularity\": 1126521\n  },\n  {\n    \"tag\": "polisman",\n    \"popularity\": 1107759\n  },\n  {\n    \"tag\": "acetometer",\n    \"popularity\": 1089482\n  },\n  {\n    \"tag\": "unsnatched",\n    \"popularity\": 1071672\n  },\n  {\n    \"tag\": "yabber",\n    \"popularity\": 1054313\n  },\n  {\n    \"tag\": "demiwolf",\n    \"popularity\": 1037390\n  },\n  {\n    \"tag\": "chromascope",\n    \"popularity\": 1020888\n  },\n  {\n    \"tag\": "seamanship",\n    \"popularity\": 1004794\n  },\n  {\n    \"tag\": "nonfenestrated",\n    \"popularity\": 989092\n  },\n  {\n    \"tag\": "hydrophytism",\n    \"popularity\": 973771\n  },\n  {\n    \"tag\": "dotter",\n    \"popularity\": 958819\n  },\n  {\n    \"tag\": "thermoperiodism",\n    \"popularity\": 944222\n  },\n  {\n    \"tag\": "unlawyerlike",\n    \"popularity\": 929970\n  },\n  {\n    \"tag\": "enantiomeride citywards",\n    \"popularity\": 916052\n  },\n  {\n    \"tag\": "unmetallurgical",\n    \"popularity\": 902456\n  },\n  {\n    \"tag\": "prickled",\n    \"popularity\": 889174\n  },\n  {\n    \"tag\": "strangerwise manioc",\n    \"popularity\": 876195\n  },\n  {\n    \"tag\": "incisorial",\n    \"popularity\": 863510\n  },\n  {\n    \"tag\": "irrationalize",\n    \"popularity\": 851110\n  },\n  {\n    \"tag\": "nasology",\n    \"popularity\": 838987\n  },\n  {\n    \"tag\": "fatuism",\n    \"popularity\": 827131\n  },\n  {\n    \"tag\": "Huk",\n    \"popularity\": 815535\n  },\n  {\n    \"tag\": "properispomenon",\n    \"popularity\": 804192\n  },\n  {\n    \"tag\": "unpummelled",\n    \"popularity\": 793094\n  },\n  {\n    \"tag\": "technographically",\n    \"popularity\": 782233\n  },\n  {\n    \"tag\": "underfurnish",\n    \"popularity\": 771603\n  },\n  {\n    \"tag\": "sinter",\n    \"popularity\": 761198\n  },\n  {\n    \"tag\": "lateroanterior",\n    \"popularity\": 751010\n  },\n  {\n    \"tag\": "nonpersonification",\n    \"popularity\": 741034\n  },\n  {\n    \"tag\": "Sitophilus",\n    \"popularity\": 731264\n  },\n  {\n    \"tag\": "unstudded overexerted",\n    \"popularity\": 721694\n  },\n  {\n    \"tag\": "tracheation",\n    \"popularity\": 712318\n  },\n  {\n    \"tag\": "thirteenth begloze",\n    \"popularity\": 703131\n  },\n  {\n    \"tag\": "bespice",\n    \"popularity\": 694129\n  },\n  {\n    \"tag\": "doppia",\n    \"popularity\": 685305\n  },\n  {\n    \"tag\": "unadorned",\n    \"popularity\": 676656\n  },\n  {\n    \"tag\": "dovelet engraff",\n    \"popularity\": 668176\n  },\n  {\n    \"tag\": "diphyozooid",\n    \"popularity\": 659862\n  },\n  {\n    \"tag\": "mure",\n    \"popularity\": 651708\n  },\n  {\n    \"tag\": "Tripitaka",\n    \"popularity\": 643710\n  },\n  {\n    \"tag\": "Billjim",\n    \"popularity\": 635865\n  },\n  {\n    \"tag\": "pyramidical",\n    \"popularity\": 628169\n  },\n  {\n    \"tag\": "circumlocutionist",\n    \"popularity\": 620617\n  },\n  {\n    \"tag\": "slapstick",\n    \"popularity\": 613207\n  },\n  {\n    \"tag\": "preobedience",\n    \"popularity\": 605934\n  },\n  {\n    \"tag\": "unfriarlike",\n    \"popularity\": 598795\n  },\n  {\n    \"tag\": "microchromosome",\n    \"popularity\": 591786\n  },\n  {\n    \"tag\": "Orphicism",\n    \"popularity\": 584905\n  },\n  {\n    \"tag\": "peel",\n    \"popularity\": 578149\n  },\n  {\n    \"tag\": "obediential",\n    \"popularity\": 571514\n  },\n  {\n    \"tag\": "Peripatidea",\n    \"popularity\": 564997\n  },\n  {\n    \"tag\": "undoubtful",\n    \"popularity\": 558596\n  },\n  {\n    \"tag\": "lodgeable",\n    \"popularity\": 552307\n  },\n  {\n    \"tag\": "pustulated woodchat",\n    \"popularity\": 546129\n  },\n  {\n    \"tag\": "antepast",\n    \"popularity\": 540057\n  },\n  {\n    \"tag\": "sagittoid matrimoniously",\n    \"popularity\": 534091\n  },\n  {\n    \"tag\": "Albizzia",\n    \"popularity\": 528228\n  },\n  {\n    \"tag\": "Elateridae unnewness",\n    \"popularity\": 522464\n  },\n  {\n    \"tag\": "convertingness",\n    \"popularity\": 516798\n  },\n  {\n    \"tag\": "Pelew",\n    \"popularity\": 511228\n  },\n  {\n    \"tag\": "recapitulation",\n    \"popularity\": 505751\n  },\n  {\n    \"tag\": "shack",\n    \"popularity\": 500365\n  },\n  {\n    \"tag\": "unmellowed",\n    \"popularity\": 495069\n  },\n  {\n    \"tag\": "pavis capering",\n    \"popularity\": 489859\n  },\n  {\n    \"tag\": "fanfare",\n    \"popularity\": 484735\n  },\n  {\n    \"tag\": "sole",\n    \"popularity\": 479695\n  },\n  {\n    \"tag\": "subarcuate",\n    \"popularity\": 474735\n  },\n  {\n    \"tag\": "multivious",\n    \"popularity\": 469856\n  },\n  {\n    \"tag\": "squandermania",\n    \"popularity\": 465054\n  },\n  {\n    \"tag\": "scintle",\n    \"popularity\": 460329\n  },\n  {\n    \"tag\": "hash chirognomic",\n    \"popularity\": 455679\n  },\n  {\n    \"tag\": "linseed",\n    \"popularity\": 451101\n  },\n  {\n    \"tag\": "redoubtable",\n    \"popularity\": 446596\n  },\n  {\n    \"tag\": "poachy reimpact",\n    \"popularity\": 442160\n  },\n  {\n    \"tag\": "limestone",\n    \"popularity\": 437792\n  },\n  {\n    \"tag\": "serranid",\n    \"popularity\": 433492\n  },\n  {\n    \"tag\": "pohna",\n    \"popularity\": 429258\n  },\n  {\n    \"tag\": "warwolf",\n    \"popularity\": 425088\n  },\n  {\n    \"tag\": "ruthenous",\n    \"popularity\": 420981\n  },\n  {\n    \"tag\": "dover",\n    \"popularity\": 416935\n  },\n  {\n    \"tag\": "deuteroalbumose",\n    \"popularity\": 412950\n  },\n  {\n    \"tag\": "pseudoprophetic",\n    \"popularity\": 409025\n  },\n  {\n    \"tag\": "dissoluteness",\n    \"popularity\": 405157\n  },\n  {\n    \"tag\": "preinvention",\n    \"popularity\": 401347\n  },\n  {\n    \"tag\": "swagbellied",\n    \"popularity\": 397592\n  },\n  {\n    \"tag\": "Ophidia",\n    \"popularity\": 393892\n  },\n  {\n    \"tag\": "equanimity",\n    \"popularity\": 390245\n  },\n  {\n    \"tag\": "troutful",\n    \"popularity\": 386651\n  },\n  {\n    \"tag\": "uke",\n    \"popularity\": 383108\n  },\n  {\n    \"tag\": "preacquaint",\n    \"popularity\": 379616\n  },\n  {\n    \"tag\": "shoq",\n    \"popularity\": 376174\n  },\n  {\n    \"tag\": "yox",\n    \"popularity\": 372780\n  },\n  {\n    \"tag\": "unelemental",\n    \"popularity\": 369434\n  },\n  {\n    \"tag\": "Yavapai",\n    \"popularity\": 366134\n  },\n  {\n    \"tag\": "joulean",\n    \"popularity\": 362880\n  },\n  {\n    \"tag\": "dracontine",\n    \"popularity\": 359672\n  },\n  {\n    \"tag\": "hardmouth",\n    \"popularity\": 356507\n  },\n  {\n    \"tag\": "sylvanize",\n    \"popularity\": 353386\n  },\n  {\n    \"tag\": "intraparenchymatous meadowbur",\n    \"popularity\": 350308\n  },\n  {\n    \"tag\": "uncharily",\n    \"popularity\": 347271\n  },\n  {\n    \"tag\": "redtab flexibly",\n    \"popularity\": 344275\n  },\n  {\n    \"tag\": "centervelic",\n    \"popularity\": 341319\n  },\n  {\n    \"tag\": "unravellable",\n    \"popularity\": 338403\n  },\n  {\n    \"tag\": "infortunately",\n    \"popularity\": 335526\n  },\n  {\n    \"tag\": "cannel",\n    \"popularity\": 332687\n  },\n  {\n    \"tag\": "oxyblepsia",\n    \"popularity\": 329885\n  },\n  {\n    \"tag\": "Damon",\n    \"popularity\": 327120\n  },\n  {\n    \"tag\": "etherin",\n    \"popularity\": 324391\n  },\n  {\n    \"tag\": "luminal",\n    \"popularity\": 321697\n  },\n  {\n    \"tag\": "interrogatorily presbyte",\n    \"popularity\": 319038\n  },\n  {\n    \"tag\": "hemiclastic",\n    \"popularity\": 316414\n  },\n  {\n    \"tag\": "poh flush",\n    \"popularity\": 313823\n  },\n  {\n    \"tag\": "Psoroptes",\n    \"popularity\": 311265\n  },\n  {\n    \"tag\": "dispirit",\n    \"popularity\": 308740\n  },\n  {\n    \"tag\": "nashgab",\n    \"popularity\": 306246\n  },\n  {\n    \"tag\": "Aphidiinae",\n    \"popularity\": 303784\n  },\n  {\n    \"tag\": "rhapsody nonconstruction",\n    \"popularity\": 301353\n  },\n  {\n    \"tag\": "Osmond",\n    \"popularity\": 298952\n  },\n  {\n    \"tag\": "Leonis",\n    \"popularity\": 296581\n  },\n  {\n    \"tag\": "Lemnian",\n    \"popularity\": 294239\n  },\n  {\n    \"tag\": "acetonic gnathonic",\n    \"popularity\": 291926\n  },\n  {\n    \"tag\": "surculus",\n    \"popularity\": 289641\n  },\n  {\n    \"tag\": "diagonally",\n    \"popularity\": 287384\n  },\n  {\n    \"tag\": "counterpenalty",\n    \"popularity\": 285154\n  },\n  {\n    \"tag\": "Eugenie",\n    \"popularity\": 282952\n  },\n  {\n    \"tag\": "hornbook",\n    \"popularity\": 280776\n  },\n  {\n    \"tag\": "miscoin",\n    \"popularity\": 278626\n  },\n  {\n    \"tag\": "admi",\n    \"popularity\": 276501\n  },\n  {\n    \"tag\": "Tarmac",\n    \"popularity\": 274402\n  },\n  {\n    \"tag\": "inexplicable",\n    \"popularity\": 272328\n  },\n  {\n    \"tag\": "rascallion",\n    \"popularity\": 270278\n  },\n  {\n    \"tag\": "dusterman",\n    \"popularity\": 268252\n  },\n  {\n    \"tag\": "osteostomous unhoroscopic",\n    \"popularity\": 266250\n  },\n  {\n    \"tag\": "spinibulbar",\n    \"popularity\": 264271\n  },\n  {\n    \"tag\": "phototelegraphically",\n    \"popularity\": 262315\n  },\n  {\n    \"tag\": "Manihot",\n    \"popularity\": 260381\n  },\n  {\n    \"tag\": "neighborhood",\n    \"popularity\": 258470\n  },\n  {\n    \"tag\": "Vincetoxicum",\n    \"popularity\": 256581\n  },\n  {\n    \"tag\": "khirka",\n    \"popularity\": 254713\n  },\n  {\n    \"tag\": "conscriptive",\n    \"popularity\": 252866\n  },\n  {\n    \"tag\": "synechthran",\n    \"popularity\": 251040\n  },\n  {\n    \"tag\": "Guttiferales",\n    \"popularity\": 249235\n  },\n  {\n    \"tag\": "roomful",\n    \"popularity\": 247450\n  },\n  {\n    \"tag\": "germinal",\n    \"popularity\": 245685\n  },\n  {\n    \"tag\": "untraitorous",\n    \"popularity\": 243939\n  },\n  {\n    \"tag\": "nondissenting",\n    \"popularity\": 242213\n  },\n  {\n    \"tag\": "amotion",\n    \"popularity\": 240506\n  },\n  {\n    \"tag\": "badious",\n    \"popularity\": 238817\n  },\n  {\n    \"tag\": "sumpit",\n    \"popularity\": 237147\n  },\n  {\n    \"tag\": "ectozoic",\n    \"popularity\": 235496\n  },\n  {\n    \"tag\": "elvet",\n    \"popularity\": 233862\n  },\n  {\n    \"tag\": "underclerk",\n    \"popularity\": 232246\n  },\n  {\n    \"tag\": "reticency",\n    \"popularity\": 230647\n  },\n  {\n    \"tag\": "neutroclusion",\n    \"popularity\": 229065\n  },\n  {\n    \"tag\": "unbelieving",\n    \"popularity\": 227500\n  },\n  {\n    \"tag\": "histogenetic",\n    \"popularity\": 225952\n  },\n  {\n    \"tag\": "dermamyiasis",\n    \"popularity\": 224421\n  },\n  {\n    \"tag\": "telenergy",\n    \"popularity\": 222905\n  },\n  {\n    \"tag\": "axiomatic",\n    \"popularity\": 221406\n  },\n  {\n    \"tag\": "undominoed",\n    \"popularity\": 219922\n  },\n  {\n    \"tag\": "periosteoma",\n    \"popularity\": 218454\n  },\n  {\n    \"tag\": "justiciaryship",\n    \"popularity\": 217001\n  },\n  {\n    \"tag\": "autoluminescence",\n    \"popularity\": 215563\n  },\n  {\n    \"tag\": "osmous",\n    \"popularity\": 214140\n  },\n  {\n    \"tag\": "borgh",\n    \"popularity\": 212731\n  },\n  {\n    \"tag\": "bedebt",\n    \"popularity\": 211337\n  },\n  {\n    \"tag\": "considerableness adenoidism",\n    \"popularity\": 209957\n  },\n  {\n    \"tag\": "sailorizing",\n    \"popularity\": 208592\n  },\n  {\n    \"tag\": "Montauk",\n    \"popularity\": 207240\n  },\n  {\n    \"tag\": "Bridget",\n    \"popularity\": 205901\n  },\n  {\n    \"tag\": "Gekkota",\n    \"popularity\": 204577\n  },\n  {\n    \"tag\": "subcorymbose",\n    \"popularity\": 203265\n  },\n  {\n    \"tag\": "undersap",\n    \"popularity\": 201967\n  },\n  {\n    \"tag\": "poikilothermic",\n    \"popularity\": 200681\n  },\n  {\n    \"tag\": "enneatical",\n    \"popularity\": 199409\n  },\n  {\n    \"tag\": "martinetism",\n    \"popularity\": 198148\n  },\n  {\n    \"tag\": "sustanedly",\n    \"popularity\": 196901\n  },\n  {\n    \"tag\": "declaration",\n    \"popularity\": 195665\n  },\n  {\n    \"tag\": "myringoplasty",\n    \"popularity\": 194442\n  },\n  {\n    \"tag\": "Ginkgo",\n    \"popularity\": 193230\n  },\n  {\n    \"tag\": "unrecurrent",\n    \"popularity\": 192031\n  },\n  {\n    \"tag\": "proprecedent",\n    \"popularity\": 190843\n  },\n  {\n    \"tag\": "roadman",\n    \"popularity\": 189666\n  },\n  {\n    \"tag\": "elemin",\n    \"popularity\": 188501\n  },\n  {\n    \"tag\": "maggot",\n    \"popularity\": 187347\n  },\n  {\n    \"tag\": "alitrunk",\n    \"popularity\": 186204\n  },\n  {\n    \"tag\": "introspection",\n    \"popularity\": 185071\n  },\n  {\n    \"tag\": "batiker",\n    \"popularity\": 183950\n  },\n  {\n    \"tag\": "backhatch oversettle",\n    \"popularity\": 182839\n  },\n  {\n    \"tag\": "thresherman",\n    \"popularity\": 181738\n  },\n  {\n    \"tag\": "protemperance",\n    \"popularity\": 180648\n  },\n  {\n    \"tag\": "undern",\n    \"popularity\": 179568\n  },\n  {\n    \"tag\": "tweeg",\n    \"popularity\": 178498\n  },\n  {\n    \"tag\": "crosspath",\n    \"popularity\": 177438\n  },\n  {\n    \"tag\": "Tangaridae",\n    \"popularity\": 176388\n  },\n  {\n    \"tag\": "scrutation",\n    \"popularity\": 175348\n  },\n  {\n    \"tag\": "piecemaker",\n    \"popularity\": 174317\n  },\n  {\n    \"tag\": "paster",\n    \"popularity\": 173296\n  },\n  {\n    \"tag\": "unpretendingness",\n    \"popularity\": 172284\n  },\n  {\n    \"tag\": "inframundane",\n    \"popularity\": 171281\n  },\n  {\n    \"tag\": "kiblah",\n    \"popularity\": 170287\n  },\n  {\n    \"tag\": "playwrighting",\n    \"popularity\": 169302\n  },\n  {\n    \"tag\": "gonepoiesis snowslip",\n    \"popularity\": 168326\n  },\n  {\n    \"tag\": "hoodwise",\n    \"popularity\": 167359\n  },\n  {\n    \"tag\": "postseason",\n    \"popularity\": 166401\n  },\n  {\n    \"tag\": "equivocality",\n    \"popularity\": 165451\n  },\n  {\n    \"tag\": "Opiliaceae nuclease",\n    \"popularity\": 164509\n  },\n  {\n    \"tag\": "sextipara",\n    \"popularity\": 163576\n  },\n  {\n    \"tag\": "weeper",\n    \"popularity\": 162651\n  },\n  {\n    \"tag\": "frambesia",\n    \"popularity\": 161735\n  },\n  {\n    \"tag\": "answerable",\n    \"popularity\": 160826\n  },\n  {\n    \"tag\": "Trichosporum",\n    \"popularity\": 159925\n  },\n  {\n    \"tag\": "cajuputol",\n    \"popularity\": 159033\n  },\n  {\n    \"tag\": "pleomorphous",\n    \"popularity\": 158148\n  },\n  {\n    \"tag\": "aculeolate",\n    \"popularity\": 157270\n  },\n  {\n    \"tag\": "wherever",\n    \"popularity\": 156400\n  },\n  {\n    \"tag\": "collapse",\n    \"popularity\": 155538\n  },\n  {\n    \"tag\": "porky",\n    \"popularity\": 154683\n  },\n  {\n    \"tag\": "perule",\n    \"popularity\": 153836\n  },\n  {\n    \"tag\": "Nevada",\n    \"popularity\": 152996\n  },\n  {\n    \"tag\": "conalbumin",\n    \"popularity\": 152162\n  },\n  {\n    \"tag\": "tsunami",\n    \"popularity\": 151336\n  },\n  {\n    \"tag\": "Gulf",\n    \"popularity\": 150517\n  },\n  {\n    \"tag\": "hertz",\n    \"popularity\": 149705\n  },\n  {\n    \"tag\": "limmock",\n    \"popularity\": 148900\n  },\n  {\n    \"tag\": "Tartarize",\n    \"popularity\": 148101\n  },\n  {\n    \"tag\": "entosphenoid",\n    \"popularity\": 147310\n  },\n  {\n    \"tag\": "ibis",\n    \"popularity\": 146524\n  },\n  {\n    \"tag\": "unyeaned",\n    \"popularity\": 145746\n  },\n  {\n    \"tag\": "tritural",\n    \"popularity\": 144973\n  },\n  {\n    \"tag\": "hundredary",\n    \"popularity\": 144207\n  },\n  {\n    \"tag\": "stolonlike",\n    \"popularity\": 143448\n  },\n  {\n    \"tag\": "chorister",\n    \"popularity\": 142694\n  },\n  {\n    \"tag\": "mismove",\n    \"popularity\": 141947\n  },\n  {\n    \"tag\": "Andine",\n    \"popularity\": 141206\n  },\n  {\n    \"tag\": "Annette proneur escribe",\n    \"popularity\": 140471\n  },\n  {\n    \"tag\": "exoperidium",\n    \"popularity\": 139742\n  },\n  {\n    \"tag\": "disedge",\n    \"popularity\": 139019\n  },\n  {\n    \"tag\": "hypochloruria",\n    \"popularity\": 138302\n  },\n  {\n    \"tag\": "prepupa",\n    \"popularity\": 137590\n  },\n  {\n    \"tag\": "assent",\n    \"popularity\": 136884\n  },\n  {\n    \"tag\": "hydrazobenzene",\n    \"popularity\": 136184\n  },\n  {\n    \"tag\": "emballonurid",\n    \"popularity\": 135489\n  },\n  {\n    \"tag\": "roselle",\n    \"popularity\": 134800\n  },\n  {\n    \"tag\": "unifiedly",\n    \"popularity\": 134117\n  },\n  {\n    \"tag\": "clang",\n    \"popularity\": 133439\n  },\n  {\n    \"tag\": "acetolytic",\n    \"popularity\": 132766\n  },\n  {\n    \"tag\": "cladodont",\n    \"popularity\": 132098\n  },\n  {\n    \"tag\": "recoast",\n    \"popularity\": 131436\n  },\n  {\n    \"tag\": "celebrated tydie Eocarboniferous",\n    \"popularity\": 130779\n  },\n  {\n    \"tag\": "superconsciousness",\n    \"popularity\": 130127\n  },\n  {\n    \"tag\": "soberness",\n    \"popularity\": 129480\n  },\n  {\n    \"tag\": "panoramist",\n    \"popularity\": 128838\n  },\n  {\n    \"tag\": "Orbitolina",\n    \"popularity\": 128201\n  },\n  {\n    \"tag\": "overlewd",\n    \"popularity\": 127569\n  },\n  {\n    \"tag\": "demiquaver",\n    \"popularity\": 126942\n  },\n  {\n    \"tag\": "kamelaukion",\n    \"popularity\": 126319\n  },\n  {\n    \"tag\": "flancard",\n    \"popularity\": 125702\n  },\n  {\n    \"tag\": "tricuspid",\n    \"popularity\": 125089\n  },\n  {\n    \"tag\": "bepelt",\n    \"popularity\": 124480\n  },\n  {\n    \"tag\": "decuplet",\n    \"popularity\": 123877\n  },\n  {\n    \"tag\": "Rockies",\n    \"popularity\": 123278\n  },\n  {\n    \"tag\": "unforgeability",\n    \"popularity\": 122683\n  },\n  {\n    \"tag\": "mocha",\n    \"popularity\": 122093\n  },\n  {\n    \"tag\": "scrunge",\n    \"popularity\": 121507\n  },\n  {\n    \"tag\": "delighter",\n    \"popularity\": 120926\n  },\n  {\n    \"tag\": "willey Microtinae",\n    \"popularity\": 120349\n  },\n  {\n    \"tag\": "unhuntable",\n    \"popularity\": 119777\n  },\n  {\n    \"tag\": "historically",\n    \"popularity\": 119208\n  },\n  {\n    \"tag\": "vicegerentship",\n    \"popularity\": 118644\n  },\n  {\n    \"tag\": "hemangiosarcoma",\n    \"popularity\": 118084\n  },\n  {\n    \"tag\": "harpago",\n    \"popularity\": 117528\n  },\n  {\n    \"tag\": "unionoid",\n    \"popularity\": 116976\n  },\n  {\n    \"tag\": "wiseman",\n    \"popularity\": 116429\n  },\n  {\n    \"tag\": "diclinism",\n    \"popularity\": 115885\n  },\n  {\n    \"tag\": "Maud",\n    \"popularity\": 115345\n  },\n  {\n    \"tag\": "scaphocephalism",\n    \"popularity\": 114809\n  },\n  {\n    \"tag\": "obtenebration",\n    \"popularity\": 114277\n  },\n  {\n    \"tag\": "cymar predreadnought",\n    \"popularity\": 113749\n  },\n  {\n    \"tag\": "discommend",\n    \"popularity\": 113225\n  },\n  {\n    \"tag\": "crude",\n    \"popularity\": 112704\n  },\n  {\n    \"tag\": "upflash",\n    \"popularity\": 112187\n  },\n  {\n    \"tag\": "saltimbank",\n    \"popularity\": 111674\n  },\n  {\n    \"tag\": "posthysterical",\n    \"popularity\": 111165\n  },\n  {\n    \"tag\": "trample",\n    \"popularity\": 110659\n  },\n  {\n    \"tag\": "ungirthed",\n    \"popularity\": 110157\n  },\n  {\n    \"tag\": "unshakable",\n    \"popularity\": 109658\n  },\n  {\n    \"tag\": "hepatocystic",\n    \"popularity\": 109163\n  },\n  {\n    \"tag\": "psammophyte",\n    \"popularity\": 108671\n  },\n  {\n    \"tag\": "millionfold",\n    \"popularity\": 108183\n  },\n  {\n    \"tag\": "outtaste",\n    \"popularity\": 107698\n  },\n  {\n    \"tag\": "poppycockish",\n    \"popularity\": 107217\n  },\n  {\n    \"tag\": "viduine",\n    \"popularity\": 106739\n  },\n  {\n    \"tag\": "pleasureman",\n    \"popularity\": 106264\n  },\n  {\n    \"tag\": "cholesterolemia",\n    \"popularity\": 105792\n  },\n  {\n    \"tag\": "hostlerwife",\n    \"popularity\": 105324\n  },\n  {\n    \"tag\": "figure undergrass",\n    \"popularity\": 104859\n  },\n  {\n    \"tag\": "bedrape",\n    \"popularity\": 104398\n  },\n  {\n    \"tag\": "nuttishness",\n    \"popularity\": 103939\n  },\n  {\n    \"tag\": "fow",\n    \"popularity\": 103484\n  },\n  {\n    \"tag\": "rachianesthesia",\n    \"popularity\": 103031\n  },\n  {\n    \"tag\": "recruitable",\n    \"popularity\": 102582\n  },\n  {\n    \"tag\": "semianatomical Oenotheraceae",\n    \"popularity\": 102136\n  },\n  {\n    \"tag\": "extracapsular",\n    \"popularity\": 101693\n  },\n  {\n    \"tag\": "unsigneted",\n    \"popularity\": 101253\n  },\n  {\n    \"tag\": "fissural",\n    \"popularity\": 100816\n  },\n  {\n    \"tag\": "ayous",\n    \"popularity\": 100381\n  },\n  {\n    \"tag\": "crestfallenness odontograph",\n    \"popularity\": 99950\n  },\n  {\n    \"tag\": "monopodium",\n    \"popularity\": 99522\n  },\n  {\n    \"tag\": "germfree",\n    \"popularity\": 99096\n  },\n  {\n    \"tag\": "dauphin",\n    \"popularity\": 98673\n  },\n  {\n    \"tag\": "nonagesimal",\n    \"popularity\": 98254\n  },\n  {\n    \"tag\": "waterchat",\n    \"popularity\": 97836\n  },\n  {\n    \"tag\": "Entelodon",\n    \"popularity\": 97422\n  },\n  {\n    \"tag\": "semischolastic",\n    \"popularity\": 97010\n  },\n  {\n    \"tag\": "somata",\n    \"popularity\": 96602\n  },\n  {\n    \"tag\": "expositorily",\n    \"popularity\": 96195\n  },\n  {\n    \"tag\": "bass",\n    \"popularity\": 95792\n  },\n  {\n    \"tag\": "calorimetry",\n    \"popularity\": 95391\n  },\n  {\n    \"tag\": "entireness",\n    \"popularity\": 94993\n  },\n  {\n    \"tag\": "ratline soppiness",\n    \"popularity\": 94597\n  },\n  {\n    \"tag\": "shor",\n    \"popularity\": 94204\n  },\n  {\n    \"tag\": "coprecipitation",\n    \"popularity\": 93813\n  },\n  {\n    \"tag\": "unblushingly",\n    \"popularity\": 93425\n  },\n  {\n    \"tag\": "macarize",\n    \"popularity\": 93040\n  },\n  {\n    \"tag\": "scruplesomeness",\n    \"popularity\": 92657\n  },\n  {\n    \"tag\": "offsaddle",\n    \"popularity\": 92276\n  },\n  {\n    \"tag\": "hypertragical",\n    \"popularity\": 91898\n  },\n  {\n    \"tag\": "uncassock loined",\n    \"popularity\": 91522\n  },\n  {\n    \"tag\": "interlobate",\n    \"popularity\": 91149\n  },\n  {\n    \"tag\": "releasor orrisroot stoloniferously",\n    \"popularity\": 90778\n  },\n  {\n    \"tag\": "elementoid",\n    \"popularity\": 90410\n  },\n  {\n    \"tag\": "Lentilla",\n    \"popularity\": 90043\n  },\n  {\n    \"tag\": "distressing",\n    \"popularity\": 89679\n  },\n  {\n    \"tag\": "hydrodrome",\n    \"popularity\": 89318\n  },\n  {\n    \"tag\": "Jeannette",\n    \"popularity\": 88958\n  },\n  {\n    \"tag\": "Kuli",\n    \"popularity\": 88601\n  },\n  {\n    \"tag\": "taxinomist",\n    \"popularity\": 88246\n  },\n  {\n    \"tag\": "southwestwardly",\n    \"popularity\": 87894\n  },\n  {\n    \"tag\": "polyparia",\n    \"popularity\": 87543\n  },\n  {\n    \"tag\": "exmeridian",\n    \"popularity\": 87195\n  },\n  {\n    \"tag\": "splenius regimentaled",\n    \"popularity\": 86849\n  },\n  {\n    \"tag\": "Sphaeropsidaceae",\n    \"popularity\": 86505\n  },\n  {\n    \"tag\": "unbegun",\n    \"popularity\": 86163\n  },\n  {\n    \"tag\": "something",\n    \"popularity\": 85823\n  },\n  {\n    \"tag\": "contaminable nonexpulsion",\n    \"popularity\": 85486\n  },\n  {\n    \"tag\": "douser",\n    \"popularity\": 85150\n  },\n  {\n    \"tag\": "prostrike",\n    \"popularity\": 84817\n  },\n  {\n    \"tag\": "worky",\n    \"popularity\": 84485\n  },\n  {\n    \"tag\": "folliful",\n    \"popularity\": 84156\n  },\n  {\n    \"tag\": "prioracy",\n    \"popularity\": 83828\n  },\n  {\n    \"tag\": "undermentioned",\n    \"popularity\": 83503\n  },\n  {\n    \"tag\": "Judaica",\n    \"popularity\": 83179\n  },\n  {\n    \"tag\": "multifarious",\n    \"popularity\": 82858\n  },\n  {\n    \"tag\": "poogye",\n    \"popularity\": 82538\n  },\n  {\n    \"tag\": "Sparganium",\n    \"popularity\": 82221\n  },\n  {\n    \"tag\": "thurrock",\n    \"popularity\": 81905\n  },\n  {\n    \"tag\": "outblush",\n    \"popularity\": 81591\n  },\n  {\n    \"tag\": "Strophanthus supraordination",\n    \"popularity\": 81279\n  },\n  {\n    \"tag\": "gingerroot",\n    \"popularity\": 80969\n  },\n  {\n    \"tag\": "unconscient",\n    \"popularity\": 80661\n  },\n  {\n    \"tag\": "unconstitutionally",\n    \"popularity\": 80354\n  },\n  {\n    \"tag\": "plaguily",\n    \"popularity\": 80050\n  },\n  {\n    \"tag\": "waterily equatorwards",\n    \"popularity\": 79747\n  },\n  {\n    \"tag\": "nondeposition",\n    \"popularity\": 79446\n  },\n  {\n    \"tag\": "dronishly",\n    \"popularity\": 79147\n  },\n  {\n    \"tag\": "gateado",\n    \"popularity\": 78849\n  },\n  {\n    \"tag\": "dislink",\n    \"popularity\": 78553\n  },\n  {\n    \"tag\": "Joceline",\n    \"popularity\": 78259\n  },\n  {\n    \"tag\": "amphiboliferous",\n    \"popularity\": 77967\n  },\n  {\n    \"tag\": "bushrope",\n    \"popularity\": 77676\n  },\n  {\n    \"tag\": "plumicorn sulphosalicylic",\n    \"popularity\": 77387\n  },\n  {\n    \"tag\": "nonefficiency",\n    \"popularity\": 77100\n  },\n  {\n    \"tag\": "hieroscopy",\n    \"popularity\": 76815\n  },\n  {\n    \"tag\": "causativeness",\n    \"popularity\": 76531\n  },\n  {\n    \"tag\": "swird paleoeremology",\n    \"popularity\": 76249\n  },\n  {\n    \"tag\": "camphoric",\n    \"popularity\": 75968\n  },\n  {\n    \"tag\": "retaining",\n    \"popularity\": 75689\n  },\n  {\n    \"tag\": "thyreoprotein",\n    \"popularity\": 75411\n  },\n  {\n    \"tag\": "carbona",\n    \"popularity\": 75136\n  },\n  {\n    \"tag\": "protectively",\n    \"popularity\": 74861\n  },\n  {\n    \"tag\": "mosasaur",\n    \"popularity\": 74589\n  },\n  {\n    \"tag\": "reciprocator",\n    \"popularity\": 74317\n  },\n  {\n    \"tag\": "detentive",\n    \"popularity\": 74048\n  },\n  {\n    \"tag\": "supravital",\n    \"popularity\": 73780\n  },\n  {\n    \"tag\": "Vespertilionidae",\n    \"popularity\": 73513\n  },\n  {\n    \"tag\": "parka",\n    \"popularity\": 73248\n  },\n  {\n    \"tag\": "pickaway",\n    \"popularity\": 72984\n  },\n  {\n    \"tag\": "oleaceous",\n    \"popularity\": 72722\n  },\n  {\n    \"tag\": "anticogitative",\n    \"popularity\": 72462\n  },\n  {\n    \"tag\": "woe",\n    \"popularity\": 72203\n  },\n  {\n    \"tag\": "skeuomorph",\n    \"popularity\": 71945\n  },\n  {\n    \"tag\": "helpmeet",\n    \"popularity\": 71689\n  },\n  {\n    \"tag\": "Hexactinellida brickmaking",\n    \"popularity\": 71434\n  },\n  {\n    \"tag\": "resink",\n    \"popularity\": 71180\n  },\n  {\n    \"tag\": "diluter",\n    \"popularity\": 70928\n  },\n  {\n    \"tag\": "micromicron",\n    \"popularity\": 70677\n  },\n  {\n    \"tag\": "parentage",\n    \"popularity\": 70428\n  },\n  {\n    \"tag\": "galactorrhoea",\n    \"popularity\": 70180\n  },\n  {\n    \"tag\": "gey",\n    \"popularity\": 69934\n  },\n  {\n    \"tag\": "gesticulatory",\n    \"popularity\": 69689\n  },\n  {\n    \"tag\": "wergil",\n    \"popularity\": 69445\n  },\n  {\n    \"tag\": "Lecanora",\n    \"popularity\": 69202\n  },\n  {\n    \"tag\": "malanders karst",\n    \"popularity\": 68961\n  },\n  {\n    \"tag\": "vibetoite",\n    \"popularity\": 68721\n  },\n  {\n    \"tag\": "unrequitedness",\n    \"popularity\": 68483\n  },\n  {\n    \"tag\": "outwash",\n    \"popularity\": 68245\n  },\n  {\n    \"tag\": "unsacred",\n    \"popularity\": 68009\n  },\n  {\n    \"tag\": "unabetted dividend",\n    \"popularity\": 67775\n  },\n  {\n    \"tag\": "untraveling",\n    \"popularity\": 67541\n  },\n  {\n    \"tag\": "thermobattery",\n    \"popularity\": 67309\n  },\n  {\n    \"tag\": "polypragmist",\n    \"popularity\": 67078\n  },\n  {\n    \"tag\": "irrefutableness",\n    \"popularity\": 66848\n  },\n  {\n    \"tag\": "remiges",\n    \"popularity\": 66620\n  },\n  {\n    \"tag\": "implode",\n    \"popularity\": 66393\n  },\n  {\n    \"tag\": "superfluousness",\n    \"popularity\": 66166\n  },\n  {\n    \"tag\": "croakily unalleviated",\n    \"popularity\": 65942\n  },\n  {\n    \"tag\": "edicule",\n    \"popularity\": 65718\n  },\n  {\n    \"tag\": "entophytous",\n    \"popularity\": 65495\n  },\n  {\n    \"tag\": "benefactorship Toryish",\n    \"popularity\": 65274\n  },\n  {\n    \"tag\": "pseudoamateurish",\n    \"popularity\": 65054\n  },\n  {\n    \"tag\": "flueless Iguanodontoidea snipnose",\n    \"popularity\": 64835\n  },\n  {\n    \"tag\": "zealotical Zamicrus interpole",\n    \"popularity\": 64617\n  },\n  {\n    \"tag\": "whereabout",\n    \"popularity\": 64401\n  },\n  {\n    \"tag\": "benzazide",\n    \"popularity\": 64185\n  },\n  {\n    \"tag\": "pokeweed",\n    \"popularity\": 63971\n  },\n  {\n    \"tag\": "calamitoid",\n    \"popularity\": 63757\n  },\n  {\n    \"tag\": "sporozoal",\n    \"popularity\": 63545\n  },\n  {\n    \"tag\": "physcioid Welshwoman",\n    \"popularity\": 63334\n  },\n  {\n    \"tag\": "wanting",\n    \"popularity\": 63124\n  },\n  {\n    \"tag\": "unencumbering",\n    \"popularity\": 62915\n  },\n  {\n    \"tag\": "Tupi",\n    \"popularity\": 62707\n  },\n  {\n    \"tag\": "potbank",\n    \"popularity\": 62501\n  },\n  {\n    \"tag\": "bulked",\n    \"popularity\": 62295\n  },\n  {\n    \"tag\": "uparise",\n    \"popularity\": 62090\n  },\n  {\n    \"tag\": "Sudra",\n    \"popularity\": 61887\n  },\n  {\n    \"tag\": "hyperscrupulosity",\n    \"popularity\": 61684\n  },\n  {\n    \"tag\": "subterraneously unmaid",\n    \"popularity\": 61483\n  },\n  {\n    \"tag\": "poisonousness",\n    \"popularity\": 61282\n  },\n  {\n    \"tag\": "phare",\n    \"popularity\": 61083\n  },\n  {\n    \"tag\": "dicynodont",\n    \"popularity\": 60884\n  },\n  {\n    \"tag\": "chewer",\n    \"popularity\": 60687\n  },\n  {\n    \"tag\": "uliginous",\n    \"popularity\": 60490\n  },\n  {\n    \"tag\": "tinman",\n    \"popularity\": 60295\n  },\n  {\n    \"tag\": "coconut",\n    \"popularity\": 60100\n  },\n  {\n    \"tag\": "phryganeoid",\n    \"popularity\": 59907\n  },\n  {\n    \"tag\": "bismillah",\n    \"popularity\": 59714\n  },\n  {\n    \"tag\": "tautomeric",\n    \"popularity\": 59523\n  },\n  {\n    \"tag\": "jerquer",\n    \"popularity\": 59332\n  },\n  {\n    \"tag\": "Dryopithecinae",\n    \"popularity\": 59143\n  },\n  {\n    \"tag\": "ghizite",\n    \"popularity\": 58954\n  },\n  {\n    \"tag\": "unliveable",\n    \"popularity\": 58766\n  },\n  {\n    \"tag\": "craftsmaster",\n    \"popularity\": 58579\n  },\n  {\n    \"tag\": "semiscenic",\n    \"popularity\": 58394\n  },\n  {\n    \"tag\": "danaid",\n    \"popularity\": 58209\n  },\n  {\n    \"tag\": "flawful",\n    \"popularity\": 58025\n  },\n  {\n    \"tag\": "risibleness",\n    \"popularity\": 57841\n  },\n  {\n    \"tag\": "Muscovite",\n    \"popularity\": 57659\n  },\n  {\n    \"tag\": "snaringly",\n    \"popularity\": 57478\n  },\n  {\n    \"tag\": "brilliantwise",\n    \"popularity\": 57297\n  },\n  {\n    \"tag\": "plebeity",\n    \"popularity\": 57118\n  },\n  {\n    \"tag\": "historicalness",\n    \"popularity\": 56939\n  },\n  {\n    \"tag\": "piecemeal",\n    \"popularity\": 56761\n  },\n  {\n    \"tag\": "maxillipedary",\n    \"popularity\": 56584\n  },\n  {\n    \"tag\": "Hypenantron",\n    \"popularity\": 56408\n  },\n  {\n    \"tag\": "quaintness avigate",\n    \"popularity\": 56233\n  },\n  {\n    \"tag\": "ave",\n    \"popularity\": 56059\n  },\n  {\n    \"tag\": "mediaevally",\n    \"popularity\": 55885\n  },\n  {\n    \"tag\": "brucite",\n    \"popularity\": 55712\n  },\n  {\n    \"tag\": "Schwendenerian",\n    \"popularity\": 55541\n  },\n  {\n    \"tag\": "julole",\n    \"popularity\": 55370\n  },\n  {\n    \"tag\": "palaeolith",\n    \"popularity\": 55199\n  },\n  {\n    \"tag\": "cotyledonary",\n    \"popularity\": 55030\n  },\n  {\n    \"tag\": "rond",\n    \"popularity\": 54861\n  },\n  {\n    \"tag\": "boomster tassoo",\n    \"popularity\": 54694\n  },\n  {\n    \"tag\": "cattishly",\n    \"popularity\": 54527\n  },\n  {\n    \"tag\": "tonguefence",\n    \"popularity\": 54360\n  },\n  {\n    \"tag\": "hexastylar triskele",\n    \"popularity\": 54195\n  },\n  {\n    \"tag\": "ariot",\n    \"popularity\": 54030\n  },\n  {\n    \"tag\": "intarsist",\n    \"popularity\": 53867\n  },\n  {\n    \"tag\": "Oscines",\n    \"popularity\": 53704\n  },\n  {\n    \"tag\": "Spaniolize",\n    \"popularity\": 53541\n  },\n  {\n    \"tag\": "smellfungus",\n    \"popularity\": 53380\n  },\n  {\n    \"tag\": "redisplay",\n    \"popularity\": 53219\n  },\n  {\n    \"tag\": "phosphene",\n    \"popularity\": 53059\n  },\n  {\n    \"tag\": "phycomycete",\n    \"popularity\": 52900\n  },\n  {\n    \"tag\": "prophetic",\n    \"popularity\": 52741\n  },\n  {\n    \"tag\": "overtrustful",\n    \"popularity\": 52584\n  },\n  {\n    \"tag\": "pinitol",\n    \"popularity\": 52427\n  },\n  {\n    \"tag\": "asthmatic",\n    \"popularity\": 52270\n  },\n  {\n    \"tag\": "convulsive",\n    \"popularity\": 52115\n  },\n  {\n    \"tag\": "draughtswoman",\n    \"popularity\": 51960\n  },\n  {\n    \"tag\": "unetymologizable",\n    \"popularity\": 51806\n  },\n  {\n    \"tag\": "centrarchoid",\n    \"popularity\": 51652\n  },\n  {\n    \"tag\": "mesioincisal",\n    \"popularity\": 51500\n  },\n  {\n    \"tag\": "transbaikal",\n    \"popularity\": 51348\n  },\n  {\n    \"tag\": "silveriness",\n    \"popularity\": 51196\n  },\n  {\n    \"tag\": "costotomy",\n    \"popularity\": 51046\n  },\n  {\n    \"tag\": "caracore",\n    \"popularity\": 50896\n  },\n  {\n    \"tag\": "depotentiation",\n    \"popularity\": 50747\n  },\n  {\n    \"tag\": "glossoepiglottidean",\n    \"popularity\": 50598\n  },\n  {\n    \"tag\": "upswell",\n    \"popularity\": 50450\n  },\n  {\n    \"tag\": "flecnodal",\n    \"popularity\": 50303\n  },\n  {\n    \"tag\": "coventrate",\n    \"popularity\": 50157\n  },\n  {\n    \"tag\": "duchesse",\n    \"popularity\": 50011\n  },\n  {\n    \"tag\": "excisemanship trophied",\n    \"popularity\": 49866\n  },\n  {\n    \"tag\": "cytinaceous",\n    \"popularity\": 49721\n  },\n  {\n    \"tag\": "assuringly",\n    \"popularity\": 49577\n  },\n  {\n    \"tag\": "unconducted upliftitis",\n    \"popularity\": 49434\n  },\n  {\n    \"tag\": "rachicentesis",\n    \"popularity\": 49292\n  },\n  {\n    \"tag\": "antiangular",\n    \"popularity\": 49150\n  },\n  {\n    \"tag\": "advisal",\n    \"popularity\": 49008\n  },\n  {\n    \"tag\": "birdcatcher",\n    \"popularity\": 48868\n  },\n  {\n    \"tag\": "secularistic",\n    \"popularity\": 48728\n  },\n  {\n    \"tag\": "grandeeism superinformal",\n    \"popularity\": 48588\n  },\n  {\n    \"tag\": "unapprehension",\n    \"popularity\": 48449\n  },\n  {\n    \"tag\": "excipulum",\n    \"popularity\": 48311\n  },\n  {\n    \"tag\": "decimole",\n    \"popularity\": 48174\n  },\n  {\n    \"tag\": "semidrachm",\n    \"popularity\": 48037\n  },\n  {\n    \"tag\": "uvulotome",\n    \"popularity\": 47901\n  },\n  {\n    \"tag\": "Lemaneaceae",\n    \"popularity\": 47765\n  },\n  {\n    \"tag\": "corrade",\n    \"popularity\": 47630\n  },\n  {\n    \"tag\": "Kuroshio",\n    \"popularity\": 47495\n  },\n  {\n    \"tag\": "Araliophyllum",\n    \"popularity\": 47361\n  },\n  {\n    \"tag\": "victoriousness cardiosphygmograph",\n    \"popularity\": 47228\n  },\n  {\n    \"tag\": "reinvent",\n    \"popularity\": 47095\n  },\n  {\n    \"tag\": "Macrotolagus",\n    \"popularity\": 46963\n  },\n  {\n    \"tag\": "strenuousness",\n    \"popularity\": 46831\n  },\n  {\n    \"tag\": "deviability",\n    \"popularity\": 46700\n  },\n  {\n    \"tag\": "phyllospondylous",\n    \"popularity\": 46570\n  },\n  {\n    \"tag\": "bisect rudderhole",\n    \"popularity\": 46440\n  },\n  {\n    \"tag\": "crownwork",\n    \"popularity\": 46311\n  },\n  {\n    \"tag\": "Ascalabota",\n    \"popularity\": 46182\n  },\n  {\n    \"tag\": "prostatomyomectomy",\n    \"popularity\": 46054\n  },\n  {\n    \"tag\": "neurosyphilis",\n    \"popularity\": 45926\n  },\n  {\n    \"tag\": "tabloid scraplet",\n    \"popularity\": 45799\n  },\n  {\n    \"tag\": "nonmedullated servility",\n    \"popularity\": 45673\n  },\n  {\n    \"tag\": "melopoeic practicalization",\n    \"popularity\": 45547\n  },\n  {\n    \"tag\": "nonrhythmic",\n    \"popularity\": 45421\n  },\n  {\n    \"tag\": "deplorer",\n    \"popularity\": 45296\n  },\n  {\n    \"tag\": "Ophion",\n    \"popularity\": 45172\n  },\n  {\n    \"tag\": "subprioress",\n    \"popularity\": 45048\n  },\n  {\n    \"tag\": "semiregular",\n    \"popularity\": 44925\n  },\n  {\n    \"tag\": "praelection",\n    \"popularity\": 44802\n  },\n  {\n    \"tag\": "discinct",\n    \"popularity\": 44680\n  },\n  {\n    \"tag\": "preplace",\n    \"popularity\": 44558\n  },\n  {\n    \"tag\": "paternoster",\n    \"popularity\": 44437\n  },\n  {\n    \"tag\": "suboccipital",\n    \"popularity\": 44316\n  },\n  {\n    \"tag\": "Teutophil",\n    \"popularity\": 44196\n  },\n  {\n    \"tag\": "tracheole",\n    \"popularity\": 44076\n  },\n  {\n    \"tag\": "subsmile",\n    \"popularity\": 43957\n  },\n  {\n    \"tag\": "nonapostatizing",\n    \"popularity\": 43839\n  },\n  {\n    \"tag\": "cleidotomy",\n    \"popularity\": 43720\n  },\n  {\n    \"tag\": "hingle",\n    \"popularity\": 43603\n  },\n  {\n    \"tag\": "jocoque",\n    \"popularity\": 43486\n  },\n  {\n    \"tag\": "trundler notidanian",\n    \"popularity\": 43369\n  },\n  {\n    \"tag\": "strangling misdaub",\n    \"popularity\": 43253\n  },\n  {\n    \"tag\": "noncancellable",\n    \"popularity\": 43137\n  },\n  {\n    \"tag\": "lavabo",\n    \"popularity\": 43022\n  },\n  {\n    \"tag\": "lanterloo",\n    \"popularity\": 42907\n  },\n  {\n    \"tag\": "uncitizenly",\n    \"popularity\": 42793\n  },\n  {\n    \"tag\": "autoturning",\n    \"popularity\": 42679\n  },\n  {\n    \"tag\": "Haganah",\n    \"popularity\": 42566\n  },\n  {\n    \"tag\": "Glecoma",\n    \"popularity\": 42453\n  },\n  {\n    \"tag\": "membered",\n    \"popularity\": 42341\n  },\n  {\n    \"tag\": "consuetudinal",\n    \"popularity\": 42229\n  },\n  {\n    \"tag\": "gatehouse",\n    \"popularity\": 42117\n  },\n  {\n    \"tag\": "tetherball",\n    \"popularity\": 42006\n  },\n  {\n    \"tag\": "counterrevolutionist numismatical",\n    \"popularity\": 41896\n  },\n  {\n    \"tag\": "pagehood plateiasmus",\n    \"popularity\": 41786\n  },\n  {\n    \"tag\": "pelterer",\n    \"popularity\": 41676\n  },\n  {\n    \"tag\": "splenemphraxis",\n    \"popularity\": 41567\n  },\n  {\n    \"tag\": "Crypturidae",\n    \"popularity\": 41458\n  },\n  {\n    \"tag\": "caboodle",\n    \"popularity\": 41350\n  },\n  {\n    \"tag\": "Filaria",\n    \"popularity\": 41242\n  },\n  {\n    \"tag\": "noninvincibility",\n    \"popularity\": 41135\n  },\n  {\n    \"tag\": "preadvertisement",\n    \"popularity\": 41028\n  },\n  {\n    \"tag\": "bathrobe",\n    \"popularity\": 40921\n  },\n  {\n    \"tag\": "nitrifier",\n    \"popularity\": 40815\n  },\n  {\n    \"tag\": "furthermore",\n    \"popularity\": 40709\n  },\n  {\n    \"tag\": "recrate",\n    \"popularity\": 40604\n  },\n  {\n    \"tag\": "inexist",\n    \"popularity\": 40499\n  },\n  {\n    \"tag\": "Mocoan",\n    \"popularity\": 40395\n  },\n  {\n    \"tag\": "forint",\n    \"popularity\": 40291\n  },\n  {\n    \"tag\": "cardiomyoliposis",\n    \"popularity\": 40187\n  },\n  {\n    \"tag\": "channeling",\n    \"popularity\": 40084\n  },\n  {\n    \"tag\": "quebrachine",\n    \"popularity\": 39981\n  },\n  {\n    \"tag\": "magistery",\n    \"popularity\": 39879\n  },\n  {\n    \"tag\": "koko",\n    \"popularity\": 39777\n  },\n  {\n    \"tag\": "nobilify",\n    \"popularity\": 39676\n  },\n  {\n    \"tag\": "articulate taprooted",\n    \"popularity\": 39575\n  },\n  {\n    \"tag\": "cardiotonic Nicaragua",\n    \"popularity\": 39474\n  },\n  {\n    \"tag\": "assertiveness",\n    \"popularity\": 39374\n  },\n  {\n    \"tag\": "springtail",\n    \"popularity\": 39274\n  },\n  {\n    \"tag\": "spontoon",\n    \"popularity\": 39174\n  },\n  {\n    \"tag\": "plesiobiosis",\n    \"popularity\": 39075\n  },\n  {\n    \"tag\": "rooinek",\n    \"popularity\": 38976\n  },\n  {\n    \"tag\": "hairif falsehood",\n    \"popularity\": 38878\n  },\n  {\n    \"tag\": "synodally",\n    \"popularity\": 38780\n  },\n  {\n    \"tag\": "biodynamics",\n    \"popularity\": 38683\n  },\n  {\n    \"tag\": "trickling",\n    \"popularity\": 38585\n  },\n  {\n    \"tag\": "oxfly daystar",\n    \"popularity\": 38489\n  },\n  {\n    \"tag\": "epicycloidal",\n    \"popularity\": 38392\n  },\n  {\n    \"tag\": "shorthand",\n    \"popularity\": 38296\n  },\n  {\n    \"tag\": "herpolhode",\n    \"popularity\": 38201\n  },\n  {\n    \"tag\": "polysynthesism",\n    \"popularity\": 38105\n  },\n  {\n    \"tag\": "cany",\n    \"popularity\": 38010\n  },\n  {\n    \"tag\": "sideage",\n    \"popularity\": 37916\n  },\n  {\n    \"tag\": "strainableness",\n    \"popularity\": 37822\n  },\n  {\n    \"tag\": "superformidable",\n    \"popularity\": 37728\n  },\n  {\n    \"tag\": "slendang",\n    \"popularity\": 37634\n  },\n  {\n    \"tag\": "impropriation",\n    \"popularity\": 37541\n  },\n  {\n    \"tag\": "ficklehearted",\n    \"popularity\": 37449\n  },\n  {\n    \"tag\": "wintrify",\n    \"popularity\": 37356\n  },\n  {\n    \"tag\": "geomorphogenist",\n    \"popularity\": 37264\n  },\n  {\n    \"tag\": "smuggleable",\n    \"popularity\": 37173\n  },\n  {\n    \"tag\": "delapsion",\n    \"popularity\": 37081\n  },\n  {\n    \"tag\": "projective",\n    \"popularity\": 36990\n  },\n  {\n    \"tag\": "unglue exfoliation",\n    \"popularity\": 36900\n  },\n  {\n    \"tag\": "Acerae",\n    \"popularity\": 36810\n  },\n  {\n    \"tag\": "unstaged",\n    \"popularity\": 36720\n  },\n  {\n    \"tag\": "ranal",\n    \"popularity\": 36630\n  },\n  {\n    \"tag\": "worrier",\n    \"popularity\": 36541\n  },\n  {\n    \"tag\": "unhid",\n    \"popularity\": 36452\n  },\n  {\n    \"tag\": "adequation",\n    \"popularity\": 36363\n  },\n  {\n    \"tag\": "strongylid Sokotri",\n    \"popularity\": 36275\n  },\n  {\n    \"tag\": "fumingly",\n    \"popularity\": 36187\n  },\n  {\n    \"tag\": "gynosporangium phaenogenetic",\n    \"popularity\": 36100\n  },\n  {\n    \"tag\": "uniunguiculate",\n    \"popularity\": 36012\n  },\n  {\n    \"tag\": "prudelike",\n    \"popularity\": 35926\n  },\n  {\n    \"tag\": "seminomata",\n    \"popularity\": 35839\n  },\n  {\n    \"tag\": "trinklet",\n    \"popularity\": 35753\n  },\n  {\n    \"tag\": "risorial",\n    \"popularity\": 35667\n  },\n  {\n    \"tag\": "pericardiocentesis",\n    \"popularity\": 35581\n  },\n  {\n    \"tag\": "filmist",\n    \"popularity\": 35496\n  },\n  {\n    \"tag\": "Nana",\n    \"popularity\": 35411\n  },\n  {\n    \"tag\": "cynipoid",\n    \"popularity\": 35326\n  },\n  {\n    \"tag\": "cteniform",\n    \"popularity\": 35242\n  },\n  {\n    \"tag\": "semiflex",\n    \"popularity\": 35158\n  },\n  {\n    \"tag\": "solstitially",\n    \"popularity\": 35074\n  },\n  {\n    \"tag\": "Algarsife",\n    \"popularity\": 34991\n  },\n  {\n    \"tag\": "noncriminal",\n    \"popularity\": 34908\n  },\n  {\n    \"tag\": "compassion",\n    \"popularity\": 34825\n  },\n  {\n    \"tag\": "Buddhic",\n    \"popularity\": 34743\n  },\n  {\n    \"tag\": "vellicative dactylically hotfoot",\n    \"popularity\": 34661\n  },\n  {\n    \"tag\": "chicory",\n    \"popularity\": 34579\n  },\n  {\n    \"tag\": "transperitoneally",\n    \"popularity\": 34497\n  },\n  {\n    \"tag\": "pennae",\n    \"popularity\": 34416\n  },\n  {\n    \"tag\": "Flamandize",\n    \"popularity\": 34335\n  },\n  {\n    \"tag\": "underviewer",\n    \"popularity\": 34254\n  },\n  {\n    \"tag\": "assoil",\n    \"popularity\": 34174\n  },\n  {\n    \"tag\": "saccharobacillus",\n    \"popularity\": 34094\n  },\n  {\n    \"tag\": "biacetylene",\n    \"popularity\": 34014\n  },\n  {\n    \"tag\": "mouchardism",\n    \"popularity\": 33935\n  },\n  {\n    \"tag\": "anisomeric",\n    \"popularity\": 33856\n  },\n  {\n    \"tag\": "digestive",\n    \"popularity\": 33777\n  },\n  {\n    \"tag\": "darlingly",\n    \"popularity\": 33698\n  },\n  {\n    \"tag\": "liman",\n    \"popularity\": 33620\n  },\n  {\n    \"tag\": "soldanrie",\n    \"popularity\": 33542\n  },\n  {\n    \"tag\": "sully",\n    \"popularity\": 33464\n  },\n  {\n    \"tag\": "brightsmith",\n    \"popularity\": 33387\n  },\n  {\n    \"tag\": "inwrap antiliturgist ureterocervical",\n    \"popularity\": 33309\n  },\n  {\n    \"tag\": "discommodity",\n    \"popularity\": 33232\n  },\n  {\n    \"tag\": "typical aggrandizer",\n    \"popularity\": 33156\n  },\n  {\n    \"tag\": "xenogeny",\n    \"popularity\": 33079\n  },\n  {\n    \"tag\": "uncountrified",\n    \"popularity\": 33003\n  },\n  {\n    \"tag\": "Podarge",\n    \"popularity\": 32928\n  },\n  {\n    \"tag\": "uninterviewed",\n    \"popularity\": 32852\n  },\n  {\n    \"tag\": "underprior",\n    \"popularity\": 32777\n  },\n  {\n    \"tag\": "leiomyomatous",\n    \"popularity\": 32702\n  },\n  {\n    \"tag\": "postdysenteric",\n    \"popularity\": 32627\n  },\n  {\n    \"tag\": "Fusicladium",\n    \"popularity\": 32553\n  },\n  {\n    \"tag\": "Dulcinea",\n    \"popularity\": 32478\n  },\n  {\n    \"tag\": "interspersion",\n    \"popularity\": 32404\n  },\n  {\n    \"tag\": "preobligate",\n    \"popularity\": 32331\n  },\n  {\n    \"tag\": "subaggregate",\n    \"popularity\": 32257\n  },\n  {\n    \"tag\": "grammarianism",\n    \"popularity\": 32184\n  },\n  {\n    \"tag\": "palikar",\n    \"popularity\": 32111\n  },\n  {\n    \"tag\": "facileness",\n    \"popularity\": 32039\n  },\n  {\n    \"tag\": "deuterofibrinose",\n    \"popularity\": 31966\n  },\n  {\n    \"tag\": "pseudesthesia",\n    \"popularity\": 31894\n  },\n  {\n    \"tag\": "sedimentary",\n    \"popularity\": 31822\n  },\n  {\n    \"tag\": "typewrite",\n    \"popularity\": 31751\n  },\n  {\n    \"tag\": "immemorable",\n    \"popularity\": 31679\n  },\n  {\n    \"tag\": "Myrtus",\n    \"popularity\": 31608\n  },\n  {\n    \"tag\": "hauchecornite",\n    \"popularity\": 31537\n  },\n  {\n    \"tag\": "galleylike",\n    \"popularity\": 31467\n  },\n  {\n    \"tag\": "thimber",\n    \"popularity\": 31396\n  },\n  {\n    \"tag\": "Hegelianism",\n    \"popularity\": 31326\n  },\n  {\n    \"tag\": "strig",\n    \"popularity\": 31256\n  },\n  {\n    \"tag\": "skyre",\n    \"popularity\": 31187\n  },\n  {\n    \"tag\": "eupepticism",\n    \"popularity\": 31117\n  },\n  {\n    \"tag\": "eponymism",\n    \"popularity\": 31048\n  },\n  {\n    \"tag\": "flunkeyhood",\n    \"popularity\": 30979\n  },\n  {\n    \"tag\": "Abama",\n    \"popularity\": 30911\n  },\n  {\n    \"tag\": "adiadochokinesis",\n    \"popularity\": 30842\n  },\n  {\n    \"tag\": "spendthrifty",\n    \"popularity\": 30774\n  },\n  {\n    \"tag\": "chalcedony",\n    \"popularity\": 30706\n  },\n  {\n    \"tag\": "authorism",\n    \"popularity\": 30638\n  },\n  {\n    \"tag\": "nasturtium",\n    \"popularity\": 30571\n  },\n  {\n    \"tag\": "Acanthocereus",\n    \"popularity\": 30504\n  },\n  {\n    \"tag\": "uncollapsible",\n    \"popularity\": 30437\n  },\n  {\n    \"tag\": "excursionist",\n    \"popularity\": 30370\n  },\n  {\n    \"tag\": "fogbow",\n    \"popularity\": 30303\n  },\n  {\n    \"tag\": "overlie",\n    \"popularity\": 30237\n  },\n  {\n    \"tag\": "velours",\n    \"popularity\": 30171\n  },\n  {\n    \"tag\": "zoodendria madrigal stagbush",\n    \"popularity\": 30105\n  },\n  {\n    \"tag\": "imi",\n    \"popularity\": 30039\n  },\n  {\n    \"tag\": "cojudge",\n    \"popularity\": 29974\n  },\n  {\n    \"tag\": "depurate argal",\n    \"popularity\": 29909\n  },\n  {\n    \"tag\": "unrecognition",\n    \"popularity\": 29844\n  },\n  {\n    \"tag\": "paunchful",\n    \"popularity\": 29779\n  },\n  {\n    \"tag\": "invalued",\n    \"popularity\": 29714\n  },\n  {\n    \"tag\": "probang",\n    \"popularity\": 29650\n  },\n  {\n    \"tag\": "chetvert",\n    \"popularity\": 29586\n  },\n  {\n    \"tag\": "enactable",\n    \"popularity\": 29522\n  },\n  {\n    \"tag\": "detoxicate adhibit",\n    \"popularity\": 29458\n  },\n  {\n    \"tag\": "kullaite",\n    \"popularity\": 29395\n  },\n  {\n    \"tag\": "undazzling",\n    \"popularity\": 29332\n  },\n  {\n    \"tag\": "excalation",\n    \"popularity\": 29269\n  },\n  {\n    \"tag\": "sievings",\n    \"popularity\": 29206\n  },\n  {\n    \"tag\": "disenthral",\n    \"popularity\": 29143\n  },\n  {\n    \"tag\": "disinterestedly",\n    \"popularity\": 29081\n  },\n  {\n    \"tag\": "stanner",\n    \"popularity\": 29018\n  },\n  {\n    \"tag\": "recapitulative",\n    \"popularity\": 28956\n  },\n  {\n    \"tag\": "objectivist",\n    \"popularity\": 28895\n  },\n  {\n    \"tag\": "hypermetropia",\n    \"popularity\": 28833\n  },\n  {\n    \"tag\": "incumbency",\n    \"popularity\": 28772\n  },\n  {\n    \"tag\": "protegee",\n    \"popularity\": 28711\n  },\n  {\n    \"tag\": "zealotic",\n    \"popularity\": 28650\n  },\n  {\n    \"tag\": "predebit",\n    \"popularity\": 28589\n  },\n  {\n    \"tag\": "cupolar",\n    \"popularity\": 28528\n  },\n  {\n    \"tag\": "unattributed",\n    \"popularity\": 28468\n  },\n  {\n    \"tag\": "louisine",\n    \"popularity\": 28408\n  },\n  {\n    \"tag\": "illustrate",\n    \"popularity\": 28348\n  },\n  {\n    \"tag\": "inofficiousness",\n    \"popularity\": 28288\n  },\n  {\n    \"tag\": "Americawards",\n    \"popularity\": 28228\n  },\n  {\n    \"tag\": "foreflap",\n    \"popularity\": 28169\n  },\n  {\n    \"tag\": "eruditeness",\n    \"popularity\": 28110\n  },\n  {\n    \"tag\": "copiopsia",\n    \"popularity\": 28051\n  },\n  {\n    \"tag\": "sporuliferous",\n    \"popularity\": 27992\n  },\n  {\n    \"tag\": "muttering",\n    \"popularity\": 27934\n  },\n  {\n    \"tag\": "prepsychology adrip",\n    \"popularity\": 27875\n  },\n  {\n    \"tag\": "unfriendly",\n    \"popularity\": 27817\n  },\n  {\n    \"tag\": "sulphanilic",\n    \"popularity\": 27759\n  },\n  {\n    \"tag\": "Coelococcus",\n    \"popularity\": 27701\n  },\n  {\n    \"tag\": "undoubtfulness",\n    \"popularity\": 27643\n  },\n  {\n    \"tag\": "flaringly",\n    \"popularity\": 27586\n  },\n  {\n    \"tag\": "unordain",\n    \"popularity\": 27529\n  },\n  {\n    \"tag\": "fratchety",\n    \"popularity\": 27472\n  },\n  {\n    \"tag\": "decadentism dolefully",\n    \"popularity\": 27415\n  },\n  {\n    \"tag\": "synthronus",\n    \"popularity\": 27358\n  },\n  {\n    \"tag\": "maiid",\n    \"popularity\": 27301\n  },\n  {\n    \"tag\": "rhinobyon",\n    \"popularity\": 27245\n  },\n  {\n    \"tag\": "Didynamia",\n    \"popularity\": 27189\n  },\n  {\n    \"tag\": "millionairedom",\n    \"popularity\": 27133\n  },\n  {\n    \"tag\": "mulierine",\n    \"popularity\": 27077\n  },\n  {\n    \"tag\": "Mayo",\n    \"popularity\": 27021\n  },\n  {\n    \"tag\": "perceivedness",\n    \"popularity\": 26966\n  },\n  {\n    \"tag\": "unadoration",\n    \"popularity\": 26911\n  },\n  {\n    \"tag\": "regraft",\n    \"popularity\": 26856\n  },\n  {\n    \"tag\": "witch",\n    \"popularity\": 26801\n  },\n  {\n    \"tag\": "ungrow",\n    \"popularity\": 26746\n  },\n  {\n    \"tag\": "glossopharyngeus",\n    \"popularity\": 26691\n  },\n  {\n    \"tag\": "unstirrable",\n    \"popularity\": 26637\n  },\n  {\n    \"tag\": "synodsman",\n    \"popularity\": 26583\n  },\n  {\n    \"tag\": "placentalian",\n    \"popularity\": 26529\n  },\n  {\n    \"tag\": "corpulently",\n    \"popularity\": 26475\n  },\n  {\n    \"tag\": "photochromoscope",\n    \"popularity\": 26421\n  },\n  {\n    \"tag\": "indusiate retinasphaltum chokestrap",\n    \"popularity\": 26368\n  },\n  {\n    \"tag\": "murdrum",\n    \"popularity\": 26314\n  },\n  {\n    \"tag\": "belatedness",\n    \"popularity\": 26261\n  },\n  {\n    \"tag\": "Cochin",\n    \"popularity\": 26208\n  },\n  {\n    \"tag\": "Leonist",\n    \"popularity\": 26155\n  },\n  {\n    \"tag\": "keeker confined",\n    \"popularity\": 26102\n  },\n  {\n    \"tag\": "unintellectual",\n    \"popularity\": 26050\n  },\n  {\n    \"tag\": "nymphaline bait",\n    \"popularity\": 25997\n  },\n  {\n    \"tag\": "sarcosporidiosis",\n    \"popularity\": 25945\n  },\n  {\n    \"tag\": "catawamptiously",\n    \"popularity\": 25893\n  },\n  {\n    \"tag\": "outshame",\n    \"popularity\": 25841\n  },\n  {\n    \"tag\": "animalism",\n    \"popularity\": 25790\n  },\n  {\n    \"tag\": "epithalamial",\n    \"popularity\": 25738\n  },\n  {\n    \"tag\": "ganner",\n    \"popularity\": 25687\n  },\n  {\n    \"tag\": "desilicify",\n    \"popularity\": 25635\n  },\n  {\n    \"tag\": "dandyism",\n    \"popularity\": 25584\n  },\n  {\n    \"tag\": "hyleg",\n    \"popularity\": 25533\n  },\n  {\n    \"tag\": "photophysical",\n    \"popularity\": 25483\n  },\n  {\n    \"tag\": "underload",\n    \"popularity\": 25432\n  },\n  {\n    \"tag\": "unintrusive",\n    \"popularity\": 25382\n  },\n  {\n    \"tag\": "succinamic",\n    \"popularity\": 25331\n  },\n  {\n    \"tag\": "matchy",\n    \"popularity\": 25281\n  },\n  {\n    \"tag\": "concordal",\n    \"popularity\": 25231\n  },\n  {\n    \"tag\": "exteriority",\n    \"popularity\": 25181\n  },\n  {\n    \"tag\": "sterculiad",\n    \"popularity\": 25132\n  },\n  {\n    \"tag\": "sulfoxylic",\n    \"popularity\": 25082\n  },\n  {\n    \"tag\": "oversubscription",\n    \"popularity\": 25033\n  },\n  {\n    \"tag\": "chiasmic",\n    \"popularity\": 24984\n  },\n  {\n    \"tag\": "pseudoparthenogenesis",\n    \"popularity\": 24935\n  },\n  {\n    \"tag\": "indorse",\n    \"popularity\": 24886\n  },\n  {\n    \"tag\": "Krishnaite",\n    \"popularity\": 24837\n  },\n  {\n    \"tag\": "calcinize",\n    \"popularity\": 24788\n  },\n  {\n    \"tag\": "rhodium",\n    \"popularity\": 24740\n  },\n  {\n    \"tag\": "tragopan",\n    \"popularity\": 24692\n  },\n  {\n    \"tag\": "overwhelmingly",\n    \"popularity\": 24643\n  },\n  {\n    \"tag\": "procidence accorporate",\n    \"popularity\": 24595\n  },\n  {\n    \"tag\": "polemize speelless",\n    \"popularity\": 24548\n  },\n  {\n    \"tag\": "radiocarpal goran",\n    \"popularity\": 24500\n  },\n  {\n    \"tag\": "counteroffer Pelodytes",\n    \"popularity\": 24452\n  },\n  {\n    \"tag\": "lionhearted",\n    \"popularity\": 24405\n  },\n  {\n    \"tag\": "paramastoid",\n    \"popularity\": 24358\n  },\n  {\n    \"tag\": "murine",\n    \"popularity\": 24310\n  },\n  {\n    \"tag\": "woodbined",\n    \"popularity\": 24263\n  },\n  {\n    \"tag\": "packthread",\n    \"popularity\": 24217\n  },\n  {\n    \"tag\": "citreous",\n    \"popularity\": 24170\n  },\n  {\n    \"tag\": "unfallaciously",\n    \"popularity\": 24123\n  },\n  {\n    \"tag\": "tentwork reincarnadine",\n    \"popularity\": 24077\n  },\n  {\n    \"tag\": "verminousness",\n    \"popularity\": 24030\n  },\n  {\n    \"tag\": "sillometer",\n    \"popularity\": 23984\n  },\n  {\n    \"tag\": "jointy",\n    \"popularity\": 23938\n  },\n  {\n    \"tag\": "streptolysin",\n    \"popularity\": 23892\n  },\n  {\n    \"tag\": "Florentinism",\n    \"popularity\": 23847\n  },\n  {\n    \"tag\": "monosomatous",\n    \"popularity\": 23801\n  },\n  {\n    \"tag\": "capsulociliary",\n    \"popularity\": 23756\n  },\n  {\n    \"tag\": "organum",\n    \"popularity\": 23710\n  },\n  {\n    \"tag\": "overtly",\n    \"popularity\": 23665\n  },\n  {\n    \"tag\": "ophthalmoscopical",\n    \"popularity\": 23620\n  },\n  {\n    \"tag\": "supposititiously",\n    \"popularity\": 23575\n  },\n  {\n    \"tag\": "radiochemistry",\n    \"popularity\": 23530\n  },\n  {\n    \"tag\": "flaxtail",\n    \"popularity\": 23486\n  },\n  {\n    \"tag\": "pretympanic",\n    \"popularity\": 23441\n  },\n  {\n    \"tag\": "auscultation",\n    \"popularity\": 23397\n  },\n  {\n    \"tag\": "hairdresser",\n    \"popularity\": 23352\n  },\n  {\n    \"tag\": "chaffless",\n    \"popularity\": 23308\n  },\n  {\n    \"tag\": "polioencephalitis",\n    \"popularity\": 23264\n  },\n  {\n    \"tag\": "axolotl",\n    \"popularity\": 23220\n  },\n  {\n    \"tag\": "smous",\n    \"popularity\": 23177\n  },\n  {\n    \"tag\": "morgen disenamour toothed",\n    \"popularity\": 23133\n  },\n  {\n    \"tag\": "chaiseless",\n    \"popularity\": 23089\n  },\n  {\n    \"tag\": "frugally",\n    \"popularity\": 23046\n  },\n  {\n    \"tag\": "combustive antievolutionist cinenegative",\n    \"popularity\": 23003\n  },\n  {\n    \"tag\": "malacolite",\n    \"popularity\": 22960\n  },\n  {\n    \"tag\": "borne",\n    \"popularity\": 22917\n  },\n  {\n    \"tag\": "mercaptole",\n    \"popularity\": 22874\n  },\n  {\n    \"tag\": "judicatory",\n    \"popularity\": 22831\n  },\n  {\n    \"tag\": "noctivagation",\n    \"popularity\": 22789\n  },\n  {\n    \"tag\": "synthete",\n    \"popularity\": 22746\n  },\n  {\n    \"tag\": "tomboyism",\n    \"popularity\": 22704\n  },\n  {\n    \"tag\": "serranoid",\n    \"popularity\": 22661\n  },\n  {\n    \"tag\": "impostorism",\n    \"popularity\": 22619\n  },\n  {\n    \"tag\": "flagellosis Talitha",\n    \"popularity\": 22577\n  },\n  {\n    \"tag\": "pseudoviscous",\n    \"popularity\": 22535\n  },\n  {\n    \"tag\": "Galleriidae",\n    \"popularity\": 22494\n  },\n  {\n    \"tag\": "undulation didelph Comintern",\n    \"popularity\": 22452\n  },\n  {\n    \"tag\": "triangulopyramidal",\n    \"popularity\": 22411\n  },\n  {\n    \"tag\": "middlings",\n    \"popularity\": 22369\n  },\n  {\n    \"tag\": "piperazin",\n    \"popularity\": 22328\n  },\n  {\n    \"tag\": "endostitis",\n    \"popularity\": 22287\n  },\n  {\n    \"tag\": "swordlike",\n    \"popularity\": 22246\n  },\n  {\n    \"tag\": "forthwith",\n    \"popularity\": 22205\n  },\n  {\n    \"tag\": "menaceful",\n    \"popularity\": 22164\n  },\n  {\n    \"tag\": "explantation defective",\n    \"popularity\": 22123\n  },\n  {\n    \"tag\": "arrear",\n    \"popularity\": 22083\n  },\n  {\n    \"tag\": "engraft",\n    \"popularity\": 22042\n  },\n  {\n    \"tag\": "revolunteer",\n    \"popularity\": 22002\n  },\n  {\n    \"tag\": "foliaceous",\n    \"popularity\": 21962\n  },\n  {\n    \"tag\": "pseudograph",\n    \"popularity\": 21922\n  },\n  {\n    \"tag\": "maenaite",\n    \"popularity\": 21882\n  },\n  {\n    \"tag\": "interfinger",\n    \"popularity\": 21842\n  },\n  {\n    \"tag\": "macroscopically",\n    \"popularity\": 21802\n  },\n  {\n    \"tag\": "bluewood",\n    \"popularity\": 21762\n  },\n  {\n    \"tag\": "chikara",\n    \"popularity\": 21723\n  },\n  {\n    \"tag\": "reprehension diazeuxis nickelous",\n    \"popularity\": 21683\n  },\n  {\n    \"tag\": "vacuation",\n    \"popularity\": 21644\n  },\n  {\n    \"tag\": "Sartish",\n    \"popularity\": 21605\n  },\n  {\n    \"tag\": "pseudogyny",\n    \"popularity\": 21566\n  },\n  {\n    \"tag\": "friedcake",\n    \"popularity\": 21527\n  },\n  {\n    \"tag\": "thraw",\n    \"popularity\": 21488\n  },\n  {\n    \"tag\": "bifid",\n    \"popularity\": 21449\n  },\n  {\n    \"tag\": "truthlessly",\n    \"popularity\": 21411\n  },\n  {\n    \"tag\": "lungy",\n    \"popularity\": 21372\n  },\n  {\n    \"tag\": "fluoborite",\n    \"popularity\": 21334\n  },\n  {\n    \"tag\": "anthropolithic",\n    \"popularity\": 21295\n  },\n  {\n    \"tag\": "coachee straw",\n    \"popularity\": 21257\n  },\n  {\n    \"tag\": "dehorner Grecize",\n    \"popularity\": 21219\n  },\n  {\n    \"tag\": "spondylopyosis",\n    \"popularity\": 21181\n  },\n  {\n    \"tag\": "institutionary",\n    \"popularity\": 21143\n  },\n  {\n    \"tag\": "agentry",\n    \"popularity\": 21105\n  },\n  {\n    \"tag\": "musing bietle",\n    \"popularity\": 21068\n  },\n  {\n    \"tag\": "cormophyte",\n    \"popularity\": 21030\n  },\n  {\n    \"tag\": "semielliptic",\n    \"popularity\": 20993\n  },\n  {\n    \"tag\": "ependytes",\n    \"popularity\": 20955\n  },\n  {\n    \"tag\": "coachmaster",\n    \"popularity\": 20918\n  },\n  {\n    \"tag\": "overexuberant",\n    \"popularity\": 20881\n  },\n  {\n    \"tag\": "selectable",\n    \"popularity\": 20844\n  },\n  {\n    \"tag\": "saclike",\n    \"popularity\": 20807\n  },\n  {\n    \"tag\": "mullion",\n    \"popularity\": 20770\n  },\n  {\n    \"tag\": "pantheonize prevalency",\n    \"popularity\": 20733\n  },\n  {\n    \"tag\": "trophosperm",\n    \"popularity\": 20697\n  },\n  {\n    \"tag\": "paraphrasist",\n    \"popularity\": 20660\n  },\n  {\n    \"tag\": "undercarry",\n    \"popularity\": 20624\n  },\n  {\n    \"tag\": "thallogenic",\n    \"popularity\": 20587\n  },\n  {\n    \"tag\": "bulgy forbid",\n    \"popularity\": 20551\n  },\n  {\n    \"tag\": "proliquor gratulatory",\n    \"popularity\": 20515\n  },\n  {\n    \"tag\": "booker",\n    \"popularity\": 20479\n  },\n  {\n    \"tag\": "wizen",\n    \"popularity\": 20443\n  },\n  {\n    \"tag\": "synchondrosially",\n    \"popularity\": 20407\n  },\n  {\n    \"tag\": "herbless",\n    \"popularity\": 20371\n  },\n  {\n    \"tag\": "arfvedsonite",\n    \"popularity\": 20336\n  },\n  {\n    \"tag\": "Neuroptera",\n    \"popularity\": 20300\n  },\n  {\n    \"tag\": "fingerstone",\n    \"popularity\": 20265\n  },\n  {\n    \"tag\": "Odontoglossae",\n    \"popularity\": 20229\n  },\n  {\n    \"tag\": "transmigrator",\n    \"popularity\": 20194\n  },\n  {\n    \"tag\": "Dehaites",\n    \"popularity\": 20159\n  },\n  {\n    \"tag\": "Molinist",\n    \"popularity\": 20124\n  },\n  {\n    \"tag\": "novelistic",\n    \"popularity\": 20089\n  },\n  {\n    \"tag\": "astelic",\n    \"popularity\": 20054\n  },\n  {\n    \"tag\": "pyelometry",\n    \"popularity\": 20019\n  },\n  {\n    \"tag\": "pigmentation",\n    \"popularity\": 19984\n  },\n  {\n    \"tag\": "epinaos",\n    \"popularity\": 19950\n  },\n  {\n    \"tag\": "outdare",\n    \"popularity\": 19915\n  },\n  {\n    \"tag\": "Funje philaristocracy",\n    \"popularity\": 19881\n  },\n  {\n    \"tag\": "keddah",\n    \"popularity\": 19846\n  },\n  {\n    \"tag\": "axoidean",\n    \"popularity\": 19812\n  },\n  {\n    \"tag\": "ovule",\n    \"popularity\": 19778\n  },\n  {\n    \"tag\": "solidify",\n    \"popularity\": 19744\n  },\n  {\n    \"tag\": "noncelestial",\n    \"popularity\": 19710\n  },\n  {\n    \"tag\": "overmultiplication",\n    \"popularity\": 19676\n  },\n  {\n    \"tag\": "hexatetrahedron",\n    \"popularity\": 19642\n  },\n  {\n    \"tag\": "pliciform",\n    \"popularity\": 19609\n  },\n  {\n    \"tag\": "zimbalon",\n    \"popularity\": 19575\n  },\n  {\n    \"tag\": "annexational",\n    \"popularity\": 19542\n  },\n  {\n    \"tag\": "eurhodol",\n    \"popularity\": 19508\n  },\n  {\n    \"tag\": "yark",\n    \"popularity\": 19475\n  },\n  {\n    \"tag\": "illegality nitroalizarin",\n    \"popularity\": 19442\n  },\n  {\n    \"tag\": "quadratum",\n    \"popularity\": 19409\n  },\n  {\n    \"tag\": "saccharine",\n    \"popularity\": 19376\n  },\n  {\n    \"tag\": "unemploy",\n    \"popularity\": 19343\n  },\n  {\n    \"tag\": "uniclinal unipotent",\n    \"popularity\": 19310\n  },\n  {\n    \"tag\": "turbo",\n    \"popularity\": 19277\n  },\n  {\n    \"tag\": "sybarism",\n    \"popularity\": 19244\n  },\n  {\n    \"tag\": "motacilline",\n    \"popularity\": 19212\n  },\n  {\n    \"tag\": "weaselly",\n    \"popularity\": 19179\n  },\n  {\n    \"tag\": "plastid",\n    \"popularity\": 19147\n  },\n  {\n    \"tag\": "wasting",\n    \"popularity\": 19114\n  },\n  {\n    \"tag\": "begrime fluting",\n    \"popularity\": 19082\n  },\n  {\n    \"tag\": "Nephilinae",\n    \"popularity\": 19050\n  },\n  {\n    \"tag\": "disregardance",\n    \"popularity\": 19018\n  },\n  {\n    \"tag\": "Shakerlike",\n    \"popularity\": 18986\n  },\n  {\n    \"tag\": "uniped",\n    \"popularity\": 18954\n  },\n  {\n    \"tag\": "knap",\n    \"popularity\": 18922\n  },\n  {\n    \"tag\": "electivism undergardener",\n    \"popularity\": 18890\n  },\n  {\n    \"tag\": "hulverheaded",\n    \"popularity\": 18858\n  },\n  {\n    \"tag\": "unruptured",\n    \"popularity\": 18827\n  },\n  {\n    \"tag\": "solemnize credently",\n    \"popularity\": 18795\n  },\n  {\n    \"tag\": "pentastomoid possessingly",\n    \"popularity\": 18764\n  },\n  {\n    \"tag\": "octose",\n    \"popularity\": 18733\n  },\n  {\n    \"tag\": "psithurism indefensibility",\n    \"popularity\": 18701\n  },\n  {\n    \"tag\": "torrentuous cyanometer subcrenate",\n    \"popularity\": 18670\n  },\n  {\n    \"tag\": "photoplaywright tapaculo",\n    \"popularity\": 18639\n  },\n  {\n    \"tag\": "univalence",\n    \"popularity\": 18608\n  },\n  {\n    \"tag\": "Porthetria",\n    \"popularity\": 18577\n  },\n  {\n    \"tag\": "funambulo",\n    \"popularity\": 18546\n  },\n  {\n    \"tag\": "pedion",\n    \"popularity\": 18515\n  },\n  {\n    \"tag\": "horticulturally",\n    \"popularity\": 18485\n  },\n  {\n    \"tag\": "marennin",\n    \"popularity\": 18454\n  },\n  {\n    \"tag\": "horselaugh",\n    \"popularity\": 18423\n  },\n  {\n    \"tag\": "semiexecutive",\n    \"popularity\": 18393\n  },\n  {\n    \"tag\": "Monopteridae",\n    \"popularity\": 18363\n  },\n  {\n    \"tag\": "commonable",\n    \"popularity\": 18332\n  },\n  {\n    \"tag\": "dreariment",\n    \"popularity\": 18302\n  },\n  {\n    \"tag\": "disbud",\n    \"popularity\": 18272\n  },\n  {\n    \"tag\": "monocled",\n    \"popularity\": 18242\n  },\n  {\n    \"tag\": "hurlbarrow",\n    \"popularity\": 18212\n  },\n  {\n    \"tag\": "opiateproof",\n    \"popularity\": 18182\n  },\n  {\n    \"tag\": "Fahrenheit",\n    \"popularity\": 18152\n  },\n  {\n    \"tag\": "writhed",\n    \"popularity\": 18122\n  },\n  {\n    \"tag\": "Volstead",\n    \"popularity\": 18093\n  },\n  {\n    \"tag\": "yesternight",\n    \"popularity\": 18063\n  },\n  {\n    \"tag\": "readmittance",\n    \"popularity\": 18033\n  },\n  {\n    \"tag\": "reiterable",\n    \"popularity\": 18004\n  },\n  {\n    \"tag\": "triquetral",\n    \"popularity\": 17975\n  },\n  {\n    \"tag\": "guillotinement",\n    \"popularity\": 17945\n  },\n  {\n    \"tag\": "repermission",\n    \"popularity\": 17916\n  },\n  {\n    \"tag\": "assishly",\n    \"popularity\": 17887\n  },\n  {\n    \"tag\": "daidle",\n    \"popularity\": 17858\n  },\n  {\n    \"tag\": "prismatoid",\n    \"popularity\": 17829\n  },\n  {\n    \"tag\": "irreptitious",\n    \"popularity\": 17800\n  },\n  {\n    \"tag\": "sourdeline",\n    \"popularity\": 17771\n  },\n  {\n    \"tag\": "Austrian",\n    \"popularity\": 17742\n  },\n  {\n    \"tag\": "psychorrhagic",\n    \"popularity\": 17713\n  },\n  {\n    \"tag\": "Monumbo",\n    \"popularity\": 17685\n  },\n  {\n    \"tag\": "cloiochoanitic",\n    \"popularity\": 17656\n  },\n  {\n    \"tag\": "hant",\n    \"popularity\": 17628\n  },\n  {\n    \"tag\": "roily pulldown",\n    \"popularity\": 17599\n  },\n  {\n    \"tag\": "recongratulation",\n    \"popularity\": 17571\n  },\n  {\n    \"tag\": "Peking",\n    \"popularity\": 17543\n  },\n  {\n    \"tag\": "erdvark",\n    \"popularity\": 17514\n  },\n  {\n    \"tag\": "antimnemonic",\n    \"popularity\": 17486\n  },\n  {\n    \"tag\": "noncapillarity",\n    \"popularity\": 17458\n  },\n  {\n    \"tag\": "irrepressive",\n    \"popularity\": 17430\n  },\n  {\n    \"tag\": "Petromyzontes",\n    \"popularity\": 17402\n  },\n  {\n    \"tag\": "piscatorially",\n    \"popularity\": 17374\n  },\n  {\n    \"tag\": "cholesterosis",\n    \"popularity\": 17346\n  },\n  {\n    \"tag\": "denunciate",\n    \"popularity\": 17319\n  },\n  {\n    \"tag\": "unmetalled",\n    \"popularity\": 17291\n  },\n  {\n    \"tag\": "Tigris enruin",\n    \"popularity\": 17263\n  },\n  {\n    \"tag\": "anaspalin",\n    \"popularity\": 17236\n  },\n  {\n    \"tag\": "monodromy",\n    \"popularity\": 17208\n  },\n  {\n    \"tag\": "Canichanan",\n    \"popularity\": 17181\n  },\n  {\n    \"tag\": "mesolabe",\n    \"popularity\": 17154\n  },\n  {\n    \"tag\": "trichothallic overcunningness",\n    \"popularity\": 17127\n  },\n  {\n    \"tag\": "spinsterishly",\n    \"popularity\": 17099\n  },\n  {\n    \"tag\": "sensilla",\n    \"popularity\": 17072\n  },\n  {\n    \"tag\": "wifelkin",\n    \"popularity\": 17045\n  },\n  {\n    \"tag\": "suppositionless",\n    \"popularity\": 17018\n  },\n  {\n    \"tag\": "irksomeness",\n    \"popularity\": 16991\n  },\n  {\n    \"tag\": "sanbenito",\n    \"popularity\": 16964\n  },\n  {\n    \"tag\": "nonstatement",\n    \"popularity\": 16938\n  },\n  {\n    \"tag\": "phenoloid",\n    \"popularity\": 16911\n  },\n  {\n    \"tag\": "Steinberger",\n    \"popularity\": 16884\n  },\n  {\n    \"tag\": "replicated boom",\n    \"popularity\": 16858\n  },\n  {\n    \"tag\": "sciomachiology",\n    \"popularity\": 16831\n  },\n  {\n    \"tag\": "starwise",\n    \"popularity\": 16805\n  },\n  {\n    \"tag\": "prerich",\n    \"popularity\": 16778\n  },\n  {\n    \"tag\": "unspawned",\n    \"popularity\": 16752\n  },\n  {\n    \"tag\": "unindentable",\n    \"popularity\": 16726\n  },\n  {\n    \"tag\": "stromatic",\n    \"popularity\": 16700\n  },\n  {\n    \"tag\": "fetishize",\n    \"popularity\": 16673\n  },\n  {\n    \"tag\": "dihydroxy",\n    \"popularity\": 16647\n  },\n  {\n    \"tag\": "precaudal",\n    \"popularity\": 16621\n  },\n  {\n    \"tag\": "Madagascar",\n    \"popularity\": 16595\n  },\n  {\n    \"tag\": "repinement",\n    \"popularity\": 16570\n  },\n  {\n    \"tag\": "noncathedral wenzel",\n    \"popularity\": 16544\n  },\n  {\n    \"tag\": "corollike",\n    \"popularity\": 16518\n  },\n  {\n    \"tag\": "pubes unamortization",\n    \"popularity\": 16492\n  },\n  {\n    \"tag\": "brickcroft",\n    \"popularity\": 16467\n  },\n  {\n    \"tag\": "intertrabecular",\n    \"popularity\": 16441\n  },\n  {\n    \"tag\": "formulaic",\n    \"popularity\": 16416\n  },\n  {\n    \"tag\": "arienzo",\n    \"popularity\": 16390\n  },\n  {\n    \"tag\": "Mazzinian",\n    \"popularity\": 16365\n  },\n  {\n    \"tag\": "wallowishly",\n    \"popularity\": 16339\n  },\n  {\n    \"tag\": "sysselman",\n    \"popularity\": 16314\n  },\n  {\n    \"tag\": "seligmannite",\n    \"popularity\": 16289\n  },\n  {\n    \"tag\": "harlequinery",\n    \"popularity\": 16264\n  },\n  {\n    \"tag\": "zucchetto",\n    \"popularity\": 16239\n  },\n  {\n    \"tag\": "malonyl",\n    \"popularity\": 16214\n  },\n  {\n    \"tag\": "patwari",\n    \"popularity\": 16189\n  },\n  {\n    \"tag\": "neoholmia venturesomeness",\n    \"popularity\": 16164\n  },\n  {\n    \"tag\": "Dehwar",\n    \"popularity\": 16139\n  },\n  {\n    \"tag\": "fetiferous",\n    \"popularity\": 16114\n  },\n  {\n    \"tag\": "chromatophore",\n    \"popularity\": 16090\n  },\n  {\n    \"tag\": "reregistration",\n    \"popularity\": 16065\n  },\n  {\n    \"tag\": "alienor",\n    \"popularity\": 16040\n  },\n  {\n    \"tag\": "Hexagynia",\n    \"popularity\": 16016\n  },\n  {\n    \"tag\": "cerebrotonia",\n    \"popularity\": 15991\n  },\n  {\n    \"tag\": "deedbox",\n    \"popularity\": 15967\n  },\n  {\n    \"tag\": "staab",\n    \"popularity\": 15943\n  },\n  {\n    \"tag\": "uratemia",\n    \"popularity\": 15918\n  },\n  {\n    \"tag\": "flaunt",\n    \"popularity\": 15894\n  },\n  {\n    \"tag\": "bogy",\n    \"popularity\": 15870\n  },\n  {\n    \"tag\": "subcartilaginous",\n    \"popularity\": 15846\n  },\n  {\n    \"tag\": "protonephridial",\n    \"popularity\": 15822\n  },\n  {\n    \"tag\": "Boswellia",\n    \"popularity\": 15798\n  },\n  {\n    \"tag\": "relaxant untiaraed protoepiphyte",\n    \"popularity\": 15774\n  },\n  {\n    \"tag\": "nesslerization",\n    \"popularity\": 15750\n  },\n  {\n    \"tag\": "precession",\n    \"popularity\": 15726\n  },\n  {\n    \"tag\": "peat",\n    \"popularity\": 15702\n  },\n  {\n    \"tag\": "unbit",\n    \"popularity\": 15678\n  },\n  {\n    \"tag\": "snailish",\n    \"popularity\": 15655\n  },\n  {\n    \"tag\": "porismatical",\n    \"popularity\": 15631\n  },\n  {\n    \"tag\": "hooflike",\n    \"popularity\": 15608\n  },\n  {\n    \"tag\": "resuppose phene cranic",\n    \"popularity\": 15584\n  },\n  {\n    \"tag\": "peptonization kipskin",\n    \"popularity\": 15561\n  },\n  {\n    \"tag\": "birdstone",\n    \"popularity\": 15537\n  },\n  {\n    \"tag\": "empty inferoanterior",\n    \"popularity\": 15514\n  },\n  {\n    \"tag\": "androtauric",\n    \"popularity\": 15491\n  },\n  {\n    \"tag\": "triamide",\n    \"popularity\": 15467\n  },\n  {\n    \"tag\": "showmanry",\n    \"popularity\": 15444\n  },\n  {\n    \"tag\": "doing",\n    \"popularity\": 15421\n  },\n  {\n    \"tag\": "bouchaleen",\n    \"popularity\": 15398\n  },\n  {\n    \"tag\": "precollude",\n    \"popularity\": 15375\n  },\n  {\n    \"tag\": "finger",\n    \"popularity\": 15352\n  },\n  {\n    \"tag\": "limnetic intermessenger",\n    \"popularity\": 15329\n  },\n  {\n    \"tag\": "uncharitable picrotoxic",\n    \"popularity\": 15306\n  },\n  {\n    \"tag\": "nationalizer Phasmidae",\n    \"popularity\": 15283\n  },\n  {\n    \"tag\": "laughingstock",\n    \"popularity\": 15261\n  },\n  {\n    \"tag\": "nondeferential",\n    \"popularity\": 15238\n  },\n  {\n    \"tag\": "uproariously",\n    \"popularity\": 15215\n  },\n  {\n    \"tag\": "manzanilla",\n    \"popularity\": 15193\n  },\n  {\n    \"tag\": "khahoon",\n    \"popularity\": 15170\n  },\n  {\n    \"tag\": "olericulturally longshanks",\n    \"popularity\": 15148\n  },\n  {\n    \"tag\": "enthusiastically methionic",\n    \"popularity\": 15125\n  },\n  {\n    \"tag\": "pobs",\n    \"popularity\": 15103\n  },\n  {\n    \"tag\": "tricarpellate",\n    \"popularity\": 15081\n  },\n  {\n    \"tag\": "souterrain",\n    \"popularity\": 15058\n  },\n  {\n    \"tag\": "tethelin",\n    \"popularity\": 15036\n  },\n  {\n    \"tag\": "tartle",\n    \"popularity\": 15014\n  },\n  {\n    \"tag\": "tidelike",\n    \"popularity\": 14992\n  },\n  {\n    \"tag\": "cosmoramic",\n    \"popularity\": 14970\n  },\n  {\n    \"tag\": "pretardiness",\n    \"popularity\": 14948\n  },\n  {\n    \"tag\": "insoul",\n    \"popularity\": 14926\n  },\n  {\n    \"tag\": "anthroxan",\n    \"popularity\": 14904\n  },\n  {\n    \"tag\": "jilter",\n    \"popularity\": 14882\n  },\n  {\n    \"tag\": "pectinibranchian trematode",\n    \"popularity\": 14860\n  },\n  {\n    \"tag\": "Renaissancist",\n    \"popularity\": 14838\n  },\n  {\n    \"tag\": "imaginant",\n    \"popularity\": 14817\n  },\n  {\n    \"tag\": "supercensure",\n    \"popularity\": 14795\n  },\n  {\n    \"tag\": "festilogy",\n    \"popularity\": 14773\n  },\n  {\n    \"tag\": "regression",\n    \"popularity\": 14752\n  },\n  {\n    \"tag\": "mesobregmate languorously",\n    \"popularity\": 14730\n  },\n  {\n    \"tag\": "unsupernaturalized",\n    \"popularity\": 14709\n  },\n  {\n    \"tag\": "boobyish",\n    \"popularity\": 14687\n  },\n  {\n    \"tag\": "scopolamine",\n    \"popularity\": 14666\n  },\n  {\n    \"tag\": "reamputation unchristianly",\n    \"popularity\": 14645\n  },\n  {\n    \"tag\": "cuneatic",\n    \"popularity\": 14623\n  },\n  {\n    \"tag\": "heathberry",\n    \"popularity\": 14602\n  },\n  {\n    \"tag\": "hate",\n    \"popularity\": 14581\n  },\n  {\n    \"tag\": "redeemableness",\n    \"popularity\": 14560\n  },\n  {\n    \"tag\": "damasse",\n    \"popularity\": 14539\n  },\n  {\n    \"tag\": "thrillsome",\n    \"popularity\": 14518\n  },\n  {\n    \"tag\": "disseverment",\n    \"popularity\": 14497\n  },\n  {\n    \"tag\": "underbishopric Ostyak",\n    \"popularity\": 14476\n  },\n  {\n    \"tag\": "Exoascales",\n    \"popularity\": 14455\n  },\n  {\n    \"tag\": "soiled",\n    \"popularity\": 14434\n  },\n  {\n    \"tag\": "Cain",\n    \"popularity\": 14413\n  },\n  {\n    \"tag\": "mismanageable arenae",\n    \"popularity\": 14392\n  },\n  {\n    \"tag\": "manducate unhinderably",\n    \"popularity\": 14372\n  },\n  {\n    \"tag\": "peregrin",\n    \"popularity\": 14351\n  },\n  {\n    \"tag\": "musicianly",\n    \"popularity\": 14330\n  },\n  {\n    \"tag\": "aln",\n    \"popularity\": 14310\n  },\n  {\n    \"tag\": "intercentrum",\n    \"popularity\": 14289\n  },\n  {\n    \"tag\": "roothold",\n    \"popularity\": 14269\n  },\n  {\n    \"tag\": "jane aneurism",\n    \"popularity\": 14248\n  },\n  {\n    \"tag\": "insinuatively forefeel phytolatrous",\n    \"popularity\": 14228\n  },\n  {\n    \"tag\": "kanchil",\n    \"popularity\": 14208\n  },\n  {\n    \"tag\": "Austrophile",\n    \"popularity\": 14187\n  },\n  {\n    \"tag\": "unterrorized",\n    \"popularity\": 14167\n  },\n  {\n    \"tag\": "admeasure",\n    \"popularity\": 14147\n  },\n  {\n    \"tag\": "electrodissolution",\n    \"popularity\": 14127\n  },\n  {\n    \"tag\": "unweddedly",\n    \"popularity\": 14107\n  },\n  {\n    \"tag\": "unannoying",\n    \"popularity\": 14087\n  },\n  {\n    \"tag\": "uningenuous",\n    \"popularity\": 14067\n  },\n  {\n    \"tag\": "omnibenevolent",\n    \"popularity\": 14047\n  },\n  {\n    \"tag\": "commissure",\n    \"popularity\": 14027\n  },\n  {\n    \"tag\": "tellureted",\n    \"popularity\": 14007\n  },\n  {\n    \"tag\": "suffragan",\n    \"popularity\": 13987\n  },\n  {\n    \"tag\": "sphaeriaceous",\n    \"popularity\": 13967\n  },\n  {\n    \"tag\": "unfearing",\n    \"popularity\": 13947\n  },\n  {\n    \"tag\": "stentoriousness precounsellor",\n    \"popularity\": 13928\n  },\n  {\n    \"tag\": "haemaspectroscope",\n    \"popularity\": 13908\n  },\n  {\n    \"tag\": "teras",\n    \"popularity\": 13888\n  },\n  {\n    \"tag\": "pulicine",\n    \"popularity\": 13869\n  },\n  {\n    \"tag\": "colicystopyelitis",\n    \"popularity\": 13849\n  },\n  {\n    \"tag\": "Physalia",\n    \"popularity\": 13830\n  },\n  {\n    \"tag\": "Saxicolidae",\n    \"popularity\": 13810\n  },\n  {\n    \"tag\": "peritonital",\n    \"popularity\": 13791\n  },\n  {\n    \"tag\": "dysphotic",\n    \"popularity\": 13771\n  },\n  {\n    \"tag\": "unabandoned",\n    \"popularity\": 13752\n  },\n  {\n    \"tag\": "rashful",\n    \"popularity\": 13733\n  },\n  {\n    \"tag\": "goodyness Manobo",\n    \"popularity\": 13714\n  },\n  {\n    \"tag\": "glaring",\n    \"popularity\": 13694\n  },\n  {\n    \"tag\": "horrorful",\n    \"popularity\": 13675\n  },\n  {\n    \"tag\": "intercepting",\n    \"popularity\": 13656\n  },\n  {\n    \"tag\": "semifine",\n    \"popularity\": 13637\n  },\n  {\n    \"tag\": "Gaypoo",\n    \"popularity\": 13618\n  },\n  {\n    \"tag\": "Metrosideros",\n    \"popularity\": 13599\n  },\n  {\n    \"tag\": "thoracicolumbar",\n    \"popularity\": 13580\n  },\n  {\n    \"tag\": "unserried",\n    \"popularity\": 13561\n  },\n  {\n    \"tag\": "keeperess cauterization",\n    \"popularity\": 13542\n  },\n  {\n    \"tag\": "administrant",\n    \"popularity\": 13523\n  },\n  {\n    \"tag\": "unpropitiatedness",\n    \"popularity\": 13505\n  },\n  {\n    \"tag\": "pensileness",\n    \"popularity\": 13486\n  },\n  {\n    \"tag\": "quinaldic unreceivable",\n    \"popularity\": 13467\n  },\n  {\n    \"tag\": "Carnaria",\n    \"popularity\": 13448\n  },\n  {\n    \"tag\": "azothionium wurrus",\n    \"popularity\": 13430\n  },\n  {\n    \"tag\": "mistresshood",\n    \"popularity\": 13411\n  },\n  {\n    \"tag\": "Savara",\n    \"popularity\": 13393\n  },\n  {\n    \"tag\": "dasyurine",\n    \"popularity\": 13374\n  },\n  {\n    \"tag\": "superideal",\n    \"popularity\": 13356\n  },\n  {\n    \"tag\": "Parisianize",\n    \"popularity\": 13337\n  },\n  {\n    \"tag\": "underearth",\n    \"popularity\": 13319\n  },\n  {\n    \"tag\": "athrogenic",\n    \"popularity\": 13301\n  },\n  {\n    \"tag\": "communicate",\n    \"popularity\": 13282\n  },\n  {\n    \"tag\": "denervation enworthed",\n    \"popularity\": 13264\n  },\n  {\n    \"tag\": "subbromide",\n    \"popularity\": 13246\n  },\n  {\n    \"tag\": "stenocoriasis",\n    \"popularity\": 13228\n  },\n  {\n    \"tag\": "facetiousness",\n    \"popularity\": 13209\n  },\n  {\n    \"tag\": "twaddling",\n    \"popularity\": 13191\n  },\n  {\n    \"tag\": "tetartoconid",\n    \"popularity\": 13173\n  },\n  {\n    \"tag\": "audiophile",\n    \"popularity\": 13155\n  },\n  {\n    \"tag\": "fustigate",\n    \"popularity\": 13137\n  },\n  {\n    \"tag\": "Sorbian cacophonia",\n    \"popularity\": 13119\n  },\n  {\n    \"tag\": "fondish",\n    \"popularity\": 13101\n  },\n  {\n    \"tag\": "endomastoiditis",\n    \"popularity\": 13084\n  },\n  {\n    \"tag\": "sniptious",\n    \"popularity\": 13066\n  },\n  {\n    \"tag\": "glochidiate",\n    \"popularity\": 13048\n  },\n  {\n    \"tag\": "polycarboxylic",\n    \"popularity\": 13030\n  },\n  {\n    \"tag\": "stamp",\n    \"popularity\": 13012\n  },\n  {\n    \"tag\": "tritonymph endotoxoid",\n    \"popularity\": 12995\n  },\n  {\n    \"tag\": "wolfskin",\n    \"popularity\": 12977\n  },\n  {\n    \"tag\": "oncosimeter",\n    \"popularity\": 12959\n  },\n  {\n    \"tag\": "outward",\n    \"popularity\": 12942\n  },\n  {\n    \"tag\": "circumscribed",\n    \"popularity\": 12924\n  },\n  {\n    \"tag\": "autohemolytic",\n    \"popularity\": 12907\n  },\n  {\n    \"tag\": "isorhamnose",\n    \"popularity\": 12889\n  },\n  {\n    \"tag\": "monarchomachic",\n    \"popularity\": 12872\n  },\n  {\n    \"tag\": "phaenomenon",\n    \"popularity\": 12855\n  },\n  {\n    \"tag\": "angiopressure",\n    \"popularity\": 12837\n  },\n  {\n    \"tag\": "similarize",\n    \"popularity\": 12820\n  },\n  {\n    \"tag\": "unseeable",\n    \"popularity\": 12803\n  },\n  {\n    \"tag\": "Toryize",\n    \"popularity\": 12785\n  },\n  {\n    \"tag\": "fruitling",\n    \"popularity\": 12768\n  },\n  {\n    \"tag\": "axle",\n    \"popularity\": 12751\n  },\n  {\n    \"tag\": "priestal cocked",\n    \"popularity\": 12734\n  },\n  {\n    \"tag\": "serotoxin",\n    \"popularity\": 12717\n  },\n  {\n    \"tag\": "unmovably",\n    \"popularity\": 12700\n  },\n  {\n    \"tag\": "darbha",\n    \"popularity\": 12683\n  },\n  {\n    \"tag\": "Mongolize",\n    \"popularity\": 12666\n  },\n  {\n    \"tag\": "clusteringly",\n    \"popularity\": 12649\n  },\n  {\n    \"tag\": "tendence",\n    \"popularity\": 12632\n  },\n  {\n    \"tag\": "foziness",\n    \"popularity\": 12615\n  },\n  {\n    \"tag\": "brickkiln lithify",\n    \"popularity\": 12598\n  },\n  {\n    \"tag\": "unpriest",\n    \"popularity\": 12581\n  },\n  {\n    \"tag\": "convincer",\n    \"popularity\": 12564\n  },\n  {\n    \"tag\": "mornlike",\n    \"popularity\": 12548\n  },\n  {\n    \"tag\": "overaddiction ostentatiousness",\n    \"popularity\": 12531\n  },\n  {\n    \"tag\": "diffusively moccasin pendom",\n    \"popularity\": 12514\n  },\n  {\n    \"tag\": "boose",\n    \"popularity\": 12498\n  },\n  {\n    \"tag\": "myonosus",\n    \"popularity\": 12481\n  },\n  {\n    \"tag\": "handsome",\n    \"popularity\": 12464\n  },\n  {\n    \"tag\": "paroxysmic",\n    \"popularity\": 12448\n  },\n  {\n    \"tag\": "Ulidian",\n    \"popularity\": 12431\n  },\n  {\n    \"tag\": "heartache",\n    \"popularity\": 12415\n  },\n  {\n    \"tag\": "torporize",\n    \"popularity\": 12398\n  },\n  {\n    \"tag\": "hippish",\n    \"popularity\": 12382\n  },\n  {\n    \"tag\": "stigmal militation",\n    \"popularity\": 12366\n  },\n  {\n    \"tag\": "matmaker",\n    \"popularity\": 12349\n  },\n  {\n    \"tag\": "marantaceous bivoluminous",\n    \"popularity\": 12333\n  },\n  {\n    \"tag\": "Uraniidae",\n    \"popularity\": 12317\n  },\n  {\n    \"tag\": "risper",\n    \"popularity\": 12301\n  },\n  {\n    \"tag\": "tintinnabulation",\n    \"popularity\": 12284\n  },\n  {\n    \"tag\": "tributorian",\n    \"popularity\": 12268\n  },\n  {\n    \"tag\": "ashamedly",\n    \"popularity\": 12252\n  },\n  {\n    \"tag\": "Macrourus",\n    \"popularity\": 12236\n  },\n  {\n    \"tag\": "Chora",\n    \"popularity\": 12220\n  },\n  {\n    \"tag\": "caul",\n    \"popularity\": 12204\n  },\n  {\n    \"tag\": "exsector",\n    \"popularity\": 12188\n  },\n  {\n    \"tag\": "acutish",\n    \"popularity\": 12172\n  },\n  {\n    \"tag\": "amphichrome",\n    \"popularity\": 12156\n  },\n  {\n    \"tag\": "guarder",\n    \"popularity\": 12140\n  },\n  {\n    \"tag\": "sculpturally",\n    \"popularity\": 12124\n  },\n  {\n    \"tag\": "benightmare",\n    \"popularity\": 12108\n  },\n  {\n    \"tag\": "chucky",\n    \"popularity\": 12093\n  },\n  {\n    \"tag\": "Venetian",\n    \"popularity\": 12077\n  },\n  {\n    \"tag\": "autotheater",\n    \"popularity\": 12061\n  },\n  {\n    \"tag\": "planarioid",\n    \"popularity\": 12045\n  },\n  {\n    \"tag\": "handkerchiefful",\n    \"popularity\": 12030\n  },\n  {\n    \"tag\": "fuliginousness potentize",\n    \"popularity\": 12014\n  },\n  {\n    \"tag\": "pantheum",\n    \"popularity\": 11998\n  },\n  {\n    \"tag\": "heavyweight",\n    \"popularity\": 11983\n  },\n  {\n    \"tag\": "unbrick",\n    \"popularity\": 11967\n  },\n  {\n    \"tag\": "duomachy",\n    \"popularity\": 11952\n  },\n  {\n    \"tag\": "polyphyodont",\n    \"popularity\": 11936\n  },\n  {\n    \"tag\": "hibernacle",\n    \"popularity\": 11921\n  },\n  {\n    \"tag\": "undistend",\n    \"popularity\": 11905\n  },\n  {\n    \"tag\": "hystericky",\n    \"popularity\": 11890\n  },\n  {\n    \"tag\": "paleolimnology",\n    \"popularity\": 11875\n  },\n  {\n    \"tag\": "cedarware",\n    \"popularity\": 11859\n  },\n  {\n    \"tag\": "overwrested",\n    \"popularity\": 11844\n  },\n  {\n    \"tag\": "Syriacism",\n    \"popularity\": 11829\n  },\n  {\n    \"tag\": "pretan",\n    \"popularity\": 11813\n  },\n  {\n    \"tag\": "formant",\n    \"popularity\": 11798\n  },\n  {\n    \"tag\": "pharmacopoeist Fedia",\n    \"popularity\": 11783\n  },\n  {\n    \"tag\": "exorcist eerisome",\n    \"popularity\": 11768\n  },\n  {\n    \"tag\": "separation",\n    \"popularity\": 11753\n  },\n  {\n    \"tag\": "infancy",\n    \"popularity\": 11738\n  },\n  {\n    \"tag\": "ecrasite",\n    \"popularity\": 11723\n  },\n  {\n    \"tag\": "propolize",\n    \"popularity\": 11708\n  },\n  {\n    \"tag\": "uncram phyllin",\n    \"popularity\": 11693\n  },\n  {\n    \"tag\": "thymopathy",\n    \"popularity\": 11678\n  },\n  {\n    \"tag\": "omniscient",\n    \"popularity\": 11663\n  },\n  {\n    \"tag\": "coussinet hazer",\n    \"popularity\": 11648\n  },\n  {\n    \"tag\": "contributiveness",\n    \"popularity\": 11633\n  },\n  {\n    \"tag\": "septifluous",\n    \"popularity\": 11618\n  },\n  {\n    \"tag\": "halfness",\n    \"popularity\": 11603\n  },\n  {\n    \"tag\": "tocher",\n    \"popularity\": 11589\n  },\n  {\n    \"tag\": "monotonist",\n    \"popularity\": 11574\n  },\n  {\n    \"tag\": "headchair",\n    \"popularity\": 11559\n  },\n  {\n    \"tag\": "everywhence",\n    \"popularity\": 11544\n  },\n  {\n    \"tag\": "gerate",\n    \"popularity\": 11530\n  },\n  {\n    \"tag\": "unrepellent",\n    \"popularity\": 11515\n  },\n  {\n    \"tag\": "inidoneous",\n    \"popularity\": 11500\n  },\n  {\n    \"tag\": "Rifi",\n    \"popularity\": 11486\n  },\n  {\n    \"tag\": "unstop",\n    \"popularity\": 11471\n  },\n  {\n    \"tag\": "conformer",\n    \"popularity\": 11457\n  },\n  {\n    \"tag\": "vivisectionally",\n    \"popularity\": 11442\n  },\n  {\n    \"tag\": "nonfinishing",\n    \"popularity\": 11428\n  },\n  {\n    \"tag\": "tyranness",\n    \"popularity\": 11413\n  },\n  {\n    \"tag\": "shepherdage havoc",\n    \"popularity\": 11399\n  },\n  {\n    \"tag\": "coronale",\n    \"popularity\": 11385\n  },\n  {\n    \"tag\": "airmarker",\n    \"popularity\": 11370\n  },\n  {\n    \"tag\": "subpanel",\n    \"popularity\": 11356\n  },\n  {\n    \"tag\": "conciliation",\n    \"popularity\": 11342\n  },\n  {\n    \"tag\": "supergun",\n    \"popularity\": 11327\n  },\n  {\n    \"tag\": "photoheliography",\n    \"popularity\": 11313\n  },\n  {\n    \"tag\": "cacosmia",\n    \"popularity\": 11299\n  },\n  {\n    \"tag\": "caressant",\n    \"popularity\": 11285\n  },\n  {\n    \"tag\": "swivet",\n    \"popularity\": 11270\n  },\n  {\n    \"tag\": "coddler",\n    \"popularity\": 11256\n  },\n  {\n    \"tag\": "rakehellish",\n    \"popularity\": 11242\n  },\n  {\n    \"tag\": "recohabitation",\n    \"popularity\": 11228\n  },\n  {\n    \"tag\": "postillator",\n    \"popularity\": 11214\n  },\n  {\n    \"tag\": "receipt",\n    \"popularity\": 11200\n  },\n  {\n    \"tag\": "nonconformistical",\n    \"popularity\": 11186\n  },\n  {\n    \"tag\": "unglorified",\n    \"popularity\": 11172\n  },\n  {\n    \"tag\": "unordinariness",\n    \"popularity\": 11158\n  },\n  {\n    \"tag\": "tetrahydroxy",\n    \"popularity\": 11144\n  },\n  {\n    \"tag\": "haploperistomic corporeity",\n    \"popularity\": 11130\n  },\n  {\n    \"tag\": "varical",\n    \"popularity\": 11117\n  },\n  {\n    \"tag\": "pilferment",\n    \"popularity\": 11103\n  },\n  {\n    \"tag\": "reverentially playcraft",\n    \"popularity\": 11089\n  },\n  {\n    \"tag\": "unretentive",\n    \"popularity\": 11075\n  },\n  {\n    \"tag\": "readiness",\n    \"popularity\": 11061\n  },\n  {\n    \"tag\": "thermomagnetism",\n    \"popularity\": 11048\n  },\n  {\n    \"tag\": "spotless",\n    \"popularity\": 11034\n  },\n  {\n    \"tag\": "semishrubby",\n    \"popularity\": 11020\n  },\n  {\n    \"tag\": "metrotomy",\n    \"popularity\": 11007\n  },\n  {\n    \"tag\": "hocker",\n    \"popularity\": 10993\n  },\n  {\n    \"tag\": "anecdotal",\n    \"popularity\": 10979\n  },\n  {\n    \"tag\": "tetrabelodont",\n    \"popularity\": 10966\n  },\n  {\n    \"tag\": "Ramillied",\n    \"popularity\": 10952\n  },\n  {\n    \"tag\": "sympatheticism",\n    \"popularity\": 10939\n  },\n  {\n    \"tag\": "kiskatom",\n    \"popularity\": 10925\n  },\n  {\n    \"tag\": "concyclically",\n    \"popularity\": 10912\n  },\n  {\n    \"tag\": "tunicless",\n    \"popularity\": 10899\n  },\n  {\n    \"tag\": "formalistic",\n    \"popularity\": 10885\n  },\n  {\n    \"tag\": "thermacogenesis",\n    \"popularity\": 10872\n  },\n  {\n    \"tag\": "multimotored",\n    \"popularity\": 10858\n  },\n  {\n    \"tag\": "inversive",\n    \"popularity\": 10845\n  },\n  {\n    \"tag\": "Jatki",\n    \"popularity\": 10832\n  },\n  {\n    \"tag\": "highest",\n    \"popularity\": 10818\n  },\n  {\n    \"tag\": "rubidic",\n    \"popularity\": 10805\n  },\n  {\n    \"tag\": "acranial",\n    \"popularity\": 10792\n  },\n  {\n    \"tag\": "pulvinulus",\n    \"popularity\": 10779\n  },\n  {\n    \"tag\": "nattiness",\n    \"popularity\": 10766\n  },\n  {\n    \"tag\": "antisimoniacal",\n    \"popularity\": 10752\n  },\n  {\n    \"tag\": "tetanize",\n    \"popularity\": 10739\n  },\n  {\n    \"tag\": "spectrophobia",\n    \"popularity\": 10726\n  },\n  {\n    \"tag\": "monopolitical",\n    \"popularity\": 10713\n  },\n  {\n    \"tag\": "teallite",\n    \"popularity\": 10700\n  },\n  {\n    \"tag\": "alicyclic interpellator",\n    \"popularity\": 10687\n  },\n  {\n    \"tag\": "nonsynthesized",\n    \"popularity\": 10674\n  },\n  {\n    \"tag\": "wheelwrighting",\n    \"popularity\": 10661\n  },\n  {\n    \"tag\": "pelliculate",\n    \"popularity\": 10648\n  },\n  {\n    \"tag\": "Euphyllopoda",\n    \"popularity\": 10635\n  },\n  {\n    \"tag\": "graver",\n    \"popularity\": 10622\n  },\n  {\n    \"tag\": "automorph",\n    \"popularity\": 10609\n  },\n  {\n    \"tag\": "underhanded",\n    \"popularity\": 10597\n  },\n  {\n    \"tag\": "causal",\n    \"popularity\": 10584\n  },\n  {\n    \"tag\": "odoom",\n    \"popularity\": 10571\n  },\n  {\n    \"tag\": "apodictical",\n    \"popularity\": 10558\n  },\n  {\n    \"tag\": "foundery",\n    \"popularity\": 10545\n  },\n  {\n    \"tag\": "unneighbored",\n    \"popularity\": 10533\n  },\n  {\n    \"tag\": "woolshearing",\n    \"popularity\": 10520\n  },\n  {\n    \"tag\": "boschveld",\n    \"popularity\": 10507\n  },\n  {\n    \"tag\": "unhardened lipopod",\n    \"popularity\": 10495\n  },\n  {\n    \"tag\": "unenriching",\n    \"popularity\": 10482\n  },\n  {\n    \"tag\": "spak",\n    \"popularity\": 10469\n  },\n  {\n    \"tag\": "yogasana",\n    \"popularity\": 10457\n  },\n  {\n    \"tag\": "depoetize",\n    \"popularity\": 10444\n  },\n  {\n    \"tag\": "parousiamania",\n    \"popularity\": 10432\n  },\n  {\n    \"tag\": "longlegs",\n    \"popularity\": 10419\n  },\n  {\n    \"tag\": "gelatinizability",\n    \"popularity\": 10407\n  },\n  {\n    \"tag\": "edeology",\n    \"popularity\": 10394\n  },\n  {\n    \"tag\": "sodwork",\n    \"popularity\": 10382\n  },\n  {\n    \"tag\": "somnambule",\n    \"popularity\": 10369\n  },\n  {\n    \"tag\": "antiquing",\n    \"popularity\": 10357\n  },\n  {\n    \"tag\": "intaker",\n    \"popularity\": 10344\n  },\n  {\n    \"tag\": "Gerberia",\n    \"popularity\": 10332\n  },\n  {\n    \"tag\": "preadmit",\n    \"popularity\": 10320\n  },\n  {\n    \"tag\": "bullhorn",\n    \"popularity\": 10307\n  },\n  {\n    \"tag\": "sororal",\n    \"popularity\": 10295\n  },\n  {\n    \"tag\": "phaeophyceous",\n    \"popularity\": 10283\n  },\n  {\n    \"tag\": "omphalopsychite",\n    \"popularity\": 10271\n  },\n  {\n    \"tag\": "substantious",\n    \"popularity\": 10258\n  },\n  {\n    \"tag\": "undemonstratively",\n    \"popularity\": 10246\n  },\n  {\n    \"tag\": "corallike blackit",\n    \"popularity\": 10234\n  },\n  {\n    \"tag\": "amoebous",\n    \"popularity\": 10222\n  },\n  {\n    \"tag\": "Polypodium",\n    \"popularity\": 10210\n  },\n  {\n    \"tag\": "blodite",\n    \"popularity\": 10198\n  },\n  {\n    \"tag\": "hordarian",\n    \"popularity\": 10186\n  },\n  {\n    \"tag\": "nonmoral",\n    \"popularity\": 10174\n  },\n  {\n    \"tag\": "dredgeful",\n    \"popularity\": 10162\n  },\n  {\n    \"tag\": "nourishingly",\n    \"popularity\": 10150\n  },\n  {\n    \"tag\": "seamy",\n    \"popularity\": 10138\n  },\n  {\n    \"tag\": "vara",\n    \"popularity\": 10126\n  },\n  {\n    \"tag\": "incorruptibleness",\n    \"popularity\": 10114\n  },\n  {\n    \"tag\": "manipulator",\n    \"popularity\": 10102\n  },\n  {\n    \"tag\": "chromodiascope uncountably",\n    \"popularity\": 10090\n  },\n  {\n    \"tag\": "typhemia",\n    \"popularity\": 10078\n  },\n  {\n    \"tag\": "Smalcaldic",\n    \"popularity\": 10066\n  },\n  {\n    \"tag\": "precontrive",\n    \"popularity\": 10054\n  },\n  {\n    \"tag\": "sowarry",\n    \"popularity\": 10042\n  },\n  {\n    \"tag\": "monopodic",\n    \"popularity\": 10031\n  },\n  {\n    \"tag\": "recodify",\n    \"popularity\": 10019\n  },\n  {\n    \"tag\": "phosphowolframic rimple",\n    \"popularity\": 10007\n  },\n  {\n    \"tag\": "triconch",\n    \"popularity\": 9995\n  },\n  {\n    \"tag\": "pycnodontoid",\n    \"popularity\": 9984\n  },\n  {\n    \"tag\": "bradyspermatism",\n    \"popularity\": 9972\n  },\n  {\n    \"tag\": "extensionist",\n    \"popularity\": 9960\n  },\n  {\n    \"tag\": "characterize",\n    \"popularity\": 9949\n  },\n  {\n    \"tag\": "anatreptic proteolytic",\n    \"popularity\": 9937\n  },\n  {\n    \"tag\": "waterboard",\n    \"popularity\": 9925\n  },\n  {\n    \"tag\": "allopathically",\n    \"popularity\": 9914\n  },\n  {\n    \"tag\": "arithmetician",\n    \"popularity\": 9902\n  },\n  {\n    \"tag\": "subsist",\n    \"popularity\": 9891\n  },\n  {\n    \"tag\": "Islamitish",\n    \"popularity\": 9879\n  },\n  {\n    \"tag\": "biddy",\n    \"popularity\": 9868\n  },\n  {\n    \"tag\": "reverberation",\n    \"popularity\": 9856\n  },\n  {\n    \"tag\": "Zaporogue",\n    \"popularity\": 9845\n  },\n  {\n    \"tag\": "soapberry",\n    \"popularity\": 9833\n  },\n  {\n    \"tag\": "physiognomics",\n    \"popularity\": 9822\n  },\n  {\n    \"tag\": "hospitalization",\n    \"popularity\": 9810\n  },\n  {\n    \"tag\": "dissembler",\n    \"popularity\": 9799\n  },\n  {\n    \"tag\": "festinate",\n    \"popularity\": 9788\n  },\n  {\n    \"tag\": "angiectopia",\n    \"popularity\": 9776\n  },\n  {\n    \"tag\": "Pulicidae",\n    \"popularity\": 9765\n  },\n  {\n    \"tag\": "beslimer",\n    \"popularity\": 9754\n  },\n  {\n    \"tag\": "nontreaty",\n    \"popularity\": 9743\n  },\n  {\n    \"tag\": "unhaggled",\n    \"popularity\": 9731\n  },\n  {\n    \"tag\": "catfall",\n    \"popularity\": 9720\n  },\n  {\n    \"tag\": "stola",\n    \"popularity\": 9709\n  },\n  {\n    \"tag\": "pataco",\n    \"popularity\": 9698\n  },\n  {\n    \"tag\": "ontologistic",\n    \"popularity\": 9686\n  },\n  {\n    \"tag\": "aerosphere",\n    \"popularity\": 9675\n  },\n  {\n    \"tag\": "deobstruent",\n    \"popularity\": 9664\n  },\n  {\n    \"tag\": "threepence",\n    \"popularity\": 9653\n  },\n  {\n    \"tag\": "cyprinoid",\n    \"popularity\": 9642\n  },\n  {\n    \"tag\": "overbank",\n    \"popularity\": 9631\n  },\n  {\n    \"tag\": "prostyle",\n    \"popularity\": 9620\n  },\n  {\n    \"tag\": "photoactivation",\n    \"popularity\": 9609\n  },\n  {\n    \"tag\": "homothetic",\n    \"popularity\": 9598\n  },\n  {\n    \"tag\": "roguedom",\n    \"popularity\": 9587\n  },\n  {\n    \"tag\": "underschool",\n    \"popularity\": 9576\n  },\n  {\n    \"tag\": "tractility",\n    \"popularity\": 9565\n  },\n  {\n    \"tag\": "gardenin",\n    \"popularity\": 9554\n  },\n  {\n    \"tag\": "Micromastictora",\n    \"popularity\": 9543\n  },\n  {\n    \"tag\": "gossypine",\n    \"popularity\": 9532\n  },\n  {\n    \"tag\": "amylodyspepsia",\n    \"popularity\": 9521\n  },\n  {\n    \"tag\": "Luciana",\n    \"popularity\": 9510\n  },\n  {\n    \"tag\": "meetly nonfisherman",\n    \"popularity\": 9500\n  },\n  {\n    \"tag\": "backhanded",\n    \"popularity\": 9489\n  },\n  {\n    \"tag\": "decrustation",\n    \"popularity\": 9478\n  },\n  {\n    \"tag\": "pinrail",\n    \"popularity\": 9467\n  },\n  {\n    \"tag\": "Mahori",\n    \"popularity\": 9456\n  },\n  {\n    \"tag\": "unsizable",\n    \"popularity\": 9446\n  },\n  {\n    \"tag\": "disawa",\n    \"popularity\": 9435\n  },\n  {\n    \"tag\": "launderability inconsidered",\n    \"popularity\": 9424\n  },\n  {\n    \"tag\": "unclassical",\n    \"popularity\": 9414\n  },\n  {\n    \"tag\": "inobtrusiveness",\n    \"popularity\": 9403\n  },\n  {\n    \"tag\": "sialogenous",\n    \"popularity\": 9392\n  },\n  {\n    \"tag\": "sulphonamide",\n    \"popularity\": 9382\n  },\n  {\n    \"tag\": "diluvion",\n    \"popularity\": 9371\n  },\n  {\n    \"tag\": "deuteranope",\n    \"popularity\": 9361\n  },\n  {\n    \"tag\": "addition",\n    \"popularity\": 9350\n  },\n  {\n    \"tag\": "bockeret",\n    \"popularity\": 9339\n  },\n  {\n    \"tag\": "unidentified",\n    \"popularity\": 9329\n  },\n  {\n    \"tag\": "caryatic",\n    \"popularity\": 9318\n  },\n  {\n    \"tag\": "misattribution",\n    \"popularity\": 9308\n  },\n  {\n    \"tag\": "outray",\n    \"popularity\": 9297\n  },\n  {\n    \"tag\": "areometrical",\n    \"popularity\": 9287\n  },\n  {\n    \"tag\": "antilogism",\n    \"popularity\": 9277\n  },\n  {\n    \"tag\": "inadjustable",\n    \"popularity\": 9266\n  },\n  {\n    \"tag\": "byssus",\n    \"popularity\": 9256\n  },\n  {\n    \"tag\": "trun",\n    \"popularity\": 9245\n  },\n  {\n    \"tag\": "thereology",\n    \"popularity\": 9235\n  },\n  {\n    \"tag\": "extort",\n    \"popularity\": 9225\n  },\n  {\n    \"tag\": "bumpkin",\n    \"popularity\": 9214\n  },\n  {\n    \"tag\": "sulphobenzide",\n    \"popularity\": 9204\n  },\n  {\n    \"tag\": "hydrogeology",\n    \"popularity\": 9194\n  },\n  {\n    \"tag\": "nidulariaceous",\n    \"popularity\": 9183\n  },\n  {\n    \"tag\": "propodiale",\n    \"popularity\": 9173\n  },\n  {\n    \"tag\": "fierily",\n    \"popularity\": 9163\n  },\n  {\n    \"tag\": "aerotonometry",\n    \"popularity\": 9153\n  },\n  {\n    \"tag\": "pelobatid oversuperstitious",\n    \"popularity\": 9142\n  },\n  {\n    \"tag\": "restringent",\n    \"popularity\": 9132\n  },\n  {\n    \"tag\": "tetrapodic",\n    \"popularity\": 9122\n  },\n  {\n    \"tag\": "heroicness Vendidad",\n    \"popularity\": 9112\n  },\n  {\n    \"tag\": "Sphingurus",\n    \"popularity\": 9102\n  },\n  {\n    \"tag\": "sclerote",\n    \"popularity\": 9092\n  },\n  {\n    \"tag\": "unkeyed",\n    \"popularity\": 9082\n  },\n  {\n    \"tag\": "superparliamentary",\n    \"popularity\": 9072\n  },\n  {\n    \"tag\": "hetericism",\n    \"popularity\": 9061\n  },\n  {\n    \"tag\": "hucklebone",\n    \"popularity\": 9051\n  },\n  {\n    \"tag\": "yojan",\n    \"popularity\": 9041\n  },\n  {\n    \"tag\": "bossed",\n    \"popularity\": 9031\n  },\n  {\n    \"tag\": "spiderwork",\n    \"popularity\": 9021\n  },\n  {\n    \"tag\": "millfeed dullery",\n    \"popularity\": 9011\n  },\n  {\n    \"tag\": "adnoun",\n    \"popularity\": 9001\n  },\n  {\n    \"tag\": "mesometric",\n    \"popularity\": 8992\n  },\n  {\n    \"tag\": "doublehandedness",\n    \"popularity\": 8982\n  },\n  {\n    \"tag\": "suppurant",\n    \"popularity\": 8972\n  },\n  {\n    \"tag\": "Berlinize",\n    \"popularity\": 8962\n  },\n  {\n    \"tag\": "sontag",\n    \"popularity\": 8952\n  },\n  {\n    \"tag\": "biplane",\n    \"popularity\": 8942\n  },\n  {\n    \"tag\": "insula",\n    \"popularity\": 8932\n  },\n  {\n    \"tag\": "unbrand",\n    \"popularity\": 8922\n  },\n  {\n    \"tag\": "Basilosaurus",\n    \"popularity\": 8913\n  },\n  {\n    \"tag\": "prenomination",\n    \"popularity\": 8903\n  },\n  {\n    \"tag\": "untextual",\n    \"popularity\": 8893\n  },\n  {\n    \"tag\": "coleslaw",\n    \"popularity\": 8883\n  },\n  {\n    \"tag\": "langsyne",\n    \"popularity\": 8874\n  },\n  {\n    \"tag\": "impede",\n    \"popularity\": 8864\n  },\n  {\n    \"tag\": "irrigator",\n    \"popularity\": 8854\n  },\n  {\n    \"tag\": "deflocculation",\n    \"popularity\": 8844\n  },\n  {\n    \"tag\": "narghile",\n    \"popularity\": 8835\n  },\n  {\n    \"tag\": "unguardedly ebenaceous",\n    \"popularity\": 8825\n  },\n  {\n    \"tag\": "conversantly subocular",\n    \"popularity\": 8815\n  },\n  {\n    \"tag\": "hydroponic",\n    \"popularity\": 8806\n  },\n  {\n    \"tag\": "anthropopsychism",\n    \"popularity\": 8796\n  },\n  {\n    \"tag\": "panoptic",\n    \"popularity\": 8787\n  },\n  {\n    \"tag\": "insufferable",\n    \"popularity\": 8777\n  },\n  {\n    \"tag\": "salema",\n    \"popularity\": 8768\n  },\n  {\n    \"tag\": "Myriapoda",\n    \"popularity\": 8758\n  },\n  {\n    \"tag\": "regarrison",\n    \"popularity\": 8748\n  },\n  {\n    \"tag\": "overlearned",\n    \"popularity\": 8739\n  },\n  {\n    \"tag\": "ultraroyalist conventical bureaucratical",\n    \"popularity\": 8729\n  },\n  {\n    \"tag\": "epicaridan",\n    \"popularity\": 8720\n  },\n  {\n    \"tag\": "poetastress",\n    \"popularity\": 8711\n  },\n  {\n    \"tag\": "monophthalmus",\n    \"popularity\": 8701\n  },\n  {\n    \"tag\": "simnel",\n    \"popularity\": 8692\n  },\n  {\n    \"tag\": "compotor",\n    \"popularity\": 8682\n  },\n  {\n    \"tag\": "hydrolase",\n    \"popularity\": 8673\n  },\n  {\n    \"tag\": "attemptless",\n    \"popularity\": 8663\n  },\n  {\n    \"tag\": "visceroptosis",\n    \"popularity\": 8654\n  },\n  {\n    \"tag\": "unpreparedly",\n    \"popularity\": 8645\n  },\n  {\n    \"tag\": "mastage",\n    \"popularity\": 8635\n  },\n  {\n    \"tag\": "preinfluence",\n    \"popularity\": 8626\n  },\n  {\n    \"tag\": "Siwan",\n    \"popularity\": 8617\n  },\n  {\n    \"tag\": "ceratotheca belvedere",\n    \"popularity\": 8607\n  },\n  {\n    \"tag\": "disenablement",\n    \"popularity\": 8598\n  },\n  {\n    \"tag\": "nine",\n    \"popularity\": 8589\n  },\n  {\n    \"tag\": "spellingdown abridgment",\n    \"popularity\": 8580\n  },\n  {\n    \"tag\": "twilightless",\n    \"popularity\": 8571\n  },\n  {\n    \"tag\": "overflow",\n    \"popularity\": 8561\n  },\n  {\n    \"tag\": "mismeasurement",\n    \"popularity\": 8552\n  },\n  {\n    \"tag\": "nawabship",\n    \"popularity\": 8543\n  },\n  {\n    \"tag\": "Phrynosoma",\n    \"popularity\": 8534\n  },\n  {\n    \"tag\": "unanticipatingly",\n    \"popularity\": 8525\n  },\n  {\n    \"tag\": "blankite",\n    \"popularity\": 8516\n  },\n  {\n    \"tag\": "role",\n    \"popularity\": 8506\n  },\n  {\n    \"tag\": "peperine edelweiss",\n    \"popularity\": 8497\n  },\n  {\n    \"tag\": "unhysterical",\n    \"popularity\": 8488\n  },\n  {\n    \"tag\": "attentiveness",\n    \"popularity\": 8479\n  },\n  {\n    \"tag\": "scintillant",\n    \"popularity\": 8470\n  },\n  {\n    \"tag\": "stenostomatous",\n    \"popularity\": 8461\n  },\n  {\n    \"tag\": "pectinite",\n    \"popularity\": 8452\n  },\n  {\n    \"tag\": "herring",\n    \"popularity\": 8443\n  },\n  {\n    \"tag\": "interroom",\n    \"popularity\": 8434\n  },\n  {\n    \"tag\": "laccol",\n    \"popularity\": 8425\n  },\n  {\n    \"tag\": "unpartably kylite",\n    \"popularity\": 8416\n  },\n  {\n    \"tag\": "spirivalve",\n    \"popularity\": 8407\n  },\n  {\n    \"tag\": "hoosegow",\n    \"popularity\": 8398\n  },\n  {\n    \"tag\": "doat",\n    \"popularity\": 8389\n  },\n  {\n    \"tag\": "amphibian",\n    \"popularity\": 8380\n  },\n  {\n    \"tag\": "exposit",\n    \"popularity\": 8371\n  },\n  {\n    \"tag\": "canopy",\n    \"popularity\": 8363\n  },\n  {\n    \"tag\": "houndlike",\n    \"popularity\": 8354\n  },\n  {\n    \"tag\": "spikebill",\n    \"popularity\": 8345\n  },\n  {\n    \"tag\": "wiseacre pyrotechnic",\n    \"popularity\": 8336\n  },\n  {\n    \"tag\": "confessingly woodman",\n    \"popularity\": 8327\n  },\n  {\n    \"tag\": "overside",\n    \"popularity\": 8318\n  },\n  {\n    \"tag\": "oftwhiles",\n    \"popularity\": 8310\n  },\n  {\n    \"tag\": "Musophagidae",\n    \"popularity\": 8301\n  },\n  {\n    \"tag\": "slumberer",\n    \"popularity\": 8292\n  },\n  {\n    \"tag\": "leiotrichy",\n    \"popularity\": 8283\n  },\n  {\n    \"tag\": "Mantispidae",\n    \"popularity\": 8275\n  },\n  {\n    \"tag\": "perceptually",\n    \"popularity\": 8266\n  },\n  {\n    \"tag\": "biller",\n    \"popularity\": 8257\n  },\n  {\n    \"tag\": "eudaemonical",\n    \"popularity\": 8249\n  },\n  {\n    \"tag\": "underfiend",\n    \"popularity\": 8240\n  },\n  {\n    \"tag\": "impartible",\n    \"popularity\": 8231\n  },\n  {\n    \"tag\": "saxicavous",\n    \"popularity\": 8223\n  },\n  {\n    \"tag\": "yapster",\n    \"popularity\": 8214\n  },\n  {\n    \"tag\": "aliseptal",\n    \"popularity\": 8205\n  },\n  {\n    \"tag\": "omniparient",\n    \"popularity\": 8197\n  },\n  {\n    \"tag\": "nishiki",\n    \"popularity\": 8188\n  },\n  {\n    \"tag\": "yuzluk",\n    \"popularity\": 8180\n  },\n  {\n    \"tag\": "solderer",\n    \"popularity\": 8171\n  },\n  {\n    \"tag\": "Pinna",\n    \"popularity\": 8162\n  },\n  {\n    \"tag\": "reinterfere",\n    \"popularity\": 8154\n  },\n  {\n    \"tag\": "superepic",\n    \"popularity\": 8145\n  },\n  {\n    \"tag\": "ronquil",\n    \"popularity\": 8137\n  },\n  {\n    \"tag\": "bratstvo",\n    \"popularity\": 8128\n  },\n  {\n    \"tag\": "Thea",\n    \"popularity\": 8120\n  },\n  {\n    \"tag\": "hermaphroditical",\n    \"popularity\": 8111\n  },\n  {\n    \"tag\": "enlief",\n    \"popularity\": 8103\n  },\n  {\n    \"tag\": "Jesuate",\n    \"popularity\": 8095\n  },\n  {\n    \"tag\": "gaysome",\n    \"popularity\": 8086\n  },\n  {\n    \"tag\": "iliohypogastric",\n    \"popularity\": 8078\n  },\n  {\n    \"tag\": "regardance",\n    \"popularity\": 8069\n  },\n  {\n    \"tag\": "cumulately",\n    \"popularity\": 8061\n  },\n  {\n    \"tag\": "haustorial nucleolocentrosome",\n    \"popularity\": 8053\n  },\n  {\n    \"tag\": "cosmocrat",\n    \"popularity\": 8044\n  },\n  {\n    \"tag\": "onyxitis",\n    \"popularity\": 8036\n  },\n  {\n    \"tag\": "Cabinda",\n    \"popularity\": 8028\n  },\n  {\n    \"tag\": "coresort",\n    \"popularity\": 8019\n  },\n  {\n    \"tag\": "drusy preformant",\n    \"popularity\": 8011\n  },\n  {\n    \"tag\": "piningly",\n    \"popularity\": 8003\n  },\n  {\n    \"tag\": "bootlessly",\n    \"popularity\": 7994\n  },\n  {\n    \"tag\": "talari",\n    \"popularity\": 7986\n  },\n  {\n    \"tag\": "amidoacetal",\n    \"popularity\": 7978\n  },\n  {\n    \"tag\": "pschent",\n    \"popularity\": 7970\n  },\n  {\n    \"tag\": "consumptional scarer titivate",\n    \"popularity\": 7962\n  },\n  {\n    \"tag\": "Anserinae",\n    \"popularity\": 7953\n  },\n  {\n    \"tag\": "flaunter",\n    \"popularity\": 7945\n  },\n  {\n    \"tag\": "reindeer",\n    \"popularity\": 7937\n  },\n  {\n    \"tag\": "disparage",\n    \"popularity\": 7929\n  },\n  {\n    \"tag\": "superheat",\n    \"popularity\": 7921\n  },\n  {\n    \"tag\": "Chromatium",\n    \"popularity\": 7912\n  },\n  {\n    \"tag\": "Tina",\n    \"popularity\": 7904\n  },\n  {\n    \"tag\": "rededicatory",\n    \"popularity\": 7896\n  },\n  {\n    \"tag\": "nontransient",\n    \"popularity\": 7888\n  },\n  {\n    \"tag\": "Phocaean brinkless",\n    \"popularity\": 7880\n  },\n  {\n    \"tag\": "ventriculose",\n    \"popularity\": 7872\n  },\n  {\n    \"tag\": "upplough",\n    \"popularity\": 7864\n  },\n  {\n    \"tag\": "succorless",\n    \"popularity\": 7856\n  },\n  {\n    \"tag\": "hayrake",\n    \"popularity\": 7848\n  },\n  {\n    \"tag\": "merriness amorphia",\n    \"popularity\": 7840\n  },\n  {\n    \"tag\": "merycism",\n    \"popularity\": 7832\n  },\n  {\n    \"tag\": "checkrow",\n    \"popularity\": 7824\n  },\n  {\n    \"tag\": "scry",\n    \"popularity\": 7816\n  },\n  {\n    \"tag\": "obvolve",\n    \"popularity\": 7808\n  },\n  {\n    \"tag\": "orchard",\n    \"popularity\": 7800\n  },\n  {\n    \"tag\": "isomerize",\n    \"popularity\": 7792\n  },\n  {\n    \"tag\": "competitrix",\n    \"popularity\": 7784\n  },\n  {\n    \"tag\": "unbannered",\n    \"popularity\": 7776\n  },\n  {\n    \"tag\": "undoctrined",\n    \"popularity\": 7768\n  },\n  {\n    \"tag\": "theologian",\n    \"popularity\": 7760\n  },\n  {\n    \"tag\": "nebby",\n    \"popularity\": 7752\n  },\n  {\n    \"tag\": "Cardiazol",\n    \"popularity\": 7745\n  },\n  {\n    \"tag\": "phagedenic",\n    \"popularity\": 7737\n  },\n  {\n    \"tag\": "nostalgic",\n    \"popularity\": 7729\n  },\n  {\n    \"tag\": "orthodoxy",\n    \"popularity\": 7721\n  },\n  {\n    \"tag\": "oversanguine",\n    \"popularity\": 7713\n  },\n  {\n    \"tag\": "lish",\n    \"popularity\": 7705\n  },\n  {\n    \"tag\": "ketogenic",\n    \"popularity\": 7698\n  },\n  {\n    \"tag\": "syndicalize",\n    \"popularity\": 7690\n  },\n  {\n    \"tag\": "leeftail",\n    \"popularity\": 7682\n  },\n  {\n    \"tag\": "bulbomedullary",\n    \"popularity\": 7674\n  },\n  {\n    \"tag\": "reletter",\n    \"popularity\": 7667\n  },\n  {\n    \"tag\": "bitterly",\n    \"popularity\": 7659\n  },\n  {\n    \"tag\": "participatory",\n    \"popularity\": 7651\n  },\n  {\n    \"tag\": "baldberry",\n    \"popularity\": 7643\n  },\n  {\n    \"tag\": "prowaterpower",\n    \"popularity\": 7636\n  },\n  {\n    \"tag\": "lexicographical",\n    \"popularity\": 7628\n  },\n  {\n    \"tag\": "Anisodactyli",\n    \"popularity\": 7620\n  },\n  {\n    \"tag\": "amphipodous",\n    \"popularity\": 7613\n  },\n  {\n    \"tag\": "triglandular",\n    \"popularity\": 7605\n  },\n  {\n    \"tag\": "xanthopsin",\n    \"popularity\": 7597\n  },\n  {\n    \"tag\": "indefinitude",\n    \"popularity\": 7590\n  },\n  {\n    \"tag\": "bookworm",\n    \"popularity\": 7582\n  },\n  {\n    \"tag\": "suffocative",\n    \"popularity\": 7574\n  },\n  {\n    \"tag\": "uncongested tyrant",\n    \"popularity\": 7567\n  },\n  {\n    \"tag\": "alow harmoniously Pamir",\n    \"popularity\": 7559\n  },\n  {\n    \"tag\": "monander",\n    \"popularity\": 7552\n  },\n  {\n    \"tag\": "bagatelle",\n    \"popularity\": 7544\n  },\n  {\n    \"tag\": "membranology",\n    \"popularity\": 7537\n  },\n  {\n    \"tag\": "parturifacient",\n    \"popularity\": 7529\n  },\n  {\n    \"tag\": "excitovascular",\n    \"popularity\": 7522\n  },\n  {\n    \"tag\": "homopolar",\n    \"popularity\": 7514\n  },\n  {\n    \"tag\": "phobiac",\n    \"popularity\": 7507\n  },\n  {\n    \"tag\": "clype",\n    \"popularity\": 7499\n  },\n  {\n    \"tag\": "unsubversive",\n    \"popularity\": 7492\n  },\n  {\n    \"tag\": "bostrychoidal scorpionwort",\n    \"popularity\": 7484\n  },\n  {\n    \"tag\": "biliteralism",\n    \"popularity\": 7477\n  },\n  {\n    \"tag\": "dentatocostate",\n    \"popularity\": 7469\n  },\n  {\n    \"tag\": "Pici",\n    \"popularity\": 7462\n  },\n  {\n    \"tag\": "sideritic",\n    \"popularity\": 7454\n  },\n  {\n    \"tag\": "syntaxis",\n    \"popularity\": 7447\n  },\n  {\n    \"tag\": "ingest",\n    \"popularity\": 7440\n  },\n  {\n    \"tag\": "rigmarolish",\n    \"popularity\": 7432\n  },\n  {\n    \"tag\": "ocreaceous",\n    \"popularity\": 7425\n  },\n  {\n    \"tag\": "hyperbrachyskelic",\n    \"popularity\": 7418\n  },\n  {\n    \"tag\": "basophobia",\n    \"popularity\": 7410\n  },\n  {\n    \"tag\": "substantialness",\n    \"popularity\": 7403\n  },\n  {\n    \"tag\": "agglutinoid",\n    \"popularity\": 7396\n  },\n  {\n    \"tag\": "longleaf",\n    \"popularity\": 7388\n  },\n  {\n    \"tag\": "electroengraving",\n    \"popularity\": 7381\n  },\n  {\n    \"tag\": "laparoenterotomy",\n    \"popularity\": 7374\n  },\n  {\n    \"tag\": "oxalylurea",\n    \"popularity\": 7366\n  },\n  {\n    \"tag\": "unattaintedly",\n    \"popularity\": 7359\n  },\n  {\n    \"tag\": "pennystone",\n    \"popularity\": 7352\n  },\n  {\n    \"tag\": "Plumbaginaceae",\n    \"popularity\": 7345\n  },\n  {\n    \"tag\": "horntip",\n    \"popularity\": 7337\n  },\n  {\n    \"tag\": "begrudge",\n    \"popularity\": 7330\n  },\n  {\n    \"tag\": "bechignoned",\n    \"popularity\": 7323\n  },\n  {\n    \"tag\": "hologonidium",\n    \"popularity\": 7316\n  },\n  {\n    \"tag\": "Pulian",\n    \"popularity\": 7309\n  },\n  {\n    \"tag\": "gratulation",\n    \"popularity\": 7301\n  },\n  {\n    \"tag\": "Sebright",\n    \"popularity\": 7294\n  },\n  {\n    \"tag\": "coinstantaneous emotionally",\n    \"popularity\": 7287\n  },\n  {\n    \"tag\": "thoracostracan",\n    \"popularity\": 7280\n  },\n  {\n    \"tag\": "saurodont",\n    \"popularity\": 7273\n  },\n  {\n    \"tag\": "coseat",\n    \"popularity\": 7266\n  },\n  {\n    \"tag\": "irascibility",\n    \"popularity\": 7259\n  },\n  {\n    \"tag\": "occlude",\n    \"popularity\": 7251\n  },\n  {\n    \"tag\": "metallurgist",\n    \"popularity\": 7244\n  },\n  {\n    \"tag\": "extraviolet",\n    \"popularity\": 7237\n  },\n  {\n    \"tag\": "clinic",\n    \"popularity\": 7230\n  },\n  {\n    \"tag\": "skater",\n    \"popularity\": 7223\n  },\n  {\n    \"tag\": "linguistic",\n    \"popularity\": 7216\n  },\n  {\n    \"tag\": "attacheship",\n    \"popularity\": 7209\n  },\n  {\n    \"tag\": "Rachianectes",\n    \"popularity\": 7202\n  },\n  {\n    \"tag\": "foliolose",\n    \"popularity\": 7195\n  },\n  {\n    \"tag\": "claudetite",\n    \"popularity\": 7188\n  },\n  {\n    \"tag\": "aphidian scratching",\n    \"popularity\": 7181\n  },\n  {\n    \"tag\": "Carida",\n    \"popularity\": 7174\n  },\n  {\n    \"tag\": "tiepin polymicroscope",\n    \"popularity\": 7167\n  },\n  {\n    \"tag\": "telpherage",\n    \"popularity\": 7160\n  },\n  {\n    \"tag\": "meek",\n    \"popularity\": 7153\n  },\n  {\n    \"tag\": "swiftness",\n    \"popularity\": 7146\n  },\n  {\n    \"tag\": "gentes",\n    \"popularity\": 7139\n  },\n  {\n    \"tag\": "uncommemorated",\n    \"popularity\": 7132\n  },\n  {\n    \"tag\": "Lazarus",\n    \"popularity\": 7125\n  },\n  {\n    \"tag\": "redivive",\n    \"popularity\": 7119\n  },\n  {\n    \"tag\": "nonfebrile",\n    \"popularity\": 7112\n  },\n  {\n    \"tag\": "nymphet",\n    \"popularity\": 7105\n  },\n  {\n    \"tag\": "areologically",\n    \"popularity\": 7098\n  },\n  {\n    \"tag\": "undonkey",\n    \"popularity\": 7091\n  },\n  {\n    \"tag\": "projecting",\n    \"popularity\": 7084\n  },\n  {\n    \"tag\": "pinnigrade",\n    \"popularity\": 7077\n  },\n  {\n    \"tag\": "butylation",\n    \"popularity\": 7071\n  },\n  {\n    \"tag\": "philologistic lenticle",\n    \"popularity\": 7064\n  },\n  {\n    \"tag\": "nooky",\n    \"popularity\": 7057\n  },\n  {\n    \"tag\": "incestuousness",\n    \"popularity\": 7050\n  },\n  {\n    \"tag\": "palingenetically",\n    \"popularity\": 7043\n  },\n  {\n    \"tag\": "mitochondria",\n    \"popularity\": 7037\n  },\n  {\n    \"tag\": "truthify",\n    \"popularity\": 7030\n  },\n  {\n    \"tag\": "titanyl",\n    \"popularity\": 7023\n  },\n  {\n    \"tag\": "bestride",\n    \"popularity\": 7016\n  },\n  {\n    \"tag\": "chende",\n    \"popularity\": 7010\n  },\n  {\n    \"tag\": "Chaucerian monophote",\n    \"popularity\": 7003\n  },\n  {\n    \"tag\": "cutback",\n    \"popularity\": 6996\n  },\n  {\n    \"tag\": "unpatiently",\n    \"popularity\": 6989\n  },\n  {\n    \"tag\": "subvitreous",\n    \"popularity\": 6983\n  },\n  {\n    \"tag\": "organizable",\n    \"popularity\": 6976\n  },\n  {\n    \"tag\": "anniverse uncomprehensible",\n    \"popularity\": 6969\n  },\n  {\n    \"tag\": "hyalescence",\n    \"popularity\": 6963\n  },\n  {\n    \"tag\": "amniochorial",\n    \"popularity\": 6956\n  },\n  {\n    \"tag\": "Corybantian",\n    \"popularity\": 6949\n  },\n  {\n    \"tag\": "genocide Scaphitidae",\n    \"popularity\": 6943\n  },\n  {\n    \"tag\": "accordionist",\n    \"popularity\": 6936\n  },\n  {\n    \"tag\": "becheck",\n    \"popularity\": 6930\n  },\n  {\n    \"tag\": "overproduce",\n    \"popularity\": 6923\n  },\n  {\n    \"tag\": "unmaniac frijolillo",\n    \"popularity\": 6916\n  },\n  {\n    \"tag\": "multisulcated",\n    \"popularity\": 6910\n  },\n  {\n    \"tag\": "wennebergite",\n    \"popularity\": 6903\n  },\n  {\n    \"tag\": "tautousious mowth",\n    \"popularity\": 6897\n  },\n  {\n    \"tag\": "marigold",\n    \"popularity\": 6890\n  },\n  {\n    \"tag\": "affray",\n    \"popularity\": 6884\n  },\n  {\n    \"tag\": "nonidolatrous",\n    \"popularity\": 6877\n  },\n  {\n    \"tag\": "aphrasia",\n    \"popularity\": 6871\n  },\n  {\n    \"tag\": "muddlingly",\n    \"popularity\": 6864\n  },\n  {\n    \"tag\": "clear",\n    \"popularity\": 6858\n  },\n  {\n    \"tag\": "Clitoria",\n    \"popularity\": 6851\n  },\n  {\n    \"tag\": "apportionment underwaist",\n    \"popularity\": 6845\n  },\n  {\n    \"tag\": "kodakist",\n    \"popularity\": 6838\n  },\n  {\n    \"tag\": "Momotidae",\n    \"popularity\": 6832\n  },\n  {\n    \"tag\": "cryptovalency",\n    \"popularity\": 6825\n  },\n  {\n    \"tag\": "floe",\n    \"popularity\": 6819\n  },\n  {\n    \"tag\": "aphagia",\n    \"popularity\": 6812\n  },\n  {\n    \"tag\": "brontograph",\n    \"popularity\": 6806\n  },\n  {\n    \"tag\": "tubulous",\n    \"popularity\": 6799\n  },\n  {\n    \"tag\": "unhorse",\n    \"popularity\": 6793\n  },\n  {\n    \"tag\": "chlordane",\n    \"popularity\": 6787\n  },\n  {\n    \"tag\": "colloquy brochan",\n    \"popularity\": 6780\n  },\n  {\n    \"tag\": "sloosh",\n    \"popularity\": 6774\n  },\n  {\n    \"tag\": "battered",\n    \"popularity\": 6767\n  },\n  {\n    \"tag\": "monocularity pluriguttulate",\n    \"popularity\": 6761\n  },\n  {\n    \"tag\": "chiastoneury",\n    \"popularity\": 6755\n  },\n  {\n    \"tag\": "Sanguinaria",\n    \"popularity\": 6748\n  },\n  {\n    \"tag\": "confessionary",\n    \"popularity\": 6742\n  },\n  {\n    \"tag\": "enzymic",\n    \"popularity\": 6736\n  },\n  {\n    \"tag\": "cord",\n    \"popularity\": 6729\n  },\n  {\n    \"tag\": "oviducal",\n    \"popularity\": 6723\n  },\n  {\n    \"tag\": "crozzle outsea",\n    \"popularity\": 6717\n  },\n  {\n    \"tag\": "balladical",\n    \"popularity\": 6710\n  },\n  {\n    \"tag\": "uncollectibleness",\n    \"popularity\": 6704\n  },\n  {\n    \"tag\": "predorsal",\n    \"popularity\": 6698\n  },\n  {\n    \"tag\": "reauthenticate",\n    \"popularity\": 6692\n  },\n  {\n    \"tag\": "ravissant",\n    \"popularity\": 6685\n  },\n  {\n    \"tag\": "advantageousness",\n    \"popularity\": 6679\n  },\n  {\n    \"tag\": "rung",\n    \"popularity\": 6673\n  },\n  {\n    \"tag\": "duncedom",\n    \"popularity\": 6667\n  },\n  {\n    \"tag\": "hematolite",\n    \"popularity\": 6660\n  },\n  {\n    \"tag\": "thisness",\n    \"popularity\": 6654\n  },\n  {\n    \"tag\": "mapau",\n    \"popularity\": 6648\n  },\n  {\n    \"tag\": "Hecatic",\n    \"popularity\": 6642\n  },\n  {\n    \"tag\": "meningoencephalocele",\n    \"popularity\": 6636\n  },\n  {\n    \"tag\": "confection sorra",\n    \"popularity\": 6630\n  },\n  {\n    \"tag\": "unsedate",\n    \"popularity\": 6623\n  },\n  {\n    \"tag\": "meningocerebritis",\n    \"popularity\": 6617\n  },\n  {\n    \"tag\": "biopsychological",\n    \"popularity\": 6611\n  },\n  {\n    \"tag\": "clavicithern",\n    \"popularity\": 6605\n  },\n  {\n    \"tag\": "resun",\n    \"popularity\": 6599\n  },\n  {\n    \"tag\": "bayamo",\n    \"popularity\": 6593\n  },\n  {\n    \"tag\": "seeableness",\n    \"popularity\": 6587\n  },\n  {\n    \"tag\": "hypsidolichocephalism",\n    \"popularity\": 6581\n  },\n  {\n    \"tag\": "salivous",\n    \"popularity\": 6574\n  },\n  {\n    \"tag\": "neumatize",\n    \"popularity\": 6568\n  },\n  {\n    \"tag\": "stree",\n    \"popularity\": 6562\n  },\n  {\n    \"tag\": "markshot",\n    \"popularity\": 6556\n  },\n  {\n    \"tag\": "phraseologically",\n    \"popularity\": 6550\n  },\n  {\n    \"tag\": "yealing",\n    \"popularity\": 6544\n  },\n  {\n    \"tag\": "puggy",\n    \"popularity\": 6538\n  },\n  {\n    \"tag\": "sexadecimal",\n    \"popularity\": 6532\n  },\n  {\n    \"tag\": "unofficerlike",\n    \"popularity\": 6526\n  },\n  {\n    \"tag\": "curiosa",\n    \"popularity\": 6520\n  },\n  {\n    \"tag\": "pedomotor",\n    \"popularity\": 6514\n  },\n  {\n    \"tag\": "astrally",\n    \"popularity\": 6508\n  },\n  {\n    \"tag\": "prosomatic",\n    \"popularity\": 6502\n  },\n  {\n    \"tag\": "bulletheaded",\n    \"popularity\": 6496\n  },\n  {\n    \"tag\": "fortuned",\n    \"popularity\": 6490\n  },\n  {\n    \"tag\": "pixy",\n    \"popularity\": 6484\n  },\n  {\n    \"tag\": "protectrix",\n    \"popularity\": 6478\n  },\n  {\n    \"tag\": "arthritical",\n    \"popularity\": 6472\n  },\n  {\n    \"tag\": "coction",\n    \"popularity\": 6466\n  },\n  {\n    \"tag\": "Anthropos",\n    \"popularity\": 6460\n  },\n  {\n    \"tag\": "runer",\n    \"popularity\": 6454\n  },\n  {\n    \"tag\": "prenotify",\n    \"popularity\": 6449\n  },\n  {\n    \"tag\": "microspheric gastroparalysis",\n    \"popularity\": 6443\n  },\n  {\n    \"tag\": "Jovicentrical",\n    \"popularity\": 6437\n  },\n  {\n    \"tag\": "ceratopsid",\n    \"popularity\": 6431\n  },\n  {\n    \"tag\": "Theodoric",\n    \"popularity\": 6425\n  },\n  {\n    \"tag\": "Pactolus",\n    \"popularity\": 6419\n  },\n  {\n    \"tag\": "spawning",\n    \"popularity\": 6413\n  },\n  {\n    \"tag\": "nonconfidential",\n    \"popularity\": 6407\n  },\n  {\n    \"tag\": "halotrichite infumate",\n    \"popularity\": 6402\n  },\n  {\n    \"tag\": "undiscriminatingly",\n    \"popularity\": 6396\n  },\n  {\n    \"tag\": "unexasperated",\n    \"popularity\": 6390\n  },\n  {\n    \"tag\": "isoeugenol",\n    \"popularity\": 6384\n  },\n  {\n    \"tag\": "pressboard",\n    \"popularity\": 6378\n  },\n  {\n    \"tag\": "unshrew",\n    \"popularity\": 6372\n  },\n  {\n    \"tag\": "huffingly",\n    \"popularity\": 6367\n  },\n  {\n    \"tag\": "wagaun",\n    \"popularity\": 6361\n  },\n  {\n    \"tag\": "squirt Philistine",\n    \"popularity\": 6355\n  },\n  {\n    \"tag\": "kryptic",\n    \"popularity\": 6349\n  },\n  {\n    \"tag\": "paraform",\n    \"popularity\": 6344\n  },\n  {\n    \"tag\": "preverify",\n    \"popularity\": 6338\n  },\n  {\n    \"tag\": "dalar",\n    \"popularity\": 6332\n  },\n  {\n    \"tag\": "interdictor appraisingly",\n    \"popularity\": 6326\n  },\n  {\n    \"tag\": "chipped",\n    \"popularity\": 6321\n  },\n  {\n    \"tag\": "Pteropoda",\n    \"popularity\": 6315\n  },\n  {\n    \"tag\": "Bohairic",\n    \"popularity\": 6309\n  },\n  {\n    \"tag\": "felting",\n    \"popularity\": 6303\n  },\n  {\n    \"tag\": "compurgatorial",\n    \"popularity\": 6298\n  },\n  {\n    \"tag\": "unclead",\n    \"popularity\": 6292\n  },\n  {\n    \"tag\": "stockish",\n    \"popularity\": 6286\n  },\n  {\n    \"tag\": "mulligatawny",\n    \"popularity\": 6281\n  },\n  {\n    \"tag\": "Monotheletism",\n    \"popularity\": 6275\n  },\n  {\n    \"tag\": "lutanist",\n    \"popularity\": 6269\n  },\n  {\n    \"tag\": "gluttonize",\n    \"popularity\": 6264\n  },\n  {\n    \"tag\": "hackneyed",\n    \"popularity\": 6258\n  },\n  {\n    \"tag\": "yield",\n    \"popularity\": 6253\n  },\n  {\n    \"tag\": "sulphonamido",\n    \"popularity\": 6247\n  },\n  {\n    \"tag\": "granulative",\n    \"popularity\": 6241\n  },\n  {\n    \"tag\": "swingy",\n    \"popularity\": 6236\n  },\n  {\n    \"tag\": "Desmidiales",\n    \"popularity\": 6230\n  },\n  {\n    \"tag\": "tootlish",\n    \"popularity\": 6224\n  },\n  {\n    \"tag\": "unsatisfiedly",\n    \"popularity\": 6219\n  },\n  {\n    \"tag\": "burucha",\n    \"popularity\": 6213\n  },\n  {\n    \"tag\": "premeditatingly",\n    \"popularity\": 6208\n  },\n  {\n    \"tag\": "cowrie",\n    \"popularity\": 6202\n  },\n  {\n    \"tag\": "pleurolysis",\n    \"popularity\": 6197\n  },\n  {\n    \"tag\": "nationalist",\n    \"popularity\": 6191\n  },\n  {\n    \"tag\": "Pholadacea",\n    \"popularity\": 6186\n  },\n  {\n    \"tag\": "anakrousis",\n    \"popularity\": 6180\n  },\n  {\n    \"tag\": "proctorial",\n    \"popularity\": 6175\n  },\n  {\n    \"tag\": "cavillation",\n    \"popularity\": 6169\n  },\n  {\n    \"tag\": "cervicobregmatic",\n    \"popularity\": 6163\n  },\n  {\n    \"tag\": "interspecific",\n    \"popularity\": 6158\n  },\n  {\n    \"tag\": "Teutonity",\n    \"popularity\": 6152\n  },\n  {\n    \"tag\": "snakeholing",\n    \"popularity\": 6147\n  },\n  {\n    \"tag\": "balcony",\n    \"popularity\": 6142\n  },\n  {\n    \"tag\": "latchless",\n    \"popularity\": 6136\n  },\n  {\n    \"tag\": "Mithraea",\n    \"popularity\": 6131\n  },\n  {\n    \"tag\": "pseudepigraph",\n    \"popularity\": 6125\n  },\n  {\n    \"tag\": "flosser",\n    \"popularity\": 6120\n  },\n  {\n    \"tag\": "kotyle",\n    \"popularity\": 6114\n  },\n  {\n    \"tag\": "outdo",\n    \"popularity\": 6109\n  },\n  {\n    \"tag\": "interclerical",\n    \"popularity\": 6103\n  },\n  {\n    \"tag\": "aurar",\n    \"popularity\": 6098\n  },\n  {\n    \"tag\": "apophyseal",\n    \"popularity\": 6093\n  },\n  {\n    \"tag\": "Miro",\n    \"popularity\": 6087\n  },\n  {\n    \"tag\": "Priscillian",\n    \"popularity\": 6082\n  },\n  {\n    \"tag\": "alluvia",\n    \"popularity\": 6076\n  },\n  {\n    \"tag\": "exordize",\n    \"popularity\": 6071\n  },\n  {\n    \"tag\": "breakage",\n    \"popularity\": 6066\n  },\n  {\n    \"tag\": "unclosable",\n    \"popularity\": 6060\n  },\n  {\n    \"tag\": "monocondylous",\n    \"popularity\": 6055\n  },\n  {\n    \"tag\": "dyarchy",\n    \"popularity\": 6050\n  },\n  {\n    \"tag\": "subchelate",\n    \"popularity\": 6044\n  },\n  {\n    \"tag\": "hearsay",\n    \"popularity\": 6039\n  },\n  {\n    \"tag\": "prestigiously",\n    \"popularity\": 6034\n  },\n  {\n    \"tag\": "unimuscular",\n    \"popularity\": 6028\n  },\n  {\n    \"tag\": "lingwort",\n    \"popularity\": 6023\n  },\n  {\n    \"tag\": "jealous",\n    \"popularity\": 6018\n  },\n  {\n    \"tag\": "artilleryman",\n    \"popularity\": 6012\n  },\n  {\n    \"tag\": "phantasmagorially",\n    \"popularity\": 6007\n  },\n  {\n    \"tag\": "stagnum",\n    \"popularity\": 6002\n  },\n  {\n    \"tag\": "organotropism shatteringly",\n    \"popularity\": 5997\n  },\n  {\n    \"tag\": "Mytilus Hebraist",\n    \"popularity\": 5991\n  },\n  {\n    \"tag\": "returf",\n    \"popularity\": 5986\n  },\n  {\n    \"tag\": "townfolk",\n    \"popularity\": 5981\n  },\n  {\n    \"tag\": "propitiative",\n    \"popularity\": 5976\n  },\n  {\n    \"tag\": "Anita unsullied",\n    \"popularity\": 5970\n  },\n  {\n    \"tag\": "bandoleered",\n    \"popularity\": 5965\n  },\n  {\n    \"tag\": "cubby",\n    \"popularity\": 5960\n  },\n  {\n    \"tag\": "Hexanchus",\n    \"popularity\": 5955\n  },\n  {\n    \"tag\": "circuminsular",\n    \"popularity\": 5949\n  },\n  {\n    \"tag\": "chamberletted eumycete",\n    \"popularity\": 5944\n  },\n  {\n    \"tag\": "secure",\n    \"popularity\": 5939\n  },\n  {\n    \"tag\": "Edwardean",\n    \"popularity\": 5934\n  },\n  {\n    \"tag\": "strenth",\n    \"popularity\": 5929\n  },\n  {\n    \"tag\": "exhaustless",\n    \"popularity\": 5923\n  },\n  {\n    \"tag\": "electioneerer",\n    \"popularity\": 5918\n  },\n  {\n    \"tag\": "estoile",\n    \"popularity\": 5913\n  },\n  {\n    \"tag\": "redden",\n    \"popularity\": 5908\n  },\n  {\n    \"tag\": "solicitee",\n    \"popularity\": 5903\n  },\n  {\n    \"tag\": "nonpatented",\n    \"popularity\": 5898\n  },\n  {\n    \"tag\": "lemming",\n    \"popularity\": 5893\n  },\n  {\n    \"tag\": "marled subalate",\n    \"popularity\": 5887\n  },\n  {\n    \"tag\": "premial horizonward",\n    \"popularity\": 5882\n  },\n  {\n    \"tag\": "nonrefueling",\n    \"popularity\": 5877\n  },\n  {\n    \"tag\": "rupturewort",\n    \"popularity\": 5872\n  },\n  {\n    \"tag\": "unfed",\n    \"popularity\": 5867\n  },\n  {\n    \"tag\": "empanelment",\n    \"popularity\": 5862\n  },\n  {\n    \"tag\": "isoosmosis",\n    \"popularity\": 5857\n  },\n  {\n    \"tag\": "jipijapa",\n    \"popularity\": 5852\n  },\n  {\n    \"tag\": "Fiji",\n    \"popularity\": 5847\n  },\n  {\n    \"tag\": "interferant",\n    \"popularity\": 5842\n  },\n  {\n    \"tag\": "reconstitution",\n    \"popularity\": 5837\n  },\n  {\n    \"tag\": "dockyardman",\n    \"popularity\": 5832\n  },\n  {\n    \"tag\": "dolichopodous",\n    \"popularity\": 5826\n  },\n  {\n    \"tag\": "whiteworm",\n    \"popularity\": 5821\n  },\n  {\n    \"tag\": "atheistically",\n    \"popularity\": 5816\n  },\n  {\n    \"tag\": "nonconcern",\n    \"popularity\": 5811\n  },\n  {\n    \"tag\": "scarabaeidoid",\n    \"popularity\": 5806\n  },\n  {\n    \"tag\": "triumviri",\n    \"popularity\": 5801\n  },\n  {\n    \"tag\": "rakit",\n    \"popularity\": 5796\n  },\n  {\n    \"tag\": "leecheater",\n    \"popularity\": 5791\n  },\n  {\n    \"tag\": "Arthrostraca",\n    \"popularity\": 5786\n  },\n  {\n    \"tag\": "upknit",\n    \"popularity\": 5781\n  },\n  {\n    \"tag\": "tymbalon",\n    \"popularity\": 5776\n  },\n  {\n    \"tag\": "inventurous",\n    \"popularity\": 5771\n  },\n  {\n    \"tag\": "perradiate",\n    \"popularity\": 5766\n  },\n  {\n    \"tag\": "seer",\n    \"popularity\": 5762\n  },\n  {\n    \"tag\": "Auricularia",\n    \"popularity\": 5757\n  },\n  {\n    \"tag\": "wettish exclusivity",\n    \"popularity\": 5752\n  },\n  {\n    \"tag\": "arteriosympathectomy",\n    \"popularity\": 5747\n  },\n  {\n    \"tag\": "tunlike",\n    \"popularity\": 5742\n  },\n  {\n    \"tag\": "cephalocercal",\n    \"popularity\": 5737\n  },\n  {\n    \"tag\": "meaninglessness",\n    \"popularity\": 5732\n  },\n  {\n    \"tag\": "fountful",\n    \"popularity\": 5727\n  },\n  {\n    \"tag\": "appraisement",\n    \"popularity\": 5722\n  },\n  {\n    \"tag\": "geniculated",\n    \"popularity\": 5717\n  },\n  {\n    \"tag\": "rotator",\n    \"popularity\": 5712\n  },\n  {\n    \"tag\": "foremarch biography",\n    \"popularity\": 5707\n  },\n  {\n    \"tag\": "arid",\n    \"popularity\": 5703\n  },\n  {\n    \"tag\": "inapprehensible",\n    \"popularity\": 5698\n  },\n  {\n    \"tag\": "chlorosulphonic",\n    \"popularity\": 5693\n  },\n  {\n    \"tag\": "braguette",\n    \"popularity\": 5688\n  },\n  {\n    \"tag\": "panophthalmitis",\n    \"popularity\": 5683\n  },\n  {\n    \"tag\": "pro objurgatorily",\n    \"popularity\": 5678\n  },\n  {\n    \"tag\": "zooplasty",\n    \"popularity\": 5673\n  },\n  {\n    \"tag\": "Terebratulidae",\n    \"popularity\": 5669\n  },\n  {\n    \"tag\": "Mahran",\n    \"popularity\": 5664\n  },\n  {\n    \"tag\": "anthologize merocele",\n    \"popularity\": 5659\n  },\n  {\n    \"tag\": "firecracker chiropractic",\n    \"popularity\": 5654\n  },\n  {\n    \"tag\": "tenorist",\n    \"popularity\": 5649\n  },\n  {\n    \"tag\": "amphitene",\n    \"popularity\": 5645\n  },\n  {\n    \"tag\": "silverbush toadstone",\n    \"popularity\": 5640\n  },\n  {\n    \"tag\": "entozoological",\n    \"popularity\": 5635\n  },\n  {\n    \"tag\": "trustlessness",\n    \"popularity\": 5630\n  },\n  {\n    \"tag\": "reassay",\n    \"popularity\": 5625\n  },\n  {\n    \"tag\": "chrysalides",\n    \"popularity\": 5621\n  },\n  {\n    \"tag\": "truncation",\n    \"popularity\": 5616\n  },\n  {\n    \"tag\": "unwavered mausoleal",\n    \"popularity\": 5611\n  },\n  {\n    \"tag\": "unserrated",\n    \"popularity\": 5606\n  },\n  {\n    \"tag\": "frampler",\n    \"popularity\": 5602\n  },\n  {\n    \"tag\": "celestial",\n    \"popularity\": 5597\n  },\n  {\n    \"tag\": "depreter",\n    \"popularity\": 5592\n  },\n  {\n    \"tag\": "retaliate",\n    \"popularity\": 5588\n  },\n  {\n    \"tag\": "decempunctate",\n    \"popularity\": 5583\n  },\n  {\n    \"tag\": "submitter",\n    \"popularity\": 5578\n  },\n  {\n    \"tag\": "phenothiazine",\n    \"popularity\": 5573\n  },\n  {\n    \"tag\": "hobbledehoyish",\n    \"popularity\": 5569\n  },\n  {\n    \"tag\": "erraticness",\n    \"popularity\": 5564\n  },\n  {\n    \"tag\": "ovariodysneuria",\n    \"popularity\": 5559\n  },\n  {\n    \"tag\": "puja",\n    \"popularity\": 5555\n  },\n  {\n    \"tag\": "cesspool",\n    \"popularity\": 5550\n  },\n  {\n    \"tag\": "sonation",\n    \"popularity\": 5545\n  },\n  {\n    \"tag\": "moggan",\n    \"popularity\": 5541\n  },\n  {\n    \"tag\": "overjutting",\n    \"popularity\": 5536\n  },\n  {\n    \"tag\": "cohobate",\n    \"popularity\": 5531\n  },\n  {\n    \"tag\": "Distoma",\n    \"popularity\": 5527\n  },\n  {\n    \"tag\": "Plectognathi",\n    \"popularity\": 5522\n  },\n  {\n    \"tag\": "dumple caliphate",\n    \"popularity\": 5517\n  },\n  {\n    \"tag\": "shiko",\n    \"popularity\": 5513\n  },\n  {\n    \"tag\": "downness",\n    \"popularity\": 5508\n  },\n  {\n    \"tag\": "whippletree",\n    \"popularity\": 5504\n  },\n  {\n    \"tag\": "nymphaeum",\n    \"popularity\": 5499\n  },\n  {\n    \"tag\": "there trest",\n    \"popularity\": 5494\n  },\n  {\n    \"tag\": "psychrometer",\n    \"popularity\": 5490\n  },\n  {\n    \"tag\": "pyelograph",\n    \"popularity\": 5485\n  },\n  {\n    \"tag\": "unsalvable",\n    \"popularity\": 5481\n  },\n  {\n    \"tag\": "bescreen",\n    \"popularity\": 5476\n  },\n  {\n    \"tag\": "cushy",\n    \"popularity\": 5471\n  },\n  {\n    \"tag\": "plicatolobate",\n    \"popularity\": 5467\n  },\n  {\n    \"tag\": "lakie",\n    \"popularity\": 5462\n  },\n  {\n    \"tag\": "anthropodeoxycholic",\n    \"popularity\": 5458\n  },\n  {\n    \"tag\": "resatisfaction",\n    \"popularity\": 5453\n  },\n  {\n    \"tag\": "unravelment unaccidental",\n    \"popularity\": 5449\n  },\n  {\n    \"tag\": "telewriter monogeneous",\n    \"popularity\": 5444\n  },\n  {\n    \"tag\": "unsabred",\n    \"popularity\": 5440\n  },\n  {\n    \"tag\": "startlingly",\n    \"popularity\": 5435\n  },\n  {\n    \"tag\": "Aralia",\n    \"popularity\": 5431\n  },\n  {\n    \"tag\": "alamonti",\n    \"popularity\": 5426\n  },\n  {\n    \"tag\": "Franklinization",\n    \"popularity\": 5422\n  },\n  {\n    \"tag\": "parliament",\n    \"popularity\": 5417\n  },\n  {\n    \"tag\": "schoolkeeper",\n    \"popularity\": 5413\n  },\n  {\n    \"tag\": "nonsociety",\n    \"popularity\": 5408\n  },\n  {\n    \"tag\": "parenthetic",\n    \"popularity\": 5404\n  },\n  {\n    \"tag\": "stog",\n    \"popularity\": 5399\n  },\n  {\n    \"tag\": "Pristipomidae",\n    \"popularity\": 5395\n  },\n  {\n    \"tag\": "exocarp",\n    \"popularity\": 5390\n  },\n  {\n    \"tag\": "monaxonial",\n    \"popularity\": 5386\n  },\n  {\n    \"tag\": "tramroad",\n    \"popularity\": 5381\n  },\n  {\n    \"tag\": "hookah",\n    \"popularity\": 5377\n  },\n  {\n    \"tag\": "saccharonic",\n    \"popularity\": 5372\n  },\n  {\n    \"tag\": "perimetrium",\n    \"popularity\": 5368\n  },\n  {\n    \"tag\": "libelluloid",\n    \"popularity\": 5364\n  },\n  {\n    \"tag\": "overrunningly",\n    \"popularity\": 5359\n  },\n  {\n    \"tag\": "untwister",\n    \"popularity\": 5355\n  },\n  {\n    \"tag\": "ninnyhammer",\n    \"popularity\": 5350\n  },\n  {\n    \"tag\": "metranate",\n    \"popularity\": 5346\n  },\n  {\n    \"tag\": "sarcoblast",\n    \"popularity\": 5341\n  },\n  {\n    \"tag\": "porkish",\n    \"popularity\": 5337\n  },\n  {\n    \"tag\": "chauvinistic",\n    \"popularity\": 5333\n  },\n  {\n    \"tag\": "sexagesimal",\n    \"popularity\": 5328\n  },\n  {\n    \"tag\": "hematogenic",\n    \"popularity\": 5324\n  },\n  {\n    \"tag\": "selfpreservatory",\n    \"popularity\": 5320\n  },\n  {\n    \"tag\": "myelauxe",\n    \"popularity\": 5315\n  },\n  {\n    \"tag\": "triply",\n    \"popularity\": 5311\n  },\n  {\n    \"tag\": "metaphysicous",\n    \"popularity\": 5306\n  },\n  {\n    \"tag\": "vitrinoid",\n    \"popularity\": 5302\n  },\n  {\n    \"tag\": "glabellae",\n    \"popularity\": 5298\n  },\n  {\n    \"tag\": "moonlighter",\n    \"popularity\": 5293\n  },\n  {\n    \"tag\": "monotheistically epexegetical",\n    \"popularity\": 5289\n  },\n  {\n    \"tag\": "pseudolateral",\n    \"popularity\": 5285\n  },\n  {\n    \"tag\": "heptamethylene",\n    \"popularity\": 5280\n  },\n  {\n    \"tag\": "salvadora",\n    \"popularity\": 5276\n  },\n  {\n    \"tag\": "unjovial diphenylthiourea",\n    \"popularity\": 5272\n  },\n  {\n    \"tag\": "thievishness",\n    \"popularity\": 5268\n  },\n  {\n    \"tag\": "unridable",\n    \"popularity\": 5263\n  },\n  {\n    \"tag\": "underhandedly",\n    \"popularity\": 5259\n  },\n  {\n    \"tag\": "fungiform",\n    \"popularity\": 5255\n  },\n  {\n    \"tag\": "scruffle",\n    \"popularity\": 5250\n  },\n  {\n    \"tag\": "preindisposition",\n    \"popularity\": 5246\n  },\n  {\n    \"tag\": "Amadis",\n    \"popularity\": 5242\n  },\n  {\n    \"tag\": "Culex",\n    \"popularity\": 5238\n  },\n  {\n    \"tag\": "churning",\n    \"popularity\": 5233\n  },\n  {\n    \"tag\": "imperite",\n    \"popularity\": 5229\n  },\n  {\n    \"tag\": "levorotation",\n    \"popularity\": 5225\n  },\n  {\n    \"tag\": "barbate",\n    \"popularity\": 5221\n  },\n  {\n    \"tag\": "knotwort",\n    \"popularity\": 5216\n  },\n  {\n    \"tag\": "gypsiferous",\n    \"popularity\": 5212\n  },\n  {\n    \"tag\": "tourmalinic",\n    \"popularity\": 5208\n  },\n  {\n    \"tag\": "helleboric",\n    \"popularity\": 5204\n  },\n  {\n    \"tag\": "pneumograph",\n    \"popularity\": 5199\n  },\n  {\n    \"tag\": "Peltigeraceae",\n    \"popularity\": 5195\n  },\n  {\n    \"tag\": "busine",\n    \"popularity\": 5191\n  },\n  {\n    \"tag\": "Ailuridae",\n    \"popularity\": 5187\n  },\n  {\n    \"tag\": "azotate",\n    \"popularity\": 5183\n  },\n  {\n    \"tag\": "unlikable",\n    \"popularity\": 5178\n  },\n  {\n    \"tag\": "sloyd",\n    \"popularity\": 5174\n  },\n  {\n    \"tag\": "biblioclasm",\n    \"popularity\": 5170\n  },\n  {\n    \"tag\": "Seres",\n    \"popularity\": 5166\n  },\n  {\n    \"tag\": "unaccurateness",\n    \"popularity\": 5162\n  },\n  {\n    \"tag\": "scrollwise",\n    \"popularity\": 5157\n  },\n  {\n    \"tag\": "flandowser",\n    \"popularity\": 5153\n  },\n  {\n    \"tag\": "unblackened",\n    \"popularity\": 5149\n  },\n  {\n    \"tag\": "schistosternia",\n    \"popularity\": 5145\n  },\n  {\n    \"tag\": "fuse",\n    \"popularity\": 5141\n  },\n  {\n    \"tag\": "narthecal",\n    \"popularity\": 5137\n  },\n  {\n    \"tag\": "Cueva",\n    \"popularity\": 5133\n  },\n  {\n    \"tag\": "appositeness",\n    \"popularity\": 5128\n  },\n  {\n    \"tag\": "proindustrial",\n    \"popularity\": 5124\n  },\n  {\n    \"tag\": "dermatorrhoea",\n    \"popularity\": 5120\n  },\n  {\n    \"tag\": "oxyurous tendential",\n    \"popularity\": 5116\n  },\n  {\n    \"tag\": "isopurpurin",\n    \"popularity\": 5112\n  },\n  {\n    \"tag\": "impose",\n    \"popularity\": 5108\n  },\n  {\n    \"tag\": "wordsmanship",\n    \"popularity\": 5104\n  },\n  {\n    \"tag\": "saturator",\n    \"popularity\": 5100\n  },\n  {\n    \"tag\": "Nordicity",\n    \"popularity\": 5096\n  },\n  {\n    \"tag\": "interaccuse",\n    \"popularity\": 5092\n  },\n  {\n    \"tag\": "acridinic",\n    \"popularity\": 5087\n  },\n  {\n    \"tag\": "scholion",\n    \"popularity\": 5083\n  },\n  {\n    \"tag\": "pseudoaconitine",\n    \"popularity\": 5079\n  },\n  {\n    \"tag\": "doctorial",\n    \"popularity\": 5075\n  },\n  {\n    \"tag\": "Etchimin",\n    \"popularity\": 5071\n  },\n  {\n    \"tag\": "oliviform",\n    \"popularity\": 5067\n  },\n  {\n    \"tag\": "Pele",\n    \"popularity\": 5063\n  },\n  {\n    \"tag\": "Chiromantis Progymnasium",\n    \"popularity\": 5059\n  },\n  {\n    \"tag\": "toxosis",\n    \"popularity\": 5055\n  },\n  {\n    \"tag\": "spadilla",\n    \"popularity\": 5051\n  },\n  {\n    \"tag\": "Actinopterygii",\n    \"popularity\": 5047\n  },\n  {\n    \"tag\": "untiring",\n    \"popularity\": 5043\n  },\n  {\n    \"tag\": "butyral",\n    \"popularity\": 5039\n  },\n  {\n    \"tag\": "Gymnoderinae",\n    \"popularity\": 5035\n  },\n  {\n    \"tag\": "testudo",\n    \"popularity\": 5031\n  },\n  {\n    \"tag\": "frigorify",\n    \"popularity\": 5027\n  },\n  {\n    \"tag\": "aliency",\n    \"popularity\": 5023\n  },\n  {\n    \"tag\": "jargon",\n    \"popularity\": 5019\n  },\n  {\n    \"tag\": "counterservice",\n    \"popularity\": 5015\n  },\n  {\n    \"tag\": "isostrychnine",\n    \"popularity\": 5011\n  },\n  {\n    \"tag\": "tellership",\n    \"popularity\": 5007\n  },\n  {\n    \"tag\": "miscegenetic",\n    \"popularity\": 5003\n  },\n  {\n    \"tag\": "sorcer",\n    \"popularity\": 4999\n  },\n  {\n    \"tag\": "tilewright",\n    \"popularity\": 4995\n  },\n  {\n    \"tag\": "cyanoplastid",\n    \"popularity\": 4991\n  },\n  {\n    \"tag\": "fluxionally",\n    \"popularity\": 4987\n  },\n  {\n    \"tag\": "proudhearted",\n    \"popularity\": 4983\n  },\n  {\n    \"tag\": "blithely",\n    \"popularity\": 4979\n  },\n  {\n    \"tag\": "jestproof",\n    \"popularity\": 4975\n  },\n  {\n    \"tag\": "jestwise",\n    \"popularity\": 4971\n  },\n  {\n    \"tag\": "nonassimilable",\n    \"popularity\": 4967\n  },\n  {\n    \"tag\": "compurgation",\n    \"popularity\": 4964\n  },\n  {\n    \"tag\": "unhate",\n    \"popularity\": 4960\n  },\n  {\n    \"tag\": "haplodonty",\n    \"popularity\": 4956\n  },\n  {\n    \"tag\": "cardholder",\n    \"popularity\": 4952\n  },\n  {\n    \"tag\": "rainlight megohmmeter overstout",\n    \"popularity\": 4948\n  },\n  {\n    \"tag\": "itchless",\n    \"popularity\": 4944\n  },\n  {\n    \"tag\": "begiggle",\n    \"popularity\": 4940\n  },\n  {\n    \"tag\": "chromatosphere",\n    \"popularity\": 4936\n  },\n  {\n    \"tag\": "typicality",\n    \"popularity\": 4932\n  },\n  {\n    \"tag\": "overgrown",\n    \"popularity\": 4928\n  },\n  {\n    \"tag\": "envolume",\n    \"popularity\": 4925\n  },\n  {\n    \"tag\": "pachycholia",\n    \"popularity\": 4921\n  },\n  {\n    \"tag\": "passageable",\n    \"popularity\": 4917\n  },\n  {\n    \"tag\": "pathopoiesis",\n    \"popularity\": 4913\n  },\n  {\n    \"tag\": "overbreak",\n    \"popularity\": 4909\n  },\n  {\n    \"tag\": "satyric",\n    \"popularity\": 4905\n  },\n  {\n    \"tag\": "unaudited",\n    \"popularity\": 4901\n  },\n  {\n    \"tag\": "whimble",\n    \"popularity\": 4898\n  },\n  {\n    \"tag\": "pressureless",\n    \"popularity\": 4894\n  },\n  {\n    \"tag\": "Selene",\n    \"popularity\": 4890\n  },\n  {\n    \"tag\": "slithery",\n    \"popularity\": 4886\n  },\n  {\n    \"tag\": "nondisfigurement",\n    \"popularity\": 4882\n  },\n  {\n    \"tag\": "overdelicious",\n    \"popularity\": 4878\n  },\n  {\n    \"tag\": "Perca",\n    \"popularity\": 4875\n  },\n  {\n    \"tag\": "Palladium",\n    \"popularity\": 4871\n  },\n  {\n    \"tag\": "insagacity",\n    \"popularity\": 4867\n  },\n  {\n    \"tag\": "peristoma",\n    \"popularity\": 4863\n  },\n  {\n    \"tag\": "uncreativeness",\n    \"popularity\": 4859\n  },\n  {\n    \"tag\": "incomparability surfboarding",\n    \"popularity\": 4856\n  },\n  {\n    \"tag\": "bacillar",\n    \"popularity\": 4852\n  },\n  {\n    \"tag\": "ulcerative",\n    \"popularity\": 4848\n  },\n  {\n    \"tag\": "stychomythia",\n    \"popularity\": 4844\n  },\n  {\n    \"tag\": "sesma somatics nonentry",\n    \"popularity\": 4840\n  },\n  {\n    \"tag\": "unsepulchred",\n    \"popularity\": 4837\n  },\n  {\n    \"tag\": "cephalanthium",\n    \"popularity\": 4833\n  },\n  {\n    \"tag\": "Asiaticization",\n    \"popularity\": 4829\n  },\n  {\n    \"tag\": "killeen",\n    \"popularity\": 4825\n  },\n  {\n    \"tag\": "Pseudococcus",\n    \"popularity\": 4822\n  },\n  {\n    \"tag\": "untractable",\n    \"popularity\": 4818\n  },\n  {\n    \"tag\": "apolegamic",\n    \"popularity\": 4814\n  },\n  {\n    \"tag\": "hyperpnea",\n    \"popularity\": 4810\n  },\n  {\n    \"tag\": "martyrolatry",\n    \"popularity\": 4807\n  },\n  {\n    \"tag\": "Sarmatic",\n    \"popularity\": 4803\n  },\n  {\n    \"tag\": "nonsurface",\n    \"popularity\": 4799\n  },\n  {\n    \"tag\": "adjoined",\n    \"popularity\": 4796\n  },\n  {\n    \"tag\": "vasiform",\n    \"popularity\": 4792\n  },\n  {\n    \"tag\": "tastelessness",\n    \"popularity\": 4788\n  },\n  {\n    \"tag\": "rumbo",\n    \"popularity\": 4784\n  },\n  {\n    \"tag\": "subdititious",\n    \"popularity\": 4781\n  },\n  {\n    \"tag\": "reparticipation",\n    \"popularity\": 4777\n  },\n  {\n    \"tag\": "Yorkshireism",\n    \"popularity\": 4773\n  },\n  {\n    \"tag\": "outcrow",\n    \"popularity\": 4770\n  },\n  {\n    \"tag\": "casserole",\n    \"popularity\": 4766\n  },\n  {\n    \"tag\": "semideltaic",\n    \"popularity\": 4762\n  },\n  {\n    \"tag\": "freemason",\n    \"popularity\": 4759\n  },\n  {\n    \"tag\": "catkin",\n    \"popularity\": 4755\n  },\n  {\n    \"tag\": "conscient",\n    \"popularity\": 4751\n  },\n  {\n    \"tag\": "reliably",\n    \"popularity\": 4748\n  },\n  {\n    \"tag\": "Telembi",\n    \"popularity\": 4744\n  },\n  {\n    \"tag\": "hide",\n    \"popularity\": 4740\n  },\n  {\n    \"tag\": "social",\n    \"popularity\": 4737\n  },\n  {\n    \"tag\": "ichneutic",\n    \"popularity\": 4733\n  },\n  {\n    \"tag\": "polypotome blouse pentagrammatic",\n    \"popularity\": 4729\n  },\n  {\n    \"tag\": "airdrome pesthole",\n    \"popularity\": 4726\n  },\n  {\n    \"tag\": "unportended",\n    \"popularity\": 4722\n  },\n  {\n    \"tag\": "sheerly",\n    \"popularity\": 4719\n  },\n  {\n    \"tag\": "acardiac",\n    \"popularity\": 4715\n  },\n  {\n    \"tag\": "fetor",\n    \"popularity\": 4711\n  },\n  {\n    \"tag\": "storax",\n    \"popularity\": 4708\n  },\n  {\n    \"tag\": "syndactylic",\n    \"popularity\": 4704\n  },\n  {\n    \"tag\": "otiatrics",\n    \"popularity\": 4700\n  },\n  {\n    \"tag\": "range",\n    \"popularity\": 4697\n  },\n  {\n    \"tag\": "branchway",\n    \"popularity\": 4693\n  },\n  {\n    \"tag\": "beatific",\n    \"popularity\": 4690\n  },\n  {\n    \"tag\": "Rugosa",\n    \"popularity\": 4686\n  },\n  {\n    \"tag\": "rafty",\n    \"popularity\": 4682\n  },\n  {\n    \"tag\": "gapy",\n    \"popularity\": 4679\n  },\n  {\n    \"tag\": "heterocercal",\n    \"popularity\": 4675\n  },\n  {\n    \"tag\": "actinopterygious",\n    \"popularity\": 4672\n  },\n  {\n    \"tag\": "glauconite",\n    \"popularity\": 4668\n  },\n  {\n    \"tag\": "limbless priest",\n    \"popularity\": 4665\n  },\n  {\n    \"tag\": "chrysene",\n    \"popularity\": 4661\n  },\n  {\n    \"tag\": "isentropic",\n    \"popularity\": 4658\n  },\n  {\n    \"tag\": "lairdess",\n    \"popularity\": 4654\n  },\n  {\n    \"tag\": "butterhead choliambic",\n    \"popularity\": 4650\n  },\n  {\n    \"tag\": "hexaseme",\n    \"popularity\": 4647\n  },\n  {\n    \"tag\": "treeify",\n    \"popularity\": 4643\n  },\n  {\n    \"tag\": "coronetted fructify",\n    \"popularity\": 4640\n  },\n  {\n    \"tag\": "admiralty",\n    \"popularity\": 4636\n  },\n  {\n    \"tag\": "Flosculariidae",\n    \"popularity\": 4633\n  },\n  {\n    \"tag\": "limaceous",\n    \"popularity\": 4629\n  },\n  {\n    \"tag\": "subterconscious",\n    \"popularity\": 4626\n  },\n  {\n    \"tag\": "stayless",\n    \"popularity\": 4622\n  },\n  {\n    \"tag\": "psha",\n    \"popularity\": 4619\n  },\n  {\n    \"tag\": "Mediterraneanize",\n    \"popularity\": 4615\n  },\n  {\n    \"tag\": "impenetrably",\n    \"popularity\": 4612\n  },\n  {\n    \"tag\": "Myrmeleonidae",\n    \"popularity\": 4608\n  },\n  {\n    \"tag\": "germander",\n    \"popularity\": 4605\n  },\n  {\n    \"tag\": "Buri",\n    \"popularity\": 4601\n  },\n  {\n    \"tag\": "papyrotamia",\n    \"popularity\": 4598\n  },\n  {\n    \"tag\": "Toxylon",\n    \"popularity\": 4594\n  },\n  {\n    \"tag\": "batatilla",\n    \"popularity\": 4591\n  },\n  {\n    \"tag\": "fabella assumer",\n    \"popularity\": 4587\n  },\n  {\n    \"tag\": "macromethod",\n    \"popularity\": 4584\n  },\n  {\n    \"tag\": "Blechnum",\n    \"popularity\": 4580\n  },\n  {\n    \"tag\": "pantography",\n    \"popularity\": 4577\n  },\n  {\n    \"tag\": "seminovel",\n    \"popularity\": 4574\n  },\n  {\n    \"tag\": "disembarrassment",\n    \"popularity\": 4570\n  },\n  {\n    \"tag\": "bushmaking",\n    \"popularity\": 4567\n  },\n  {\n    \"tag\": "neurosis",\n    \"popularity\": 4563\n  },\n  {\n    \"tag\": "Animalia",\n    \"popularity\": 4560\n  },\n  {\n    \"tag\": "Bernice",\n    \"popularity\": 4556\n  },\n  {\n    \"tag\": "wisen",\n    \"popularity\": 4553\n  },\n  {\n    \"tag\": "subhymenium",\n    \"popularity\": 4549\n  },\n  {\n    \"tag\": "esophagomycosis",\n    \"popularity\": 4546\n  },\n  {\n    \"tag\": "wireworks",\n    \"popularity\": 4543\n  },\n  {\n    \"tag\": "Sabellidae",\n    \"popularity\": 4539\n  },\n  {\n    \"tag\": "fustianish",\n    \"popularity\": 4536\n  },\n  {\n    \"tag\": "professively",\n    \"popularity\": 4532\n  },\n  {\n    \"tag\": "overcorruptly",\n    \"popularity\": 4529\n  },\n  {\n    \"tag\": "overcreep",\n    \"popularity\": 4526\n  },\n  {\n    \"tag\": "Castilloa",\n    \"popularity\": 4522\n  },\n  {\n    \"tag\": "forelady Georgie",\n    \"popularity\": 4519\n  },\n  {\n    \"tag\": "outsider",\n    \"popularity\": 4515\n  },\n  {\n    \"tag\": "Enukki",\n    \"popularity\": 4512\n  },\n  {\n    \"tag\": "gypsy",\n    \"popularity\": 4509\n  },\n  {\n    \"tag\": "Passamaquoddy",\n    \"popularity\": 4505\n  },\n  {\n    \"tag\": "reposit",\n    \"popularity\": 4502\n  },\n  {\n    \"tag\": "overtenderness",\n    \"popularity\": 4499\n  },\n  {\n    \"tag\": "keratome",\n    \"popularity\": 4495\n  },\n  {\n    \"tag\": "interclavicular hypermonosyllable Susanna",\n    \"popularity\": 4492\n  },\n  {\n    \"tag\": "mispropose",\n    \"popularity\": 4489\n  },\n  {\n    \"tag\": "Membranipora",\n    \"popularity\": 4485\n  },\n  {\n    \"tag\": "lampad",\n    \"popularity\": 4482\n  },\n  {\n    \"tag\": "header",\n    \"popularity\": 4479\n  },\n  {\n    \"tag\": "triseriate",\n    \"popularity\": 4475\n  },\n  {\n    \"tag\": "distrainment",\n    \"popularity\": 4472\n  },\n  {\n    \"tag\": "staphyloplastic",\n    \"popularity\": 4469\n  },\n  {\n    \"tag\": "outscour",\n    \"popularity\": 4465\n  },\n  {\n    \"tag\": "tallowmaking",\n    \"popularity\": 4462\n  },\n  {\n    \"tag\": "plugger",\n    \"popularity\": 4459\n  },\n  {\n    \"tag\": "fashionize",\n    \"popularity\": 4455\n  },\n  {\n    \"tag\": "puzzle",\n    \"popularity\": 4452\n  },\n  {\n    \"tag\": "imbrue",\n    \"popularity\": 4449\n  },\n  {\n    \"tag\": "osteoblast",\n    \"popularity\": 4445\n  },\n  {\n    \"tag\": "Hydrocores",\n    \"popularity\": 4442\n  },\n  {\n    \"tag\": "Lutra",\n    \"popularity\": 4439\n  },\n  {\n    \"tag\": "upridge scarfy",\n    \"popularity\": 4435\n  },\n  {\n    \"tag\": "ancon taffle",\n    \"popularity\": 4432\n  },\n  {\n    \"tag\": "impest",\n    \"popularity\": 4429\n  },\n  {\n    \"tag\": "uncollatedness",\n    \"popularity\": 4426\n  },\n  {\n    \"tag\": "hypersensitize",\n    \"popularity\": 4422\n  },\n  {\n    \"tag\": "autographically",\n    \"popularity\": 4419\n  },\n  {\n    \"tag\": "louther",\n    \"popularity\": 4416\n  },\n  {\n    \"tag\": "Ollie",\n    \"popularity\": 4413\n  },\n  {\n    \"tag\": "recompensate",\n    \"popularity\": 4409\n  },\n  {\n    \"tag\": "Shan",\n    \"popularity\": 4406\n  },\n  {\n    \"tag\": "brachycnemic",\n    \"popularity\": 4403\n  },\n  {\n    \"tag\": "Carinatae",\n    \"popularity\": 4399\n  },\n  {\n    \"tag\": "geotherm",\n    \"popularity\": 4396\n  },\n  {\n    \"tag\": "sawback",\n    \"popularity\": 4393\n  },\n  {\n    \"tag\": "Novatianist",\n    \"popularity\": 4390\n  },\n  {\n    \"tag\": "reapproach",\n    \"popularity\": 4387\n  },\n  {\n    \"tag\": "myelopoietic",\n    \"popularity\": 4383\n  },\n  {\n    \"tag\": "cyanin",\n    \"popularity\": 4380\n  },\n  {\n    \"tag\": "unsmutted",\n    \"popularity\": 4377\n  },\n  {\n    \"tag\": "nonpapist",\n    \"popularity\": 4374\n  },\n  {\n    \"tag\": "transbaikalian",\n    \"popularity\": 4370\n  },\n  {\n    \"tag\": "connately",\n    \"popularity\": 4367\n  },\n  {\n    \"tag\": "tenderize iterance",\n    \"popularity\": 4364\n  },\n  {\n    \"tag\": "hydrostatical",\n    \"popularity\": 4361\n  },\n  {\n    \"tag\": "unflag",\n    \"popularity\": 4358\n  },\n  {\n    \"tag\": "translate",\n    \"popularity\": 4354\n  },\n  {\n    \"tag\": "Scorzonera",\n    \"popularity\": 4351\n  },\n  {\n    \"tag\": "uncomforted",\n    \"popularity\": 4348\n  },\n  {\n    \"tag\": "risser varied",\n    \"popularity\": 4345\n  },\n  {\n    \"tag\": "plumbate",\n    \"popularity\": 4342\n  },\n  {\n    \"tag\": "Usneaceae",\n    \"popularity\": 4338\n  },\n  {\n    \"tag\": "fohat",\n    \"popularity\": 4335\n  },\n  {\n    \"tag\": "slagging",\n    \"popularity\": 4332\n  },\n  {\n    \"tag\": "superserious",\n    \"popularity\": 4329\n  },\n  {\n    \"tag\": "theocracy",\n    \"popularity\": 4326\n  },\n  {\n    \"tag\": "valonia",\n    \"popularity\": 4323\n  },\n  {\n    \"tag\": "Sapindales",\n    \"popularity\": 4319\n  },\n  {\n    \"tag\": "palaeozoologist",\n    \"popularity\": 4316\n  },\n  {\n    \"tag\": "yalb",\n    \"popularity\": 4313\n  },\n  {\n    \"tag\": "unviewed",\n    \"popularity\": 4310\n  },\n  {\n    \"tag\": "polyarteritis",\n    \"popularity\": 4307\n  },\n  {\n    \"tag\": "vectorial",\n    \"popularity\": 4304\n  },\n  {\n    \"tag\": "skimpingly",\n    \"popularity\": 4301\n  },\n  {\n    \"tag\": "athort",\n    \"popularity\": 4297\n  },\n  {\n    \"tag\": "tribofluorescence",\n    \"popularity\": 4294\n  },\n  {\n    \"tag\": "benzonitrol",\n    \"popularity\": 4291\n  },\n  {\n    \"tag\": "swiller subobtuse subjacency",\n    \"popularity\": 4288\n  },\n  {\n    \"tag\": "uncompassed",\n    \"popularity\": 4285\n  },\n  {\n    \"tag\": "cacochymia",\n    \"popularity\": 4282\n  },\n  {\n    \"tag\": "commensalist butadiene",\n    \"popularity\": 4279\n  },\n  {\n    \"tag\": "culpable",\n    \"popularity\": 4276\n  },\n  {\n    \"tag\": "contributive",\n    \"popularity\": 4273\n  },\n  {\n    \"tag\": "attemperately",\n    \"popularity\": 4269\n  },\n  {\n    \"tag\": "spelt",\n    \"popularity\": 4266\n  },\n  {\n    \"tag\": "exoneration",\n    \"popularity\": 4263\n  },\n  {\n    \"tag\": "antivivisectionist",\n    \"popularity\": 4260\n  },\n  {\n    \"tag\": "granitification",\n    \"popularity\": 4257\n  },\n  {\n    \"tag\": "palladize",\n    \"popularity\": 4254\n  },\n  {\n    \"tag\": "marksmanship",\n    \"popularity\": 4251\n  },\n  {\n    \"tag\": "bullydom",\n    \"popularity\": 4248\n  },\n  {\n    \"tag\": "spirality",\n    \"popularity\": 4245\n  },\n  {\n    \"tag\": "caliginous",\n    \"popularity\": 4242\n  },\n  {\n    \"tag\": "reportedly",\n    \"popularity\": 4239\n  },\n  {\n    \"tag\": "polyad",\n    \"popularity\": 4236\n  },\n  {\n    \"tag\": "arthroempyesis",\n    \"popularity\": 4233\n  },\n  {\n    \"tag\": "semibay facultatively",\n    \"popularity\": 4229\n  },\n  {\n    \"tag\": "metastatically",\n    \"popularity\": 4226\n  },\n  {\n    \"tag\": "prophetically",\n    \"popularity\": 4223\n  },\n  {\n    \"tag\": "Linguatula elapid",\n    \"popularity\": 4220\n  },\n  {\n    \"tag\": "pyknatom",\n    \"popularity\": 4217\n  },\n  {\n    \"tag\": "centimeter",\n    \"popularity\": 4214\n  },\n  {\n    \"tag\": "mensurate",\n    \"popularity\": 4211\n  },\n  {\n    \"tag\": "migraine",\n    \"popularity\": 4208\n  },\n  {\n    \"tag\": "pentagamist",\n    \"popularity\": 4205\n  },\n  {\n    \"tag\": "querken",\n    \"popularity\": 4202\n  },\n  {\n    \"tag\": "ambulance",\n    \"popularity\": 4199\n  },\n  {\n    \"tag\": "Stokavian",\n    \"popularity\": 4196\n  },\n  {\n    \"tag\": "malvasian",\n    \"popularity\": 4193\n  },\n  {\n    \"tag\": "uncouthsome",\n    \"popularity\": 4190\n  },\n  {\n    \"tag\": "readable",\n    \"popularity\": 4187\n  },\n  {\n    \"tag\": "enlodge",\n    \"popularity\": 4184\n  },\n  {\n    \"tag\": "plasterwise Appendiculariidae perspectograph",\n    \"popularity\": 4181\n  },\n  {\n    \"tag\": "inkweed",\n    \"popularity\": 4178\n  },\n  {\n    \"tag\": "streep",\n    \"popularity\": 4175\n  },\n  {\n    \"tag\": "diadelphian cultured",\n    \"popularity\": 4172\n  },\n  {\n    \"tag\": "hymenopterous",\n    \"popularity\": 4169\n  },\n  {\n    \"tag\": "unexorableness",\n    \"popularity\": 4166\n  },\n  {\n    \"tag\": "cascaron",\n    \"popularity\": 4163\n  },\n  {\n    \"tag\": "undaintiness",\n    \"popularity\": 4160\n  },\n  {\n    \"tag\": "Curtana",\n    \"popularity\": 4157\n  },\n  {\n    \"tag\": "scurvied",\n    \"popularity\": 4154\n  },\n  {\n    \"tag\": "molluscoidal",\n    \"popularity\": 4151\n  },\n  {\n    \"tag\": "yurt",\n    \"popularity\": 4148\n  },\n  {\n    \"tag\": "deciduitis",\n    \"popularity\": 4145\n  },\n  {\n    \"tag\": "creephole",\n    \"popularity\": 4142\n  },\n  {\n    \"tag\": "quatrefeuille",\n    \"popularity\": 4139\n  },\n  {\n    \"tag\": "bicapitate adenomatome",\n    \"popularity\": 4136\n  },\n  {\n    \"tag\": "damassin",\n    \"popularity\": 4134\n  },\n  {\n    \"tag\": "planching",\n    \"popularity\": 4131\n  },\n  {\n    \"tag\": "dashedly inferential",\n    \"popularity\": 4128\n  },\n  {\n    \"tag\": "lobe",\n    \"popularity\": 4125\n  },\n  {\n    \"tag\": "Hyrachyus",\n    \"popularity\": 4122\n  },\n  {\n    \"tag\": "knab",\n    \"popularity\": 4119\n  },\n  {\n    \"tag\": "discohexaster",\n    \"popularity\": 4116\n  },\n  {\n    \"tag\": "malign",\n    \"popularity\": 4113\n  },\n  {\n    \"tag\": "pedagoguism",\n    \"popularity\": 4110\n  },\n  {\n    \"tag\": "shrubbery",\n    \"popularity\": 4107\n  },\n  {\n    \"tag\": "undershrub",\n    \"popularity\": 4104\n  },\n  {\n    \"tag\": "bureaucrat",\n    \"popularity\": 4101\n  },\n  {\n    \"tag\": "pantaleon",\n    \"popularity\": 4098\n  },\n  {\n    \"tag\": "mesoventral",\n    \"popularity\": 4096\n  }]';
+
+var log2 = Math.log(2);
+var tagInfo = tagInfoJSON.parseJSON(function(a, b) { if (a == "popularity") { return Math.log(b) / log2; } else {return b; } });
+
+function makeTagCloud(tagInfo)
+{
+    var output = '<div class="tagCloud" style="width: 100%">';
+
+    tagInfo.sort(function(a, b) { if (a.tag < b.tag) { return -1; } else if (a.tag == b.tag) { return 0; } else return 1; });
+
+    for (var i = 0; i < tagInfo.length; i++) {
+        var tag = tagInfo[i].tag;
+
+        var validates = true;
+        for (var j = 0; j < tag.length; j++) {
+            var ch = tag.charCodeAt(j);
+            if (ch < 0x20 || ch >= 0x7f) {
+                validates = false;
+                break;
+            }
+        }
+
+        if (!validates)
+            continue;
+
+        var url = "http://example.com/tag/" + tag.replace(" ", "").toLowerCase();
+        var popularity = tagInfo[i].popularity;
+        var color = 'rgb(' + Math.floor(255 * (popularity - 12) / 20) + ', 0, 255)';
+        output += ' <a href="' + url + '" style="font-size: ' + popularity + 'px; color: ' + color + '">' + tag + '</a> \n';
+    }
+
+    output += '</div>';
+    output.replace(" ", "&nbsp;");
+
+    return output;
+}
+
+var tagcloud = makeTagCloud(tagInfo);
+tagInfo = null;
+
+
+var _sunSpiderInterval = new Date() - _sunSpiderStartDate;
+
+document.getElementById("console").innerHTML = _sunSpiderInterval;
+</script>
+
+
+</body>
+</html>
diff --git a/src/third_party/mozjs-45/build/pgo/js-input/sunspider/string-unpack-code.html b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/string-unpack-code.html
new file mode 100644
index 0000000..ba80c99
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/string-unpack-code.html
@@ -0,0 +1,117 @@
+<!DOCTYPE html>
+<head>
+<!--
+ Copyright (C) 2007 Apple Inc.  All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+-->
+
+<title>SunSpider string-unpack-code</title>
+
+</head>
+
+<body>
+<h3>string-unpack-code</h3>
+<div id="console">
+</div>
+
+<script>
+
+var _sunSpiderStartDate = new Date();
+
+// This test case unpacks the compressed code for the MochiKit,
+// jQuery, Dojo and Prototype JavaScript libraries.
+
+/***
+    MochiKit.MochiKit 1.3.1 : PACKED VERSION
+    THIS FILE IS AUTOMATICALLY GENERATED.  If creating patches, please
+    diff against the source tree, not this file.
+
+    See <http://mochikit.com/> for documentation, downloads, license, etc.
+
+    (c) 2005 Bob Ippolito.  All rights Reserved.
+***/
+
+for (var i = 0; i < 2; i++) {
+
+var decompressedMochiKit = function(p,a,c,k,e,d){e=function(c){return(c<a?"":e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)d[e(c)]=k[c]||e(c);k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('if(H(1q)!="L"){1q.2X("B.J")}if(H(B)=="L"){B={}}if(H(B.J)=="L"){B.J={}}B.J.1Y="1.3.1";B.J.1r="B.J";B.J.2l=G(7V,vR){if(7V===O){7V={}}R(u i=1;i<M.K;i++){u o=M[i];if(H(o)!="L"&&o!==O){R(u k in o){7V[k]=o[k]}}}F 7V};B.J.2l(B.J,{1K:G(){F"["+D.1r+" "+D.1Y+"]"},1l:G(){F D.1K()},4f:G(n){if(M.K===0){n=1}F G(){F n++}},4L:G(mw){u me=M.2U;if(M.K==1){me.1U=mw;F Y me()}},bg:G(vQ){u X=[];u m=B.J;u aw=m.1R(O,M);1M(aw.K){u o=aw.2P();if(o&&H(o)=="3n"&&H(o.K)=="2y"){R(u i=o.K-1;i>=0;i--){aw.e9(o[i])}}N{X.1c(o)}}F X},1R:G(7U,1i,av){if(!av){av=0}if(1i){u l=1i.K;if(H(l)!="2y"){if(H(B.15)!="L"){1i=B.15.2G(1i);l=1i.K}N{14 Y 3p("au 2E an at-as 3W B.15 2E ar")}}if(!7U){7U=[]}R(u i=av;i<l;i++){7U.1c(1i[i])}}F 7U},8Z:G(5g,1i){if(5g===O){5g={}}R(u i=1;i<M.K;i++){u o=M[i];if(H(o)!="L"&&o!==O){R(u k in o){u v=o[k];if(H(5g[k])=="3n"&&H(v)=="3n"){M.2U(5g[k],v)}N{5g[k]=v}}}}F 5g},lO:G(6c,1i){if(6c===O){6c={}}R(u i=1;i<M.K;i++){u o=M[i];R(u k in o){if(!(k in 6c)){6c[k]=o[k]}}}F 6c},lN:G(1i){u fj=[];R(u mv in 1i){fj.1c(mv)}F fj},lM:G(1i){u fh=[];u e;R(u fi in 1i){u v;1f{v=1i[fi]}1e(e){2V}fh.1c([fi,v])}F fh},jq:G(fg,ff,fe){fe.1U=Y B.J.5a(fg.1r+"."+ff);fg[ff]=fe},4i:{7L:G(a){F!!a},vP:G(a){F!a},eE:G(a){F a},2E:G(a){F~a},vO:G(a){F-a},vN:G(a,b){F a+b},vM:G(a,b){F a-b},4u:G(a,b){F a/b},vL:G(a,b){F a%b},vK:G(a,b){F a*b},3W:G(a,b){F a&b},or:G(a,b){F a|b},vJ:G(a,b){F a^b},vI:G(a,b){F a<<b},vH:G(a,b){F a>>b},vG:G(a,b){F a>>>b},eq:G(a,b){F a==b},ne:G(a,b){F a!=b},gt:G(a,b){F a>b},ge:G(a,b){F a>=b},lt:G(a,b){F a<b},le:G(a,b){F a<=b},vF:G(a,b){F B.J.2f(a,b)===0},vE:G(a,b){F B.J.2f(a,b)!==0},vD:G(a,b){F B.J.2f(a,b)==1},vC:G(a,b){F B.J.2f(a,b)!=-1},vB:G(a,b){F B.J.2f(a,b)==-1},vA:G(a,b){F B.J.2f(a,b)!=1},vz:G(a,b){F a&&b},vy:G(a,b){F a||b},vx:G(a,b){F b in a}},24:G(mu){F G(){F D[mu].1w(D,M)}},lL:G(mt){F G(a9){F a9[mt]}},66:G(){u fd={};R(u i=0;i<M.K;i++){u 6b=M[i];fd[6b]=6b}F G(){R(u i=0;i<M.K;i++){if(!(H(M[i])in fd)){F 1m}}F 1h}},lJ:G(){R(u i=0;i<M.K;i++){if(M[i]!==O){F 1m}}F 1h},lK:G(){R(u i=0;i<M.K;i++){u o=M[i];if(!(H(o)=="L"||o===O)){F 1m}}F 1h},lI:G(1i){F!B.J.7e.1w(D,M)},7e:G(1i){R(u i=0;i<M.K;i++){u o=M[i];if(!(o&&o.K)){F 1m}}F 1h},3A:G(){R(u i=0;i<M.K;i++){u o=M[i];u 6b=H(o);if((6b!="3n"&&!(6b=="G"&&H(o.vw)=="G"))||o===O||H(o.K)!="2y"){F 1m}}F 1h},eN:G(){R(u i=0;i<M.K;i++){u o=M[i];if(H(o)!="3n"||o===O||H(o.9P)!="G"){F 1m}}F 1h},lH:G(fn){if(fn===O){F B.J.1R(O,M,1)}u fc=[];R(u i=1;i<M.K;i++){fc.1c(fn(M[i]))}F fc},2r:G(fn,1g){u m=B.J;u 6a=B.15;u fb=m.3A;if(M.K<=2){if(!fb(1g)){if(6a){1g=6a.2G(1g);if(fn===O){F 1g}}N{14 Y 3p("au 2E an at-as 3W B.15 2E ar")}}if(fn===O){F m.1R(O,1g)}u 69=[];R(u i=0;i<1g.K;i++){69.1c(fn(1g[i]))}F 69}N{if(fn===O){fn=7o}u 7T=O;R(i=1;i<M.K;i++){if(!fb(M[i])){if(6a){F 6a.2G(6a.4c.1w(O,M))}N{14 Y 3p("au 2E an at-as 3W B.15 2E ar")}}u l=M[i].K;if(7T===O||7T>l){7T=l}}69=[];R(i=0;i<7T;i++){u fa=[];R(u j=1;j<M.K;j++){fa.1c(M[j][i])}69.1c(fn.1w(D,fa))}F 69}},lG:G(fn){u f9=[];if(fn===O){fn=B.J.4i.7L}R(u i=1;i<M.K;i++){u o=M[i];if(fn(o)){f9.1c(o)}}F f9},47:G(fn,1g,7S){u aq=[];u m=B.J;if(!m.3A(1g)){if(B.15){1g=B.15.2G(1g)}N{14 Y 3p("au 2E an at-as 3W B.15 2E ar")}}if(fn===O){fn=m.4i.7L}if(H(7o.1U.47)=="G"){F 7o.1U.47.cz(1g,fn,7S)}N{if(H(7S)=="L"||7S===O){R(u i=0;i<1g.K;i++){u o=1g[i];if(fn(o)){aq.1c(o)}}}N{R(i=0;i<1g.K;i++){o=1g[i];if(fn.cz(7S,o)){aq.1c(o)}}}}F aq},mq:G(7R){F G(){hd(M.K){3j 0:F 7R();3j 1:F 7R(M[0]);3j 2:F 7R(M[0],M[1]);3j 3:F 7R(M[0],M[1],M[2])}u f8=[];R(u i=0;i<M.K;i++){f8.1c("M["+i+"]")}F dB("(1A("+f8.2b(",")+"))")}},lv:G(mr,ms){u m=B.J;F m.1O.1w(D,m.1R([ms,mr],M,2))},1O:G(3c,4o){if(H(3c)=="1n"){3c=4o[3c]}u ao=3c.f5;u 5f=3c.am;u f6=3c.f7;u m=B.J;if(H(3c)=="G"&&H(3c.1w)=="L"){3c=m.mq(3c)}if(H(ao)!="G"){ao=3c}if(H(4o)!="L"){f6=4o}if(H(5f)=="L"){5f=[]}N{5f=5f.9T()}m.1R(5f,M,2);u 7Q=G(){u ap=M;u me=M.2U;if(me.am.K>0){ap=m.2o(me.am,ap)}u 4o=me.f7;if(!4o){4o=D}F me.f5.1w(4o,ap)};7Q.f7=f6;7Q.f5=ao;7Q.am=5f;F 7Q},lF:G(7P){u mp=B.J.1O;R(u k in 7P){u f4=7P[k];if(H(f4)=="G"){7P[k]=mp(f4,7P)}}},5u:G(mo,mn,ml,mk){B.J.ae.5M(mo,mn,ml,mk)},mj:{"5L":1h,"1n":1h,"2y":1h},2f:G(a,b){if(a==b){F 0}u f3=(H(a)=="L"||a===O);u f2=(H(b)=="L"||b===O);if(f3&&f2){F 0}N{if(f3){F-1}N{if(f2){F 1}}}u m=B.J;u f1=m.mj;if(!(H(a)in f1&&H(b)in f1)){1f{F m.ae.3C(a,b)}1e(e){if(e!=m.4d){14 e}}}if(a<b){F-1}N{if(a>b){F 1}}u f0=m.U;14 Y 3p(f0(a)+" 3W "+f0(b)+" 9v 2E be vv")},eM:G(a,b){F B.J.2f(a.9P(),b.9P())},eL:G(a,b){u mi=B.J.2f;u 7O=a.K;u al=0;if(7O>b.K){al=1;7O=b.K}N{if(7O<b.K){al=-1}}R(u i=0;i<7O;i++){u 4j=mi(a[i],b[i]);if(4j){F 4j}}F al},7M:G(mh,mg,mf,md){B.J.ad.5M(mh,mg,mf,md)},U:G(o){if(H(o)=="L"){F"L"}N{if(o===O){F"O"}}1f{if(H(o.1K)=="G"){F o.1K()}N{if(H(o.U)=="G"&&o.U!=M.2U){F o.U()}}F B.J.ad.3C(o)}1e(e){if(H(o.1r)=="1n"&&(o.1l==cZ.1U.1l||o.1l==vu.1U.1l)){F o.1r}}1f{u eZ=(o+"")}1e(e){F"["+H(o)+"]"}if(H(o)=="G"){o=eZ.23(/^\\s+/,"");u 5n=o.2A("{");if(5n!=-1){o=o.3H(0,5n)+"{...}"}}F eZ},eK:G(o){u m=B.J;F"["+m.2r(m.U,o).2b(", ")+"]"},ac:G(o){F("\\""+o.23(/(["\\\\])/g,"\\\\$1")+"\\"").23(/[\\f]/g,"\\\\f").23(/[\\b]/g,"\\\\b").23(/[\\n]/g,"\\\\n").23(/[\\t]/g,"\\\\t").23(/[\\r]/g,"\\\\r")},eJ:G(o){F o+""},ly:G(mc,mb,ma,m9){B.J.ab.5M(mc,mb,ma,m9)},lx:G(){F dB("("+M[0]+")")},lz:G(o){u 5e=H(o);if(5e=="L"){F"L"}N{if(5e=="2y"||5e=="5L"){F o+""}N{if(o===O){F"O"}}}u m=B.J;u eY=m.ac;if(5e=="1n"){F eY(o)}u me=M.2U;u 3S;if(H(o.m8)=="G"){3S=o.m8();if(o!==3S){F me(3S)}}if(H(o.m7)=="G"){3S=o.m7();if(o!==3S){F me(3S)}}if(5e!="G"&&H(o.K)=="2y"){u X=[];R(u i=0;i<o.K;i++){u 2i=me(o[i]);if(H(2i)!="1n"){2i="L"}X.1c(2i)}F"["+X.2b(", ")+"]"}1f{3S=m.ab.3C(o);F me(3S)}1e(e){if(e!=m.4d){14 e}}if(5e=="G"){F O}X=[];R(u k in o){u ak;if(H(k)=="2y"){ak="\\""+k+"\\""}N{if(H(k)=="1n"){ak=eY(k)}N{2V}}2i=me(o[k]);if(H(2i)!="1n"){2V}X.1c(ak+":"+2i)}F"{"+X.2b(", ")+"}"},lE:G(a,b){F(B.J.2f(a,b)===0)},lD:G(eX,4n){if(eX.K!=4n.K){F 1m}F(B.J.2f(eX,4n)===0)},2o:G(){u eW=[];u m6=B.J.1R;R(u i=0;i<M.K;i++){m6(eW,M[i])}F eW},eR:G(2h){u m=B.J;u eU=m.2f;if(M.K==1){F G(a,b){F eU(a[2h],b[2h])}}u eV=m.1R(O,M);F G(a,b){u aj=0;R(u i=0;(aj===0)&&(i<eV.K);i++){u 2h=eV[i];aj=eU(a[2h],b[2h])}F aj}},lC:G(2h){u m5=B.J.eR.1w(D,M);F G(a,b){F m5(b,a)}},2z:G(m4){u m=B.J;F m.1O.1w(D,m.1R([m4,L],M,1))},67:G(m0,1g){if(1g.K===0){F O}u ai=1g[0];u m3=B.J.2f;R(u i=1;i<1g.K;i++){u o=1g[i];if(m3(o,ai)==m0){ai=o}}F ai},lB:G(){F B.J.67(1,M)},lA:G(){F B.J.67(-1,M)},bi:G(1g,lY,lZ,3B){if(H(3B)=="L"||3B===O){3B=1g.K}R(u i=(lZ||0);i<3B;i++){if(1g[i]===lY){F i}}F-1},eO:G(1g,lW,lX,3B){if(H(3B)=="L"||3B===O){3B=1g.K}u 4j=B.J.2f;R(u i=(lX||0);i<3B;i++){if(4j(1g[i],lW)===0){F i}}F-1},d4:G(1j,lV){u ah=[1j];u lU=B.J.1R;1M(ah.K){u X=lV(ah.2P());if(X){lU(ah,X)}}},3f:G(ag){u 2w=ag.1r;if(H(2w)=="L"){2w=""}N{2w=2w+"."}R(u 1b in ag){u o=ag[1b];if(H(o)=="G"&&H(o.1r)=="L"){1f{o.1r=2w+1b}1e(e){}}}},dw:G(3s,68){if(H(B.S)!="L"&&M.K==1&&(H(3s)=="1n"||(H(3s.3T)!="L"&&3s.3T>0))){u kv=B.S.d5(3s);3s=kv[0];68=kv[1]}N{if(M.K==1){u o=3s;3s=[];68=[];R(u k in o){u v=o[k];if(H(v)!="G"){3s.1c(k);68.1c(v)}}}}u W=[];u lT=28.2a(3s.K,68.K);u eT=B.J.af;R(u i=0;i<lT;i++){v=68[i];if(H(v)!="L"&&v!==O){W.1c(eT(3s[i])+"="+eT(v))}}F W.2b("&")},lw:G(lS,lQ){u 7N=lS.23(/\\+/g,"%20").2R("&");u o={};u 5d;if(H(lR)!="L"){5d=lR}N{5d=vt}if(lQ){R(u i=0;i<7N.K;i++){u 2n=7N[i].2R("=");u 1b=5d(2n[0]);u 4n=o[1b];if(!(4n 2C 7o)){4n=[];o[1b]=4n}4n.1c(5d(2n[1]))}}N{R(i=0;i<7N.K;i++){2n=7N[i].2R("=");o[5d(2n[0])]=5d(2n[1])}}F o}});B.J.4a=G(){D.4m=[]};B.J.4a.1U={5M:G(1b,eS,3y,lP){if(lP){D.4m.e9([1b,eS,3y])}N{D.4m.1c([1b,eS,3y])}},3C:G(){R(u i=0;i<D.4m.K;i++){u 2n=D.4m[i];if(2n[1].1w(D,M)){F 2n[2].1w(D,M)}}14 B.J.4d},vs:G(1b){R(u i=0;i<D.4m.K;i++){u 2n=D.4m[i];if(2n[0]==1b){D.4m.4y(i,1);F 1h}}F 1m}};B.J.1z=["4f","4L","1R","2l","8Z","lO","lN","lM","5a","4i","24","lL","66","lo","ln","lK","lJ","lI","7e","3A","eN","lH","2r","lG","47","1O","lF","4d","4a","5u","2f","7M","U","lE","lD","2o","eR","lC","2z","lm","67","lp","eI","lB","lA","d4","ll","af","dw","lz","ly","lx","lw","eO","bi","bg","lv"];B.J.1W=["3f","ae","ad","ab","eM","eL","eK","ac","eJ"];B.J.2Y=G(lu,eP){if(H(B.eQ)=="L"){B.eQ=(B.3d||(H(1x)=="L"&&H(1q)=="L"))}if(!B.eQ){F}u 1p=eP.2k[":1p"];R(u i=0;i<1p.K;i++){lu[1p[i]]=eP[1p[i]]}};B.J.2d=G(){u m=D;m.vr=m.24;m.vq=m.eO;if(H(ls)!="L"){m.af=G(lr){F ls(lr).23(/\\\'/g,"%27")}}N{m.af=G(lq){F vp(lq).23(/\\+/g,"%2B").23(/\\"/g,"%22").W.23(/\\\'/g,"%27")}}m.5a=G(1b){D.43=1b;D.1b=1b};m.5a.1U=Y 2x();m.2l(m.5a.1U,{U:G(){if(D.43&&D.43!=D.1b){F D.1b+"("+m.U(D.43)+")"}N{F D.1b+"()"}},1l:m.24("U")});m.4d=Y m.5a("B.J.4d");m.lp=m.2z(m.67,1);m.eI=m.2z(m.67,-1);m.lo=m.66("G");m.ln=m.66("L");m.lm=m.2z(m.2l,O);m.ll=m.2z(m.2r,O);m.ae=Y m.4a();m.5u("vo",m.eN,m.eM);m.5u("ej",m.3A,m.eL);m.ad=Y m.4a();m.7M("ej",m.3A,m.eK);m.7M("1n",m.66("1n"),m.ac);m.7M("vn",m.66("2y","5L"),m.eJ);m.ab=Y m.4a();u 1p=m.2o(m.1z,m.1W);m.2k={":3e":m.2o(m.1W),":1p":1p};m.3f(D)};B.J.2d();if(!B.3d){2f=B.J.2f}B.J.2Y(D,B.J);if(H(1q)!="L"){1q.2X("B.15");1q.2M("B.J")}if(H(1x)!="L"){1x.26("B.J",[])}1f{if(H(B.J)=="L"){14""}}1e(e){14"B.15 3F on B.J!"}if(H(B.15)=="L"){B.15={}}B.15.1r="B.15";B.15.1Y="1.3.1";B.J.2l(B.15,{1K:G(){F"["+D.1r+" "+D.1Y+"]"},1l:G(){F D.1K()},9W:G(1b,lk,lj,lh){B.15.9Y.5M(1b,lk,lj,lh)},1Q:G(3R,lg){u I=B.15;if(M.K==2){F I.9Z(G(a){F a!=lg},3R)}if(H(3R.1a)=="G"){F 3R}N{if(H(3R.1Q)=="G"){F 3R.1Q()}}1f{F I.9Y.3C(3R)}1e(e){u m=B.J;if(e==m.4d){e=Y 3p(H(3R)+": "+m.U(3R)+" is 2E vm")}14 e}},eu:G(n){if(!n){n=0}u m=B.J;F{U:G(){F"eu("+n+")"},1l:m.24("U"),1a:m.4f(n)}},et:G(p){u I=B.15;u m=B.J;u 1g=[];u lf=I.1Q(p);F{U:G(){F"et(...)"},1l:m.24("U"),1a:G(){1f{u W=lf.1a();1g.1c(W);F W}1e(e){if(e!=I.25){14 e}if(1g.K===0){D.1a=G(){14 I.25}}N{u i=-1;D.1a=G(){i=(i+1)%1g.K;F 1g[i]}}F D.1a()}}}},7b:G(Q,n){u m=B.J;if(H(n)=="L"){F{U:G(){F"7b("+m.U(Q)+")"},1l:m.24("U"),1a:G(){F Q}}}F{U:G(){F"7b("+m.U(Q)+", "+n+")"},1l:m.24("U"),1a:G(){if(n<=0){14 B.15.25}n-=1;F Q}}},1a:G(ld){F ld.1a()},es:G(p,q){u m=B.J;u 1a=B.15.1a;u lc=m.2r(1Q,M);F{U:G(){F"es(...)"},1l:m.24("U"),1a:G(){F m.2r(1a,lc)}}},a1:G(3b,1V){u m=B.J;1V=B.15.1Q(1V);if(3b===O){3b=m.4i.7L}F{U:G(){F"a1(...)"},1l:m.24("U"),1a:G(){1M(1h){u W=1V.1a();if(3b(W)){F W}}F L}}},a0:G(3b,1V){u m=B.J;1V=B.15.1Q(1V);if(3b===O){3b=m.4i.7L}F{U:G(){F"a0(...)"},1l:m.24("U"),1a:G(){1M(1h){u W=1V.1a();if(!3b(W)){F W}}F L}}},er:G(1V){u I=B.15;u m=B.J;1V=I.1Q(1V);u 5c=0;u 2J=0;u 3a=1;u i=-1;if(M.K==2){2J=M[1]}N{if(M.K==3){5c=M[1];2J=M[2]}N{5c=M[1];2J=M[2];3a=M[3]}}F{U:G(){F"er("+["...",5c,2J,3a].2b(", ")+")"},1l:m.24("U"),1a:G(){u W;1M(i<5c){W=1V.1a();i++}if(5c>=2J){14 I.25}5c+=3a;F W}}},4c:G(aa,p,q){u m=B.J;u I=B.15;u lb=m.2r(I.1Q,m.1R(O,M,1));u 2r=m.2r;u 1a=I.1a;F{U:G(){F"4c(...)"},1l:m.24("U"),1a:G(){F aa.1w(D,2r(1a,lb))}}},ep:G(aa,1V,I){1V=B.15.1Q(1V);u m=B.J;F{U:G(){F"ep(...)"},1l:m.24("U"),1a:G(){F aa.1w(I,1V.1a())}}},55:G(p,q){u I=B.15;u m=B.J;if(M.K==1){F I.1Q(M[0])}u 64=m.2r(I.1Q,M);F{U:G(){F"55(...)"},1l:m.24("U"),1a:G(){1M(64.K>1){1f{F 64[0].1a()}1e(e){if(e!=I.25){14 e}64.2P()}}if(64.K==1){u a9=64.2P();D.1a=m.1O("1a",a9);F D.1a()}14 I.25}}},9Z:G(3b,1V){u I=B.15;1V=I.1Q(1V);F{U:G(){F"9Z(...)"},1l:B.J.24("U"),1a:G(){u W=1V.1a();if(!3b(W)){D.1a=G(){14 I.25};D.1a()}F W}}},eo:G(3b,1V){1V=B.15.1Q(1V);u m=B.J;u 1O=m.1O;F{"U":G(){F"eo(...)"},"1l":m.24("U"),"1a":G(){1M(1h){u W=1V.1a();if(!3b(W)){2K}}D.1a=1O("1a",1V);F W}}},a7:G(63,2u,la){2u.62[63]=-1;u m=B.J;u l9=m.eI;F{U:G(){F"en("+63+", ...)"},1l:m.24("U"),1a:G(){u W;u i=2u.62[63];if(i==2u.29){W=la.1a();2u.a8.1c(W);2u.29+=1;2u.62[63]+=1}N{W=2u.a8[i-2u.2a];2u.62[63]+=1;if(i==2u.2a&&l9(2u.62)!=2u.2a){2u.2a+=1;2u.a8.2P()}}F W}}},en:G(a6,n){u W=[];u 2u={"62":[],"a8":[],"29":-1,"2a":-1};if(M.K==1){n=2}u I=B.15;a6=I.1Q(a6);u a7=I.a7;R(u i=0;i<n;i++){W.1c(a7(i,2u,a6))}F W},2G:G(4l){u m=B.J;if(H(4l.9T)=="G"){F 4l.9T()}N{if(m.3A(4l)){F m.2o(4l)}}u I=B.15;4l=I.1Q(4l);u W=[];1f{1M(1h){W.1c(4l.1a())}}1e(e){if(e!=I.25){14 e}F W}F L},7H:G(fn,7K,l8){u i=0;u x=l8;u I=B.15;7K=I.1Q(7K);if(M.K<3){1f{x=7K.1a()}1e(e){if(e==I.25){e=Y 3p("7H() of vl vk vj no vi 3m")}14 e}i++}1f{1M(1h){x=fn(x,7K.1a())}}1e(e){if(e!=I.25){14 e}}F x},7I:G(){u 4k=0;u 2J=0;u 3a=1;if(M.K==1){2J=M[0]}N{if(M.K==2){4k=M[0];2J=M[1]}N{if(M.K==3){4k=M[0];2J=M[1];3a=M[2]}N{14 Y 3p("7I() vh 1, 2, or 3 M!")}}}if(3a===0){14 Y 3p("7I() 3a 5p 2E be 0")}F{1a:G(){if((3a>0&&4k>=2J)||(3a<0&&4k<=2J)){14 B.15.25}u W=4k;4k+=3a;F W},U:G(){F"7I("+[4k,2J,3a].2b(", ")+")"},1l:B.J.24("U")}},l0:G(a5,l7){u x=l7||0;u I=B.15;a5=I.1Q(a5);1f{1M(1h){x+=a5.1a()}}1e(e){if(e!=I.25){14 e}}F x},em:G(a4){u I=B.15;a4=I.1Q(a4);1f{1M(1h){a4.1a()}}1e(e){if(e!=I.25){14 e}}},9a:G(7J,1A,I){u m=B.J;if(M.K>2){1A=m.1O(1A,I)}if(m.3A(7J)){1f{R(u i=0;i<7J.K;i++){1A(7J[i])}}1e(e){if(e!=B.15.25){14 e}}}N{I=B.15;I.em(I.4c(1A,7J))}},kZ:G(l6,1A){u I=B.15;1f{I.a0(1A,l6).1a();F 1m}1e(e){if(e!=I.25){14 e}F 1h}},kY:G(l5,4j){u W=B.15.2G(l5);if(M.K==1){4j=B.J.2f}W.iz(4j);F W},kX:G(l4){u W=B.15.2G(l4);W.vg();F W},kW:G(l3,1A){u I=B.15;1f{I.a1(1A,l3).1a();F 1h}1e(e){if(e!=I.25){14 e}F 1m}},kV:G(1g,5b){if(B.J.3A(5b)){R(u i=0;i<5b.K;i++){1g.1c(5b[i])}}N{u I=B.15;5b=I.1Q(5b);1f{1M(1h){1g.1c(5b.1a())}}1e(e){if(e!=I.25){14 e}}}F 1g},ek:G(a3,eH){u m=B.J;u I=B.15;if(M.K<2){eH=m.4i.eE}a3=I.1Q(a3);u pk=L;u k=L;u v;G eF(){v=a3.1a();k=eH(v)}G l2(){u 7j=v;v=L;F 7j}u eG=1h;F{U:G(){F"ek(...)"},1a:G(){1M(k==pk){eF();if(eG){eG=1m;2K}}pk=k;F[k,{1a:G(){if(v==L){eF()}if(k!=pk){14 I.25}F l2()}}]}}},kU:G(a2,eD){u m=B.J;u I=B.15;if(M.K<2){eD=m.4i.eE}a2=I.1Q(a2);u ey=[];u eA=1h;u ez;1M(1h){1f{u eB=a2.1a();u 2h=eD(eB)}1e(e){if(e==I.25){2K}14 e}if(eA||2h!=ez){u eC=[];ey.1c([2h,eC])}eC.1c(eB);eA=1m;ez=2h}F ey},9X:G(ex){u i=0;F{U:G(){F"9X(...)"},1l:B.J.24("U"),1a:G(){if(i>=ex.K){14 B.15.25}F ex[i++]}}},eh:G(ew){F(ew&&H(ew.ei)=="G")},9V:G(l1){F{U:G(){F"9V(...)"},1l:B.J.24("U"),1a:G(){u W=l1.ei();if(W===O||W===L){14 B.15.25}F W}}}});B.15.1W=["9Y","9X","eh","9V",];B.15.1z=["25","9W","1Q","eu","et","7b","1a","es","a1","a0","er","4c","ep","55","9Z","eo","en","2G","7H","7I","l0","em","9a","kZ","kY","kX","kW","kV","ek","kU"];B.15.2d=G(){u m=B.J;D.25=Y m.5a("25");D.9Y=Y m.4a();D.9W("ej",m.3A,D.9X);D.9W("ei",D.eh,D.9V);D.2k={":3e":D.1z,":1p":m.2o(D.1z,D.1W)};m.3f(D)};B.15.2d();if(!B.3d){7H=B.15.7H}B.J.2Y(D,B.15);if(H(1q)!="L"){1q.2X("B.1H");1q.2M("B.J")}if(H(1x)!="L"){1x.26("B.J",[])}1f{if(H(B.J)=="L"){14""}}1e(e){14"B.1H 3F on B.J!"}if(H(B.1H)=="L"){B.1H={}}B.1H.1r="B.1H";B.1H.1Y="1.3.1";B.1H.1K=G(){F"["+D.1r+" "+D.1Y+"]"};B.1H.1l=G(){F D.1K()};B.1H.1z=["5C","49","7A","kR","2L","5Z","kG","ch","kE","kC"];B.1H.1W=["ef","e8","e7"];B.1H.49=G(1P,kT,3z){D.1P=1P;D.3N=kT;D.3z=3z;D.vf=Y 3Q()};B.1H.49.1U={U:G(){u m=B.J;F"49("+m.2r(m.U,[D.1P,D.3N,D.3z]).2b(", ")+")"},1l:B.J.24("U")};B.J.2l(B.1H,{ef:G(7F){u I=B.1H;if(H(7F)=="1n"){7F=I.5C[7F]}F G(1t){u 7G=1t.3N;if(H(7G)=="1n"){7G=I.5C[7G]}F 7G>=7F}},e8:G(){u kS=B.1H.49;R(u i=0;i<M.K;i++){if(!(M[i]2C kS)){F 1m}}F 1h},e7:G(a,b){F B.J.2f([a.3N,a.3z],[b.3N,b.3z])},kR:G(1t){cq("1P: "+1t.1P+"\\ve: "+1t.3N+"\\vd: "+1t.3z.2b(" "))}});B.1H.7A=G(7E){D.4f=0;if(H(7E)=="L"||7E===O){7E=-1}D.ec=7E;D.4h=[];D.7C={};D.e5=1m};B.1H.7A.1U={vc:G(){D.4h.4y(0,D.4h.K)},kK:G(1t){if(H(2O)!="L"&&2O.eg&&2O.eg.5Z){2O.eg.5Z(1t)}N{if(H(7h)!="L"&&7h.kQ){7h.kQ(1t)}N{if(H(5X)=="G"){5X(1t)}}}},kL:G(1t){R(u k in D.7C){u 2n=D.7C[k];if(2n.kO!=k||(2n[0]&&!2n[0](1t))){2V}2n[1](1t)}},hE:G(ee,7D,kP){if(H(7D)=="1n"){7D=B.1H.ef(7D)}u ed=[7D,kP];ed.kO=ee;D.7C[ee]=ed},c9:G(kN){gi D.7C[kN]},kH:G(kM,vb){u 1t=Y B.1H.49(D.4f,kM,B.J.1R(O,M,1));D.4h.1c(1t);D.kL(1t);if(D.e5){D.kK(1t.3N+": "+1t.3z.2b(" "))}D.4f+=1;1M(D.ec>=0&&D.4h.K>D.ec){D.4h.2P()}},c8:G(9U){u ea=0;if(!(H(9U)=="L"||9U===O)){ea=28.29(0,D.4h.K-9U)}F D.4h.9T(ea)},kJ:G(7B){if(H(7B)=="L"||7B===O){7B=30}u 9S=D.c8(7B);if(9S.K){u 1g=2r(G(m){F"\\n  ["+m.1P+"] "+m.3N+": "+m.3z.2b(" ")},9S);1g.e9("va "+9S.K+" v9:");F 1g.2b("")}F""},v8:G(kI){if(H(B.1I)=="L"){cq(D.kJ())}N{B.1I.bY(kI||1m)}}};B.1H.2d=G(){D.5C={8M:40,8L:50,8K:30,8J:20,8I:10};u m=B.J;m.5u("49",D.e8,D.e7);u 61=m.2z;u e6=D.7A;u 60=e6.1U.kH;m.2l(D.7A.1U,{kF:61(60,"8I"),5Z:61(60,"8J"),dE:61(60,"8M"),kD:61(60,"8L"),kB:61(60,"8K")});u I=D;u 5Y=G(1b){F G(){I.2L[1b].1w(I.2L,M)}};D.5Z=5Y("5Z");D.kG=5Y("dE");D.ch=5Y("kF");D.kE=5Y("kD");D.kC=5Y("kB");D.2L=Y e6();D.2L.e5=1h;D.2k={":3e":D.1z,":1p":m.2o(D.1z,D.1W)};m.3f(D)};if(H(5X)=="L"&&H(2v)!="L"&&2v.kA&&H(kz)!="L"){5X=G(){5X.3G=M;u ev=2v.kA("v7");ev.v6("5X",1m,1h);kz(ev)}}B.1H.2d();B.J.2Y(D,B.1H);if(H(1q)!="L"){1q.2X("B.1D")}if(H(B)=="L"){B={}}if(H(B.1D)=="L"){B.1D={}}B.1D.1r="B.1D";B.1D.1Y="1.3.1";B.1D.1K=G(){F"["+D.1r+" "+D.1Y+"]"};B.1D.1l=G(){F D.1K()};B.1D.ks=G(1y){1y=1y+"";if(H(1y)!="1n"||1y.K===0){F O}u 7z=1y.2R("-");if(7z.K===0){F O}F Y 3Q(7z[0],7z[1]-1,7z[2])};B.1D.ky=/(\\d{4,})(?:-(\\d{1,2})(?:-(\\d{1,2})(?:[T ](\\d{1,2}):(\\d{1,2})(?::(\\d{1,2})(?:\\.(\\d+))?)?(?:(Z)|([+-])(\\d{1,2})(?::(\\d{1,2}))?)?)?)?)?/;B.1D.kr=G(1y){1y=1y+"";if(H(1y)!="1n"||1y.K===0){F O}u X=1y.3C(B.1D.ky);if(H(X)=="L"||X===O){F O}u 5W,7y,7x,9R,2a,9Q,7w;5W=3w(X[1],10);if(H(X[2])=="L"||X[2]===""){F Y 3Q(5W)}7y=3w(X[2],10)-1;7x=3w(X[3],10);if(H(X[4])=="L"||X[4]===""){F Y 3Q(5W,7y,7x)}9R=3w(X[4],10);2a=3w(X[5],10);9Q=(H(X[6])!="L"&&X[6]!=="")?3w(X[6],10):0;if(H(X[7])!="L"&&X[7]!==""){7w=28.ha(c5*4M("0."+X[7]))}N{7w=0}if((H(X[8])=="L"||X[8]==="")&&(H(X[9])=="L"||X[9]==="")){F Y 3Q(5W,7y,7x,9R,2a,9Q,7w)}u 58;if(H(X[9])!="L"&&X[9]!==""){58=3w(X[10],10)*v5;if(H(X[11])!="L"&&X[11]!==""){58+=3w(X[11],10)*kw}if(X[9]=="-"){58=-58}}N{58=0}F Y 3Q(3Q.v4(5W,7y,7x,9R,2a,9Q,7w)-58)};B.1D.dY=G(2g,kx){if(H(2g)=="L"||2g===O){F O}u hh=2g.v3();u mm=2g.v2();u ss=2g.v1();u 1g=[((kx&&(hh<10))?"0"+hh:hh),((mm<10)?"0"+mm:mm),((ss<10)?"0"+ss:ss)];F 1g.2b(":")};B.1D.kq=G(2g,7v){if(H(2g)=="L"||2g===O){F O}u ku=7v?"T":" ";u kt=7v?"Z":"";if(7v){2g=Y 3Q(2g.9P()+(2g.v0()*kw))}F B.1D.dX(2g)+ku+B.1D.dY(2g,7v)+kt};B.1D.dX=G(2g){if(H(2g)=="L"||2g===O){F O}u e4=B.1D.e3;F[2g.dZ(),e4(2g.e1()+1),e4(2g.e0())].2b("-")};B.1D.kp=G(d){d=d+"";if(H(d)!="1n"||d.K===0){F O}u a=d.2R("/");F Y 3Q(a[2],a[0]-1,a[1])};B.1D.e3=G(n){F(n>9)?n:"0"+n};B.1D.ko=G(d){if(H(d)=="L"||d===O){F O}u e2=B.1D.e3;F[e2(d.e1()+1),e2(d.e0()),d.dZ()].2b("/")};B.1D.kn=G(d){if(H(d)=="L"||d===O){F O}F[d.e1()+1,d.e0(),d.dZ()].2b("/")};B.1D.1z=["ks","kr","dY","kq","dX","kp","ko","kn"];B.1D.1W=[];B.1D.2k={":3e":B.1D.1z,":1p":B.1D.1z};B.1D.2d=G(){u 2w=D.1r+".";R(u k in D){u o=D[k];if(H(o)=="G"&&H(o.1r)=="L"){1f{o.1r=2w+k}1e(e){}}}};B.1D.2d();if(H(B.J)!="L"){B.J.2Y(D,B.1D)}N{(G(km,dW){if((H(1x)=="L"&&H(1q)=="L")||(H(B.3d)=="5L"&&B.3d)){u 1p=dW.2k[":1p"];R(u i=0;i<1p.K;i++){km[1p[i]]=dW[1p[i]]}}})(D,B.1D)}if(H(1q)!="L"){1q.2X("B.1s")}if(H(B)=="L"){B={}}if(H(B.1s)=="L"){B.1s={}}B.1s.1r="B.1s";B.1s.1Y="1.3.1";B.1s.1K=G(){F"["+D.1r+" "+D.1Y+"]"};B.1s.1l=G(){F D.1K()};B.1s.ke=G(kl,kk,kj,ki,kh,dV,kg,9N,kf){F G(1P){1P=4M(1P);if(H(1P)=="L"||1P===O||k8(1P)){F kl}u 9L=kk;u 9K=kj;if(1P<0){1P=-1P}N{9L=9L.23(/-/,"")}u me=M.2U;u 9M=B.1s.dJ(ki);if(kh){1P=1P*3k;9K=9M.9y+9K}1P=B.1s.dK(1P,dV);u 9O=1P.2R(/\\./);u 3r=9O[0];u 3P=(9O.K==1)?"":9O[1];u X="";1M(3r.K<kg){3r="0"+3r}if(9N){1M(3r.K>9N){u i=3r.K-9N;X=9M.9A+3r.2W(i,3r.K)+X;3r=3r.2W(0,i)}}X=3r+X;if(dV>0){1M(3P.K<kf){3P=3P+"0"}X=X+9M.9z+3P}F 9L+X+9K}};B.1s.k5=G(9J,9H,9G){if(H(9H)=="L"){9H=""}u 3q=9J.3C(/((?:[0#]+,)?[0#]+)(?:\\.([0#]+))?(%)?/);if(!3q){14 3p("uZ uY")}u 7u=9J.3H(0,3q.c6);u kd=9J.3H(3q.c6+3q[0].K);if(7u.uX(/-/)==-1){7u=7u+"-"}u 9I=3q[1];u 3P=(H(3q[2])=="1n"&&3q[2]!="")?3q[2]:"";u kc=(H(3q[3])=="1n"&&3q[3]!="");u dU=9I.2R(/,/);u 9F;if(H(9G)=="L"){9G="dG"}if(dU.K==1){9F=O}N{9F=dU[1].K}u ka=9I.K-9I.23(/0/g,"").K;u k9=3P.K-3P.23(/0/g,"").K;u kb=3P.K;u W=B.1s.ke(9H,7u,kd,9G,kc,kb,ka,9F,k9);u m=B.J;if(m){u fn=M.2U;u 3G=m.2o(M);W.U=G(){F[I.1r,"(",2r(m.U,3G).2b(", "),")"].2b("")}}F W};B.1s.dJ=G(4g){if(H(4g)=="L"||4g===O){4g="dG"}if(H(4g)=="1n"){u W=B.1s.5V[4g];if(H(W)=="1n"){W=M.2U(W);B.1s.5V[4g]=W}F W}N{F 4g}};B.1s.k4=G(dT,9E){if(9E){u X=dT/9E;if(!k8(X)){F B.1s.9B(dT/9E)}}F"0"};B.1s.9B=G(dS){u dR=(dS<0?"-":"");u s=28.8B(28.uW(dS)*3k).1l();if(s=="0"){F s}if(s.K<3){1M(s.3Z(s.K-1)=="0"){s=s.2W(0,s.K-1)}F dR+"0."+s}u 5E=dR+s.2W(0,s.K-2);u 7t=s.2W(s.K-2,s.K);if(7t=="uV"){F 5E}N{if(7t.3Z(1)=="0"){F 5E+"."+7t.3Z(0)}N{F 5E+"."+7t}}};B.1s.dI=G(1y,dQ){1y=1y+"";if(H(1y)!="1n"){F O}if(!dQ){F 1y.23(/^\\s+/,"")}N{F 1y.23(Y 8V("^["+dQ+"]+"),"")}};B.1s.dH=G(1y,dP){1y=1y+"";if(H(1y)!="1n"){F O}if(!dP){F 1y.23(/\\s+$/,"")}N{F 1y.23(Y 8V("["+dP+"]+$"),"")}};B.1s.k2=G(1y,dO){u I=B.1s;F I.dH(I.dI(1y,dO),dO)};B.1s.dL=G(9D,9C){9D=28.8B(9D*28.dN(10,9C));u X=(9D*28.dN(10,-9C)).6I(9C);if(X.3Z(0)=="."){X="0"+X}F X};B.1s.dK=G(k7,dM){F B.1s.dL(k7+0.5*28.dN(10,-dM),dM)};B.1s.k3=G(k6){F B.1s.9B(3k*k6)+"%"};B.1s.1z=["dL","dK","k5","dJ","k4","9B","k3","dI","dH","k2"];B.1s.5V={k1:{9A:",",9z:".",9y:"%"},uU:{9A:".",9z:",",9y:"%"},uT:{9A:" ",9z:",",9y:"%"},"dG":"k1"};B.1s.1W=[];B.1s.2k={":1p":B.1s.1z,":3e":B.1s.1z};B.1s.2d=G(){u 2w=D.1r+".";u k,v,o;R(k in D.5V){o=D.5V[k];if(H(o)=="3n"){o.U=G(){F D.1r};o.1r=2w+"5V."+k}}R(k in D){o=D[k];if(H(o)=="G"&&H(o.1r)=="L"){1f{o.1r=2w+k}1e(e){}}}};B.1s.2d();if(H(B.J)!="L"){B.J.2Y(D,B.1s)}N{(G(k0,dF){if((H(1x)=="L"&&H(1q)=="L")||(H(B.3d)=="5L"&&B.3d)){u 1p=dF.2k[":1p"];R(u i=0;i<1p.K;i++){k0[1p[i]]=dF[1p[i]]}}})(D,B.1s)}if(H(1q)!="L"){1q.2X("B.1k");1q.2M("B.J")}if(H(1x)!="L"){1x.26("B.J",[])}1f{if(H(B.J)=="L"){14""}}1e(e){14"B.1k 3F on B.J!"}if(H(B.1k)=="L"){B.1k={}}B.1k.1r="B.1k";B.1k.1Y="1.3.1";B.1k.1K=G(){F"["+D.1r+" "+D.1Y+"]"};B.1k.1l=G(){F D.1K()};B.1k.2t=G(jZ){D.55=[];D.id=D.7n();D.2H=-1;D.54=0;D.53=[O,O];D.7m=jZ;D.7l=1m;D.7r=1m};B.1k.2t.1U={U:G(){u 7s;if(D.2H==-1){7s="uS"}N{if(D.2H===0){7s="uR"}N{7s="dE"}}F"2t("+D.id+", "+7s+")"},1l:B.J.24("U"),7n:B.J.4f(),jY:G(){u I=B.1k;if(D.2H==-1){if(D.7m){D.7m(D)}N{D.7l=1h}if(D.2H==-1){D.52(Y I.di(D))}}N{if((D.2H===0)&&(D.53[0]2C I.2t)){D.53[0].jY()}}},jQ:G(){D.54++},jX:G(){D.54--;if((D.54===0)&&(D.2H>=0)){D.9u()}},jR:G(X){D.9x(X);D.jX()},9x:G(X){D.2H=((X 2C 2x)?1:0);D.53[D.2H]=X;D.9u()},dD:G(){if(D.2H!=-1){if(!D.7l){14 Y B.1k.dj(D)}D.7l=1m;F}},3o:G(X){D.dD();if(X 2C B.1k.2t){14 Y 2x("2t jW 9v aB be 7r if jV jU jT jS of a 3o")}D.9x(X)},52:G(X){D.dD();u I=B.1k;if(X 2C I.2t){14 Y 2x("2t jW 9v aB be 7r if jV jU jT jS of a 3o")}if(!(X 2C 2x)){X=Y I.9p(X)}D.9x(X)},jP:G(fn){if(M.K>1){fn=B.J.2z.1w(O,M)}F D.9w(fn,fn)},5Q:G(fn){if(M.K>1){fn=B.J.2z.1w(O,M)}F D.9w(fn,O)},jA:G(fn){if(M.K>1){fn=B.J.2z.1w(O,M)}F D.9w(O,fn)},9w:G(cb,eb){if(D.7r){14 Y 2x("uQ uP 9v 2E be re-uO")}D.55.1c([cb,eb]);if(D.2H>=0){D.9u()}F D},9u:G(){u dC=D.55;u 56=D.2H;u X=D.53[56];u I=D;u cb=O;1M(dC.K>0&&D.54===0){u 2n=dC.2P();u f=2n[56];if(f===O){2V}1f{X=f(X);56=((X 2C 2x)?1:0);if(X 2C B.1k.2t){cb=G(X){I.jR(X)};D.jQ()}}1e(3O){56=1;if(!(3O 2C 2x)){3O=Y B.1k.9p(3O)}X=3O}}D.2H=56;D.53[56]=X;if(cb&&D.54){X.jP(cb);X.7r=1h}}};B.J.2l(B.1k,{dk:G(){F dB("("+M[0].jN+")")},dp:G(uN){u d=Y B.1k.2t();d.3o.1w(d,M);F d},9q:G(uM){u d=Y B.1k.2t();d.52.1w(d,M);F d},do:G(){u I=M.2U;if(!I.7q){u dy=[G(){F Y 7q()},G(){F Y dA("jO.dz")},G(){F Y dA("uL.dz")},G(){F Y dA("jO.dz.4.0")},G(){14 Y B.1k.dh("uK uJ 2E uI 7q")}];R(u i=0;i<dy.K;i++){u 1A=dy[i];1f{I.7q=1A;F 1A()}1e(e){}}}F I.7q()},dx:G(){},jK:G(d){if(D.uH==4){1f{D.5T=O}1e(e){1f{D.5T=B.1k.dx}1e(e){}}u 5U=O;1f{5U=D.jm;if(!5U&&B.J.7e(D.jN)){5U=jM}}1e(e){}if(5U==hQ||5U==jM){d.3o(D)}N{u 3O=Y B.1k.dg(D,"uG uF");if(3O.2y){d.52(3O)}N{d.52(3O)}}}},jL:G(2s){1f{2s.5T=O}1e(e){1f{2s.5T=B.1k.dx}1e(e){}}2s.uE()},dl:G(2s,7p){if(H(7p)=="L"||7p===O){7p=""}u m=B.J;u I=B.1k;u d=Y I.2t(m.2z(I.jL,2s));1f{2s.5T=m.1O(I.jK,2s,d);2s.uD(7p)}1e(e){1f{2s.5T=O}1e(uC){}d.52(e)}F d},dn:G(5F){u I=B.1k;u 2s=I.do();if(M.K>1){u m=B.J;u qs=m.dw.1w(O,m.1R(O,M,1));if(qs){5F+="?"+qs}}2s.cp("uB",5F,1h);F I.dl(2s)},jv:G(5F){u I=B.1k;u d=I.dn.1w(I,M);d=d.5Q(I.dk);F d},dm:G(jJ,dv){u d=Y B.1k.2t();u m=B.J;if(H(dv)!="L"){d.5Q(G(){F dv})}u jI=uA(m.1O("3o",d),28.8B(jJ*c5));d.7m=G(){1f{uz(jI)}1e(e){}};F d},ju:G(jH,1A){u m=B.J;u jG=m.2z.1w(m,m.1R(O,M,1));F B.1k.dm(jH).5Q(G(X){F jG()})}});B.1k.5O=G(){D.5S=[];D.4e=1m;D.id=D.7n()};B.1k.5O.1U={bX:B.1k.5O,uy:G(){d=Y B.1k.2t();if(D.4e){D.5S.1c(d)}N{D.4e=1h;d.3o(D)}F d},jF:G(){if(!D.4e){14 3p("ux to jF an jE 5O")}D.4e=1m;if(D.5S.K>0){D.4e=1h;D.5S.2P().3o(D)}},7n:B.J.4f(),U:G(){u 9t;if(D.4e){9t="4e, "+D.5S.K+" 5S"}N{9t="jE"}F"5O("+D.id+", "+9t+")"},1l:B.J.24("U")};B.1k.7i=G(2G,du,jC,jB,jD){D.2G=2G;D.9r=Y 7o(D.2G.K);D.55=[];D.id=D.7n();D.2H=-1;D.54=0;D.53=[O,O];D.7m=jD;D.7l=1m;if(D.2G.K===0&&!du){D.3o(D.9r)}D.dr=0;D.jz=du;D.jy=jC;D.jx=jB;u 9s=0;B.J.2r(B.J.1O(G(d){d.5Q(B.J.1O(D.dt,D),9s,1h);d.jA(B.J.1O(D.dt,D),9s,1m);9s+=1},D),D.2G)};B.J.2l(B.1k.7i.1U,B.1k.2t.1U);B.J.2l(B.1k.7i.1U,{dt:G(ds,7k,5R){D.9r[ds]=[7k,5R];D.dr+=1;if(D.2H!==0){if(7k&&D.jz){D.3o([ds,5R])}N{if(!7k&&D.jy){D.52(5R)}N{if(D.dr==D.2G.K){D.3o(D.9r)}}}}if(!7k&&D.jx){5R=O}F 5R}});B.1k.jt=G(jw){u d=Y B.1k.7i(jw,1m,1h,1m);d.5Q(G(dq){u 7j=[];R(u i=0;i<dq.K;i++){7j.1c(dq[i][1])}F 7j});F d};B.1k.jr=G(1A){u I=B.1k;u 5P;1f{u r=1A.1w(O,B.J.1R([],M,1));if(r 2C I.2t){5P=r}N{if(r 2C 2x){5P=I.9q(r)}N{5P=I.dp(r)}}}1e(e){5P=I.9q(e)}F 5P};B.1k.1z=["dj","di","dh","9p","dg","2t","dp","9q","do","dn","jv","dm","ju","dl","5O","7i","jt","jr"];B.1k.1W=["dk"];B.1k.2d=G(){u m=B.J;u ne=m.2z(m.jq,D);ne("dj",G(jp){D.jo=jp});ne("di",G(jn){D.jo=jn});ne("dh",G(1t){D.43=1t});ne("9p",G(1t){D.43=1t});ne("dg",G(2s,1t){D.2s=2s;D.43=1t;1f{D.2y=2s.jm}1e(e){}});D.2k={":3e":D.1z,":1p":m.2o(D.1z,D.1W)};m.3f(D)};B.1k.2d();B.J.2Y(D,B.1k);if(H(1q)!="L"){1q.2X("B.S");1q.2M("B.15")}if(H(1x)!="L"){1x.26("B.15",[])}1f{if(H(B.15)=="L"){14""}}1e(e){14"B.S 3F on B.15!"}if(H(B.S)=="L"){B.S={}}B.S.1r="B.S";B.S.1Y="1.3.1";B.S.1K=G(){F"["+D.1r+" "+D.1Y+"]"};B.S.1l=G(){F D.1K()};B.S.1z=["d5","cr","b9","95","94","j3","9k","cX","cw","iT","iV","4X","9j","iQ","hS","cs","ia","i9","i8","i7","i6","i5","i4","hV","i3","i2","i1","cu","hW","ct","i0","hZ","hY","hX","P","io","il","ik","ij","cm","ih","ii","ig","ie","ic","cv","8d","A","6m","ib","1E","$","4q","aH","cO","cN","iM","5G","iK","9d","9e","iH","iD","9c","iB","cG","97","hU","hT","iw","jh","jb","j6","j5","jk","jl"];B.S.1W=["9b"];B.S.5N=G(w,h){D.w=w;D.h=h};B.S.5N.1U.U=G(){u U=B.J.U;F"{w: "+U(D.w)+", h: "+U(D.h)+"}"};B.S.5t=G(x,y){D.x=x;D.y=y};B.S.5t.1U.U=G(){u U=B.J.U;F"{x: "+U(D.x)+", y: "+U(D.y)+"}"};B.S.5t.1U.1l=G(){F D.U()};B.J.2l(B.S,{jl:G(Q,o){Q=B.S.1E(Q);B.S.4X(Q,{"1T":{"9o":o,"-hL-9o":o,"-uw-9o":o,"47":" uv(9o="+(o*3k)+")"}})},jk:G(){u d=Y B.S.5N();u w=B.S.3X;u b=B.S.1Z.5s;if(w.jj){d.w=w.jj;d.h=w.uu}N{if(b.dd.9n){d.w=b.dd.9n;d.h=b.dd.ji}N{if(b&&b.9n){d.w=b.9n;d.h=b.ji}}}F d},jh:G(Q){u I=B.S;if(H(Q.w)=="2y"||H(Q.h)=="2y"){F Y I.5N(Q.w||0,Q.h||0)}Q=I.1E(Q);if(!Q){F L}if(I.4q(Q,"3u")!="98"){F Y I.5N(Q.jg||0,Q.ci||0)}u s=Q.1T;u je=s.dc;u jf=s.6P;s.dc="fR";s.6P="j8";s.3u="";u jd=Q.jg;u jc=Q.ci;s.3u="98";s.6P=jf;s.dc=je;F Y I.5N(jd,jc)},jb:G(Q,4Z){u I=B.S;Q=I.1E(Q);if(!Q){F L}u c=Y I.5t(0,0);if(Q.x&&Q.y){c.x+=Q.x||0;c.y+=Q.y||0;F c}N{if(Q.3t===O||I.4q(Q,"3u")=="98"){F L}}u 51=O;u 2j=O;u d=B.S.1Z;u de=d.7Z;u b=d.5s;if(Q.ja){51=Q.ja();c.x+=51.2I+(de.6y||b.6y)-(de.8q||b.8q);c.y+=51.3D+(de.4C||b.4C)-(de.8p||b.8p)}N{if(d.j9){51=d.j9(Q);c.x+=51.x;c.y+=51.y}N{if(Q.8g){c.x+=Q.db;c.y+=Q.da;2j=Q.8g;if(2j!=Q){1M(2j){c.x+=2j.db;c.y+=2j.da;2j=2j.8g}}u ua=ut.us.8G();if((H(7h)!="L"&&4M(7h.ur())<9)||(ua.2A("uq")!=-1&&I.4q(Q,"6P")=="j8")){c.x-=b.db;c.y-=b.da}}}}if(H(4Z)!="L"){4Z=M.2U(4Z);if(4Z){c.x-=(4Z.x||0);c.y-=(4Z.y||0)}}if(Q.3t){2j=Q.3t}N{2j=O}1M(2j&&2j.j7!="uo"&&2j.j7!="co"){c.x-=2j.6y;c.y-=2j.4C;if(2j.3t){2j=2j.3t}N{2j=O}}F c},j6:G(Q,d9,7g){Q=B.S.1E(Q);if(H(7g)=="L"){7g="px"}B.S.4X(Q,{"1T":{"5A":d9.w+7g,"3V":d9.h+7g}})},j5:G(Q,d8,7f){Q=B.S.1E(Q);if(H(7f)=="L"){7f="px"}B.S.4X(Q,{"1T":{"2I":d8.x+7f,"3D":d8.y+7f}})},cr:G(){F B.S.3X},b9:G(){F B.S.1Z},95:G(2m,1A){u I=B.S;u d6=I.1Z;u d7=I.un;u W;1f{I.3X=2m;I.1Z=2m.2v;W=1A()}1e(e){I.3X=d7;I.1Z=d6;14 e}I.3X=d7;I.1Z=d6;F W},d5:G(Q){u 7d=[];u 7c=[];u m=B.J;u I=B.S;if(H(Q)=="L"||Q===O){Q=I.1Z}N{Q=I.1E(Q)}m.d4(Q,G(Q){u 1b=Q.1b;if(m.7e(1b)){u 4Y=Q.cD;if(4Y=="cv"&&(Q.1J=="um"||Q.1J=="uk")&&!Q.ip){F O}if(4Y=="ct"){if(Q.j4>=0){u 9m=Q.1S[Q.j4];7d.1c(1b);7c.1c((9m.3m)?9m.3m:9m.7X);F O}7d.1c(1b);7c.1c("");F O}if(4Y=="cu"||4Y=="P"||4Y=="8d"||4Y=="6m"){F Q.5h}7d.1c(1b);7c.1c(Q.3m||"");F O}F Q.5h});F[7d,7c]},94:G(1N,1A){u I=B.S;u d3=I.1Z;u W;1f{I.1Z=1N;W=1A()}1e(e){I.1Z=d3;14 e}I.1Z=d3;F W},j3:G(1b,j2,3y,j1){B.S.9b.5M(1b,j2,3y,j1)},9k:G(1j,7a){u im=B.15;u I=B.S;u 1Q=im.1Q;u iY=im.7b;u 4c=im.4c;u iX=I.9b;u iZ=I.9k;u iW=B.J.4d;1M(1h){if(H(1j)=="L"||1j===O){F O}if(H(1j.3T)!="L"&&1j.3T>0){F 1j}if(H(1j)=="2y"||H(1j)=="5L"){1j=1j.1l()}if(H(1j)=="1n"){F I.1Z.4S(1j)}if(H(1j.j0)=="G"){1j=1j.j0(7a);2V}if(H(1j)=="G"){1j=1j(7a);2V}u 9l=O;1f{9l=1Q(1j)}1e(e){}if(9l){F 4c(iZ,9l,iY(7a))}1f{1j=iX.3C(1j,7a);2V}1e(e){if(e!=iW){14 e}}F I.1Z.4S(1j.1l())}F L},iV:G(1j,79,iU){u o={};o[79]=iU;1f{F B.S.4X(1j,o)}1e(e){}F O},iT:G(1j,79){u I=B.S;u d2=I.4U.99[79];1j=I.1E(1j);1f{if(d2){F 1j[d2]}F 1j.fm(79)}1e(e){}F O},4X:G(1j,5K){u Q=1j;u I=B.S;if(H(1j)=="1n"){Q=I.1E(1j)}if(5K){u d0=B.J.8Z;if(I.4U.6X){R(u k in 5K){u v=5K[k];if(H(v)=="3n"&&H(Q[k])=="3n"){d0(Q[k],v)}N{if(k.2W(0,2)=="on"){if(H(v)=="1n"){v=Y cZ(v)}Q[k]=v}N{Q.4p(k,v)}}}}N{u iS=I.4U.99;R(k in 5K){v=5K[k];u d1=iS[k];if(k=="1T"&&H(v)=="1n"){Q.1T.3x=v}N{if(H(d1)=="1n"){Q[d1]=v}N{if(H(Q[k])=="3n"&&H(v)=="3n"){d0(Q[k],v)}N{if(k.2W(0,2)=="on"){if(H(v)=="1n"){v=Y cZ(v)}Q[k]=v}N{Q.4p(k,v)}}}}}}}F Q},9j:G(1j){u Q=1j;u I=B.S;if(H(1j)=="1n"){Q=I.1E(1j)}u 78=[I.9k(B.J.1R(O,M,1),Q)];u iR=B.J.2o;1M(78.K){u n=78.2P();if(H(n)=="L"||n===O){}N{if(H(n.3T)=="2y"){Q.2c(n)}N{78=iR(n,78)}}}F Q},iQ:G(1j){u Q=1j;u I=B.S;if(H(1j)=="1n"){Q=I.1E(1j);M[0]=Q}u cY;1M((cY=Q.6n)){Q.6S(cY)}if(M.K<2){F Q}N{F I.9j.1w(D,M)}},cX:G(1b,4b){u Q;u I=B.S;u m=B.J;if(H(4b)=="1n"||H(4b)=="2y"){u 3G=m.1R([1b,O],M,1);F M.2U.1w(D,3G)}if(H(1b)=="1n"){if(4b&&"1b"in 4b&&!I.4U.6X){1b=("<"+1b+" 1b=\\""+I.9c(4b.1b)+"\\">")}Q=I.1Z.2S(1b)}N{Q=1b}if(4b){I.4X(Q,4b)}if(M.K<=2){F Q}N{u 3G=m.1R([Q],M,2);F I.9j.1w(D,3G)}},cw:G(){u m=B.J;F m.2z.1w(D,m.1R([B.S.cX],M))},cs:G(5J,1d){u I=B.S;5J=I.1E(5J);u cW=5J.3t;if(1d){1d=I.1E(1d);cW.uj(1d,5J)}N{cW.6S(5J)}F 1d},1E:G(id){u I=B.S;if(M.K==1){F((H(id)=="1n")?I.1Z.hN(id):id)}N{F B.J.2r(I.1E,M)}},4q:G(iP,cV,cU){if(M.K==2){cU=cV}u I=B.S;u el=I.1E(iP);u 77=I.1Z;if(!el||el==77){F L}if(el.iO){F el.iO[cV]}if(H(77.5k)=="L"){F L}if(77.5k===O){F L}u 9i=77.5k.g4(el,O);if(H(9i)=="L"||9i===O){F L}F 9i.6q(cU)},aH:G(76,9g,4W){u I=B.S;if(H(76)=="L"||76===O){76="*"}if(H(4W)=="L"||4W===O){4W=I.1Z}4W=I.1E(4W);u 9h=(4W.fr(76)||I.1Z.1p);if(H(9g)=="L"||9g===O){F B.J.1R(O,9h)}u cR=[];R(u i=0;i<9h.K;i++){u cS=9h[i];u cT=cS.3M.2R(" ");R(u j=0;j<cT.K;j++){if(cT[j]==9g){cR.1c(cS);2K}}}F cR},iN:G(5I,9f){u W=G(){u cQ=M.2U.5H;R(u i=0;i<cQ.K;i++){if(cQ[i].1w(D,M)===1m){2K}}if(9f){1f{D[5I]=O}1e(e){}}};W.5H=[];F W},cO:G(cP,5I,1A,9f){u I=B.S;u 4V=cP[5I];u 75=4V;if(!(H(4V)=="G"&&H(4V.5H)=="3n"&&4V.5H!==O)){75=I.iN(5I,9f);if(H(4V)=="G"){75.5H.1c(4V)}cP[5I]=75}75.5H.1c(1A)},cN:G(1A){u I=B.S;I.cO(I.3X,"gh",1A,1h)},iM:G(74){u I=B.S;I.cN(G(){74=I.1E(74);if(74){74.ui()}})},5G:G(iL,cM){u I=B.S;u 1i=I.1E(iL);if(I.4U.6X){1i.4p("iq",cM)}N{1i.4p("3M",cM)}},iK:G(cL){u I=B.S;R(u i=1;i<M.K;i++){u 1i=I.1E(M[i]);if(!I.9d(1i,cL)){I.9e(1i,cL)}}},9d:G(iJ,73){u I=B.S;u 1i=I.1E(iJ);u 2F=1i.3M;if(2F.K===0){I.5G(1i,73);F 1h}if(2F==73){F 1m}u cK=1i.3M.2R(" ");R(u i=0;i<cK.K;i++){if(cK[i]==73){F 1m}}I.5G(1i,2F+" "+73);F 1h},9e:G(iI,cJ){u I=B.S;u 1i=I.1E(iI);u 2F=1i.3M;if(2F.K===0){F 1m}if(2F==cJ){I.5G(1i,"");F 1h}u 72=1i.3M.2R(" ");R(u i=0;i<72.K;i++){if(72[i]==cJ){72.4y(i,1);I.5G(1i,72.2b(" "));F 1h}}F 1m},iH:G(iG,iF,iE){u 1i=B.S.1E(iG);u X=B.S.9e(1i,iF);if(X){B.S.9d(1i,iE)}F X},iD:G(iC,uh){u 1i=B.S.1E(iC);u cI=1i.3M.2R(" ");R(u i=1;i<M.K;i++){u cH=1m;R(u j=0;j<cI.K;j++){if(cI[j]==M[i]){cH=1h;2K}}if(!cH){F 1m}}F 1h},9c:G(s){F s.23(/&/g,"&ug;").23(/"/g,"&uf;").23(/</g,"&lt;").23(/>/g,"&gt;")},iB:G(2q){F B.S.cG(2q).2b("")},cG:G(2q,1g){if(H(1g)=="L"||1g===O){1g=[]}u 70=[2q];u I=B.S;u cB=I.9c;u iA=I.4U;1M(70.K){2q=70.hP();if(H(2q)=="1n"){1g.1c(2q)}N{if(2q.3T==1){1g.1c("<"+2q.cD.8G());u 71=[];u cF=iA(2q);R(u i=0;i<cF.K;i++){u a=cF[i];71.1c([" ",a.1b,"=\\"",cB(a.3m),"\\""])}71.iz();R(i=0;i<71.K;i++){u cE=71[i];R(u j=0;j<cE.K;j++){1g.1c(cE[j])}}if(2q.ue()){1g.1c(">");70.1c("</"+2q.cD.8G()+">");u cC=2q.5h;R(i=cC.K-1;i>=0;i--){70.1c(cC[i])}}N{1g.1c("/>")}}N{if(2q.3T==3){1g.1c(cB(2q.iv))}}}}F 1g},97:G(ix,cA){u m=B.J;u iy=m.1R(O,M,1);B.15.9a(m.47(O,m.2r(B.S.1E,iy)),G(cA){cA.1T.3u=ix})},iw:G(1j,iu){u W=[];(G(1j){u cn=1j.5h;if(cn){R(u i=0;i<cn.K;i++){M.2U.cz(D,cn[i])}}u cy=1j.iv;if(H(cy)=="1n"){W.1c(cy)}})(B.S.1E(1j));if(iu){F W}N{F W.2b("")}},2d:G(2m){u m=B.J;D.1Z=2v;D.3X=2m;D.9b=Y m.4a();u 6Z=D.1Z.2S("cj");u 2T;if(6Z&&6Z.6Y&&6Z.6Y.K>0){u it=m.47;2T=G(1j){F it(2T.ir,1j.6Y)};2T.cx={};B.15.9a(6Z.6Y,G(a){2T.cx[a.1b]=a.3m});2T.ir=G(a){F(2T.cx[a.1b]!=a.3m)};2T.6X=1m;2T.99={"iq":"3M","ip":"ud","uc":"ub","R":"u9"}}N{2T=G(1j){F 1j.6Y};2T.6X=1h;2T.99={}}D.4U=2T;u 1C=D.cw;D.io=1C("ul");D.il=1C("ol");D.ik=1C("li");D.ij=1C("td");D.cm=1C("tr");D.ii=1C("u8");D.ih=1C("u7");D.ig=1C("u6");D.ie=1C("u5");D.ic=1C("th");D.cv=1C("ck");D.8d=1C("cj");D.A=1C("a");D.6m=1C("4u");D.ib=1C("u4");D.ia=1C("2e");D.i9=1C("tt");D.i8=1C("4O");D.i7=1C("h1");D.i6=1C("h2");D.i5=1C("h3");D.i4=1C("br");D.i3=1C("hr");D.i2=1C("u3");D.i1=1C("u2");D.cu=1C("u1");D.P=1C("p");D.ct=1C("u0");D.i0=1C("hJ");D.hZ=1C("tZ");D.hY=1C("tY");D.hX=1C("tX");D.hW=1C("tW");D.hV=1C("tV");D.hU=m.2z(D.97,"98");D.hT=m.2z(D.97,"8c");D.hS=D.cs;D.$=D.1E;D.2k={":3e":D.1z,":1p":m.2o(D.1z,D.1W)};m.3f(D)}});B.S.2d(((H(2O)=="L")?D:2O));if(!B.3d){95=B.S.95;94=B.S.94}B.J.2Y(D,B.S);if(H(1q)!="L"){1q.2X("B.1I");1q.2M("B.1H");1q.2M("B.J")}if(H(1x)!="L"){1x.26("B.1H",[]);1x.26("B.J",[])}1f{if(H(B.J)=="L"||H(B.1H)=="L"){14""}}1e(e){14"B.1I 3F on B.J 3W B.1H!"}if(H(B.1I)=="L"){B.1I={}}B.1I.1r="B.1I";B.1I.1Y="1.3.1";B.1I.1K=G(){F"["+D.1r+" "+D.1Y+"]"};B.1I.1l=G(){F D.1K()};B.1I.bY=G(6W){u m=B.1I;6W=!(!6W);if(m.3l&&m.3l.8Q!=6W){m.3l.hA();m.3l=O}if(!m.3l||m.3l.8P){m.3l=Y m.1I(6W,B.1H.2L)}F m.3l};B.1I.1I=G(4R,6V){if(H(6V)=="L"||6V===O){6V=B.1H.2L}D.2L=6V;u tU=B.J.2l;u c3=B.J.8Z;u 1O=B.J.1O;u hM=B.J.4L;u 2m=2O;u 6U="tT";if(H(B.S)!="L"){2m=B.S.cr()}if(!4R){u 5F=2m.tS.tR.2R("?")[0].23(/[:\\/.><&]/g,"hR");u 1b=6U+"hR"+5F;u 5D=2m.cp("",1b,"tQ,tP,3V=hQ");if(!5D){cq("tO tN to cp tM 2O tL to hP-up tK.");F L}5D.2v.fl("<!tJ co tI \\"-//tH//tG co 4.0 tF//tE\\" "+"\\"fq://fp.tD.fo/cm/tC/tB.tA\\">"+"<hO><5E><8Y>[B.1I]</8Y></5E>"+"<5s></5s></hO>");5D.2v.hG();5D.2v.8Y+=" "+2m.2v.8Y;2m=5D}u 1N=2m.2v;D.1N=1N;u 21=1N.hN(6U);u c4=!!21;if(21&&H(21.5B)!="L"){21.5B.2L=D.2L;21.5B.6K();F 21.5B}if(c4){u cl;1M((cl=21.6n)){21.6S(cl)}}N{21=1N.2S("4u");21.id=6U}21.5B=D;u 8T=1N.2S("ck");u 8S=1N.2S("ck");u 6O=1N.2S("2e");u 6N=1N.2S("2e");u 6M=1N.2S("2e");u 6L=1N.2S("2e");u 3L=1N.2S("4u");u 42=1N.2S("4u");u 8U=6U+"tz";D.8N=hM(D.8N);u 4T=[];u 6R=O;u cf=G(1t){u 6T=1t.3N;if(H(6T)=="2y"){6T=B.1H.5C[6T]}F 6T};u cd=G(1t){F 1t.3z.2b(" ")};u ca=1O(G(1t){u 8W=cf(1t);u 7X=cd(1t);u c=D.8N[8W];u p=1N.2S("cj");p.3M="B-49 B-5C-"+8W;p.1T.3x="ty: 2N; 4F-8X: -hL-4O-3y; 4F-8X: -o-4O-3y; 4F-8X: 4O-3y; 4F-8X: 4O-tx; hK-3y: 2K-hK; 3y-hJ: tw; 3U: "+c;p.2c(1N.4S(8W+": "+7X));42.2c(p);42.2c(1N.2S("br"));if(3L.ci>3L.hI){3L.4C=0}N{3L.4C=3L.hI}},D);u hD=G(1t){4T[4T.K]=1t;ca(1t)};u hF=G(){u cg,ce;1f{cg=Y 8V(8T.3m);ce=Y 8V(8S.3m)}1e(e){ch("2x in 47 tv: "+e.43);F O}F G(1t){F(cg.hH(cf(1t))&&ce.hH(cd(1t)))}};u cc=G(){1M(42.6n){42.6S(42.6n)}};u hB=G(){4T=[];cc()};u bZ=1O(G(){if(D.8P){F}D.8P=1h;if(B.1I.3l==D){B.1I.3l=O}D.2L.c9(8U);21.5B=O;if(4R){21.3t.6S(21)}N{D.2m.hG()}},D);u c7=G(){cc();R(u i=0;i<4T.K;i++){u 1t=4T[i];if(6R===O||6R(1t)){ca(1t)}}};D.6K=G(){6R=hF();c7();D.2L.c9(8U);D.2L.hE(8U,6R,hD)};u c0=1O(G(){4T=D.2L.c8();c7()},D);u c2=1O(G(6Q){6Q=6Q||2O.6D;2h=6Q.6w||6Q.8t;if(2h==13){D.6K()}},D);u 31="3u: 8c; z-c6: c5; 2I: 2N; 6f: 2N; 6P: tu; 5A: 3k%; he-3U: 4F; c1: "+D.8O;if(4R){31+="; 3V: ts; 3E-3D: fO 8a 8y"}N{31+="; 3V: 3k%;"}21.1T.3x=31;if(!c4){1N.5s.2c(21)}31={"3x":"5A: 33%; 3u: 8Q; c1: "+D.8O};c3(8T,{"3m":"8L|8M|8K|8J|8I","hC":c2,"1T":31});21.2c(8T);c3(8S,{"3m":".*","hC":c2,"1T":31});21.2c(8S);31="5A: 8%; 3u:8Q; c1: "+D.8O;6O.2c(1N.4S("tq"));6O.8R=1O("6K",D);6O.1T.3x=31;21.2c(6O);6N.2c(1N.4S("tp"));6N.8R=c0;6N.1T.3x=31;21.2c(6N);6M.2c(1N.4S("tn"));6M.8R=hB;6M.1T.3x=31;21.2c(6M);6L.2c(1N.4S("tm"));6L.8R=bZ;6L.1T.3x=31;21.2c(6L);3L.1T.3x="fS: tk; 5A: 3k%";42.1T.3x="5A: 3k%; 3V: "+(4R?"tj":"3k%");3L.2c(42);21.2c(3L);D.6K();c0();if(4R){D.2m=L}N{D.2m=2m}D.8Q=4R;D.hA=bZ;D.8P=1m;F D};B.1I.1I.1U={"8O":"ti tg,tf-te","8N":{"8M":"1v","8L":"gU","8K":"1F","8J":"8y","8I":"bx"}};B.1I.1W=["1I"];B.1I.1z=["bY"];B.1I.2d=G(){D.2k={":3e":D.1z,":1p":B.J.2o(D.1z,D.1W)};B.J.3f(D);B.1I.3l=O};B.1I.2d();B.J.2Y(D,B.1I);if(H(1q)!="L"){1q.2X("B.V");1q.2M("B.J")}if(H(1x)!="L"){1x.26("B.J",[])}1f{if(H(B.J)=="L"){14""}}1e(e){14"B.V 3F on B.J"}if(H(B.V)=="L"){B.V={}}B.V.1r="B.V";B.V.1Y="1.3.1";B.V.1K=G(){F"["+D.1r+" "+D.1Y+"]"};B.V.1l=G(){F D.1K()};B.V.V=G(1v,hz,1F,6J){if(H(6J)=="L"||6J===O){6J=1}D.1B={r:1v,g:hz,b:1F,a:6J}};B.V.V.1U={bX:B.V.V,tc:G(hy){u 1B=D.1B;u m=B.V;F m.V.3Y(1B.r,1B.g,1B.b,hy)},tb:G(1o){u 1G=D.41();1G.h=1o;u m=B.V;F m.V.4H(1G)},ta:G(hx){u 1G=D.41();1G.s=hx;u m=B.V;F m.V.4H(1G)},t9:G(hw){u 1G=D.41();1G.l=hw;u m=B.V;F m.V.4H(1G)},t8:G(hv){u 1G=D.41();1G.l=28.29(1G.l-hv,0);u m=B.V;F m.V.4H(1G)},t7:G(hu){u 1G=D.41();1G.l=28.2a(1G.l+hu,1);u m=B.V;F m.V.4H(1G)},fJ:G(ht,5z){if(H(5z)=="L"||5z===O){5z=0.5}u sf=1-5z;u s=D.1B;u d=ht.1B;u df=5z;F B.V.V.3Y((s.r*sf)+(d.r*df),(s.g*sf)+(d.g*df),(s.b*sf)+(d.b*df),(s.a*sf)+(d.a*df))},h4:G(hs){u a=D.6r();u b=hs.6r();F B.J.2f([a.r,a.g,a.b,a.a],[b.r,b.g,b.b,b.a])},hq:G(){F D.41().b>0.5},t6:G(){F(!D.hq())},t5:G(){u c=D.41();u 2Z=B.V.6F;u W=D.ho;if(!W){u 5y=(2Z(c.h,bF).6I(0)+","+2Z(c.s,3k).hp(4)+"%"+","+2Z(c.l,3k).hp(4)+"%");u a=c.a;if(a>=1){a=1;W="1G("+5y+")"}N{if(a<=0){a=0}W="t4("+5y+","+a+")"}D.ho=W}F W},hl:G(){u c=D.1B;u 2Z=B.V.6F;u W=D.hn;if(!W){u 5y=(2Z(c.r,3h).6I(0)+","+2Z(c.g,3h).6I(0)+","+2Z(c.b,3h).6I(0));if(c.a!=1){W="t3("+5y+","+c.a+")"}N{W="1B("+5y+")"}D.hn=W}F W},6r:G(){F B.J.4L(D.1B)},t2:G(){u m=B.V;u c=D.1B;u 2Z=B.V.6F;u W=D.hm;if(!W){W=("#"+m.6E(2Z(c.r,3h))+m.6E(2Z(c.g,3h))+m.6E(2Z(c.b,3h)));D.hm=W}F W},t1:G(){u 2Q=D.2Q;u c=D.1B;if(H(2Q)=="L"||2Q===O){2Q=B.V.bA(D.1B);D.2Q=2Q}F B.J.4L(2Q)},41:G(){u 1G=D.1G;u c=D.1B;if(H(1G)=="L"||1G===O){1G=B.V.bC(D.1B);D.1G=1G}F B.J.4L(1G)},1l:G(){F D.hl()},U:G(){u c=D.1B;u hk=[c.r,c.g,c.b,c.a];F D.bX.1r+"("+hk.2b(", ")+")"}};B.J.2l(B.V.V,{3Y:G(1v,bW,1F,8H){u hj=B.V.V;if(M.K==1){u 1B=1v;1v=1B.r;bW=1B.g;1F=1B.b;if(H(1B.a)=="L"){8H=L}N{8H=1B.a}}F Y hj(1v,bW,1F,8H)},4H:G(1o,t0,sZ,sY){u m=B.V;F m.V.3Y(m.bB.1w(m,M))},sX:G(1o,sW,sV,sU){u m=B.V;F m.V.3Y(m.bz.1w(m,M))},hi:G(1b){u 8F=B.V.V;if(1b.3Z(0)=="\\""){1b=1b.3H(1,1b.K-2)}u bV=8F.by[1b.8G()];if(H(bV)=="1n"){F 8F.bT(bV)}N{if(1b=="aP"){F 8F.sT()}}F O},8f:G(4Q){u I=B.V.V;u bU=4Q.3H(0,3);if(bU=="1B"){F I.h9(4Q)}N{if(bU=="1G"){F I.h8(4Q)}N{if(4Q.3Z(0)=="#"){F I.bT(4Q)}}}F I.hi(4Q)},bT:G(4P){if(4P.3Z(0)=="#"){4P=4P.2W(1)}u 8E=[];u i,5x;if(4P.K==3){R(i=0;i<3;i++){5x=4P.3H(i,1);8E.1c(3w(5x+5x,16)/3h)}}N{R(i=0;i<6;i+=2){5x=4P.3H(i,2);8E.1c(3w(5x,16)/3h)}}u bS=B.V.V;F bS.3Y.1w(bS,8E)},bG:G(4O,hf,hg,4N){if(4N.2A(4O)===0){4N=4N.2W(4N.2A("(",3)+1,4N.K-1)}u bR=4N.2R(/\\s*,\\s*/);u bP=[];R(u i=0;i<bR.K;i++){u c=bR[i];u 2i;u bQ=c.2W(c.K-3);if(c.3Z(c.K-1)=="%"){2i=0.bE*4M(c.2W(0,c.K-1))}N{if(bQ=="sS"){2i=4M(c)/bF}N{if(bQ=="sR"){2i=4M(c)/(28.sQ*2)}N{2i=hg[i]*4M(c)}}}bP.1c(2i)}F D[hf].1w(D,bP)},bN:G(Q,sP,sO){u d=B.S;u 2F=B.V.V;R(Q=d.1E(Q);Q;Q=Q.3t){u bO=d.4q.1w(d,M);if(!bO){2V}u 8D=2F.8f(bO);if(!8D){2K}if(8D.6r().a>0){F 8D}}F O},ba:G(Q){u 2F=B.V.V;F 2F.bN(Q,"aZ","he-3U")||2F.sN()},sM:G(Q){u 2F=B.V.V;F 2F.bN(Q,"3U","3U")||2F.sL()},sK:G(){F B.J.4L(B.V.V.by)}});B.J.2l(B.V,{6F:G(v,8C){v*=8C;if(v<0){F 0}N{if(v>8C){F 8C}N{F v}}},hc:G(n1,n2,1o){if(1o>6){1o-=6}N{if(1o<0){1o+=6}}u 2i;if(1o<1){2i=n1+(n2-n1)*1o}N{if(1o<3){2i=n2}N{if(1o<4){2i=n1+(n2-n1)*(4-1o)}N{2i=n1}}}F 2i},bz:G(1o,5w,3i,bM){if(M.K==1){u 2Q=1o;1o=2Q.h;5w=2Q.s;3i=2Q.v;bM=2Q.a}u 1v;u 3K;u 1F;if(5w===0){1v=0;3K=0;1F=0}N{u i=28.8B(1o*6);u f=(1o*6)-i;u p=3i*(1-5w);u q=3i*(1-(5w*f));u t=3i*(1-(5w*(1-f)));hd(i){3j 1:1v=q;3K=3i;1F=p;2K;3j 2:1v=p;3K=3i;1F=t;2K;3j 3:1v=p;3K=q;1F=3i;2K;3j 4:1v=t;3K=p;1F=3i;2K;3j 5:1v=3i;3K=p;1F=q;2K;3j 6:3j 0:1v=3i;3K=t;1F=p;2K}}F{r:1v,g:3K,b:1F,a:bM}},bB:G(1o,5v,3v,bL){if(M.K==1){u 1G=1o;1o=1G.h;5v=1G.s;3v=1G.l;bL=1G.a}u 1v;u 8A;u 1F;if(5v===0){1v=3v;8A=3v;1F=3v}N{u m2;if(3v<=0.5){m2=3v*(1+5v)}N{m2=3v+5v-(3v*5v)}u m1=(2*3v)-m2;u f=B.V.hc;u h6=1o*6;1v=f(m1,m2,h6+2);8A=f(m1,m2,h6);1F=f(m1,m2,h6-2)}F{r:1v,g:8A,b:1F,a:bL}},bA:G(1v,4K,1F,bK){if(M.K==1){u 1B=1v;1v=1B.r;4K=1B.g;1F=1B.b;bK=1B.a}u 29=28.29(28.29(1v,4K),1F);u 2a=28.2a(28.2a(1v,4K),1F);u 1o;u 8z;u hb=29;if(2a==29){1o=0;8z=0}N{u 6H=(29-2a);8z=6H/29;if(1v==29){1o=(4K-1F)/6H}N{if(4K==29){1o=2+((1F-1v)/6H)}N{1o=4+((1v-4K)/6H)}}1o/=6;if(1o<0){1o+=1}if(1o>1){1o-=1}}F{h:1o,s:8z,v:hb,a:bK}},bC:G(1v,4J,1F,bI){if(M.K==1){u 1B=1v;1v=1B.r;4J=1B.g;1F=1B.b;bI=1B.a}u 29=28.29(1v,28.29(4J,1F));u 2a=28.2a(1v,28.2a(4J,1F));u 1o;u 6G;u bJ=(29+2a)/2;u 4I=29-2a;if(4I===0){1o=0;6G=0}N{if(bJ<=0.5){6G=4I/(29+2a)}N{6G=4I/(2-29-2a)}if(1v==29){1o=(4J-1F)/4I}N{if(4J==29){1o=2+((1F-1v)/4I)}N{1o=4+((1v-4J)/4I)}}1o/=6;if(1o<0){1o+=1}if(1o>1){1o-=1}}F{h:1o,s:6G,l:bJ,a:bI}},6E:G(1P){1P=28.ha(1P);u bH=1P.1l(16);if(1P<16){F"0"+bH}F bH},2d:G(){u m=B.J;D.V.h9=m.1O(D.V.bG,D.V,"1B","3Y",[1/3h,1/3h,1/3h,1]);D.V.h8=m.1O(D.V.bG,D.V,"1G","4H",[1/bF,0.bE,0.bE,1]);u 4G=1/3;u bD={8y:[0,0,0],1F:[0,0,1],gY:[0.6,0.4,0.2],gX:[0,1,1],sJ:[4G,4G,4G],gR:[0.5,0.5,0.5],bx:[0,1,0],sI:[2*4G,2*4G,2*4G],gN:[1,0,1],gL:[1,0.5,0],gK:[0.5,0,0.5],1v:[1,0,0],aP:[0,0,0,0],4F:[1,1,1],gI:[1,1,0]};u h7=G(1b,r,g,b,a){u W=D.3Y(r,g,b,a);D[1b]=G(){F W};F W};R(u k in bD){u 1b=k+"V";u h5=m.2o([h7,D.V,1b],bD[k]);D.V[1b]=m.1O.1w(O,h5)}u h0=G(){R(u i=0;i<M.K;i++){if(!(M[i]2C V)){F 1m}}F 1h};u gZ=G(a,b){F a.h4(b)};m.3f(D);m.5u(D.V.1r,h0,gZ);D.2k={":3e":D.1z,":1p":m.2o(D.1z,D.1W)}}});B.V.1z=["V"];B.V.1W=["6F","bC","bB","bA","bz","6E"];B.V.2d();B.J.2Y(D,B.V);B.V.V.by={sH:"#sG",sF:"#sE",sD:"#gW",sC:"#sB",sA:"#sz",sy:"#sx",sw:"#sv",8y:"#su",st:"#sr",1F:"#sq",sp:"#so",gY:"#sn",sm:"#sl",sk:"#sj",si:"#sh",sg:"#se",sd:"#sc",sb:"#sa",s9:"#s8",s7:"#s6",gX:"#gW",s5:"#s4",s3:"#s2",s1:"#s0",rZ:"#gV",rY:"#rX",rW:"#gV",rV:"#rU",rT:"#rS",rR:"#rQ",rP:"#rO",rN:"#rM",gU:"#rL",rK:"#rJ",rI:"#rH",rG:"#rF",rE:"#gT",rD:"#gT",rC:"#rB",rA:"#rz",ry:"#rx",rw:"#rv",ru:"#gS",rt:"#gS",rs:"#rr",rq:"#rp",ro:"#rn",rm:"#rl",rk:"#gM",rj:"#ri",rh:"#rg",rf:"#rd",rc:"#rb",gR:"#gQ",bx:"#ra",r9:"#r8",r7:"#gQ",r6:"#r5",r4:"#r3",r2:"#r1",r0:"#qZ",qY:"#qX",qW:"#qV",qU:"#qT",qS:"#qR",qQ:"#qP",qO:"#qN",qM:"#qL",qK:"#qJ",qI:"#qH",qG:"#qF",qE:"#gP",qD:"#qC",qB:"#gP",qA:"#qz",qy:"#qx",qw:"#qv",qu:"#qt",qr:"#gO",qq:"#gO",qp:"#qo",qn:"#qm",ql:"#qk",qj:"#qi",qh:"#qg",gN:"#gM",qf:"#qe",qd:"#qc",qb:"#qa",q9:"#q8",q7:"#q6",q5:"#q4",q3:"#q2",q1:"#q0",pZ:"#pY",pX:"#pW",pV:"#pU",pT:"#pS",pR:"#pQ",pP:"#pO",pN:"#pM",pL:"#pK",pJ:"#pI",pH:"#pG",pF:"#pE",gL:"#pD",pC:"#pB",pA:"#pz",py:"#pw",pv:"#pu",pt:"#ps",pr:"#pq",pp:"#po",pn:"#pm",pl:"#pj",pi:"#ph",pg:"#pf",pe:"#pd",gK:"#pc",1v:"#pb",pa:"#p9",p8:"#p7",p6:"#p5",p4:"#p3",p2:"#p1",p0:"#oZ",oY:"#oX",oW:"#oV",oU:"#oT",oS:"#oR",oQ:"#oP",oO:"#gJ",oN:"#gJ",oM:"#oL",oK:"#oJ",oI:"#oH",oG:"#oF",oE:"#oD",oC:"#oB",oA:"#oz",oy:"#ox",ow:"#ov",ou:"#ot",4F:"#os",oq:"#op",gI:"#oo",om:"#ok"};if(H(1q)!="L"){1q.2X("B.1u");1q.2M("B.J");1q.2M("B.S")}if(H(1x)!="L"){1x.26("B.J",[]);1x.26("B.S",[])}1f{if(H(B.J)=="L"){14""}}1e(e){14"B.1u 3F on B.J!"}1f{if(H(B.S)=="L"){14""}}1e(e){14"B.1u 3F on B.S!"}if(H(B.1u)=="L"){B.1u={}}B.1u.1r="B.1u";B.1u.1Y="1.3.1";B.1u.4x=[];B.1u.bq=G(1d,e){D.1L=e||2O.6D;D.gH=1d};B.J.2l(B.1u.bq.1U,{1K:G(){u U=B.J.U;u 1y="{6D(): "+U(D.6D())+", 1d(): "+U(D.1d())+", 1J(): "+U(D.1J())+", 8x(): "+U(D.8x())+", 4E(): "+"{8w: "+U(D.4E().8w)+", 8v: "+U(D.4E().8v)+", 8u: "+U(D.4E().8u)+", 2P: "+U(D.4E().2P)+", bw: "+U(D.4E().bw)+"}";if(D.1J()&&D.1J().2A("2h")===0){1y+=", 2h(): {3J: "+U(D.2h().3J)+", 1n: "+U(D.2h().1n)+"}"}if(D.1J()&&(D.1J().2A("3I")===0||D.1J().2A("gE")!=-1||D.1J()=="gD")){1y+=", 3I(): {4D: "+U(D.3I().4D)+", 6A: "+U(D.3I().6A);if(D.1J()!="gC"){1y+=", 2e: {2I: "+U(D.3I().2e.2I)+", 6v: "+U(D.3I().2e.6v)+", 3g: "+U(D.3I().2e.3g)+"}}"}N{1y+="}"}}if(D.1J()=="gG"||D.1J()=="gF"){1y+=", 6C(): "+U(D.6C())}1y+="}";F 1y},1l:G(){F D.1K()},1d:G(){F D.gH},6D:G(){F D.1L},1J:G(){F D.1L.1J||L},8x:G(){F D.1L.8x||D.1L.oj},6C:G(){if(D.1J()=="gG"){F(D.1L.6C||D.1L.aW)}N{if(D.1J()=="gF"){F(D.1L.6C||D.1L.oi)}}F L},4E:G(){u m={};m.8w=D.1L.oh;m.8v=D.1L.og;m.8u=D.1L.oe||1m;m.2P=D.1L.od;m.bw=m.8w||m.8v||m.2P||m.8u;F m},2h:G(){u k={};if(D.1J()&&D.1J().2A("2h")===0){if(D.1J()=="oc"||D.1J()=="ob"){k.3J=D.1L.8t;k.1n=(B.1u.5r[k.3J]||"oa");F k}N{if(D.1J()=="o9"){k.3J=0;k.1n="";if(H(D.1L.6B)!="L"&&D.1L.6B!==0&&!B.1u.bv[D.1L.6B]){k.3J=D.1L.6B;k.1n=bu.bt(k.3J)}N{if(D.1L.8t&&H(D.1L.6B)=="L"){k.3J=D.1L.8t;k.1n=bu.bt(k.3J)}}F k}}}F L},3I:G(){u m={};u e=D.1L;if(D.1J()&&(D.1J().2A("3I")===0||D.1J().2A("gE")!=-1||D.1J()=="gD")){m.6A=Y B.S.5t(0,0);if(e.6z||e.6x){m.6A.x=(!e.6z||e.6z<0)?0:e.6z;m.6A.y=(!e.6x||e.6x<0)?0:e.6x}m.4D=Y B.S.5t(0,0);if(e.8s||e.8r){m.4D.x=(!e.8s||e.8s<0)?0:e.8s;m.4D.y=(!e.8r||e.8r<0)?0:e.8r}N{u de=B.S.1Z.7Z;u b=B.S.1Z.5s;m.4D.x=e.6z+(de.6y||b.6y)-(de.8q||b.8q);m.4D.y=e.6x+(de.4C||b.4C)-(de.8p||b.8p)}if(D.1J()!="gC"){m.2e={};m.2e.2I=1m;m.2e.3g=1m;m.2e.6v=1m;if(e.6w){m.2e.2I=(e.6w==1);m.2e.6v=(e.6w==2);m.2e.3g=(e.6w==3)}N{m.2e.2I=!!(e.2e&1);m.2e.3g=!!(e.2e&2);m.2e.6v=!!(e.2e&4)}}F m}F L},2J:G(){D.8o();D.8n()},8o:G(){if(D.1L.8o){D.1L.8o()}N{D.1L.o8=1h}},8n:G(){if(D.1L.8n){D.1L.8n()}N{D.1L.o7=1m}}});B.1u.bv={3:"gz",o6:"gA",o5:"gy",o4:"gx",o3:"gw",o2:"gv",o1:"gu",o0:"gs",nZ:"gr",nY:"gq",nX:"gp",nW:"go"};R(i=gB;i<=nV;i++){B.1u.bv[i]="gk"+(i-gB+1)}B.1u.5r={8:"nU",9:"nT",12:"gA",13:"gz",16:"nS",17:"nR",18:"nQ",19:"nP",20:"nO",27:"nN",32:"nM",33:"gy",34:"gx",35:"gw",36:"gv",37:"gu",38:"gs",39:"gr",40:"gq",44:"nL",45:"gp",46:"go",59:"gn",91:"nK",92:"nJ",93:"nI",nH:"nG",nF:"nE",nD:"nC-gm",nB:"nA",nz:"ny",nx:"nw",nv:"nu",nt:"gn",ns:"nr",nq:"np",nn:"nm-gm",nl:"nk",nj:"ni",nh:"ng",nf:"nd",nc:"nb",na:"n9",n8:"n7"};R(u i=48;i<=57;i++){B.1u.5r[i]="gl"+(i-48)}R(i=65;i<=90;i++){B.1u.5r[i]="gl"+bu.bt(i)}R(i=96;i<=n6;i++){B.1u.5r[i]="n5"+(i-96)}R(i=gj;i<=n4;i++){B.1u.5r[i]="gk"+(i-gj+1)}B.J.2l(B.1u,{1K:G(){F"["+D.1r+" "+D.1Y+"]"},1l:G(){F D.1K()},g7:G(){u I=B.1u;u bs=I.4x;R(u i=0;i<bs.K;i++){I.6t(bs[i])}gi I.4x;1f{2O.gh=L}1e(e){}1f{2O.g8=L}1e(e){}},gb:G(1d,1A,1i,gg){u E=B.1u.bq;if(!gg){F B.J.1O(1A,1i)}1i=1i||1d;if(H(1A)=="1n"){F G(gf){1i[1A].1w(1i,[Y E(1d,gf)])}}N{F G(gd){1A.1w(1i,[Y E(1d,gd)])}}},6s:G(1d,2D,5q,4B){1d=B.S.1E(1d);u I=B.1u;if(H(2D)!="1n"){14 Y 2x("\'2D\' 5p be a 1n")}u 1i=O;u 1A=O;if(H(4B)!="L"){1i=5q;1A=4B;if(H(4B)=="1n"){if(H(5q[4B])!="G"){14 Y 2x("\'bp\' 5p be a G on \'gc\'")}}N{if(H(4B)!="G"){14 Y 2x("\'bp\' 5p be a G or 1n")}}}N{if(H(5q)!="G"){14 Y 2x("\'gc\' 5p be a G if \'bp\' is 2E n3")}N{1A=5q}}if(H(1i)=="L"||1i===O){1i=1d}u bm=!!(1d.bo||1d.bn);u 8m=I.gb(1d,1A,1i,bm);if(1d.bo){1d.bo(2D.3H(2),8m,1m)}N{if(1d.bn){1d.bn(2D,8m)}}u bk=[1d,2D,8m,bm,5q,4B];I.4x.1c(bk);F bk},6t:G(6u){if(!6u[3]){F}u 1d=6u[0];u 2D=6u[1];u bj=6u[2];if(1d.ga){1d.ga(2D.3H(2),bj,1m)}N{if(1d.g9){1d.g9(2D,bj)}N{14 Y 2x("\'1d\' 5p be a S n0")}}},8j:G(bh){u I=B.1u;u 5o=I.4x;u m=B.J;if(M.K>1){u 1d=B.S.1E(M[0]);u 2D=M[1];u 1i=M[2];u 1A=M[3];R(u i=5o.K-1;i>=0;i--){u o=5o[i];if(o[0]===1d&&o[1]===2D&&o[4]===1i&&o[5]===1A){I.6t(o);5o.4y(i,1);F 1h}}}N{u 5n=m.bi(5o,bh);if(5n>=0){I.6t(bh);5o.4y(5n,1);F 1h}}F 1m},8i:G(1d,2D){1d=B.S.1E(1d);u m=B.J;u 8l=m.bg(m.1R(O,M,1));u I=B.1u;u bd=I.6t;u 4z=I.4x;if(8l.K===0){R(u i=4z.K-1;i>=0;i--){u 4A=4z[i];if(4A[0]===1d){bd(4A);4z.4y(i,1)}}}N{u bf={};R(u i=0;i<8l.K;i++){bf[8l[i]]=1h}R(u i=4z.K-1;i>=0;i--){u 4A=4z[i];if(4A[0]===1d&&4A[1]in bf){bd(4A);4z.4y(i,1)}}}},8h:G(1d,2D){u bc=B.1u.4x;1d=B.S.1E(1d);u 3G=B.J.1R(O,M,2);u 5m=[];R(u i=0;i<bc.K;i++){u 8k=bc[i];if(8k[0]===1d&&8k[1]===2D){1f{8k[2].1w(1d,3G)}1e(e){5m.1c(e)}}}if(5m.K==1){14 5m[0]}N{if(5m.K>1){u e=Y 2x("mZ bb mY in mX \'2D\', mW bb mV");e.bb=5m;14 e}}}});B.1u.1W=[];B.1u.1z=["6s","8j","8h","8i"];B.1u.2d=G(2m){u m=B.J;D.1Z=2v;D.3X=2m;1f{D.6s(2O,"g8",D.g7)}1e(e){}D.2k={":3e":D.1z,":1p":m.2o(D.1z,D.1W)};m.3f(D)};B.1u.2d(D);if(!B.3d){6s=B.1u.6s;8j=B.1u.8j;8i=B.1u.8i;8h=B.1u.8h}B.J.2Y(D,B.1u);if(H(1q)!="L"){1q.2X("B.1X");1q.2M("B.J");1q.2M("B.S");1q.2M("B.V")}if(H(1x)!="L"){1x.26("B.J",[]);1x.26("B.S",[]);1x.26("B.V",[])}1f{if(H(B.J)=="L"||H(B.S)=="L"||H(B.V)=="L"){14""}}1e(e){14"B.1X 3F on B.J, B.S 3W B.V!"}if(H(B.1X)=="L"){B.1X={}}B.1X.1r="B.1X";B.1X.1Y="1.3.1";B.1X.1K=G(){F"["+D.1r+" "+D.1Y+"]"};B.1X.1l=G(){F D.1K()};B.1X.aI=G(e,g6){e=B.S.1E(e);D.fN(g6);if(D.1S.fL){e=D.g5(e)}u 4w=D.1S.3U;u C=B.V.V;if(D.1S.3U=="aW"){4w=C.ba(e)}N{if(!(4w 2C C)){4w=C.8f(4w)}}D.82=(4w.6r().a<=0);u 5l=D.1S.aV;if(D.1S.aV=="fM"){5l=C.ba(e.8g)}N{if(!(5l 2C C)){5l=C.8f(5l)}}D.g3(e,4w,5l)};B.1X.aI.1U={g5:G(e){u mU=e.3t;u 1N=B.S.b9();if(H(1N.5k)=="L"||1N.5k===O){F e}u 4v=1N.5k.g4(e,O);if(H(4v)=="L"||4v===O){F e}u b8=B.S.6m({"1T":{3u:"8c",mT:4v.6q("6p-3D"),85:4v.6q("6p-3g"),mS:4v.6q("6p-6f"),86:4v.6q("6p-2I"),6p:"2N"}});b8.6o=e.6o;e.6o="";e.2c(b8);F e},g3:G(e,b7,8e){if(D.1S.3E){D.g2(e,8e)}if(D.fy()){D.fX(e,b7,8e)}if(D.fx()){D.fV(e,b7,8e)}},g2:G(el,g1){u b6="6l 8a "+D.aQ(g1);u g0="3E-2I: "+b6;u fZ="3E-3g: "+b6;u fY="1T=\'"+g0+";"+fZ+"\'";el.6o="<4u "+fY+">"+el.6o+"</4u>"},fX:G(el,fW,b5){u b4=D.b1(b5);R(u i=0;i<D.1S.89;i++){b4.2c(D.b0(fW,b5,i,"3D"))}el.1T.mR=0;el.mQ(b4,el.6n)},fV:G(el,fU,b3){u b2=D.b1(b3);R(u i=(D.1S.89-1);i>=0;i--){b2.2c(D.b0(fU,b3,i,"6f"))}el.1T.mP=0;el.2c(b2)},b1:G(fT){u 2q=B.S;F 2q.6m({1T:{aZ:fT.1l()}})},b0:G(aY,fQ,n,aX){u 6k=B.S.8d();u 2p=6k.1T;2p.aZ=aY.1l();2p.3u="8c";2p.3V="6l";2p.fS="fR";2p.mO="6l";u 8b=D.aQ(aY,fQ);if(D.1S.3E&&n===0){2p.mN="8a";2p.mM="6l";2p.84="2N";2p.83="2N";2p.mL="2N";2p.3V="2N";2p.fP=8b.1l()}N{if(8b){2p.fP=8b.1l();2p.mK="8a";2p.mJ="2N 6l"}}if(!D.1S.4r&&(n==(D.1S.89-1))){2p.3V="fO"}D.fI(6k,n,aX);D.fG(6k,n,aX);F 6k},fN:G(fK){D.1S={6g:"1p",3U:"aW",aV:"fM",5j:1h,3E:1m,4r:1m,fL:1m};B.J.2l(D.1S,fK);D.1S.89=(D.1S.4r?2:4)},aL:G(){u 88=D.1S.6g;if(D.6h(88,"1p","3D")){F""}u aU=(88.2A("tl")!=-1);u aT=(88.2A("tr")!=-1);if(aU&&aT){F""}if(aU){F"2I"}if(aT){F"3g"}F""},aK:G(){u 87=D.1S.6g;if(D.6h(87,"1p","6f")){F""}u aS=(87.2A("bl")!=-1);u aR=(87.2A("br")!=-1);if(aS&&aR){F""}if(aS){F"2I"}if(aR){F"3g"}F""},aQ:G(aN,aO){if(aN=="aP"){F aO}N{if(D.1S.3E){F D.1S.3E}N{if(D.1S.5j){F aO.fJ(aN)}}}F""},fI:G(el,n,fH){u 6j=D.fE(n)+"px";u aM=(fH=="3D"?D.aL():D.aK());u 4t=el.1T;if(aM=="2I"){4t.86=6j;4t.85="2N"}N{if(aM=="3g"){4t.85=6j;4t.86="2N"}N{4t.86=6j;4t.85=6j}}},fG:G(el,n,fF){u 6i=D.fz(n)+"px";u aJ=(fF=="3D"?D.aL():D.aK());u 4s=el.1T;if(aJ=="2I"){4s.84=6i;4s.83="2N"}N{if(aJ=="3g"){4s.83=6i;4s.84="2N"}N{4s.84=6i;4s.83=6i}}},fE:G(n){if(D.82){F 0}u o=D.1S;if(o.4r&&o.5j){u fD=[1,0];F fD[n]}N{if(o.4r){u fC=[2,1];F fC[n]}N{if(o.5j){u fB=[3,2,1,0];F fB[n]}N{u fA=[5,3,2,1];F fA[n]}}}},fz:G(n){u o=D.1S;u 5i;if(o.4r&&(o.5j||D.82)){F 1}N{if(o.4r){5i=[1,0]}N{if(o.5j){5i=[2,1,1,1]}N{if(o.3E){5i=[0,2,0,0]}N{if(D.82){5i=[5,3,2,1]}N{F 0}}}}}F 5i[n]},6h:G(1y){R(u i=1;i<M.K;i++){if(1y.2A(M[i])!=-1){F 1h}}F 1m},fy:G(){F D.6h(D.1S.6g,"1p","3D","tl","tr")},fx:G(){F D.6h(D.1S.6g,"1p","6f","bl","br")},mI:G(el){F(el.5h.K==1&&el.5h[0].3T==3)}};B.1X.aF=G(e,fw){Y B.1X.aI(e,fw)};B.1X.fs=G(fv,fu,ft){u aG=B.S.aH(fv,fu);R(u i=0;i<aG.K;i++){B.1X.aF(aG[i],ft)}};B.1X.V=B.V.V;B.1X.mH=B.S.4q;B.1X.2d=G(){u m=B.J;m.3f(D);D.2k={":3e":D.1z,":1p":m.2o(D.1z,D.1W)}};B.1X.1z=["aF","fs"];B.1X.1W=[];B.1X.2d();B.J.2Y(D,B.1X);if(H(B)=="L"){B={}}if(H(B.B)=="L"){B.B={}}B.B.1r="B.B";B.B.1Y="1.3.1";B.B.1K=G(){F"["+D.1r+" "+D.1Y+"]"};B.B.1l=G(){F D.1K()};B.B.aA=["J","15","1H","1D","1s","1k","S","1I","V","1u","1X"];if(H(1x)!="L"||H(1q)!="L"){if(H(1q)!="L"){1q.2X("B.B");1q.2M("B.*")}if(H(1x)!="L"){1x.26("B.J",[]);1x.26("B.15",[]);1x.26("B.1H",[]);1x.26("B.1D",[]);1x.26("B.1s",[]);1x.26("B.1k",[]);1x.26("B.S",[]);1x.26("B.1I",[]);1x.26("B.V",[]);1x.26("B.1u",[]);1x.26("B.1X",[])}(G(){u 6e=B.J.1R;u I=B.B;u aE=I.aA;u aD=[];u aC=[];u 81={};u i,k,m,1p;R(i=0;i<aE.K;i++){m=B[aE[i]];6e(aD,m.1z);6e(aC,m.1W);R(k in m.2k){81[k]=6e(81[k],m.2k[k])}1p=m.2k[":1p"];if(!1p){1p=6e(O,m.1z,m.1W)}u j;R(j=0;j<1p.K;j++){k=1p[j];I[k]=m[k]}}I.1z=aD;I.1W=aC;I.2k=81}())}N{if(H(B.3d)=="L"){B.3d=1h}(G(){u 80=2v.fr("7W");u ay="fq://fp.mG.fo/mF/mE/mD.is.aB.mC";u 2w=O;u ax=O;u az={};u i;R(i=0;i<80.K;i++){u 1d=80[i].fm("1d");if(!1d){2V}az[1d]=1h;if(1d.3C(/B.js$/)){2w=1d.2W(0,1d.mB("B.js"));ax=80[i]}}if(2w===O){F}u 6d=B.B.aA;R(u i=0;i<6d.K;i++){if(B[6d[i]]){2V}u 7Y=2w+6d[i]+".js";if(7Y in az){2V}if(2v.7Z&&2v.7Z.mA==ay){u s=2v.mz(ay,"7W");s.4p("id","my"+2w+6d[i]);s.4p("1d",7Y);s.4p("1J","mx/x-fk");ax.3t.2c(s)}N{2v.fl("<7W 1d=\\""+7Y+"\\" 1J=\\"7X/fk\\"></7W>")}}})()}',62,1976,'||||||||||||||||||||||||||||||var|||||||MochiKit||this||return|function|typeof|self|Base|length|undefined|arguments|else|null||elem|for|DOM||repr|Color|rval|res|new||||||throw|Iter|||||next|name|push|src|catch|try|lst|true|obj|node|Async|toString|false|string|hue|all|dojo|NAME|Format|msg|Signal|red|apply|JSAN|str|EXPORT|func|rgb|_425|DateTime|getElement|blue|hsl|Logging|LoggingPane|type|__repr__|_event|while|doc|bind|num|iter|extend|options|style|prototype|seq|EXPORT_OK|Visual|VERSION|_document||_434||replace|forwardCall|StopIteration|use||Math|max|min|join|appendChild|__new__|button|compare|date|key|val|_329|EXPORT_TAGS|update|win|pair|concat|_596|dom|map|req|Deferred|sync|document|base|Error|number|partial|indexOf||instanceof|sig|not|cls|list|fired|left|stop|break|logger|require|0px|window|shift|hsv|split|createElement|_423|callee|continue|substring|provide|_exportSymbols|ccc||_464|||||||||step|pred|_51|__compat__|common|nameFunctions|right|255|_517|case|100|_loggingPane|value|object|callback|TypeError|_251|_246|_113|parentNode|display|_522|parseInt|cssText|wrap|info|isArrayLike|end|match|top|border|depends|args|substr|mouse|code|_519|_443|className|level|err|frac|Date|_135|_85|nodeType|color|height|and|_window|fromRGB|charAt||asHSL|_444|message||||filter||LogMessage|AdapterRegistry|_366|imap|NotFound|locked|counter|_262|_messages|operator|cmp|_165|_161|pairs|arr|_52|setAttribute|computedStyle|compact|_614|_610|div|_576|_572|_observers|splice|_565|_566|_555|scrollTop|page|modifier|white|_541|fromHSL|_539|_535|_528|clone|parseFloat|_505|pre|_499|_497|_427|createTextNode|_446|attributeArray|_388|_379|updateNodeAttributes|_341|_326||box|errback|results|paused|chain|_285||ofs||NamedError|_175|_147|_122|_83|_54|_17|childNodes|_619|blend|defaultView|_574|_569|idx|_562|must|_554|_specialKeys|body|Coordinates|registerComparator|_521|_516|hex|mid|_478|width|loggingPane|LogLevel|nwin|head|url|setElementClass|callStack|path|dest|_359|boolean|register|Dimensions|DeferredLock|_313|addCallback|_310|waiting|onreadystatechange|_290|LOCALE|year|printfire|_214|log|_213|_211|pos|_155|_153||typeMatcher|listMinMax|_114|_40|itr|typ|_19|_634|_625|bottom|corners|_hasString|_612|_608|_595|1px|DIV|firstChild|innerHTML|padding|getPropertyValue|asRGB|connect|_disconnect|_559|middle|which|clientY|scrollLeft|clientX|client|charCode|relatedTarget|event|toColorPart|clampColorComponent|_537|_534|toFixed|_468|buildAndApplyFilter|_442|_441|_440|_439|position|_463|_447|removeChild|_449|uid|_428|_426|compliant|attributes|_422|_409|_412|_400|_395|_390|_389|_377|_375|_363|attr|ctx|repeat|_340|_339|isNotEmpty|_335|_333|opera|DeferredList|ret|_309|silentlyCancelled|canceller|_nextId|Array|_293|XMLHttpRequest|chained|_281|tail|_252|_225|msec|day|month|iso|Logger|_208|listeners|_200|_198|_194|_196|reduce|range|_169|_162|truth|registerRepr|_121|_70|_58|_56|_47|_45|_41|_13|_1|script|text|uri|documentElement|_630|_629|isTransparent|borderRightWidth|borderLeftWidth|marginRight|marginLeft|_602|_599|numSlices|solid|_597|block|SPAN|_579|fromString|offsetParent|signal|disconnectAll|disconnect|_570|_563|_557|preventDefault|stopPropagation|clientTop|clientLeft|pageY|pageX|keyCode|meta|ctrl|alt|target|black|_532|_524|floor|_513|_512|_500|_495|toLowerCase|_487|DEBUG|INFO|WARNING|FATAL|ERROR|colorTable|logFont|closed|inline|onclick|_438|_437|_445|RegExp|_452|space|title|updatetree|||||withDocument|withWindow||setDisplayForElement|none|renames|forEach|domConverters|escapeHTML|addElementClass|removeElementClass|once|_378|_380|_376|appendChildNodes|coerceToDOM|_355|opt|clientWidth|opacity|GenericError|fail|resultList|_307|_301|_fire|can|addCallbacks|_resback|percent|decimal|separator|twoDigitFloat|_274|_273|_264|_257|_250|_249|_254|_248|_243|_242|fmt|_240|_245|getTime|sec|hour|_209|slice|_206|iterateNextIter|registerIteratorFactory|arrayLikeIter|iteratorRegistry|takewhile|ifilterfalse|ifilter|_181|_176|_168|_166|_159|_tee|deque|arg|fun|jsonRegistry|reprString|reprRegistry|comparatorRegistry|urlEncode|_110|_108|cur|_95|_87|_71|im_preargs||_53|_57|_46|present|like|array|Argument|_15|_12|_632|_631|_633|SUBMODULES|only|_628|_627|_626|roundElement|_624|getElementsByTagAndClassName|_RoundCorners|_613|_whichSideBottom|_whichSideTop|_609|_605|_606|transparent|_borderColor|_604|_603|_601|_600|bgColor|fromElement|_594|_592|backgroundColor|_createCornerSlice|_createCorner|_590|_589|_587|_586|_581|_578|_577|currentDocument|fromBackground|errors|_568|_564||sigs|flattenArguments|_561|findIdentical|_560|_558||_556|attachEvent|addEventListener|funcOrStr|Event||_548|fromCharCode|String|_specialMacKeys|any|green|_namedColors|hsvToRGB|rgbToHSV|hslToRGB|rgbToHSL|_542|01|360|_fromColorString|_540|_536|_538|_529|_523|_518|fromComputedStyle|_511|_507|_508|_506|_501|fromHexString|_498|_496|_486|__class__|createLoggingPane|_459|_461|font|_462|_430|_435|1000|index|_460|getMessages|removeListener|_451||_457|_450|infore|_448|_456|logDebug|offsetHeight|span|input|_436|TR||HTML|open|alert|currentWindow|swapDOM|SELECT|FORM|INPUT|createDOMFunc|ignoreAttr|_421|call|_417|_410|_415|nodeName|_414|_413|emitHTML|good|_406|_399|_397|_393|_392|addLoadEvent|addToCallStack|_387|_386|_381|_382|_383|_373|_372|_369|createDOM|_365|Function|_360|_362|_358|_344|nodeWalk|formContents|_337|_338|_334|_332|offsetTop|offsetLeft|visibility|parentElement|||XMLHttpRequestError|BrowserComplianceError|CancelledError|AlreadyCalledError|evalJSONRequest|sendXMLHttpRequest|wait|doSimpleXMLHttpRequest|getXMLHttpRequest|succeed|_312|finishedCount|_308|_cbDeferred|_303|_297|queryString|_nothing|_289|XMLHTTP|ActiveXObject|eval|_284|_check|error|_279|default|rstrip|lstrip|formatLocale|roundToFixed|truncToFixed|_276|pow|_272|_271|_270|sign|_265|_263|tmp|_238|_232|toISODate|toISOTime|getFullYear|getDate|getMonth|_230|_padTwo|_228|useNativeConsole|_212|compareLogMessage|isLogMessage|unshift|_207||maxSize|_202|_199|logLevelAtLeast|console|hasIterateNext|iterateNext|arrayLike|groupby||exhaust|tee|dropwhile|applymap||islice|izip|cycle|count||_189|_188|_183|_185|_184|_186|_187|_182|identity|fetch|_180|_177|listMin|reprNumber|reprArrayLike|compareArrayLike|compareDateLike|isDateLike|findValue|_128|__export__|keyComparator|_124|_118|_93|_94|_90|_88|_84|_77|_68|_67|_66|_65|_60|im_func|_55|im_self|_48|_44|_42|_39|_36|_33|_27|_26|_25|_22|_24|_20|javascript|write|getAttribute||org|www|http|getElementsByTagName|roundClass|_623|_622|_621|_620|_isBottomRounded|_isTopRounded|_borderSize|_618|_617|_616|_615|_marginSize|_611|_setBorder|_607|_setMargin|blendedColor|_598|__unstable__wrapElement|fromParent|_setOptions|2px|borderColor|_593|hidden|overflow|_591|_588|_roundBottomCorners|_585|_roundTopCorners|_584|_583|_582|_580|_renderBorder|_roundCornersImpl|getComputedStyle|_doWrap|_571|_unloadCache|onunload|detachEvent|removeEventListener|_listener|objOrFunc|_552||_551|_549|onload|delete|112|KEY_F|KEY_|MINUS|KEY_SEMICOLON|KEY_DELETE|KEY_INSERT|KEY_ARROW_DOWN|KEY_ARROW_RIGHT|KEY_ARROW_UP||KEY_ARROW_LEFT|KEY_HOME|KEY_END|KEY_PAGE_DOWN|KEY_PAGE_UP|KEY_ENTER|KEY_NUM_PAD_CLEAR|63236|mousemove|contextmenu|click|mouseout|mouseover|_src|yellow|708090|purple|orange|ff00ff|magenta|778899|d3d3d3|808080|gray|696969|2f4f4f|darkred|a9a9a9|00ffff|cyan|brown|_547|_546||||compareRGB|_545||_543|fromHSLString|fromRGBString|round|_533|_hslValue|switch|background|_503|_504||fromName|_488|col|toRGBString|_hexString|_rgbString|_hslString|toPrecision|isLight||_481|_477|_476|_475|_474|_473|_469|_466|closePane|_458|onkeypress|_454|addListener|_455|close|test|scrollHeight|option|word|moz|_431|getElementById|html|pop|200|_|removeElement|showElement|hideElement|CANVAS|STRONG|FIELDSET|LEGEND|OPTGROUP|OPTION|TEXTAREA|LABEL|HR|BR|H3|H2|H1|PRE|TT|BUTTON|IMG|TH||TABLE||TFOOT|THEAD|TBODY|TD|LI|OL|||UL|checked|class|ignoreAttrFilter||_424|_419|nodeValue|scrapeText|_416|_418|sort|_411|toHTML|_404|hasElementClass|_403|_402|_401|swapElementClass|_398|_394|toggleElementClass|_391|focusOnLoad|_newCallStack|currentStyle|_371|replaceChildNodes|_364|_361|getNodeAttribute|_357|setNodeAttribute|_354|_352|_350|_353|toDOM|_346|_345|registerDOMConverter|selectedIndex|setElementPosition|setElementDimensions|tagName|absolute|getBoxObjectFor|getBoundingClientRect|elementPosition|_325|_324|_322|_323|offsetWidth|elementDimensions|clientHeight|innerWidth|getViewportDimensions|setOpacity|status|_317|deferred|_316|_newNamedError|maybeDeferred||gatherResults|callLater|loadJSONDoc|_311|consumeErrors|fireOnOneErrback|fireOnOneCallback|addErrback|_305|_304|_306|unlocked|release|_300|_299|_298|_296|_xhr_onreadystatechange|_xhr_canceller|304|responseText|Msxml2|addBoth|_pause|_continue|result|the|are|they|instances|_unpause|cancel|_280|_278|en_US|strip|percentFormat|twoDigitAverage|numberFormatter|_277|_275|isNaN|_259|_258|_260|_255|_253|_numberFormatter|_241|_239|_237|_236|_235|_234|_233|_231|toAmericanDate|toPaddedAmericanDate|americanDate|toISOTimestamp|isoTimestamp|isoDate|foot|sep||60000|_221|_isoRegexp|dispatchEvent|createEvent|warning|logWarning|fatal|logFatal|debug|logError|baseLog|_210|getMessageText|logToConsole|dispatchListeners|_204|_203|ident|_201|postError|alertListener|_197|_192|groupby_as_array|iextend|some|reversed|sorted|every|sum|_190|eat|_174|_173|_172|_171|_167|_163|_158|_157|_151|_144|_141||_139|_136|_134||_133|_132|zip|merge|isUndefined|isCallable|listMax|_131|_130|encodeURIComponent||_127|method|parseQueryString|evalJSON|registerJSON|serializeJSON|objMin|objMax|reverseKeyComparator|arrayEqual|objEqual|bindMethods|xfilter|xmap|isEmpty|isNull|isUndefinedOrNull|itemgetter|items|keys|setdefault|_126|_120|decodeURIComponent|_119|len|_109|_107|_104|_105|_101|_102|_98|||_100|_97|_96|_91|json|__json__|_82|_81|_80|_79|_76||_75|_74|_73|_69|_primitives|_64|_63||_62|_61|_59|_wrapDumbFunction|_49|_50|_31|_30|_21|_7|application|MochiKit_|createElementNS|namespaceURI|lastIndexOf|xul|there|gatekeeper|keymaster|mozilla|getElementsComputedStyle|_hasSingleTextChild|borderWidth|borderStyle|borderBottomWidth|borderTopWidth|borderTopStyle|fontSize|paddingBottom|insertBefore|paddingTop|marginBottom|marginTop|_575|property|see|handling|thrown|Multiple|element|||given|123|KEY_NUM_PAD_|105|KEY_APOSTROPHE|222|KEY_RIGHT_SQUARE_BRACKET|221|KEY_REVERSE_SOLIDUS|220|KEY_LEFT_SQUARE_BRACKET||219|KEY_GRAVE_ACCENT|192|KEY_SOLIDUS|191|KEY_FULL_STOP|190|KEY_HYPHEN|189||KEY_COMMA|188|KEY_EQUALS_SIGN|187|186|KEY_SCROLL_LOCK|145|KEY_NUM_LOCK|144|KEY_NUM_PAD_SOLIDUS|111|KEY_NUM_PAD_FULL_STOP|110|KEY_NUM_PAD_HYPHEN|109|KEY_NUM_PAD_PLUS_SIGN|107|KEY_NUM_PAD_ASTERISK|106|KEY_SELECT|KEY_WINDOWS_RIGHT|KEY_WINDOWS_LEFT|KEY_PRINT_SCREEN|KEY_SPACEBAR|KEY_ESCAPE|KEY_CAPS_LOCK|KEY_PAUSE|KEY_ALT|KEY_CTRL|KEY_SHIFT|KEY_TAB|KEY_BACKSPACE|63242|63272|63302|63233|63235|63232|63234|63273|63275|63277|63276|63289|returnValue|cancelBubble|keypress|KEY_UNKNOWN|keyup|keydown|shiftKey|metaKey||ctrlKey|altKey|toElement|srcElement|9acd32||yellowgreen||ffff00|f5f5f5|whitesmoke||ffffff|f5deb3|wheat|ee82ee|violet|40e0d0|turquoise|ff6347|tomato|d8bfd8|thistle|008080|teal|d2b48c|tan|4682b4|steelblue|00ff7f|springgreen|fffafa|snow|slategrey|slategray|6a5acd|slateblue|87ceeb|skyblue|c0c0c0|silver|a0522d|sienna|fff5ee|seashell|2e8b57|seagreen|f4a460|sandybrown|fa8072|salmon|8b4513|saddlebrown|4169e1|royalblue|bc8f8f|rosybrown|ff0000|800080|b0e0e6|powderblue|dda0dd|plum|ffc0cb|pink|cd853f||peru|ffdab9|peachpuff|ffefd5|papayawhip|db7093|palevioletred|afeeee|paleturquoise|98fb98|palegreen|eee8aa||palegoldenrod|da70d6|orchid|ff4500|orangered|ffa500|6b8e23|olivedrab|808000|olive|fdf5e6|oldlace|000080|navy|ffdead|navajowhite|ffe4b5|moccasin|ffe4e1|mistyrose|f5fffa|mintcream|191970|midnightblue|c71585|mediumvioletred|48d1cc|mediumturquoise|00fa9a|mediumspringgreen|7b68ee|mediumslateblue|3cb371|mediumseagreen|9370db|mediumpurple|ba55d3|mediumorchid|0000cd|mediumblue|66cdaa|mediumaquamarine|800000|maroon|faf0e6|linen|32cd32|limegreen|00ff00|lime|ffffe0|lightyellow|b0c4de|lightsteelblue|lightslategrey|lightslategray||87cefa|lightskyblue|20b2aa|lightseagreen|ffa07a|lightsalmon|ffb6c1|lightpink|lightgrey|90ee90|lightgreen|lightgray|fafad2|lightgoldenrodyellow|e0ffff|lightcyan|f08080|lightcoral|add8e6|lightblue|fffacd|lemonchiffon|7cfc00|lawngreen|fff0f5|lavenderblush|e6e6fa|lavender|f0e68c|khaki|fffff0|ivory|4b0082|indigo|cd5c5c|indianred|ff69b4|hotpink|f0fff0|honeydew|grey|adff2f|greenyellow|008000|daa520|goldenrod|ffd700||gold|f8f8ff|ghostwhite|dcdcdc|gainsboro|fuchsia|228b22|forestgreen|fffaf0|floralwhite|b22222|firebrick|1e90ff|dodgerblue|dimgrey|dimgray|00bfff|deepskyblue|ff1493|deeppink|9400d3|darkviolet|00ced1|darkturquoise|darkslategrey|darkslategray|483d8b|darkslateblue|8fbc8f|darkseagreen|e9967a|darksalmon|8b0000|9932cc|darkorchid|ff8c00|darkorange|556b2f|darkolivegreen|8b008b|darkmagenta|bdb76b|darkkhaki|darkgrey|006400|darkgreen|darkgray|b8860b|darkgoldenrod|008b8b|darkcyan|00008b|darkblue|dc143c|crimson|fff8dc|cornsilk|6495ed|cornflowerblue|ff7f50|coral|d2691e||chocolate|7fff00|chartreuse|5f9ea0|cadetblue|deb887|burlywood|a52a2a|8a2be2|blueviolet|0000ff|ffebcd||blanchedalmond|000000|ffe4c4|bisque|f5f5dc|beige|f0ffff|azure|7fffd4|aquamarine|aqua|faebd7|antiquewhite|f0f8ff|aliceblue|lightGray|darkGray|namedColors|blackColor|fromText|whiteColor|_510|_509|PI|rad|deg|transparentColor|_494|_493|_492|fromHSV|_491|_490|_489|asHSV|toHexString|rgba|hsla|toHSLString|isDark|lighterColorWithLevel|darkerColorWithLevel|colorWithLightness|colorWithSaturation|colorWithHue|colorWithAlpha||serif|sans|Verdana||8pt|8em|auto||Close|Clear||Load|Filter||10em||fixed|regex|emergency|line|margin|_Listener|dtd|loose|html4|w3|EN|Transitional|DTD|W3C|PUBLIC|DOCTYPE|blocking|due|debugging|able|Not|resizable|dependent|href|location|_MochiKit_LoggingPane|_429|canvas|strong|fieldset|legend|optgroup|select|form|textarea|label|img|table|tfoot|thead|tbody|htmlFor||useMap|usemap|defaultChecked|hasChildNodes|quot|amp|_405|focus|replaceChild|checkbox||radio|_win|BODY||safari|version|userAgent|navigator|innerHeight|alpha|khtml|Tried|acquire|clearTimeout|setTimeout|GET|ignore|send|abort|failed|Request|readyState|support|does|Browser|Microsoft|_288|_287|used|Deferreds|Chained|success|unfired|fr_FR|de_DE|00|abs|search|pattern|Invalid|getTimezoneOffset|getSeconds|getMinutes|getHours|UTC|3600000|initEvent|Events|debuggingBookmarklet|MESSAGES|LAST|_205|clear|ninfo|nlevel|timestamp|reverse|takes|initial|with|sequence|empty|iterable|numbers|dateLike|escape|find|forward|unregister|unescape|Object|compared|item|contains|logor|logand|cle|clt|cge|cgt|cne|ceq|zrshift|rshift|lshift|xor|mul|mod|sub|add|neg|lognot|_9|_2'.split('|'),0,{})
+
+
+/*
+ * jQuery 1.2.1 - New Wave Javascript
+ *
+ * Copyright (c) 2007 John Resig (jquery.com)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * $Date: 2007-09-16 23:42:06 -0400 (Sun, 16 Sep 2007) $
+ * $Rev: 3353 $
+ */
+
+var decompressedJQuery = function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(G(){9(1m E!="W")H w=E;H E=18.15=G(a,b){I 6 7u E?6.5N(a,b):1u E(a,b)};9(1m $!="W")H D=$;18.$=E;H u=/^[^<]*(<(.|\\s)+>)[^>]*$|^#(\\w+)$/;E.1b=E.3A={5N:G(c,a){c=c||U;9(1m c=="1M"){H m=u.2S(c);9(m&&(m[1]||!a)){9(m[1])c=E.4D([m[1]],a);J{H b=U.3S(m[3]);9(b)9(b.22!=m[3])I E().1Y(c);J{6[0]=b;6.K=1;I 6}J c=[]}}J I 1u E(a).1Y(c)}J 9(E.1n(c))I 1u E(U)[E.1b.2d?"2d":"39"](c);I 6.6v(c.1c==1B&&c||(c.4c||c.K&&c!=18&&!c.1y&&c[0]!=W&&c[0].1y)&&E.2h(c)||[c])},4c:"1.2.1",7Y:G(){I 6.K},K:0,21:G(a){I a==W?E.2h(6):6[a]},2o:G(a){H b=E(a);b.4Y=6;I b},6v:G(a){6.K=0;1B.3A.1a.16(6,a);I 6},N:G(a,b){I E.N(6,a,b)},4I:G(a){H b=-1;6.N(G(i){9(6==a)b=i});I b},1x:G(f,d,e){H c=f;9(f.1c==3X)9(d==W)I 6.K&&E[e||"1x"](6[0],f)||W;J{c={};c[f]=d}I 6.N(G(a){L(H b 1i c)E.1x(e?6.R:6,b,E.1e(6,c[b],e,a,b))})},17:G(b,a){I 6.1x(b,a,"3C")},2g:G(e){9(1m e!="5i"&&e!=S)I 6.4n().3g(U.6F(e));H t="";E.N(e||6,G(){E.N(6.3j,G(){9(6.1y!=8)t+=6.1y!=1?6.6x:E.1b.2g([6])})});I t},5m:G(b){9(6[0])E(b,6[0].3H).6u().3d(6[0]).1X(G(){H a=6;1W(a.1w)a=a.1w;I a}).3g(6);I 6},8m:G(a){I 6.N(G(){E(6).6q().5m(a)})},8d:G(a){I 6.N(G(){E(6).5m(a)})},3g:G(){I 6.3z(1q,Q,1,G(a){6.58(a)})},6j:G(){I 6.3z(1q,Q,-1,G(a){6.3d(a,6.1w)})},6g:G(){I 6.3z(1q,P,1,G(a){6.12.3d(a,6)})},50:G(){I 6.3z(1q,P,-1,G(a){6.12.3d(a,6.2q)})},2D:G(){I 6.4Y||E([])},1Y:G(t){H b=E.1X(6,G(a){I E.1Y(t,a)});I 6.2o(/[^+>] [^+>]/.14(t)||t.1g("..")>-1?E.4V(b):b)},6u:G(e){H f=6.1X(G(){I 6.67?E(6.67)[0]:6.4R(Q)});H d=f.1Y("*").4O().N(G(){9(6[F]!=W)6[F]=S});9(e===Q)6.1Y("*").4O().N(G(i){H c=E.M(6,"2P");L(H a 1i c)L(H b 1i c[a])E.1j.1f(d[i],a,c[a][b],c[a][b].M)});I f},1E:G(t){I 6.2o(E.1n(t)&&E.2W(6,G(b,a){I t.16(b,[a])})||E.3m(t,6))},5V:G(t){I 6.2o(t.1c==3X&&E.3m(t,6,Q)||E.2W(6,G(a){I(t.1c==1B||t.4c)?E.2A(a,t)<0:a!=t}))},1f:G(t){I 6.2o(E.1R(6.21(),t.1c==3X?E(t).21():t.K!=W&&(!t.11||E.11(t,"2Y"))?t:[t]))},3t:G(a){I a?E.3m(a,6).K>0:P},7c:G(a){I 6.3t("."+a)},3i:G(b){9(b==W){9(6.K){H c=6[0];9(E.11(c,"24")){H e=c.4Z,a=[],Y=c.Y,2G=c.O=="24-2G";9(e<0)I S;L(H i=2G?e:0,33=2G?e+1:Y.K;i<33;i++){H d=Y[i];9(d.26){H b=E.V.1h&&!d.9V["1Q"].9L?d.2g:d.1Q;9(2G)I b;a.1a(b)}}I a}J I 6[0].1Q.1p(/\\r/g,"")}}J I 6.N(G(){9(b.1c==1B&&/4k|5j/.14(6.O))6.2Q=(E.2A(6.1Q,b)>=0||E.2A(6.2H,b)>=0);J 9(E.11(6,"24")){H a=b.1c==1B?b:[b];E("9h",6).N(G(){6.26=(E.2A(6.1Q,a)>=0||E.2A(6.2g,a)>=0)});9(!a.K)6.4Z=-1}J 6.1Q=b})},4o:G(a){I a==W?(6.K?6[0].3O:S):6.4n().3g(a)},6H:G(a){I 6.50(a).28()},6E:G(i){I 6.2J(i,i+1)},2J:G(){I 6.2o(1B.3A.2J.16(6,1q))},1X:G(b){I 6.2o(E.1X(6,G(a,i){I b.2O(a,i,a)}))},4O:G(){I 6.1f(6.4Y)},3z:G(f,d,g,e){H c=6.K>1,a;I 6.N(G(){9(!a){a=E.4D(f,6.3H);9(g<0)a.8U()}H b=6;9(d&&E.11(6,"1I")&&E.11(a[0],"4m"))b=6.4l("1K")[0]||6.58(U.5B("1K"));E.N(a,G(){H a=c?6.4R(Q):6;9(!5A(0,a))e.2O(b,a)})})}};G 5A(i,b){H a=E.11(b,"1J");9(a){9(b.3k)E.3G({1d:b.3k,3e:P,1V:"1J"});J E.5f(b.2g||b.6s||b.3O||"");9(b.12)b.12.3b(b)}J 9(b.1y==1)E("1J",b).N(5A);I a}E.1k=E.1b.1k=G(){H c=1q[0]||{},a=1,2c=1q.K,5e=P;9(c.1c==8o){5e=c;c=1q[1]||{}}9(2c==1){c=6;a=0}H b;L(;a<2c;a++)9((b=1q[a])!=S)L(H i 1i b){9(c==b[i])6r;9(5e&&1m b[i]==\'5i\'&&c[i])E.1k(c[i],b[i]);J 9(b[i]!=W)c[i]=b[i]}I c};H F="15"+(1u 3D()).3B(),6p=0,5c={};E.1k({8a:G(a){18.$=D;9(a)18.15=w;I E},1n:G(a){I!!a&&1m a!="1M"&&!a.11&&a.1c!=1B&&/G/i.14(a+"")},4a:G(a){I a.2V&&!a.1G||a.37&&a.3H&&!a.3H.1G},5f:G(a){a=E.36(a);9(a){9(18.6l)18.6l(a);J 9(E.V.1N)18.56(a,0);J 3w.2O(18,a)}},11:G(b,a){I b.11&&b.11.27()==a.27()},1L:{},M:G(c,d,b){c=c==18?5c:c;H a=c[F];9(!a)a=c[F]=++6p;9(d&&!E.1L[a])E.1L[a]={};9(b!=W)E.1L[a][d]=b;I d?E.1L[a][d]:a},30:G(c,b){c=c==18?5c:c;H a=c[F];9(b){9(E.1L[a]){2E E.1L[a][b];b="";L(b 1i E.1L[a])1T;9(!b)E.30(c)}}J{2a{2E c[F]}29(e){9(c.53)c.53(F)}2E E.1L[a]}},N:G(a,b,c){9(c){9(a.K==W)L(H i 1i a)b.16(a[i],c);J L(H i=0,48=a.K;i<48;i++)9(b.16(a[i],c)===P)1T}J{9(a.K==W)L(H i 1i a)b.2O(a[i],i,a[i]);J L(H i=0,48=a.K,3i=a[0];i<48&&b.2O(3i,i,3i)!==P;3i=a[++i]){}}I a},1e:G(c,b,d,e,a){9(E.1n(b))b=b.2O(c,[e]);H f=/z-?4I|7T-?7Q|1r|69|7P-?1H/i;I b&&b.1c==4W&&d=="3C"&&!f.14(a)?b+"2T":b},1o:{1f:G(b,c){E.N((c||"").2l(/\\s+/),G(i,a){9(!E.1o.3K(b.1o,a))b.1o+=(b.1o?" ":"")+a})},28:G(b,c){b.1o=c!=W?E.2W(b.1o.2l(/\\s+/),G(a){I!E.1o.3K(c,a)}).66(" "):""},3K:G(t,c){I E.2A(c,(t.1o||t).3s().2l(/\\s+/))>-1}},2k:G(e,o,f){L(H i 1i o){e.R["3r"+i]=e.R[i];e.R[i]=o[i]}f.16(e,[]);L(H i 1i o)e.R[i]=e.R["3r"+i]},17:G(e,p){9(p=="1H"||p=="2N"){H b={},42,41,d=["7J","7I","7G","7F"];E.N(d,G(){b["7C"+6]=0;b["7B"+6+"5Z"]=0});E.2k(e,b,G(){9(E(e).3t(\':3R\')){42=e.7A;41=e.7w}J{e=E(e.4R(Q)).1Y(":4k").5W("2Q").2D().17({4C:"1P",2X:"4F",19:"2Z",7o:"0",1S:"0"}).5R(e.12)[0];H a=E.17(e.12,"2X")||"3V";9(a=="3V")e.12.R.2X="7g";42=e.7e;41=e.7b;9(a=="3V")e.12.R.2X="3V";e.12.3b(e)}});I p=="1H"?42:41}I E.3C(e,p)},3C:G(h,j,i){H g,2w=[],2k=[];G 3n(a){9(!E.V.1N)I P;H b=U.3o.3Z(a,S);I!b||b.4y("3n")==""}9(j=="1r"&&E.V.1h){g=E.1x(h.R,"1r");I g==""?"1":g}9(j.1t(/4u/i))j=y;9(!i&&h.R[j])g=h.R[j];J 9(U.3o&&U.3o.3Z){9(j.1t(/4u/i))j="4u";j=j.1p(/([A-Z])/g,"-$1").2p();H d=U.3o.3Z(h,S);9(d&&!3n(h))g=d.4y(j);J{L(H a=h;a&&3n(a);a=a.12)2w.4w(a);L(a=0;a<2w.K;a++)9(3n(2w[a])){2k[a]=2w[a].R.19;2w[a].R.19="2Z"}g=j=="19"&&2k[2w.K-1]!=S?"2s":U.3o.3Z(h,S).4y(j)||"";L(a=0;a<2k.K;a++)9(2k[a]!=S)2w[a].R.19=2k[a]}9(j=="1r"&&g=="")g="1"}J 9(h.3Q){H f=j.1p(/\\-(\\w)/g,G(m,c){I c.27()});g=h.3Q[j]||h.3Q[f];9(!/^\\d+(2T)?$/i.14(g)&&/^\\d/.14(g)){H k=h.R.1S;H e=h.4v.1S;h.4v.1S=h.3Q.1S;h.R.1S=g||0;g=h.R.71+"2T";h.R.1S=k;h.4v.1S=e}}I g},4D:G(a,e){H r=[];e=e||U;E.N(a,G(i,d){9(!d)I;9(d.1c==4W)d=d.3s();9(1m d=="1M"){d=d.1p(/(<(\\w+)[^>]*?)\\/>/g,G(m,a,b){I b.1t(/^(70|6Z|6Y|9Q|4t|9N|9K|3a|9G|9E)$/i)?m:a+"></"+b+">"});H s=E.36(d).2p(),1s=e.5B("1s"),2x=[];H c=!s.1g("<9y")&&[1,"<24>","</24>"]||!s.1g("<9w")&&[1,"<6T>","</6T>"]||s.1t(/^<(9u|1K|9t|9r|9p)/)&&[1,"<1I>","</1I>"]||!s.1g("<4m")&&[2,"<1I><1K>","</1K></1I>"]||(!s.1g("<9m")||!s.1g("<9k"))&&[3,"<1I><1K><4m>","</4m></1K></1I>"]||!s.1g("<6Y")&&[2,"<1I><1K></1K><6L>","</6L></1I>"]||E.V.1h&&[1,"1s<1s>","</1s>"]||[0,"",""];1s.3O=c[1]+d+c[2];1W(c[0]--)1s=1s.5p;9(E.V.1h){9(!s.1g("<1I")&&s.1g("<1K")<0)2x=1s.1w&&1s.1w.3j;J 9(c[1]=="<1I>"&&s.1g("<1K")<0)2x=1s.3j;L(H n=2x.K-1;n>=0;--n)9(E.11(2x[n],"1K")&&!2x[n].3j.K)2x[n].12.3b(2x[n]);9(/^\\s/.14(d))1s.3d(e.6F(d.1t(/^\\s*/)[0]),1s.1w)}d=E.2h(1s.3j)}9(0===d.K&&(!E.11(d,"2Y")&&!E.11(d,"24")))I;9(d[0]==W||E.11(d,"2Y")||d.Y)r.1a(d);J r=E.1R(r,d)});I r},1x:G(c,d,a){H e=E.4a(c)?{}:E.5o;9(d=="26"&&E.V.1N)c.12.4Z;9(e[d]){9(a!=W)c[e[d]]=a;I c[e[d]]}J 9(E.V.1h&&d=="R")I E.1x(c.R,"9e",a);J 9(a==W&&E.V.1h&&E.11(c,"2Y")&&(d=="9d"||d=="9a"))I c.97(d).6x;J 9(c.37){9(a!=W){9(d=="O"&&E.11(c,"4t")&&c.12)6G"O 94 93\'t 92 91";c.90(d,a)}9(E.V.1h&&/6C|3k/.14(d)&&!E.4a(c))I c.4p(d,2);I c.4p(d)}J{9(d=="1r"&&E.V.1h){9(a!=W){c.69=1;c.1E=(c.1E||"").1p(/6O\\([^)]*\\)/,"")+(3I(a).3s()=="8S"?"":"6O(1r="+a*6A+")")}I c.1E?(3I(c.1E.1t(/1r=([^)]*)/)[1])/6A).3s():""}d=d.1p(/-([a-z])/8Q,G(z,b){I b.27()});9(a!=W)c[d]=a;I c[d]}},36:G(t){I(t||"").1p(/^\\s+|\\s+$/g,"")},2h:G(a){H r=[];9(1m a!="8P")L(H i=0,2c=a.K;i<2c;i++)r.1a(a[i]);J r=a.2J(0);I r},2A:G(b,a){L(H i=0,2c=a.K;i<2c;i++)9(a[i]==b)I i;I-1},1R:G(a,b){9(E.V.1h){L(H i=0;b[i];i++)9(b[i].1y!=8)a.1a(b[i])}J L(H i=0;b[i];i++)a.1a(b[i]);I a},4V:G(b){H r=[],2f={};2a{L(H i=0,6y=b.K;i<6y;i++){H a=E.M(b[i]);9(!2f[a]){2f[a]=Q;r.1a(b[i])}}}29(e){r=b}I r},2W:G(b,a,c){9(1m a=="1M")a=3w("P||G(a,i){I "+a+"}");H d=[];L(H i=0,4g=b.K;i<4g;i++)9(!c&&a(b[i],i)||c&&!a(b[i],i))d.1a(b[i]);I d},1X:G(c,b){9(1m b=="1M")b=3w("P||G(a){I "+b+"}");H d=[];L(H i=0,4g=c.K;i<4g;i++){H a=b(c[i],i);9(a!==S&&a!=W){9(a.1c!=1B)a=[a];d=d.8M(a)}}I d}});H v=8K.8I.2p();E.V={4s:(v.1t(/.+(?:8F|8E|8C|8B)[\\/: ]([\\d.]+)/)||[])[1],1N:/6w/.14(v),34:/34/.14(v),1h:/1h/.14(v)&&!/34/.14(v),35:/35/.14(v)&&!/(8z|6w)/.14(v)};H y=E.V.1h?"4h":"5h";E.1k({5g:!E.V.1h||U.8y=="8x",4h:E.V.1h?"4h":"5h",5o:{"L":"8w","8v":"1o","4u":y,5h:y,4h:y,3O:"3O",1o:"1o",1Q:"1Q",3c:"3c",2Q:"2Q",8u:"8t",26:"26",8s:"8r"}});E.N({1D:"a.12",8q:"15.4e(a,\'12\')",8p:"15.2I(a,2,\'2q\')",8n:"15.2I(a,2,\'4d\')",8l:"15.4e(a,\'2q\')",8k:"15.4e(a,\'4d\')",8j:"15.5d(a.12.1w,a)",8i:"15.5d(a.1w)",6q:"15.11(a,\'8h\')?a.8f||a.8e.U:15.2h(a.3j)"},G(i,n){E.1b[i]=G(a){H b=E.1X(6,n);9(a&&1m a=="1M")b=E.3m(a,b);I 6.2o(E.4V(b))}});E.N({5R:"3g",8c:"6j",3d:"6g",8b:"50",89:"6H"},G(i,n){E.1b[i]=G(){H a=1q;I 6.N(G(){L(H j=0,2c=a.K;j<2c;j++)E(a[j])[n](6)})}});E.N({5W:G(a){E.1x(6,a,"");6.53(a)},88:G(c){E.1o.1f(6,c)},87:G(c){E.1o.28(6,c)},86:G(c){E.1o[E.1o.3K(6,c)?"28":"1f"](6,c)},28:G(a){9(!a||E.1E(a,[6]).r.K){E.30(6);6.12.3b(6)}},4n:G(){E("*",6).N(G(){E.30(6)});1W(6.1w)6.3b(6.1w)}},G(i,n){E.1b[i]=G(){I 6.N(n,1q)}});E.N(["85","5Z"],G(i,a){H n=a.2p();E.1b[n]=G(h){I 6[0]==18?E.V.1N&&3y["84"+a]||E.5g&&38.33(U.2V["5a"+a],U.1G["5a"+a])||U.1G["5a"+a]:6[0]==U?38.33(U.1G["6n"+a],U.1G["6m"+a]):h==W?(6.K?E.17(6[0],n):S):6.17(n,h.1c==3X?h:h+"2T")}});H C=E.V.1N&&3x(E.V.4s)<83?"(?:[\\\\w*57-]|\\\\\\\\.)":"(?:[\\\\w\\82-\\81*57-]|\\\\\\\\.)",6k=1u 47("^>\\\\s*("+C+"+)"),6i=1u 47("^("+C+"+)(#)("+C+"+)"),6h=1u 47("^([#.]?)("+C+"*)");E.1k({55:{"":"m[2]==\'*\'||15.11(a,m[2])","#":"a.4p(\'22\')==m[2]",":":{80:"i<m[3]-0",7Z:"i>m[3]-0",2I:"m[3]-0==i",6E:"m[3]-0==i",3v:"i==0",3u:"i==r.K-1",6f:"i%2==0",6e:"i%2","3v-46":"a.12.4l(\'*\')[0]==a","3u-46":"15.2I(a.12.5p,1,\'4d\')==a","7X-46":"!15.2I(a.12.5p,2,\'4d\')",1D:"a.1w",4n:"!a.1w",7W:"(a.6s||a.7V||15(a).2g()||\'\').1g(m[3])>=0",3R:\'"1P"!=a.O&&15.17(a,"19")!="2s"&&15.17(a,"4C")!="1P"\',1P:\'"1P"==a.O||15.17(a,"19")=="2s"||15.17(a,"4C")=="1P"\',7U:"!a.3c",3c:"a.3c",2Q:"a.2Q",26:"a.26||15.1x(a,\'26\')",2g:"\'2g\'==a.O",4k:"\'4k\'==a.O",5j:"\'5j\'==a.O",54:"\'54\'==a.O",52:"\'52\'==a.O",51:"\'51\'==a.O",6d:"\'6d\'==a.O",6c:"\'6c\'==a.O",2r:\'"2r"==a.O||15.11(a,"2r")\',4t:"/4t|24|6b|2r/i.14(a.11)",3K:"15.1Y(m[3],a).K",7S:"/h\\\\d/i.14(a.11)",7R:"15.2W(15.32,G(1b){I a==1b.T;}).K"}},6a:[/^(\\[) *@?([\\w-]+) *([!*$^~=]*) *(\'?"?)(.*?)\\4 *\\]/,/^(:)([\\w-]+)\\("?\'?(.*?(\\(.*?\\))?[^(]*?)"?\'?\\)/,1u 47("^([:.#]*)("+C+"+)")],3m:G(a,c,b){H d,2b=[];1W(a&&a!=d){d=a;H f=E.1E(a,c,b);a=f.t.1p(/^\\s*,\\s*/,"");2b=b?c=f.r:E.1R(2b,f.r)}I 2b},1Y:G(t,o){9(1m t!="1M")I[t];9(o&&!o.1y)o=S;o=o||U;H d=[o],2f=[],3u;1W(t&&3u!=t){H r=[];3u=t;t=E.36(t);H l=P;H g=6k;H m=g.2S(t);9(m){H p=m[1].27();L(H i=0;d[i];i++)L(H c=d[i].1w;c;c=c.2q)9(c.1y==1&&(p=="*"||c.11.27()==p.27()))r.1a(c);d=r;t=t.1p(g,"");9(t.1g(" ")==0)6r;l=Q}J{g=/^([>+~])\\s*(\\w*)/i;9((m=g.2S(t))!=S){r=[];H p=m[2],1R={};m=m[1];L(H j=0,31=d.K;j<31;j++){H n=m=="~"||m=="+"?d[j].2q:d[j].1w;L(;n;n=n.2q)9(n.1y==1){H h=E.M(n);9(m=="~"&&1R[h])1T;9(!p||n.11.27()==p.27()){9(m=="~")1R[h]=Q;r.1a(n)}9(m=="+")1T}}d=r;t=E.36(t.1p(g,""));l=Q}}9(t&&!l){9(!t.1g(",")){9(o==d[0])d.44();2f=E.1R(2f,d);r=d=[o];t=" "+t.68(1,t.K)}J{H k=6i;H m=k.2S(t);9(m){m=[0,m[2],m[3],m[1]]}J{k=6h;m=k.2S(t)}m[2]=m[2].1p(/\\\\/g,"");H f=d[d.K-1];9(m[1]=="#"&&f&&f.3S&&!E.4a(f)){H q=f.3S(m[2]);9((E.V.1h||E.V.34)&&q&&1m q.22=="1M"&&q.22!=m[2])q=E(\'[@22="\'+m[2]+\'"]\',f)[0];d=r=q&&(!m[3]||E.11(q,m[3]))?[q]:[]}J{L(H i=0;d[i];i++){H a=m[1]=="#"&&m[3]?m[3]:m[1]!=""||m[0]==""?"*":m[2];9(a=="*"&&d[i].11.2p()=="5i")a="3a";r=E.1R(r,d[i].4l(a))}9(m[1]==".")r=E.4X(r,m[2]);9(m[1]=="#"){H e=[];L(H i=0;r[i];i++)9(r[i].4p("22")==m[2]){e=[r[i]];1T}r=e}d=r}t=t.1p(k,"")}}9(t){H b=E.1E(t,r);d=r=b.r;t=E.36(b.t)}}9(t)d=[];9(d&&o==d[0])d.44();2f=E.1R(2f,d);I 2f},4X:G(r,m,a){m=" "+m+" ";H c=[];L(H i=0;r[i];i++){H b=(" "+r[i].1o+" ").1g(m)>=0;9(!a&&b||a&&!b)c.1a(r[i])}I c},1E:G(t,r,h){H d;1W(t&&t!=d){d=t;H p=E.6a,m;L(H i=0;p[i];i++){m=p[i].2S(t);9(m){t=t.7O(m[0].K);m[2]=m[2].1p(/\\\\/g,"");1T}}9(!m)1T;9(m[1]==":"&&m[2]=="5V")r=E.1E(m[3],r,Q).r;J 9(m[1]==".")r=E.4X(r,m[2],h);J 9(m[1]=="["){H g=[],O=m[3];L(H i=0,31=r.K;i<31;i++){H a=r[i],z=a[E.5o[m[2]]||m[2]];9(z==S||/6C|3k|26/.14(m[2]))z=E.1x(a,m[2])||\'\';9((O==""&&!!z||O=="="&&z==m[5]||O=="!="&&z!=m[5]||O=="^="&&z&&!z.1g(m[5])||O=="$="&&z.68(z.K-m[5].K)==m[5]||(O=="*="||O=="~=")&&z.1g(m[5])>=0)^h)g.1a(a)}r=g}J 9(m[1]==":"&&m[2]=="2I-46"){H e={},g=[],14=/(\\d*)n\\+?(\\d*)/.2S(m[3]=="6f"&&"2n"||m[3]=="6e"&&"2n+1"||!/\\D/.14(m[3])&&"n+"+m[3]||m[3]),3v=(14[1]||1)-0,d=14[2]-0;L(H i=0,31=r.K;i<31;i++){H j=r[i],12=j.12,22=E.M(12);9(!e[22]){H c=1;L(H n=12.1w;n;n=n.2q)9(n.1y==1)n.4U=c++;e[22]=Q}H b=P;9(3v==1){9(d==0||j.4U==d)b=Q}J 9((j.4U+d)%3v==0)b=Q;9(b^h)g.1a(j)}r=g}J{H f=E.55[m[1]];9(1m f!="1M")f=E.55[m[1]][m[2]];f=3w("P||G(a,i){I "+f+"}");r=E.2W(r,f,h)}}I{r:r,t:t}},4e:G(b,c){H d=[];H a=b[c];1W(a&&a!=U){9(a.1y==1)d.1a(a);a=a[c]}I d},2I:G(a,e,c,b){e=e||1;H d=0;L(;a;a=a[c])9(a.1y==1&&++d==e)1T;I a},5d:G(n,a){H r=[];L(;n;n=n.2q){9(n.1y==1&&(!a||n!=a))r.1a(n)}I r}});E.1j={1f:G(g,e,c,h){9(E.V.1h&&g.4j!=W)g=18;9(!c.2u)c.2u=6.2u++;9(h!=W){H d=c;c=G(){I d.16(6,1q)};c.M=h;c.2u=d.2u}H i=e.2l(".");e=i[0];c.O=i[1];H b=E.M(g,"2P")||E.M(g,"2P",{});H f=E.M(g,"2t",G(){H a;9(1m E=="W"||E.1j.4T)I a;a=E.1j.2t.16(g,1q);I a});H j=b[e];9(!j){j=b[e]={};9(g.4S)g.4S(e,f,P);J g.7N("43"+e,f)}j[c.2u]=c;6.1Z[e]=Q},2u:1,1Z:{},28:G(d,c,b){H e=E.M(d,"2P"),2L,4I;9(1m c=="1M"){H a=c.2l(".");c=a[0]}9(e){9(c&&c.O){b=c.4Q;c=c.O}9(!c){L(c 1i e)6.28(d,c)}J 9(e[c]){9(b)2E e[c][b.2u];J L(b 1i e[c])9(!a[1]||e[c][b].O==a[1])2E e[c][b];L(2L 1i e[c])1T;9(!2L){9(d.4P)d.4P(c,E.M(d,"2t"),P);J d.7M("43"+c,E.M(d,"2t"));2L=S;2E e[c]}}L(2L 1i e)1T;9(!2L){E.30(d,"2P");E.30(d,"2t")}}},1F:G(d,b,e,c,f){b=E.2h(b||[]);9(!e){9(6.1Z[d])E("*").1f([18,U]).1F(d,b)}J{H a,2L,1b=E.1n(e[d]||S),4N=!b[0]||!b[0].2M;9(4N)b.4w(6.4M({O:d,2m:e}));b[0].O=d;9(E.1n(E.M(e,"2t")))a=E.M(e,"2t").16(e,b);9(!1b&&e["43"+d]&&e["43"+d].16(e,b)===P)a=P;9(4N)b.44();9(f&&f.16(e,b)===P)a=P;9(1b&&c!==P&&a!==P&&!(E.11(e,\'a\')&&d=="4L")){6.4T=Q;e[d]()}6.4T=P}I a},2t:G(d){H a;d=E.1j.4M(d||18.1j||{});H b=d.O.2l(".");d.O=b[0];H c=E.M(6,"2P")&&E.M(6,"2P")[d.O],3q=1B.3A.2J.2O(1q,1);3q.4w(d);L(H j 1i c){3q[0].4Q=c[j];3q[0].M=c[j].M;9(!b[1]||c[j].O==b[1]){H e=c[j].16(6,3q);9(a!==P)a=e;9(e===P){d.2M();d.3p()}}}9(E.V.1h)d.2m=d.2M=d.3p=d.4Q=d.M=S;I a},4M:G(c){H a=c;c=E.1k({},a);c.2M=G(){9(a.2M)a.2M();a.7L=P};c.3p=G(){9(a.3p)a.3p();a.7K=Q};9(!c.2m&&c.65)c.2m=c.65;9(E.V.1N&&c.2m.1y==3)c.2m=a.2m.12;9(!c.4K&&c.4J)c.4K=c.4J==c.2m?c.7H:c.4J;9(c.64==S&&c.63!=S){H e=U.2V,b=U.1G;c.64=c.63+(e&&e.2R||b.2R||0);c.7E=c.7D+(e&&e.2B||b.2B||0)}9(!c.3Y&&(c.61||c.60))c.3Y=c.61||c.60;9(!c.5F&&c.5D)c.5F=c.5D;9(!c.3Y&&c.2r)c.3Y=(c.2r&1?1:(c.2r&2?3:(c.2r&4?2:0)));I c}};E.1b.1k({3W:G(c,a,b){I c=="5Y"?6.2G(c,a,b):6.N(G(){E.1j.1f(6,c,b||a,b&&a)})},2G:G(d,b,c){I 6.N(G(){E.1j.1f(6,d,G(a){E(6).5X(a);I(c||b).16(6,1q)},c&&b)})},5X:G(a,b){I 6.N(G(){E.1j.28(6,a,b)})},1F:G(c,a,b){I 6.N(G(){E.1j.1F(c,a,6,Q,b)})},7x:G(c,a,b){9(6[0])I E.1j.1F(c,a,6[0],P,b)},25:G(){H a=1q;I 6.4L(G(e){6.4H=0==6.4H?1:0;e.2M();I a[6.4H].16(6,[e])||P})},7v:G(f,g){G 4G(e){H p=e.4K;1W(p&&p!=6)2a{p=p.12}29(e){p=6};9(p==6)I P;I(e.O=="4x"?f:g).16(6,[e])}I 6.4x(4G).5U(4G)},2d:G(f){5T();9(E.3T)f.16(U,[E]);J E.3l.1a(G(){I f.16(6,[E])});I 6}});E.1k({3T:P,3l:[],2d:G(){9(!E.3T){E.3T=Q;9(E.3l){E.N(E.3l,G(){6.16(U)});E.3l=S}9(E.V.35||E.V.34)U.4P("5S",E.2d,P);9(!18.7t.K)E(18).39(G(){E("#4E").28()})}}});E.N(("7s,7r,39,7q,6n,5Y,4L,7p,"+"7n,7m,7l,4x,5U,7k,24,"+"51,7j,7i,7h,3U").2l(","),G(i,o){E.1b[o]=G(f){I f?6.3W(o,f):6.1F(o)}});H x=P;G 5T(){9(x)I;x=Q;9(E.V.35||E.V.34)U.4S("5S",E.2d,P);J 9(E.V.1h){U.7f("<7d"+"7y 22=4E 7z=Q "+"3k=//:><\\/1J>");H a=U.3S("4E");9(a)a.62=G(){9(6.2C!="1l")I;E.2d()};a=S}J 9(E.V.1N)E.4B=4j(G(){9(U.2C=="5Q"||U.2C=="1l"){4A(E.4B);E.4B=S;E.2d()}},10);E.1j.1f(18,"39",E.2d)}E.1b.1k({39:G(g,d,c){9(E.1n(g))I 6.3W("39",g);H e=g.1g(" ");9(e>=0){H i=g.2J(e,g.K);g=g.2J(0,e)}c=c||G(){};H f="4z";9(d)9(E.1n(d)){c=d;d=S}J{d=E.3a(d);f="5P"}H h=6;E.3G({1d:g,O:f,M:d,1l:G(a,b){9(b=="1C"||b=="5O")h.4o(i?E("<1s/>").3g(a.40.1p(/<1J(.|\\s)*?\\/1J>/g,"")).1Y(i):a.40);56(G(){h.N(c,[a.40,b,a])},13)}});I 6},7a:G(){I E.3a(6.5M())},5M:G(){I 6.1X(G(){I E.11(6,"2Y")?E.2h(6.79):6}).1E(G(){I 6.2H&&!6.3c&&(6.2Q||/24|6b/i.14(6.11)||/2g|1P|52/i.14(6.O))}).1X(G(i,c){H b=E(6).3i();I b==S?S:b.1c==1B?E.1X(b,G(a,i){I{2H:c.2H,1Q:a}}):{2H:c.2H,1Q:b}}).21()}});E.N("5L,5K,6t,5J,5I,5H".2l(","),G(i,o){E.1b[o]=G(f){I 6.3W(o,f)}});H B=(1u 3D).3B();E.1k({21:G(d,b,a,c){9(E.1n(b)){a=b;b=S}I E.3G({O:"4z",1d:d,M:b,1C:a,1V:c})},78:G(b,a){I E.21(b,S,a,"1J")},77:G(c,b,a){I E.21(c,b,a,"45")},76:G(d,b,a,c){9(E.1n(b)){a=b;b={}}I E.3G({O:"5P",1d:d,M:b,1C:a,1V:c})},75:G(a){E.1k(E.59,a)},59:{1Z:Q,O:"4z",2z:0,5G:"74/x-73-2Y-72",6o:Q,3e:Q,M:S},49:{},3G:G(s){H f,2y=/=(\\?|%3F)/g,1v,M;s=E.1k(Q,s,E.1k(Q,{},E.59,s));9(s.M&&s.6o&&1m s.M!="1M")s.M=E.3a(s.M);9(s.1V=="4b"){9(s.O.2p()=="21"){9(!s.1d.1t(2y))s.1d+=(s.1d.1t(/\\?/)?"&":"?")+(s.4b||"5E")+"=?"}J 9(!s.M||!s.M.1t(2y))s.M=(s.M?s.M+"&":"")+(s.4b||"5E")+"=?";s.1V="45"}9(s.1V=="45"&&(s.M&&s.M.1t(2y)||s.1d.1t(2y))){f="4b"+B++;9(s.M)s.M=s.M.1p(2y,"="+f);s.1d=s.1d.1p(2y,"="+f);s.1V="1J";18[f]=G(a){M=a;1C();1l();18[f]=W;2a{2E 18[f]}29(e){}}}9(s.1V=="1J"&&s.1L==S)s.1L=P;9(s.1L===P&&s.O.2p()=="21")s.1d+=(s.1d.1t(/\\?/)?"&":"?")+"57="+(1u 3D()).3B();9(s.M&&s.O.2p()=="21"){s.1d+=(s.1d.1t(/\\?/)?"&":"?")+s.M;s.M=S}9(s.1Z&&!E.5b++)E.1j.1F("5L");9(!s.1d.1g("8g")&&s.1V=="1J"){H h=U.4l("9U")[0];H g=U.5B("1J");g.3k=s.1d;9(!f&&(s.1C||s.1l)){H j=P;g.9R=g.62=G(){9(!j&&(!6.2C||6.2C=="5Q"||6.2C=="1l")){j=Q;1C();1l();h.3b(g)}}}h.58(g);I}H k=P;H i=18.6X?1u 6X("9P.9O"):1u 6W();i.9M(s.O,s.1d,s.3e);9(s.M)i.5C("9J-9I",s.5G);9(s.5y)i.5C("9H-5x-9F",E.49[s.1d]||"9D, 9C 9B 9A 5v:5v:5v 9z");i.5C("X-9x-9v","6W");9(s.6U)s.6U(i);9(s.1Z)E.1j.1F("5H",[i,s]);H c=G(a){9(!k&&i&&(i.2C==4||a=="2z")){k=Q;9(d){4A(d);d=S}1v=a=="2z"&&"2z"||!E.6S(i)&&"3U"||s.5y&&E.6R(i,s.1d)&&"5O"||"1C";9(1v=="1C"){2a{M=E.6Q(i,s.1V)}29(e){1v="5k"}}9(1v=="1C"){H b;2a{b=i.5s("6P-5x")}29(e){}9(s.5y&&b)E.49[s.1d]=b;9(!f)1C()}J E.5r(s,i,1v);1l();9(s.3e)i=S}};9(s.3e){H d=4j(c,13);9(s.2z>0)56(G(){9(i){i.9q();9(!k)c("2z")}},s.2z)}2a{i.9o(s.M)}29(e){E.5r(s,i,S,e)}9(!s.3e)c();I i;G 1C(){9(s.1C)s.1C(M,1v);9(s.1Z)E.1j.1F("5I",[i,s])}G 1l(){9(s.1l)s.1l(i,1v);9(s.1Z)E.1j.1F("6t",[i,s]);9(s.1Z&&!--E.5b)E.1j.1F("5K")}},5r:G(s,a,b,e){9(s.3U)s.3U(a,b,e);9(s.1Z)E.1j.1F("5J",[a,s,e])},5b:0,6S:G(r){2a{I!r.1v&&9n.9l=="54:"||(r.1v>=6N&&r.1v<9j)||r.1v==6M||E.V.1N&&r.1v==W}29(e){}I P},6R:G(a,c){2a{H b=a.5s("6P-5x");I a.1v==6M||b==E.49[c]||E.V.1N&&a.1v==W}29(e){}I P},6Q:G(r,b){H c=r.5s("9i-O");H d=b=="6K"||!b&&c&&c.1g("6K")>=0;H a=d?r.9g:r.40;9(d&&a.2V.37=="5k")6G"5k";9(b=="1J")E.5f(a);9(b=="45")a=3w("("+a+")");I a},3a:G(a){H s=[];9(a.1c==1B||a.4c)E.N(a,G(){s.1a(3f(6.2H)+"="+3f(6.1Q))});J L(H j 1i a)9(a[j]&&a[j].1c==1B)E.N(a[j],G(){s.1a(3f(j)+"="+3f(6))});J s.1a(3f(j)+"="+3f(a[j]));I s.66("&").1p(/%20/g,"+")}});E.1b.1k({1A:G(b,a){I b?6.1U({1H:"1A",2N:"1A",1r:"1A"},b,a):6.1E(":1P").N(G(){6.R.19=6.3h?6.3h:"";9(E.17(6,"19")=="2s")6.R.19="2Z"}).2D()},1z:G(b,a){I b?6.1U({1H:"1z",2N:"1z",1r:"1z"},b,a):6.1E(":3R").N(G(){6.3h=6.3h||E.17(6,"19");9(6.3h=="2s")6.3h="2Z";6.R.19="2s"}).2D()},6J:E.1b.25,25:G(a,b){I E.1n(a)&&E.1n(b)?6.6J(a,b):a?6.1U({1H:"25",2N:"25",1r:"25"},a,b):6.N(G(){E(6)[E(6).3t(":1P")?"1A":"1z"]()})},9c:G(b,a){I 6.1U({1H:"1A"},b,a)},9b:G(b,a){I 6.1U({1H:"1z"},b,a)},99:G(b,a){I 6.1U({1H:"25"},b,a)},98:G(b,a){I 6.1U({1r:"1A"},b,a)},96:G(b,a){I 6.1U({1r:"1z"},b,a)},95:G(c,a,b){I 6.1U({1r:a},c,b)},1U:G(k,i,h,g){H j=E.6D(i,h,g);I 6[j.3L===P?"N":"3L"](G(){j=E.1k({},j);H f=E(6).3t(":1P"),3y=6;L(H p 1i k){9(k[p]=="1z"&&f||k[p]=="1A"&&!f)I E.1n(j.1l)&&j.1l.16(6);9(p=="1H"||p=="2N"){j.19=E.17(6,"19");j.2U=6.R.2U}}9(j.2U!=S)6.R.2U="1P";j.3M=E.1k({},k);E.N(k,G(c,a){H e=1u E.2j(3y,j,c);9(/25|1A|1z/.14(a))e[a=="25"?f?"1A":"1z":a](k);J{H b=a.3s().1t(/^([+-]=)?([\\d+-.]+)(.*)$/),1O=e.2b(Q)||0;9(b){H d=3I(b[2]),2i=b[3]||"2T";9(2i!="2T"){3y.R[c]=(d||1)+2i;1O=((d||1)/e.2b(Q))*1O;3y.R[c]=1O+2i}9(b[1])d=((b[1]=="-="?-1:1)*d)+1O;e.3N(1O,d,2i)}J e.3N(1O,a,"")}});I Q})},3L:G(a,b){9(E.1n(a)){b=a;a="2j"}9(!a||(1m a=="1M"&&!b))I A(6[0],a);I 6.N(G(){9(b.1c==1B)A(6,a,b);J{A(6,a).1a(b);9(A(6,a).K==1)b.16(6)}})},9f:G(){H a=E.32;I 6.N(G(){L(H i=0;i<a.K;i++)9(a[i].T==6)a.6I(i--,1)}).5n()}});H A=G(b,c,a){9(!b)I;H q=E.M(b,c+"3L");9(!q||a)q=E.M(b,c+"3L",a?E.2h(a):[]);I q};E.1b.5n=G(a){a=a||"2j";I 6.N(G(){H q=A(6,a);q.44();9(q.K)q[0].16(6)})};E.1k({6D:G(b,a,c){H d=b&&b.1c==8Z?b:{1l:c||!c&&a||E.1n(b)&&b,2e:b,3J:c&&a||a&&a.1c!=8Y&&a};d.2e=(d.2e&&d.2e.1c==4W?d.2e:{8X:8W,8V:6N}[d.2e])||8T;d.3r=d.1l;d.1l=G(){E(6).5n();9(E.1n(d.3r))d.3r.16(6)};I d},3J:{6B:G(p,n,b,a){I b+a*p},5q:G(p,n,b,a){I((-38.9s(p*38.8R)/2)+0.5)*a+b}},32:[],2j:G(b,c,a){6.Y=c;6.T=b;6.1e=a;9(!c.3P)c.3P={}}});E.2j.3A={4r:G(){9(6.Y.2F)6.Y.2F.16(6.T,[6.2v,6]);(E.2j.2F[6.1e]||E.2j.2F.6z)(6);9(6.1e=="1H"||6.1e=="2N")6.T.R.19="2Z"},2b:G(a){9(6.T[6.1e]!=S&&6.T.R[6.1e]==S)I 6.T[6.1e];H r=3I(E.3C(6.T,6.1e,a));I r&&r>-8O?r:3I(E.17(6.T,6.1e))||0},3N:G(c,b,e){6.5u=(1u 3D()).3B();6.1O=c;6.2D=b;6.2i=e||6.2i||"2T";6.2v=6.1O;6.4q=6.4i=0;6.4r();H f=6;G t(){I f.2F()}t.T=6.T;E.32.1a(t);9(E.32.K==1){H d=4j(G(){H a=E.32;L(H i=0;i<a.K;i++)9(!a[i]())a.6I(i--,1);9(!a.K)4A(d)},13)}},1A:G(){6.Y.3P[6.1e]=E.1x(6.T.R,6.1e);6.Y.1A=Q;6.3N(0,6.2b());9(6.1e=="2N"||6.1e=="1H")6.T.R[6.1e]="8N";E(6.T).1A()},1z:G(){6.Y.3P[6.1e]=E.1x(6.T.R,6.1e);6.Y.1z=Q;6.3N(6.2b(),0)},2F:G(){H t=(1u 3D()).3B();9(t>6.Y.2e+6.5u){6.2v=6.2D;6.4q=6.4i=1;6.4r();6.Y.3M[6.1e]=Q;H a=Q;L(H i 1i 6.Y.3M)9(6.Y.3M[i]!==Q)a=P;9(a){9(6.Y.19!=S){6.T.R.2U=6.Y.2U;6.T.R.19=6.Y.19;9(E.17(6.T,"19")=="2s")6.T.R.19="2Z"}9(6.Y.1z)6.T.R.19="2s";9(6.Y.1z||6.Y.1A)L(H p 1i 6.Y.3M)E.1x(6.T.R,p,6.Y.3P[p])}9(a&&E.1n(6.Y.1l))6.Y.1l.16(6.T);I P}J{H n=t-6.5u;6.4i=n/6.Y.2e;6.4q=E.3J[6.Y.3J||(E.3J.5q?"5q":"6B")](6.4i,n,0,1,6.Y.2e);6.2v=6.1O+((6.2D-6.1O)*6.4q);6.4r()}I Q}};E.2j.2F={2R:G(a){a.T.2R=a.2v},2B:G(a){a.T.2B=a.2v},1r:G(a){E.1x(a.T.R,"1r",a.2v)},6z:G(a){a.T.R[a.1e]=a.2v+a.2i}};E.1b.6m=G(){H c=0,3E=0,T=6[0],5t;9(T)8L(E.V){H b=E.17(T,"2X")=="4F",1D=T.12,23=T.23,2K=T.3H,4f=1N&&3x(4s)<8J;9(T.6V){5w=T.6V();1f(5w.1S+38.33(2K.2V.2R,2K.1G.2R),5w.3E+38.33(2K.2V.2B,2K.1G.2B));9(1h){H d=E("4o").17("8H");d=(d=="8G"||E.5g&&3x(4s)>=7)&&2||d;1f(-d,-d)}}J{1f(T.5l,T.5z);1W(23){1f(23.5l,23.5z);9(35&&/^t[d|h]$/i.14(1D.37)||!4f)d(23);9(4f&&!b&&E.17(23,"2X")=="4F")b=Q;23=23.23}1W(1D.37&&!/^1G|4o$/i.14(1D.37)){9(!/^8D|1I-9S.*$/i.14(E.17(1D,"19")))1f(-1D.2R,-1D.2B);9(35&&E.17(1D,"2U")!="3R")d(1D);1D=1D.12}9(4f&&b)1f(-2K.1G.5l,-2K.1G.5z)}5t={3E:3E,1S:c}}I 5t;G d(a){1f(E.17(a,"9T"),E.17(a,"8A"))}G 1f(l,t){c+=3x(l)||0;3E+=3x(t)||0}}})();',62,616,'||||||this|||if|||||||||||||||||||||||||||||||||function|var|return|else|length|for|data|each|type|false|true|style|null|elem|document|browser|undefined||options|||nodeName|parentNode||test|jQuery|apply|css|window|display|push|fn|constructor|url|prop|add|indexOf|msie|in|event|extend|complete|typeof|isFunction|className|replace|arguments|opacity|div|match|new|status|firstChild|attr|nodeType|hide|show|Array|success|parent|filter|trigger|body|height|table|script|tbody|cache|string|safari|start|hidden|value|merge|left|break|animate|dataType|while|map|find|global||get|id|offsetParent|select|toggle|selected|toUpperCase|remove|catch|try|cur|al|ready|duration|done|text|makeArray|unit|fx|swap|split|target||pushStack|toLowerCase|nextSibling|button|none|handle|guid|now|stack|tb|jsre|timeout|inArray|scrollTop|readyState|end|delete|step|one|name|nth|slice|doc|ret|preventDefault|width|call|events|checked|scrollLeft|exec|px|overflow|documentElement|grep|position|form|block|removeData|rl|timers|max|opera|mozilla|trim|tagName|Math|load|param|removeChild|disabled|insertBefore|async|encodeURIComponent|append|oldblock|val|childNodes|src|readyList|multiFilter|color|defaultView|stopPropagation|args|old|toString|is|last|first|eval|parseInt|self|domManip|prototype|getTime|curCSS|Date|top||ajax|ownerDocument|parseFloat|easing|has|queue|curAnim|custom|innerHTML|orig|currentStyle|visible|getElementById|isReady|error|static|bind|String|which|getComputedStyle|responseText|oWidth|oHeight|on|shift|json|child|RegExp|ol|lastModified|isXMLDoc|jsonp|jquery|previousSibling|dir|safari2|el|styleFloat|state|setInterval|radio|getElementsByTagName|tr|empty|html|getAttribute|pos|update|version|input|float|runtimeStyle|unshift|mouseover|getPropertyValue|GET|clearInterval|safariTimer|visibility|clean|__ie_init|absolute|handleHover|lastToggle|index|fromElement|relatedTarget|click|fix|evt|andSelf|removeEventListener|handler|cloneNode|addEventListener|triggered|nodeIndex|unique|Number|classFilter|prevObject|selectedIndex|after|submit|password|removeAttribute|file|expr|setTimeout|_|appendChild|ajaxSettings|client|active|win|sibling|deep|globalEval|boxModel|cssFloat|object|checkbox|parsererror|offsetLeft|wrapAll|dequeue|props|lastChild|swing|handleError|getResponseHeader|results|startTime|00|box|Modified|ifModified|offsetTop|evalScript|createElement|setRequestHeader|ctrlKey|callback|metaKey|contentType|ajaxSend|ajaxSuccess|ajaxError|ajaxStop|ajaxStart|serializeArray|init|notmodified|POST|loaded|appendTo|DOMContentLoaded|bindReady|mouseout|not|removeAttr|unbind|unload|Width|keyCode|charCode|onreadystatechange|clientX|pageX|srcElement|join|outerHTML|substr|zoom|parse|textarea|reset|image|odd|even|before|quickClass|quickID|prepend|quickChild|execScript|offset|scroll|processData|uuid|contents|continue|textContent|ajaxComplete|clone|setArray|webkit|nodeValue|fl|_default|100|linear|href|speed|eq|createTextNode|throw|replaceWith|splice|_toggle|xml|colgroup|304|200|alpha|Last|httpData|httpNotModified|httpSuccess|fieldset|beforeSend|getBoundingClientRect|XMLHttpRequest|ActiveXObject|col|br|abbr|pixelLeft|urlencoded|www|application|ajaxSetup|post|getJSON|getScript|elements|serialize|clientWidth|hasClass|scr|clientHeight|write|relative|keyup|keypress|keydown|change|mousemove|mouseup|mousedown|right|dblclick|resize|focus|blur|frames|instanceof|hover|offsetWidth|triggerHandler|ipt|defer|offsetHeight|border|padding|clientY|pageY|Left|Right|toElement|Bottom|Top|cancelBubble|returnValue|detachEvent|attachEvent|substring|line|weight|animated|header|font|enabled|innerText|contains|only|size|gt|lt|uFFFF|u0128|417|inner|Height|toggleClass|removeClass|addClass|replaceAll|noConflict|insertAfter|prependTo|wrap|contentWindow|contentDocument|http|iframe|children|siblings|prevAll|nextAll|wrapInner|prev|Boolean|next|parents|maxLength|maxlength|readOnly|readonly|class|htmlFor|CSS1Compat|compatMode|compatible|borderTopWidth|ie|ra|inline|it|rv|medium|borderWidth|userAgent|522|navigator|with|concat|1px|10000|array|ig|PI|NaN|400|reverse|fast|600|slow|Function|Object|setAttribute|changed|be|can|property|fadeTo|fadeOut|getAttributeNode|fadeIn|slideToggle|method|slideUp|slideDown|action|cssText|stop|responseXML|option|content|300|th|protocol|td|location|send|cap|abort|colg|cos|tfoot|thead|With|leg|Requested|opt|GMT|1970|Jan|01|Thu|area|Since|hr|If|Type|Content|meta|specified|open|link|XMLHTTP|Microsoft|img|onload|row|borderLeftWidth|head|attributes'.split('|'),0,{});
+
+/*
+    Copyright (c) 2004-2007, The Dojo Foundation
+    All Rights Reserved.
+
+    Licensed under the Academic Free License version 2.1 or above OR the
+    modified BSD license. For more information on Dojo licensing, see:
+
+        http://dojotoolkit.org/community/licensing.shtml
+*/
+
+/*
+    This is a compiled version of Dojo, built for deployment and not for
+    development. To get an editable version, please visit:
+
+        http://dojotoolkit.org
+
+    for documentation and information on getting the source.
+*/
+
+var decompressedDojo = function(p,a,c,k,e,d){e=function(c){return(c<a?"":e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)d[e(c)]=k[c]||e(c);k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('if(V z=="1k"){(B(){if(V D["1o"]=="1k"){D.1o={}}if((!D["1z"])||(!1z["ca"])){D.1z={}}A cn=["rA","rz","1K","ry","rx","9f","rw","rv","ru","rt","rs","rr","rq","ro","rn","rm"];A i=0,24;1s(24=cn[i++]){if(!1z[24]){1z[24]=B(){}}}if(V D["z"]=="1k"){D.z={}}z.1W=D;A d3={im:U,rl:U,rk:"",rj:"",ri:"",rh:K,rg:U};R(A 8z in d3){if(V 1o[8z]=="1k"){1o[8z]=d3[8z]}}A jK=["rf","rd","rc","rb"];A t;1s(t=jK.3a()){z["is"+t]=U}})();z.8h=1o.8h;z.cY={jJ:0,jI:9,jH:0,jG:"",jF:2V("$ra: r9 $".1f(/[0-9]+/)[0]),2i:B(){4G(z.cY){C jJ+"."+jI+"."+jH+jG+" ("+jF+")"}}};z.d1=B(jE,jD,1V){A 2h=1V||z.1W;R(A i=0,p;2h&&(p=jE[i]);i++){2h=(p in 2h?2h[p]:(jD?2h[p]={}:1k))}C 2h};z.88=B(jC,jA,jB){A d2=jC.1A("."),p=d2.8q(),M=z.d1(d2,K,jB);C(M&&p?(M[p]=jA):1k)};z.6q=B(jz,jy,jx){C z.d1(jz.1A("."),jy,jx)};z.r8=B(jw,M){C!!z.6q(jw,U,M)};z["3u"]=B(d0){C z.1W.3u?z.1W.3u(d0):3u(d0)};z.ia=B(jv,cZ,cX){A 8y="r7: "+jv;if(cZ){8y+=" "+cZ}if(cX){8y+=" -- r6 be r5 in cY: "+cX}1z.1K(8y)};z.r4=B(ju,cW){A cV="r3: "+ju+" -- r2 r1 4F r0 qZ qY.";if(cW){cV+=" "+cW}1z.1K(cV)};(B(){A cR={53:{},6p:0,1h:{},8k:{z:{1p:"z",1Z:"."},cU:{1p:"cU",1Z:"../qX/cU"},cT:{1p:"cT",1Z:"cT"}},cN:B(cS){A mp=D.8k;C jp(mp[cS]&&mp[cS].1Z)},jk:B(8x){A mp=D.8k;if(D.cN(8x)){C mp[8x].1Z}C 8x},8v:[],6t:U,56:[],8t:[],8u:U};R(A cQ in cR){z[cQ]=cR[cQ]}})();z.jg=B(8w,cP,cb){A 1g=(((8w.2s(0)=="/"||8w.1f(/^\\w+:/)))?"":D.51)+8w;if(1o.jt&&z.c8){1g+="?"+67(1o.jt).2f(/\\W+/g,"")}1u{C!cP?D.cO(1g,cb):D.jq(1g,cP,cb)}1y(e){1z.1K(e);C U}};z.cO=B(1g,cb){if(D.8v[1g]){C K}A 6u=D.iR(1g,K);if(!6u){C U}D.8v[1g]=K;D.8v.Y(1g);if(cb){6u="("+6u+")"}A jr=z["3u"](6u+"\\r\\n//@ qW="+1g);if(cb){cb(jr)}C K};z.jq=B(1g,jo,cb){A ok=U;1u{ok=D.cO(1g,cb)}1y(e){1z.1K("qV je ",1g," 4G 9f: ",e)}C jp(ok&&D.53[jo])};z.6m=B(){D.8u=K;D.6t=K;A 57=D.56;D.56=[];R(A x=0;x<57.G;x++){57[x]()}D.8u=U;if(z.6t&&z.6p==0&&D.56.G>0){z.8s()}};z.ck=B(){A 57=D.8t;1s(57.G){(57.8q())()}};z.qU=B(M,jn){A d=z;if(P.G==1){d.56.Y(M)}I{if(P.G>1){d.56.Y(B(){M[jn]()})}}if(d.6t&&d.6p==0&&!d.8u){d.8s()}};z.dW=B(M,jm){A d=z;if(P.G==1){d.8t.Y(M)}I{if(P.G>1){d.8t.Y(B(){M[jm]()})}}};z.iM=B(){if(D.6t){C}if(D.6p>0){1z.1K("qT qS in qR!");C}z.8s()};z.8s=B(){if(V 5c=="8b"||(1o["qQ"]&&z.2M)){5c("z.6m();",0)}I{z.6m()}};z.cF=B(jl){A 4v=jl.1A(".");R(A i=4v.G;i>0;i--){A 8r=4v.2w(0,i).22(".");if((i==1)&&!D.cN(8r)){4v[0]="../"+4v[0]}I{A cM=D.jk(8r);if(cM!=8r){4v.3S(0,i,cM);3f}}}C 4v};z.jj=U;z.8m=B(2T,qP,55){55=D.jj||55;A 54=D.53[2T];if(54){C 54}A cL=2T.1A(".");A 3L=D.cF(2T);A jh=((3L[0].2s(0)!="/")&&!3L[0].1f(/^\\w+:/));A ji=3L[3L.G-1];A 3m;if(ji=="*"){2T=cL.2w(0,-1).22(".");3L.8q();3m=3L.22("/")+"/"+(1o["qO"]||"qN")+".js";if(jh&&3m.2s(0)=="/"){3m=3m.2w(1)}}I{3m=3L.22("/")+".js";2T=cL.22(".")}A jf=(!55)?2T:L;A ok=D.jg(3m,jf);if((!ok)&&(!55)){2m S 1O("qM 3O 4E \'"+2T+"\'; 72 qL \'"+3m+"\'")}if((!55)&&(!D["qK"])){54=D.53[2T];if(!54){2m S 1O("qJ \'"+2T+"\' is 3O qI a8 je \'"+3m+"\'")}}C 54};z.8c=z.8m;z.1Q=B(cK){A cJ=cK+"";A 8p=cJ;A 6s=cK.1A(/\\./);if(6s[6s.G-1]=="*"){6s.8q();8p=6s.22(".")}A 8o=z.6q(8p,K);D.53[cJ]=8o;D.53[8p]=8o;C 8o};z.qH=B(8n){A jd=8n["qG"]||[];A cI=jd.3U(8n[z.j4]||8n["aY"]||[]);R(A x=0;x<cI.G;x++){A 8l=cI[x];if(8l.1P==4e){z.8m.14(z,8l)}I{z.8m(8l)}}};z.jb=B(jc,qF){if(jc===K){A cH=[];R(A i=1;i<P.G;i++){cH.Y(P[i])}z.8c.14(z,cH)}};z.qE=z.jb;z.io=B(cG,ja){D.8k[cG]={1p:cG,1Z:ja}};z.qD=B(qC,qB,qA,qz){z.8c("z.j9");z.j9.qy.14(z.qx,P)};(B(){A j7=S 9G("^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\\\?([^#]*))?(#(.*))?$");A j6=S 9G("^((([^:]+:)?([^@]+))@)?([^:]*)(:([0-9]+))?$");z.4r=B(){A n=L;A 1V=P;A 1g=1V[0];R(A i=1;i<1V.G;i++){if(!1V[i]){6c}A 1t=S z.4r(1V[i]+"");A 4u=S z.4r(1g+"");if((1t.28=="")&&(!1t.4t)&&(!1t.3l)&&(!1t.1r)){if(1t.52!=n){4u.52=1t.52}1t=4u}I{if(!1t.4t){1t.4t=4u.4t;if(!1t.3l){1t.3l=4u.3l;if(1t.28.2s(0)!="/"){A j8=4u.28.21(0,4u.28.31("/")+1)+1t.28;A 1X=j8.1A("/");R(A j=0;j<1X.G;j++){if(1X[j]=="."){if(j==1X.G-1){1X[j]=""}I{1X.3S(j,1);j--}}I{if(j>0&&!(j==1&&1X[0]=="")&&1X[j]==".."&&1X[j-1]!=".."){if(j==(1X.G-1)){1X.3S(j,1);1X[j-1]=""}I{1X.3S(j-1,2);j-=2}}}}1t.28=1X.22("/")}}}}1g="";if(1t.4t){1g+=1t.4t+":"}if(1t.3l){1g+="//"+1t.3l}1g+=1t.28;if(1t.1r){1g+="?"+1t.1r}if(1t.52){1g+="#"+1t.52}}D.1g=1g.2i();A r=D.1g.1f(j7);D.4t=r[2]||(r[1]?"":n);D.3l=r[4]||(r[3]?"":n);D.28=r[5];D.1r=r[7]||(r[6]?"":n);D.52=r[9]||(r[8]?"":n);if(D.3l!=n){r=D.3l.1f(j6);D.8X=r[3]||n;D.8W=r[4]||n;D.qw=r[5];D.qv=r[7]||n}};z.4r.1C.2i=B(){C D.1g}})();z.qu=B(j5,2E){A 2B=z.cF(j5).22("/");if(!2B){C L}if(2B.31("/")!=2B.G-1){2B+="/"}A cE=2B.T(":");if(2B.2s(0)!="/"&&(cE==-1||cE>2B.T("/"))){2B=z.51+2B}C S z.4r(2B,2E)};if(V 26!="1k"){z.c8=K;z.j4="qt";(B(){A d=z;if(1q&&1q.4I){A 8j=1q.4I("ak");A j3=/z(\\.qs)?\\.js([\\?\\.]|$)/i;R(A i=0;i<8j.G;i++){A 4X=8j[i].5t("4X");if(!4X){6c}A m=4X.1f(j3);if(m){if(!1o["51"]){1o["51"]=4X.21(0,m.hK)}A cD=8j[i].5t("1o");if(cD){A cC=3u("({ "+cD+" })");R(A x in cC){1o[x]=cC[x]}}3f}}}d.51=1o["51"];A n=cq;A 8i=n.iL;A 4Z=n.qr;A 6r=2k(4Z);d.2M=(8i.T("qq")>=0)?6r:0;d.6B=(4Z.T("qo")>=0)||(4Z.T("j2")>=0)?6r:0;d.3o=(4Z.T("j2")>=0)?6r:0;A j1=8i.T("qn");d.gu=d.7B=((j1>=0)&&(!d.6B))?6r:0;d.j0=0;d.1l=0;d.iV=0;1u{if(d.7B){d.j0=2k(8i.1A("qm/")[1].1A(" ")[0])}if((1q.gx)&&(!d.2M)){d.1l=2k(4Z.1A("qk ")[1].1A(";")[0])}}1y(e){}if(z.1l&&(26.8f.cu==="9q:")){1o.iT=K}d.iX=B(){A 2A;A qj;A cB=d.6q("cz.cy");if(cB){C cB}if(V iZ!="1k"){2A=S iZ()}I{if(d.1l){1u{2A=S 9j("qi.qh")}1y(e){}}I{if(cq.qg["8Z/x-iY"]){2A=1q.a9("8b");2A.cA("Z","8Z/x-iY");2A.cA("3n",0);2A.cA("58",0);2A.1c.gq="7C";1q.5K.4c(2A)}}}if(!2A){C L}z.88("cz.cy.qf",2A);C z.6q("cz.cy")};A iW=d.iX();if(iW){d.iV=K}A cm=1q["aX"];d.qe=(cm=="aW")||(cm=="gr")||(d.1l<6);d.8h=1o.8h||(d.1l?n.qd:n.qc).1M();d.qb=1z.1K;d.cx=["iU.8g","em.8g","iU.8g.4.0"];d.9b=B(){A 4s=L;A cv=L;if(!z.1l||!1o.iT){1u{4s=S qa()}1y(e){}}if(!4s){R(A i=0;i<3;++i){A cw=z.cx[i];1u{4s=S 9j(cw)}1y(e){cv=e}if(4s){z.cx=[cw];3f}}}if(!4s){2m S 1O("8g 3O q9: "+cv)}C 4s};d.8Y=B(iS){A 4Y=iS.3N||0;C((4Y>=q8)&&(4Y<q7))||(4Y==q6)||(4Y==q5)||(!4Y&&(8f.cu=="9q:"||8f.cu=="q4:"))};A cs=1q.4I("q3");A iQ=(cs&&cs.G>0);d.iR=B(1g,iP){A 3K=D.9b();if(!iQ&&z.4r){1g=(S z.4r(26.8f,1g)).2i()}3K.dL("dD",1g,U);1u{3K.dI(L);if(!d.8Y(3K)){A 1G=1O("q2 4F 4E "+1g+" 3N:"+3K.3N);1G.3N=3K.3N;1G.2G=3K.2G;2m 1G}}1y(e){if(iP){C L}2m e}C 3K.2G}})();z.iO=U;z.6o=B(e){z.iO=K;A cr=(e&&e.Z)?e.Z.1M():"4E";if(P.2O.iN||(cr!="q1"&&cr!="4E")){C}P.2O.iN=K;if(V z["8e"]!="1k"){dX(z.8e);63 z.8e}if(z.6p==0){z.iM()}};if(1q.66){if(z.2M||(z.7B&&(1o["q0"]===K))){1q.66("pZ",z.6o,L)}26.66("4E",z.6o,L)}if(/(pY|pX)/i.6Z(cq.iL)){z.8e=dN(B(){if(/6m|iJ/.6Z(1q.6F)){z.6o()}},10)}(B(){A 3g=26;A 8d=B(cp,fp){A iK=3g[cp]||B(){};3g[cp]=B(){fp.14(3g,P);iK.14(3g,P)}};if(z.1l){1q.fJ("<iI"+"iH pW 4X=\\"//:\\" "+"pV=\\"if(D.6F==\'iJ\'){z.6o();}\\">"+"</iI"+"iH>");A co=K;8d("iG",B(){3g.5c(B(){co=U},0)});8d("pU",B(){if(co){z.ck()}});1u{1q.pT.2P("v","pS:pR-pQ-pP:pO");1q.pN().pM("v\\\\:*","pL:2E(#aY#pK)")}1y(e){}}I{8d("iG",B(){z.ck()})}})();z.pJ=B(){};z.1e=26["1q"]||L;z.3E=B(){C z.1e.3E||z.1e.4I("3E")[0]};z.ch=B(iF,iE){z.1W=iF;z.1e=iE};z.cf=B(4q,6n,iD){if((6n)&&((V 4q=="3c")||(4q 1N 67))){4q=6n[4q]}C(6n?4q.14(6n,iD||[]):4q())};z.pI=B(cj,iC,iB,iA){A cg;A iz=z.1W;A iy=z.1e;1u{z.ch(cj,cj.1q);cg=z.cf(iC,iB,iA)}ir{z.ch(iz,iy)}C cg};z.pH=B(ix,iw,iv,iu){A ce;A ip=z.1e;1u{z.1e=ix;ce=z.cf(iw,iv,iu)}ir{z.1e=ip}C ce};if(1o["cd"]){R(A cc in 1o["cd"]){z.io(cc,1o["cd"][cc])}}}if(1o.im){if(!1z.ca){z.8c("z.pG.ca")}}}if(!z.1h["z.X.c9"]){z.1h["z.X.c9"]=K;z.1Q("z.X.c9");z.1R=B(it){C(V it=="3c"||it 1N 67)};z.2l=B(it){C(it&&it 1N 4e||V it=="6a"||((V z["1H"]!="1k")&&(it 1N z.1H)))};if(z.c8&&z.3o){z.1Y=B(it){if((V(it)=="B")&&(it=="[8b 1H]")){C U}C(V it=="B"||it 1N bI)}}I{z.1Y=B(it){C(V it=="B"||it 1N bI)}}z.ib=B(it){if(V it=="1k"){C U}C(it===L||V it=="8b"||z.2l(it)||z.1Y(it))};z.pF=B(it){A d=z;if((!it)||(V it=="1k")){C U}if(d.1R(it)){C U}if(d.1Y(it)){C U}if(d.2l(it)){C K}if((it.5w)&&(it.5w.1M()=="3R")){C U}if(pE(it.G)){C K}C U};z.pD=B(it){if(!it){C U}C!z.1Y(it)&&/\\{\\s*\\[il 5h\\]\\s*\\}/.6Z(67(it))};z.c7=B(M,4W){A 8a={};R(A x in 4W){if((V 8a[x]=="1k")||(8a[x]!=4W[x])){M[x]=4W[x]}}if(z.1l){A p=4W.2i;if((V(p)=="B")&&(p!=M.2i)&&(p!=8a.2i)&&(p!="\\pC 2i() {\\n    [il 5h]\\n}\\n")){M.2i=4W.2i}}C M};z.1x=B(M,pB){R(A i=1,l=P.G;i<l;i++){z.c7(M,P[i])}C M};z.4M=B(c6,pA){R(A i=1,l=P.G;i<l;i++){z.c7(c6.1C,P[i])}C c6};z.ig=B(c5,89){A ij=z.4d(P,2);A ik=z.1R(89);C B(){A ih=z.4d(P);A f=(ik?(c5||z.1W)[89]:89);C(f)&&(f.14(c5||D,ij.3U(ih)))}};z.2p=B(2z,3k){if(P.G>2){C z.ig.14(z,P)}if(!3k){3k=2z;2z=L}if(z.1R(3k)){2z=2z||z.1W;if(!2z[3k]){2m(["z.2p: ie[\\"",3k,"\\"] is L (ie=\\"",2z,"\\")"].22(""))}C B(){C 2z[3k].14(2z,P||[])}}I{C(!2z?3k:B(){C 3k.14(2z,P||[])})}};z.6j=B(M,c3){B c4(){};c4.1C=M;A c2=S c4();if(c3){z.1x(c2,c3)}C c2};z.7X=B(pz){A Q=[L];C z.2p.14(z,Q.3U(z.4d(P)))};z.4d=B(M,ic){A Q=[];R(A x=ic||0;x<M.G;x++){Q.Y(M[x])}C Q};z.c1=B(o){if(!o){C o}if(z.2l(o)){A r=[];R(A i=0;i<o.G;++i){r.Y(z.c1(o[i]))}C r}I{if(z.ib(o)){if(o.2t&&o.a7){C o.a7(K)}I{A r=S o.1P();R(A i in o){if(!(i in r)||r[i]!=o[i]){r[i]=z.c1(o[i])}}C r}}}C o};z.7g=B(2H){C 2H.2f(/^\\s\\s*/,"").2f(/\\s\\s*$/,"")}}if(!z.1h["z.X.2r"]){z.1h["z.X.2r"]=K;z.1Q("z.X.2r");z.2r=B(6l,4p,3j){if(z.1Y(3j)||(P.G>3)){z.ia("z.2r: R 9P \'"+6l+"\' py pw B as \'1P\' pv pu of as a pt i3.","","1.0");A c=3j;3j=P[3]||{};3j.1P=c}A dd=P.2O,4V=L;if(z.2l(4p)){4V=4p;4p=4V.3a()}if(4V){R(A i=0,m;i<4V.G;i++){m=4V[i];if(!m){2m("ps #"+i+" 4F pr of "+6l+" is L. pq\'s pp a po pl is 3O 6m.")}4p=dd.6j(4p,m)}}A i9=(3j||0).1P,6k=dd.6j(4p),fn;R(A i in 3j){if(z.1Y(fn=3j[i])&&(!0[i])){fn.i4=i}}z.4M(6k,{4o:6l,bY:i9,bZ:L},3j||0);6k.1C.1P=6k;C z.88(6l,6k)};z.1x(z.2r,{6j:B(c0,i8){A bp=(c0||0).1C,mp=(i8||0).1C;A 2S=z.2r.i7();z.1x(2S,{84:bp,1x:mp});if(c0){2S.1C=z.6j(bp)}z.4M(2S,z.2r.i6,mp||0,{bY:L});2S.1C.1P=2S;2S.1C.4o=(bp||0).4o+"pk"+(mp||0).4o;z.88(2S.1C.4o,2S);C 2S},i7:B(){C B(){D.i5(P)}},i6:{i5:B(86){A c=86.2O,s=c.84,ct=s&&s.1P,m=c.1x,87=m&&m.1P,a=86,ii,fn;if(a[0]){if((fn=a[0]["bZ"])){a=fn.14(D,a)||a}}if(fn=c.1C.bZ){a=fn.14(D,a)||a}if(ct&&ct.14){ct.14(D,a)}if(87&&87.14){87.14(D,a)}if(ii=c.1C.bY){ii.14(D,86)}},bX:B(85){A c=D.1P,p,m;1s(c){p=c.84;m=c.1x;if(m==85||(m 1N 85.1P)){C p}if(m&&(m=m.bX(85))){C m}c=p&&p.1P}},6h:B(83,82,bW,6i){A p=bW,c,m,f;do{c=p.1P;m=c.1x;if(m&&(m=D.6h(83,82,m,6i))){C m}if((f=p[83])&&(6i==(f==82))){C p}p=c.84}1s(p);C!6i&&(p=D.bX(bW))&&D.6h(83,82,p,6i)},bU:B(2R,4U,bV){A a=P;if(!z.1R(a[0])){bV=4U;4U=2R;2R=4U.2O.i4}A c=4U.2O,p=D.1P.1C,a=bV||4U,fn,mp;if(D[2R]!=c||p[2R]==c){mp=D.6h(2R,c,p,K);if(!mp){2m(D.4o+": 1p i3 (\\""+2R+"\\") 4F bU pj 1f 2O (2r.js)")}p=D.6h(2R,c,mp,U)}fn=p&&p[2R];if(!fn){1z.1K(mp.4o+": no bU \\""+2R+"\\" ph pg (2r.js)");C}C fn.14(D,a)}}})}if(!z.1h["z.X.2c"]){z.1h["z.X.2c"]=K;z.1Q("z.X.2c");z.3i={i2:B(){C B(){A ap=4e.1C,c=P.2O,ls=c.2b,t=c.5V;A r=t&&t.14(D,P);R(A i in ls){if(!(i in ap)){ls[i].14(D,P)}}C r}},2P:B(6g,bT,i1){6g=6g||z.1W;A f=6g[bT];if(!f||!f.2b){A d=z.3i.i2();d.5V=f;d.2b=[];f=6g[bT]=d}C f.2b.Y(i1)},3J:B(i0,hZ,bS){A f=(i0||z.1W)[hZ];if(f&&f.2b&&bS--){63 f.2b[bS]}}};z.2c=B(M,pd,pc,pa,p9){A a=P,F=[],i=0;F.Y(z.1R(a[0])?L:a[i++],a[i++]);A a1=a[i+1];F.Y(z.1R(a1)||z.1Y(a1)?a[i++]:L,a[i++]);R(A l=a.G;i<l;i++){F.Y(a[i])}C z.by.14(D,F)};z.by=B(M,bR,hY,hX){A l=z.3i,h=l.2P(M,bR,z.2p(hY,hX));C[M,bR,h,l]};z.p8=B(6f){if(6f&&6f[0]!==1k){z.bv.14(D,6f);63 6f[0]}};z.bv=B(M,hV,hU,hW){hW.3J(M,hV,hU)};z.80={};z.p7=B(bQ,hT,hS){C[bQ,z.3i.2P(z.80,bQ,z.2p(hT,hS))]};z.p6=B(81){if(81){z.3i.3J(z.80,81[0],81[1])}};z.hQ=B(hR,F){A f=z.80[hR];(f)&&(f.14(D,F||[]))};z.p5=B(hP,M,bP){A pf=B(){z.hQ(hP,P)};C(bP)?z.2c(M,bP,pf):z.2c(M,pf)}}if(!z.1h["z.X.30"]){z.1h["z.X.30"]=K;z.1Q("z.X.30");z.30=B(hO){D.bM=[];D.id=D.hN();D.2y=-1;D.3M=0;D.4R=[L,L];D.bO=hO;D.7Z=U};z.4M(z.30,{hN:(B(){A n=1;C B(){C n++}})(),4C:B(){if(D.2y==-1){if(D.bO){D.bO(D)}I{D.7Z=K}if(D.2y==-1){A 1G=S 1O("30 p4");1G.dY="4C";D.5i(1G)}}I{if((D.2y==0)&&(D.4R[0]1N z.30)){D.4R[0].4C()}}},7V:B(1v){D.2y=((1v 1N 1O)?1:0);D.4R[D.2y]=1v;D.7U()},bN:B(){if(D.2y!=-1){if(!D.7Z){2m S 1O("p3 p2!")}D.7Z=U;C}},dM:B(1v){D.bN();D.7V(1v)},5i:B(1v){D.bN();if(!(1v 1N 1O)){1v=S 1O(1v)}D.7V(1v)},9e:B(cb,4T){A 6e=z.2p(cb,4T);if(P.G>2){6e=z.7X(6e,P,2)}C D.5k(6e,6e)},ef:B(cb,4T){A 7Y=z.2p(cb,4T);if(P.G>2){7Y=z.7X(7Y,P,2)}C D.5k(7Y,L)},ed:B(cb,4T){A 7W=z.2p(cb,4T);if(P.G>2){7W=z.7X(7W,P,2)}C D.5k(L,7W)},5k:B(cb,eb){D.bM.Y([cb,eb]);if(D.2y>=0){D.7U()}C D},7U:B(){A bL=D.bM;A 4n=D.2y;A 1v=D.4R[4n];A 4S=D;A cb=L;1s((bL.G>0)&&(D.3M==0)){A f=bL.3a()[4n];if(!f){6c}1u{1v=f(1v);4n=((1v 1N 1O)?1:0);if(1v 1N z.30){cb=B(1v){4S.7V(1v);4S.3M--;if((4S.3M==0)&&(4S.2y>=0)){4S.7U()}};D.3M++}}1y(1G){1z.1K(1G);4n=1;1v=1G}}D.2y=4n;D.4R[4n]=1v;if((cb)&&(D.3M)){1v.9e(cb)}}})}if(!z.1h["z.X.2e"]){z.1h["z.X.2e"]=K;z.1Q("z.X.2e");z.5m=B(2e){1u{C 3u("("+2e+")")}1y(e){1z.1K(e);C 2e}};z.bK=B(2H){C("\\""+2H.2f(/(["\\\\])/g,"\\\\$1")+"\\"").2f(/[\\f]/g,"\\\\f").2f(/[\\b]/g,"\\\\b").2f(/[\\n]/g,"\\\\n").2f(/[\\t]/g,"\\\\t").2f(/[\\r]/g,"\\\\r")};z.hM="\\t";z.eq=B(it,4l,4P){4P=4P||"";A 4k=(4l?4P+z.hM:"");A 6b=(4l?"\\n":"");A 4Q=V(it);if(4Q=="1k"){C"1k"}I{if((4Q=="4J")||(4Q=="p1")){C it+""}I{if(it===L){C"L"}}}if(4Q=="3c"){C z.bK(it)}A 6d=P.2O;A 4m;if(V it.hL=="B"){4m=it.hL();if(it!==4m){C 6d(4m,4l,4k)}}if(V it.2e=="B"){4m=it.2e();if(it!==4m){C 6d(4m,4l,4k)}}if(z.2l(it)){A 1v=[];R(A i=0;i<it.G;i++){A 1U=6d(it[i],4l,4k);if(V(1U)!="3c"){1U="1k"}1v.Y(6b+4k+1U)}C"["+1v.22(", ")+6b+4P+"]"}if(4Q=="B"){C L}A bJ=[];R(A 1i in it){A 7T;if(V(1i)=="4J"){7T="\\""+1i+"\\""}I{if(V(1i)=="3c"){7T=z.bK(1i)}I{6c}}1U=6d(it[1i],4l,4k);if(V(1U)!="3c"){6c}bJ.Y(6b+4k+7T+": "+1U)}C"{"+bJ.22(", ")+6b+4P+"}"}}if(!z.1h["z.X.6a"]){z.1h["z.X.6a"]=K;z.1Q("z.X.6a");(B(){A 69=B(Q,M,cb){C[(z.1R(Q)?Q.1A(""):Q),(M||z.1W),(z.1R(cb)?(S bI("1m","hK","6a",cb)):cb)]};z.1x(z,{T:B(bH,hH,hI,hJ){A i=0,2q=1,1d=bH.G;if(hJ){i=1d-1;2q=1d=-1}R(i=hI||i;i!=1d;i+=2q){if(bH[i]==hH){C i}}C-1},31:B(hG,hF,hE){C z.T(hG,hF,hE,K)},1n:B(Q,hD,M){if(!Q||!Q.G){C}A 1I=69(Q,M,hD);Q=1I[0];R(A i=0,l=1I[0].G;i<l;i++){1I[2].2d(1I[1],Q[i],i,Q)}},bE:B(bF,Q,hC,M){A 1I=69(Q,M,hC);Q=1I[0];R(A i=0,l=Q.G;i<l;i++){A bG=!!1I[2].2d(1I[1],Q[i],i,Q);if(bF^bG){C bG}}C bF},ah:B(Q,hB,hA){C D.bE(K,Q,hB,hA)},ag:B(Q,hz,hy){C D.bE(U,Q,hz,hy)},23:B(Q,7t,M){A 1I=69(Q,M,7t);Q=1I[0];A bD=((P[3])?(S P[3]()):[]);R(A i=0;i<Q.G;++i){bD.Y(1I[2].2d(1I[1],Q[i],i,Q))}C bD},3T:B(Q,hx,M){A 1I=69(Q,M,hx);Q=1I[0];A bC=[];R(A i=0;i<Q.G;i++){if(1I[2].2d(1I[1],Q[i],i,Q)){bC.Y(Q[i])}}C bC}})})()}if(!z.1h["z.X.1J"]){z.1h["z.X.1J"]=K;z.1Q("z.X.1J");z.1J=B(bB){if(bB){D.hw(bB)}};z.1J.hp={p0:[0,0,0],oZ:[60,60,60],oY:[2j,2j,2j],oX:[1T,1T,1T],oW:[2j,0,0],oV:[1T,0,0],oU:[2j,0,2j],oT:[1T,0,1T],oS:[0,2j,0],oR:[0,1T,0],oQ:[2j,2j,0],oP:[1T,1T,0],oO:[0,0,2j],oN:[0,0,1T],oM:[0,2j,2j],oL:[0,1T,1T]};z.4M(z.1J,{r:1T,g:1T,b:1T,a:1,bz:B(r,g,b,a){A t=D;t.r=r;t.g=g;t.b=b;t.a=a},hw:B(2Q){A d=z;if(d.1R(2Q)){d.hq(2Q,D)}I{if(d.2l(2Q)){d.7P(2Q,D)}I{D.bz(2Q.r,2Q.g,2Q.b,2Q.a);if(!(2Q 1N d.1J)){D.7Q()}}}C D},7Q:B(){C D},oK:B(){A t=D;C[t.r,t.g,t.b]},oJ:B(){A t=D;C[t.r,t.g,t.b,t.a]},oI:B(){A Q=z.23(["r","g","b"],B(x){A s=D[x].2i(16);C s.G<2?"0"+s:s},D);C"#"+Q.22("")},8F:B(hv){A t=D,7S=t.r+", "+t.g+", "+t.b;C(hv?"hs("+7S+", "+t.a:"7S("+7S)+")"},2i:B(){C D.8F(K)}});z.d8=B(bA,1d,hu,M){A d=z,t=M||S z.1J();d.1n(["r","g","b","a"],B(x){t[x]=bA[x]+(1d[x]-bA[x])*hu;if(x!="a"){t[x]=2Y.oH(t[x])}});C t.7Q()};z.ho=B(ht,M){A m=ht.1M().1f(/^hs?\\(([\\s\\.,0-9]+)\\)/);C m&&z.7P(m[1].1A(/\\s*,\\s*/),M)};z.hn=B(4j,M){A d=z,t=M||S d.1J(),7R=(4j.G==4)?4:8,hr=(1<<7R)-1;4j=2V("oG"+4j.3b(1));if(2L(4j)){C L}d.1n(["b","g","r"],B(x){A c=4j&hr;4j>>=7R;t[x]=7R==4?17*c:c});t.a=1;C t};z.7P=B(a,M){A t=M||S z.1J();t.bz(2V(a[0]),2V(a[1]),2V(a[2]),2V(a[3]));if(2L(t.a)){t.a=1}C t.7Q()};z.hq=B(2H,M){A a=z.1J.hp[2H];C a&&z.7P(a,M)||z.ho(2H,M)||z.hn(2H,M)}}if(!z.1h["z.X"]){z.1h["z.X"]=K;z.1Q("z.X")}if(!z.1h["z.X.5Z"]){z.1h["z.X.5Z"]=K;z.1Q("z.X.5Z");(B(){A 1j=z.b2={2P:B(E,68,fp){if(!E){C}68=1j.4O(68);fp=1j.7G(68,fp);E.66(68,fp,U);C fp},3J:B(E,hm,hl){(E)&&(E.oF(1j.4O(hm),hl,U))},4O:B(1p){C(1p.2w(0,2)=="on"?1p.2w(2):1p)},7G:B(1p,fp){C(1p!="4b"?fp:B(e){C fp.2d(D,1j.4i(e,D))})},4i:B(H,oE){4w(H.Z){2X"4b":1j.7K(H);3f}C H},7K:B(H){H.oD=(H.3h?67.oC(H.3h):"")}};z.oB=B(H,hk){C 1j.4i(H,hk)};z.gY=B(H){H.7J();H.7I()};A 7O=z.3i;z.by=B(M,bx,hh,hg,hi){A hj=M&&(M.2t||M.oA||M.66);A bw=!hj?0:(!hi?1:2),l=[z.3i,1j,7O][bw];A h=l.2P(M,bx,z.2p(hh,hg));C[M,bx,h,bw]};z.bv=B(M,he,hd,hf){([z.3i,1j,7O][hf]).3J(M,he,hd)};z.5W={oz:8,gV:9,oy:12,ox:13,ow:16,ov:17,ou:18,gG:19,ot:20,os:27,or:32,b5:33,b4:34,gE:35,gF:36,b7:37,b9:38,b6:39,b8:40,gD:45,8S:46,oq:47,oo:91,om:92,ol:93,oj:96,oi:97,oh:98,og:99,oe:6D,od:oc,ob:oa,o9:o8,o7:o6,o5:o4,o3:bi,o2:o1,o0:nZ,nY:nX,nW:nV,nU:bk,gS:nT,gR:nS,gQ:nR,gP:nQ,gO:nP,gN:nO,gM:nN,gL:nM,gK:nL,gJ:nK,gI:nJ,gH:nI,nH:nG,nF:nE,nD:nC,gB:nB,gC:nA};if(z.1l){bf=B(e,5h){1u{C(e.3I=5h)}1y(e){C 0}};A 61=z.3i;if(!1o.nz){7O=61=z.gy={b3:[],2P:B(64,bu,hc){64=64||z.1W;A f=64[bu];if(!f||!f.2b){A d=z.gz();d.5V=f&&(7M.Y(f)-1);d.2b=[];f=64[bu]=d}C f.2b.Y(7M.Y(hc)-1)},3J:B(hb,ha,7N){A f=(hb||z.1W)[ha],l=f&&f.2b;if(f&&l&&7N--){63 7M[l[7N]];63 l[7N]}}};A 7M=61.b3}z.1x(1j,{2P:B(E,62,fp){if(!E){C}62=1j.4O(62);if(62=="h3"){A kd=E.bs;if(!kd||!kd.2b||!kd.h9){1j.2P(E,"bs",1j.h4);E.bs.h9=K}}C 61.2P(E,62,1j.7G(fp))},3J:B(E,h8,h7){61.3J(E,1j.4O(h8),h7)},4O:B(7L){C(7L.2w(0,2)!="on"?"on"+7L:7L)},ny:B(){},4i:B(H,4N){if(!H){A w=(4N)&&((4N.aD||4N.1q||4N).nx)||26;H=w.5Z}if(!H){C(H)}H.5V=H.br;H.bh=(4N||H.br);H.nw=H.nv;H.nu=H.nr;A bq=H.br,1e=(bq&&bq.aD)||1q;A bn=((z.1l<6)||(1e["aX"]=="aW"))?1e.3E:1e.5K;A bm=z.aB();H.nq=H.np+z.aH(bn.5I||0)-bm.x;H.nn=H.nm+(bn.5G||0)-bm.y;if(H.Z=="fk"){H.h6=H.nl}if(H.Z=="fj"){H.h6=H.nk}H.7I=1j.bc;H.7J=1j.ba;C 1j.h5(H)},h5:B(H){4w(H.Z){2X"4b":A c=("3h"in H?H.3h:H.3I);if(c==10){c=0;H.3I=13}I{if(c==13||c==27){c=0}I{if(c==3){c=99}}}H.3h=c;1j.7K(H);3f}C H},gZ:{bi:42,bk:47,h2:59,nj:43,ni:44,nh:45,ng:46,nf:47,60:96,h1:91,nb:92,na:93,h0:39},h4:B(H){A kp=H.bh.h3;if(!kp||!kp.2b){C}A k=H.3I;A bj=(k!=13)&&(k!=32)&&(k!=27)&&(k<48||k>90)&&(k<96||k>bk)&&(k<h2||k>60)&&(k<h1||k>h0);if(bj||H.5Y){A c=(bj?0:k);if(H.5Y){if(k==3||k==13){C}I{if(c>95&&c<bi){c-=48}I{if((!H.5X)&&(c>=65&&c<=90)){c+=32}I{c=1j.gZ[c]||c}}}}A 2x=1j.7H(H,{Z:"4b",2x:K,3h:c});kp.2d(H.bh,2x);H.bg=2x.bg;H.bd=2x.bd;bf(H,2x.3I)}},bc:B(){D.bg=K},ba:B(){D.n9=D.3I;if(D.5Y){bf(D,0)}D.bd=U}});z.gY=B(H){H=H||26.5Z;1j.bc.2d(H);1j.ba.2d(H)}}1j.7H=B(H,gX){A 2x=z.1x({},H,gX);1j.7K(2x);2x.7J=B(){H.7J()};2x.7I=B(){H.7I()};C 2x};if(z.2M){z.1x(1j,{4i:B(H,n8){4w(H.Z){2X"4b":A c=H.n7;if(c==3){c=99}c=((c<41)&&(!H.5X)?0:c);if((H.5Y)&&(!H.5X)&&(c>=65)&&(c<=90)){c+=32}C 1j.7H(H,{3h:c})}C H}})}if(z.3o){z.1x(1j,{4i:B(H,n6){4w(H.Z){2X"4b":A c=H.3h,s=H.5X,k=H.3I;k=k||gA[H.gW]||0;if(H.gW=="n5"){c=0}I{if((H.5Y)&&(c>0)&&(c<27)){c+=96}I{if(c==z.5W.gU){c=z.5W.gV;s=K}I{c=(c>=32&&c<gT?c:0)}}}C 1j.7H(H,{3h:c,5X:s,3I:k})}C H}});z.1x(z.5W,{gU:25,b9:gT,b8:n4,b7:n3,b6:n2,gS:n1,gR:n0,gQ:mZ,gP:mY,gO:mX,gN:mW,gM:mV,gL:mU,gK:mT,gJ:mS,gI:mR,gH:mQ,gG:mP,8S:mO,gF:mN,gE:mM,b5:mL,b4:mK,gD:mJ,mI:mH,gC:mG,gB:mF});A dk=z.5W,gA={"mE":dk.b9,"mD":dk.b8,"mC":dk.b7,"mB":dk.b6,"mA":dk.b5,"mz":dk.b4}}})();if(z.1l){z.gz=B(){C B(){A ap=4e.1C,h=z.gy.b3,c=P.2O,ls=c.2b,t=h[c.5V];A r=t&&t.14(D,P);R(A i in ls){if(!(i in ap)){h[ls[i]].14(D,P)}}C r}};z.b2.7G=B(fp){A f=z.b2.4i;C B(e){C fp.2d(D,f(e,D))}}}}if(!z.1h["z.X.b1"]){z.1h["z.X.b1"]=K;z.1Q("z.X.b1");1u{1q.my("mx",U,K)}1y(e){}if(z.1l||z.2M){z.1D=B(id,1e){if(z.1R(id)){A b0=(1e||z.1e);A 11=b0.gv(id);if((11)&&(11.gw.id.1Z==id)){C 11}I{A 5U=b0.gx[id];if(!5U){C}if(!5U.G){C 5U}A i=0;1s(11=5U[i++]){if(11.gw.id.1Z==id){C 11}}}}I{C id}}}I{z.1D=B(id,1e){if(z.1R(id)){C(1e||z.1e).gv(id)}I{C id}}}(B(){A 5T=L;z.mw=B(E){E=z.1D(E);1u{if(!5T){5T=1q.a9("mv")}5T.4c(E.1L?E.1L.fs(E):E);5T.9L=""}1y(e){}};z.mu=B(E,7F){1u{E=z.1D(E);7F=z.1D(7F);1s(E){if(E===7F){C K}E=E.1L}}1y(e){}C U};z.mt=B(E,5S){E=z.1D(E);if(z.gu){E.1c.ms=(5S)?"dg":"7C"}I{if(z.6B){E.1c.mr=(5S)?"8K":"7C"}I{if(z.1l){E.gs=(5S)?"":"on";z.1r("*",E).1n(B(gt){gt.gs=(5S)?"":"on"})}}}};A 5R=B(E,4h){4h.1L.mq(E,4h);C K};A aZ=B(E,4h){A pn=4h.1L;if(4h==pn.fm){pn.4c(E)}I{C 5R(E,4h.71)}C K};z.5E=B(E,2a,3H){if((!E)||(!2a)||(V 3H=="1k")){C U}E=z.1D(E);2a=z.1D(2a);if(V 3H=="4J"){A cn=2a.3W;if(((3H==0)&&(cn.G==0))||(cn.G==3H)){2a.4c(E);C K}if(3H==0){C 5R(E,2a.5A)}C aZ(E,cn[3H-1])}4w(3H.1M()){2X"mo":C 5R(E,2a);2X"a8":C aZ(E,2a);2X"9M":if(2a.5A){C 5R(E,2a.5A)}I{2a.4c(E);C K}3f;aY:2a.4c(E);C K}};z.aP="5g-3G";if(z.1l){A aV=1q.aX;z.aP=(aV=="aW")||(aV=="gr")||(z.1l<6)?"g5-3G":"5g-3G"}A 1E,dv=1q.mn;if(z.3o){1E=B(E){A s=dv.3F(E,L);if(!s&&E.1c){E.1c.gq="";s=dv.3F(E,L)}C s||{}}}I{if(z.1l){1E=B(E){C E.gn}}I{1E=B(E){C dv.3F(E,L)}}}z.3F=1E;if(!z.1l){z.4g=B(mm,gp){C 2k(gp)||0}}I{z.4g=B(go,2N){if(!2N){C 0}if(2N=="ml"){C 4}if(2N.2w&&(2N.2w(-2)=="px")){C 2k(2N)}4G(go){A gm=1c.2g;A gl=aU.2g;aU.2g=gn.2g;1u{1c.2g=2N;2N=1c.mk}1y(e){2N=0}1c.2g=gm;aU.2g=gl}C 2N}}z.ge=(z.1l?B(E){1u{C(E.mj.mi.2W/6D)}1y(e){C 1}}:B(E){C z.3F(E).2W});z.gf=(z.1l?B(E,7D){if(7D==1){E.1c.7E=E.1c.7E.2f(/gk:[^;]*;/i,"");if(E.gj.1M()=="gi"){z.1r("> gh",E).1n(B(i){i.1c.7E=i.1c.7E.2f(/gk:[^;]*;/i,"")})}}I{A o="mh(mg="+(7D*6D)+")";E.1c.3T=o}if(E.gj.1M()=="gi"){z.1r("> gh",E).1n(B(i){i.1c.3T=o})}C 7D}:B(E,gg){C E.1c.2W=gg});A 5Q={3n:K,58:K,2g:K,5J:K};A gd=B(E,Z,5P){Z=Z.1M();if(5Q[Z]===K){C z.4g(E,5P)}I{if(5Q[Z]===U){C 5P}I{if((Z.T("mf")>=0)||(Z.T("md")>=0)||(Z.T("3n")>=0)||(Z.T("58")>=0)||(Z.T("5q")>=0)||(Z.T("mc")>=0)||(Z.T("ma")>=0)){5Q[Z]=K;C z.4g(E,5P)}I{5Q[Z]=U;C 5P}}}};z.1c=B(E,5O,aT){A n=z.1D(E),F=P.G,op=(5O=="2W");if(F==3){C op?z.gf(n,aT):n.1c[5O]=aT}if(F==2&&op){C z.ge(n)}A s=z.3F(n);C(F==1)?s:gd(n,5O,s[5O])};z.7A=B(n,gc){A s=gc||1E(n),px=z.4g,l=px(n,s.m9),t=px(n,s.m8);C{l:l,t:t,w:l+px(n,s.m7),h:t+px(n,s.m6)}};z.5N=B(n,gb){A ne="7C",px=z.4g,s=gb||1E(n),bl=(s.m5!=ne?px(n,s.m4):0),bt=(s.m3!=ne?px(n,s.m2):0);C{l:bl,t:bt,w:bl+(s.m1!=ne?px(n,s.m0):0),h:bt+(s.lZ!=ne?px(n,s.lY):0)}};z.aN=B(n,ga){A s=ga||1E(n),p=z.7A(n,s),b=z.5N(n,s);C{l:p.l+b.l,t:p.t+b.t,w:p.w+b.w,h:p.h+b.h}};z.aM=B(n,g9){A s=g9||1E(n),px=z.4g,l=px(n,s.lX),t=px(n,s.lW),r=px(n,s.lV),b=px(n,s.lU);if(z.3o&&(s.ax!="fU")){r=l}C{l:l,t:t,w:l+r,h:t+b}};z.au=B(E,g8){A s=g8||1E(E),me=z.aM(E,s);A l=E.fT-me.l,t=E.fS-me.t;if(z.7B){A aS=2k(s.2g),aR=2k(s.5J);if(!2L(aS)&&!2L(aR)){l=aS,t=aR}I{A p=E.1L;if(p&&p.1c){A aQ=1E(p);if(aQ.lT!="lS"){A be=z.5N(p,aQ);l+=be.l,t+=be.t}}}}I{if(z.2M){A p=E.1L;if(p){A be=z.5N(p);l-=be.l,t-=be.t}}}C{l:l,t:t,w:E.6v+me.w,h:E.8D+me.h}};z.aK=B(E,g7){A s=g7||1E(E),pe=z.7A(E,s),be=z.5N(E,s),w=E.aF,h;if(!w){w=E.6v,h=E.8D}I{h=E.lR,be.w=be.h=0}if(z.2M){pe.l+=be.l;pe.t+=be.t}C{l:pe.l,t:pe.t,w:w-pe.w-be.w,h:h-pe.h-be.h}};z.lQ=B(E,g6){A s=g6||1E(E),pe=z.7A(E,s),cb=z.aK(E,s);C{l:cb.l-pe.l,t:cb.t-pe.t,w:cb.w+pe.w,h:cb.h+pe.h}};z.aL=B(E,l,t,w,h,u){u=u||"px";4G(E.1c){if(!2L(l)){2g=l+u}if(!2L(t)){5J=t+u}if(w>=0){3n=w+u}if(h>=0){58=h+u}}};z.aO=B(E){A n=E.5w;C(z.aP=="g5-3G")||(n=="lP")||(n=="lO")};z.fX=B(E,7z,7y,g4){A bb=z.aO(E);if(bb){A pb=z.aN(E,g4);if(7z>=0){7z+=pb.w}if(7y>=0){7y+=pb.h}}z.aL(E,g3,g3,7z,7y)};z.fY=B(E,g1,g0,5M,5L,g2){A s=g2||z.3F(E);A bb=z.aO(E),pb=bb?fZ:z.aN(E,s),mb=z.aM(E,s);if(5M>=0){5M=2Y.5q(5M-pb.w-mb.w,0)}if(5L>=0){5L=2Y.5q(5L-pb.h-mb.h,0)}z.aL(E,g1,g0,5M,5L)};A fZ={l:0,t:0,w:0,h:0};z.lN=B(E,3G){A n=z.1D(E),s=1E(n),b=3G;C!b?z.au(n,s):z.fY(n,b.l,b.t,b.w,b.h,s)};z.lM=B(E,3G){A n=z.1D(E),s=1E(n),b=3G;C!b?z.aK(n,s):z.fX(n,b.w,b.h,s)};A 5H=B(E,1a){if(!(E=(E||0).1L)){C 0}A 1U,aJ=0,2h=z.3E();1s(E&&E.1c){if(1E(E).ax=="lL"){C 0}1U=E[1a];if(1U){aJ+=1U-0;if(E==2h){3f}}E=E.1L}C aJ};z.fQ=B(){A 2h=z.3E();A 3g=z.1W;A de=z.1e.5K;C{y:(3g.lK||de.5G||2h.5G||0),x:(3g.lJ||z.aH(de.5I)||2h.5I||0)}};z.aG=B(){C V z.aI=="1k"?(z.aI=z.3F(z.3E()).lI=="lH"):z.aI};z.aB=B(){A de=z.1e.5K;if(z.1l>=7){C{x:de.aC().2g,y:de.aC().5J}}I{C{x:z.aG()||26.am==26?de.fW:de.6v-de.aF-de.fW,y:de.lG}}};z.aH=B(aE){if(z.1l&&!z.aG()){A de=z.1e.5K;C aE+de.aF-de.lF}C aE};z.fP=B(E,aw){A ay=E.aD;A J={x:0,y:0};A 7w=U;A db=z.3E();if(z.1l){A aA=E.aC();A az=z.aB();J.x=aA.2g-az.x;J.y=aA.5J-az.y}I{if(ay["fV"]){A bo=ay.fV(E);J.x=bo.x-5H(E,"5I");J.y=bo.y-5H(E,"5G")}I{if(E["fR"]){7w=K;A 7x;if(z.3o&&(1E(E).ax=="fU")&&(E.1L==db)){7x=db}I{7x=db.1L}if(E.1L!=db){A nd=E;if(z.2M){nd=db}J.x-=5H(nd,"5I");J.y-=5H(nd,"5G")}A 4f=E;do{A n=4f["fT"];if(!z.2M||n>0){J.x+=2L(n)?0:n}A m=4f["fS"];J.y+=2L(m)?0:m;4f=4f.fR}1s((4f!=7x)&&4f)}I{if(E["x"]&&E["y"]){J.x+=2L(E.x)?0:E.x;J.y+=2L(E.y)?0:E.y}}}}if(7w||aw){A av=z.fQ();A m=7w?(!aw?-1:0):1;J.y+=m*av.y;J.x+=m*av.x}C J};z.af=B(E,fO){A n=z.1D(E),s=1E(n),mb=z.au(n,s);A at=z.fP(n,fO);mb.x=at.x;mb.y=at.y;C mb}})();z.fL=B(E,fN){C((" "+E.3A+" ").T(" "+fN+" ")>=0)};z.7s=B(E,ar){A 7v=E.3A;if((" "+7v+" ").T(" "+ar+" ")<0){E.3A=7v+(7v?" ":"")+ar}};z.7r=B(E,fM){A t=z.7g((" "+E.3A+" ").2f(" "+fM+" "," "));if(E.3A!=t){E.3A=t}};z.lE=B(E,aq,7u){if(V 7u=="1k"){7u=!z.fL(E,aq)}z[7u?"7s":"7r"](E,aq)}}if(!z.1h["z.X.1H"]){z.1h["z.X.1H"]=K;z.1Q("z.X.1H");(B(){A d=z;z.1H=B(){A F=P;if((F.G==1)&&(V F[0]=="4J")){D.G=eK(F[0])}I{if(F.G){d.1n(F,B(i){D.Y(i)},D)}}};z.1H.1C=S 4e;if(d.1l){A fK=B(al){C("A a2 = am."+al+"; "+"A ap = 4e.1C; "+"A ao = a2.1C; "+"R(A x in ao){ ap[x] = ao[x]; } "+"am."+al+" = 4e; ")};A fI=fK("z.1H");A aj=26.lD();aj.1q.fJ("<ak>"+fI+"</ak>");aj.lC(1,1,1,1)}z.4M(z.1H,{T:B(fH,fG){C d.T(D,fH,fG)},31:B(lB,lA){A aa=d.4d(P);aa.ae(D);C d.31.14(d,aa)},ah:B(fF,fE){C d.ah(D,fF,fE)},ag:B(fD,fC){C d.ag(D,fD,fC)},1n:B(fB,fA){d.1n(D,fB,fA);C D},23:B(7t,M){C d.23(D,7t,M,d.1H)},af:B(){C d.23(D,d.af)},1c:B(lz,ly){A aa=d.4d(P);aa.ae(D[0]);A s=d.1c.14(d,aa);C(P.G>1)?D:s},lx:B(lw,lv){A aa=d.4d(P);aa.ae(L);A s=D.23(B(i){aa[0]=i;C d.1c.14(d,aa)});C(P.G>1)?D:s},7s:B(fz){C D.1n(B(i){z.7s(i,fz)})},7r:B(fy){C D.1n(B(i){z.7r(i,fy)})},5E:B(fw,7q){A 1m=d.1r(fw)[0];7q=7q||"72";R(A x=0;x<D.G;x++){d.5E(D[x],1m,7q)}C D},2c:B(fv,fu,ft){D.1n(B(1m){d.2c(1m,fv,fu,ft)});C D},lu:B(ad){A ac=(ad)?d.9t(D,ad):D;ac.1n(B(1m){if(1m["1L"]){1m.1L.fs(1m)}});C ac},lt:B(fr,fq){A 1m=D[0];C d.1r(fr).1n(B(ai){d.5E(ai,1m,(fq||"72"))})},1r:B(7p){7p=7p||"";A J=S d.1H();D.1n(B(1m){d.1r(7p,1m).1n(B(ab){if(V ab!="1k"){J.Y(ab)}})});C J},3T:B(fo){A 5F=D;A 1V=P;A r=S d.1H();A rp=B(t){if(V t!="1k"){r.Y(t)}};if(d.1R(fo)){5F=d.9t(D,1V[0]);if(1V.G==1){C 5F}d.1n(d.3T(5F,1V[1],1V[2]),rp);C r}d.1n(d.3T(5F,1V[0],1V[1]),rp);C r},lr:B(7o,7n){A 1S=d.1e.a9("lq");if(d.1R(7o)){1S.9L=7o}I{1S.4c(7o)}A ct=((7n=="9M")||(7n=="a8"))?"fm":"5A";D.1n(B(1m){A 24=1S.a7(K);1s(24[ct]){d.5E(24[ct],1m,7n)}});C D},7m:B(fl,F){A a5=[];F=F||{};D.1n(B(1m){A a6={E:1m};d.1x(a6,F);a5.Y(d[fl](a6))});C d.fx.lp(a5)},8I:B(F){C D.7m("8I",F)},8H:B(F){C D.7m("8H",F)},6y:B(F){C D.7m("6y",F)}});z.1n(["fk","lo","fj","fi","ln","lm","ll","fi","lk","lj","4b"],B(H){A a4="on"+H;z.1H.1C[a4]=B(a,b){C D.2c(a4,a,b)}})})()}if(!z.1h["z.X.1r"]){z.1h["z.X.1r"]=K;z.1Q("z.X.1r");(B(){A d=z;A 2I=B(q){C[q.T("#"),q.T("."),q.T("["),q.T(":")]};A a0=B(a3,fh){A ql=a3.G;A i=2I(a3);A 1d=ql;R(A x=fh;x<i.G;x++){if(i[x]>=0){if(i[x]<1d){1d=i[x]}}}C(1d<0)?ql:1d};A 6X=B(7l){A i=2I(7l);if(i[0]!=-1){C 7l.21(i[0]+1,a0(7l,1))}I{C""}};A 5r=B(7k){A 5D;A i=2I(7k);if((i[0]==0)||(i[1]==0)){5D=0}I{5D=a0(7k,0)}C((5D>0)?7k.3b(0,5D).1M():"*")};A fg=B(Q){A J=-1;R(A x=0;x<Q.G;x++){A 1S=Q[x];if(1S>=0){if((1S>J)||(J==-1)){J=1S}}}C J};A 9H=B(7i){A i=2I(7i);if(-1==i[1]){C""}A di=i[1]+1;A 7j=fg(i.2w(2));if(di<7j){C 7i.21(di,7j)}I{if(-1==7j){C 7i.3b(di)}I{C""}}};A f3=[{1i:"|=",1f:B(15,fe){C"[5z(3U(\' \',@"+15+",\' \'), \' "+fe+"-\')]"}},{1i:"~=",1f:B(15,fd){C"[5z(3U(\' \',@"+15+",\' \'), \' "+fd+" \')]"}},{1i:"^=",1f:B(15,fb){C"[li-4G(@"+15+", \'"+fb+"\')]"}},{1i:"*=",1f:B(15,fa){C"[5z(@"+15+", \'"+fa+"\')]"}},{1i:"$=",1f:B(15,9Z){C"[21(@"+15+", 3c-G(@"+15+")-"+(9Z.G-1)+")=\'"+9Z+"\']"}},{1i:"!=",1f:B(15,f9){C"[3O(@"+15+"=\'"+f9+"\')]"}},{1i:"=",1f:B(15,f8){C"[@"+15+"=\'"+f8+"\']"}}];A 9C=B(9Y,3Z,f7,f6){A 49;A i=2I(3Z);if(i[2]>=0){A 4L=3Z.T("]",i[2]);A 29=3Z.21(i[2]+1,4L);1s(29&&29.G){if(29.2s(0)=="@"){29=29.2w(1)}49=L;R(A x=0;x<9Y.G;x++){A 1S=9Y[x];A 7h=29.T(1S.1i);if(7h>=0){A 15=29.21(0,7h);A 4a=29.21(7h+1S.1i.G);if((4a.2s(0)=="\\"")||(4a.2s(0)=="\'")){4a=4a.21(1,4a.G-1)}49=1S.1f(d.7g(15),d.7g(4a));3f}}if((!49)&&(29.G)){49=f7(29)}if(49){f6(49)}29=L;A 7f=3Z.T("[",4L);if(0<=7f){4L=3Z.T("]",7f);if(0<=4L){29=3Z.21(7f+1,4L)}}}}};A f0=B(f5){A 4K=".";A 7e=f5.1A(" ");1s(7e.G){A 2K=7e.3a();A 7d;if(2K==">"){7d="/";2K=7e.3a()}I{7d="//"}A f4=5r(2K);4K+=7d+f4;A id=6X(2K);if(id.G){4K+="[@id=\'"+id+"\'][1]"}A cn=9H(2K);if(cn.G){A 9X=" ";if(cn.2s(cn.G-1)=="*"){9X="";cn=cn.3b(0,cn.G-1)}4K+="[5z(3U(\' \',@9P,\' \'), \' "+cn+9X+"\')]"}9C(f3,2K,B(f2){C"[@"+f2+"]"},B(f1){4K+=f1})}C 4K};A 7a={};A eC=B(28){if(7a[28]){C 7a[28]}A 1e=d.1e;A 9W=f0(28);A 4H=B(9V){A J=[];A 7b;1u{7b=1e.9x(9W,9V,L,lh.lg,L)}1y(e){1z.1K("lf in le:",9W,"lc:",9V);1z.1K(e)}A 7c=7b.eZ();1s(7c){J.Y(7c);7c=7b.eZ()}C J};C 7a[28]=4H};A 5x={};A 9B={};A 3y=B(79,78){if(!79){C 78}if(!78){C 79}C B(){C 79.14(26,P)&&78.14(26,P)}};A 75=B(9U,3Y,5B,2J){A 2v=2J+1;A 76=(3Y.G==2v);A 2K=3Y[2J];if(2K==">"){A 77=9U.3W;if(!77.G){C}2v++;76=(3Y.G==2v);A 4H=6O(3Y[2J+1]);R(A x=0,11;x<77.G,11=77[x];x++){if(4H(11)){if(76){5B.Y(11)}I{75(11,3Y,5B,2v)}}}}A 5C=6U(2K)(9U);if(76){1s(5C.G){5B.Y(5C.3a())}}I{1s(5C.G){75(5C.3a(),3Y,5B,2v)}}};A eE=B(9T,eY){A J=[];A x=9T.G-1,11;1s(11=9T[x--]){75(11,eY,J,0)}C J};A 6O=B(3D){if(5x[3D]){C 5x[3D]}A ff=L;A 9S=5r(3D);if(9S!="*"){ff=3y(ff,B(N){C((N.2t==1)&&(9S==N.5w.1M()))})}A 9R=6X(3D);if(9R.G){ff=3y(ff,B(N){C((N.2t==1)&&(N.id==9R))})}if(2Y.5q.14(D,2I(3D).2w(1))>=0){ff=3y(ff,9z(3D))}C 5x[3D]=ff};A 5y=B(E){A pn=E.1L;A 9Q=pn.3W;A 2v=-1;A 3C=pn.5A;if(!3C){C 2v}A ci=E["eW"];A cl=pn["eX"];if(((V cl=="4J")&&(cl!=9Q.G))||(V ci!="4J")){pn["eX"]=9Q.G;A 2J=1;do{if(3C===E){2v=2J}if(3C.2t==1){3C["eW"]=2J;2J++}3C=3C.71}1s(3C)}I{2v=ci}C 2v};A lb=0;A 3X=B(N,15){A 74="";if(15=="9P"){C N.3A||74}if(15=="R"){C N.la||74}C N.5t(15,2)||74};A eH=[{1i:"|=",1f:B(15,9O){A eV=" "+9O+"-";C B(N){A ea=" "+(N.5t(15,2)||"");C((ea==9O)||(ea.T(eV)==0))}}},{1i:"^=",1f:B(15,eU){C B(N){C(3X(N,15).T(eU)==0)}}},{1i:"*=",1f:B(15,eT){C B(N){C(3X(N,15).T(eT)>=0)}}},{1i:"~=",1f:B(15,eS){A 9N=" "+eS+" ";C B(N){A ea=" "+3X(N,15)+" ";C(ea.T(9N)>=0)}}},{1i:"$=",1f:B(15,73){A 9N=" "+73;C B(N){A ea=" "+3X(N,15);C(ea.31(73)==(ea.G-73.G))}}},{1i:"!=",1f:B(15,eR){C B(N){C(3X(N,15)!=eR)}}},{1i:"=",1f:B(15,eQ){C B(N){C(3X(N,15)==eQ)}}}];A 9E=[{1i:"9M-9K",1f:B(1p,l9){C B(N){if(N.2t!=1){C U}A fc=N.eP;1s(fc&&(fc.2t!=1)){fc=fc.eP}C(!fc)}}},{1i:"72-9K",1f:B(1p,l8){C B(N){if(N.2t!=1){C U}A nc=N.71;1s(nc&&(nc.2t!=1)){nc=nc.71}C(!nc)}}},{1i:"l7",1f:B(1p,l6){C B(N){A cn=N.3W;A eO=N.3W.G;R(A x=eO-1;x>=0;x--){A nt=cn[x].2t;if((nt==1)||(nt==3)){C U}}C K}}},{1i:"5z",1f:B(1p,eN){C B(N){C(N.9L.T(eN)>=0)}}},{1i:"3O",1f:B(1p,eM){A eL=6O(eM);C B(N){C(!eL(N))}}},{1i:"l5-9K",1f:B(1p,2u){A pi=eK;if(2u=="l4"){C B(N){C(((5y(N))%2)==1)}}I{if((2u=="2n")||(2u=="l3")){C B(N){C((5y(N)%2)==0)}}I{if(2u.T("l2+")==0){A 70=pi(2u.3b(3));C B(N){C(N.1L.3W[70-1]===N)}}I{if((2u.T("n+")>0)&&(2u.G>3)){A 9J=2u.1A("n+",2);A eJ=pi(9J[0]);A 2J=pi(9J[1]);C B(N){C((5y(N)%eJ)==2J)}}I{if(2u.T("n")==-1){A 70=pi(2u);C B(N){C(5y(N)==70)}}}}}}}}];A 9z=B(3e){A 9I=(9B[3e]||5x[3e]);if(9I){C 9I}A ff=L;A i=2I(3e);if(i[0]>=0){A 24=5r(3e);if(24!="*"){ff=3y(ff,B(N){C(N.5w.1M()==24)})}}A 5u;A 3B=9H(3e);if(3B.G){A 9F=3B.2s(3B.G-1)=="*";if(9F){3B=3B.3b(0,3B.G-1)}A re=S 9G("(?:^|\\\\s)"+3B+(9F?".*":"")+"(?:\\\\s|$)");ff=3y(ff,B(N){C re.6Z(N.3A)})}if(i[3]>=0){A 3z=3e.3b(i[3]+1);A 9D="";A 5v=3z.T("(");A 6Y=3z.31(")");if((0<=5v)&&(0<=6Y)&&(6Y>5v)){9D=3z.21(5v+1,6Y);3z=3z.3b(0,5v)}5u=L;R(A x=0;x<9E.G;x++){A 1S=9E[x];if(1S.1i==3z){5u=1S.1f(3z,9D);3f}}if(5u){ff=3y(ff,5u)}}A eG=(d.1l)?B(5s){A eI=5s.1M();C B(N){C N[5s]||N[eI]}}:B(5s){C B(N){C(N&&N.5t&&N.l1(5s))}};9C(eH,3e,eG,B(eF){ff=3y(ff,eF)});if(!ff){ff=B(){C K}}C 9B[3e]=ff};A 6W={};A 6U=B(3d,1B){A 9A=6W[3d];if(9A){C 9A}A i=2I(3d);A id=6X(3d);if(i[0]==0){C 6W[3d]=B(1B){C[d.1D(id)]}}A 9y=9z(3d);A 5p;if(i[0]>=0){5p=B(1B){A 11=d.1D(id);if(9y(11)){C[11]}}}I{A 3V;A 24=5r(3d);if(2Y.5q.14(D,2I(3d))==-1){5p=B(1B){A J=[];A 11,x=0,3V=1B.4I(24);1s(11=3V[x++]){J.Y(11)}C J}}I{5p=B(1B){A J=[];A 11,x=0,3V=1B.4I(24);1s(11=3V[x++]){if(9y(11)){J.Y(11)}}C J}}}C 6W[3d]=5p};A l0={};A 5o={">":B(1B){A J=[];A 11,x=0,3V=1B.3W;1s(11=3V[x++]){if(11.2t==1){J.Y(11)}}C J}};A 9w=B(6V){if(0>6V.T(" ")){C 6U(6V)}A eD=B(1B){A 6S=6V.1A(" ");A 6T;if(6S[0]==">"){6T=[1B]}I{6T=6U(6S.3a())(1B)}C eE(6T,6S)};C eD};A 9v=((1q["9x"]&&!d.3o)?B(3x){A 6R=3x.1A(" ");if((1q["9x"])&&(3x.T(":")==-1)&&((K))){if(((6R.G>2)&&(3x.T(">")==-1))||(6R.G>3)||(3x.T("[")>=0)||((1==6R.G)&&(0<=3x.T(".")))){C eC(3x)}}C 9w(3x)}:9w);A ey=B(3w){if(5o[3w]){C 5o[3w]}if(0>3w.T(",")){C 5o[3w]=9v(3w)}I{A eB=3w.1A(/\\s*,\\s*/);A 4H=B(1B){A eA=0;A J=[];A 6Q;1s(6Q=eB[eA++]){J=J.3U(9v(6Q,6Q.T(" "))(1B))}C J};C 5o[3w]=4H}};A 5n=0;A ez=B(Q){A J=S d.1H();if(!Q){C J}if(Q[0]){J.Y(Q[0])}if(Q.G<2){C J}5n++;Q[0]["9u"]=5n;R(A x=1,11;11=Q[x];x++){if(Q[x]["9u"]!=5n){J.Y(11)}11["9u"]=5n}C J};d.1r=B(6P,1B){if(V 6P!="3c"){C S d.1H(6P)}if(V 1B=="3c"){1B=d.1D(1B)}C ez(ey(6P)(1B||d.1e))};d.9t=B(ex,9s){A 9r=S d.1H();A ff=(9s)?6O(9s):B(){C K};R(A x=0,11;11=ex[x];x++){if(ff(11)){9r.Y(11)}}C 9r}})()}if(!z.1h["z.X.1b"]){z.1h["z.X.1b"]=K;z.1Q("z.X.1b");z.6K=B(ew){A J={};A iq="kZ[Z!=9q][Z!=kY][Z!=et][Z!=kX][Z!=kW], kV, kU";z.1r(iq,ew).3T(B(E){C(!E.kT)}).1n(B(1m){A 3v=1m.1p;A Z=(1m.Z||"").1M();if((Z=="kS")||(Z=="kR")){if(1m.kQ){J[3v]=1m.1Z}}I{if(1m.kP){A ev=J[3v]=[];z.1r("kO[kN]",1m).1n(B(eu){ev.Y(eu.1Z)})}I{J[3v]=1m.1Z;if(Z=="et"){J[3v+".x"]=J[3v+".y"]=J[3v].x=J[3v].y=0}}}});C J};z.9h=B(23){A ec=kM;A J="";A es={};R(A x in 23){if(23[x]!=es[x]){if(z.2l(23[x])){R(A y=0;y<23[x].G;y++){J+=ec(x)+"="+ec(23[x][y])+"&"}}I{J+=ec(x)+"="+ec(23[x])+"&"}}}if((J.G)&&(J.2s(J.G-1)=="&")){J=J.3b(0,J.G-1)}C J};z.kL=B(er){C z.9h(z.6K(er))};z.kK=B(ep){C z.eq(z.6K(ep))};z.kJ=B(2H){A J={};A qp=2H.1A("&");A dc=kI;z.1n(qp,B(1m){if(1m.G){A 9p=1m.1A("=");A 1p=dc(9p.3a());A 1U=dc(9p.22("="));if(z.1R(J[1p])){J[1p]=[J[1p]]}if(z.2l(J[1p])){J[1p].Y(1U)}I{J[1p]=1U}}});C J};z.e1=U;z.e6={"9g":B(1b){C 1b.2G},"2e":B(1b){if(!1o.eo){1z.1K("kH kG kF a kE of 9g/2e-6M-9m"+" 4F kD kC kB kA 4G en kz"+" (ky 1o.eo=K 4F kx kw D kv)")}C z.5m(1b.2G)},"2e-6M-ku":B(1b){A 6N=1b.2G;A 9o=6N.T("/*");A 9n=6N.31("*/");if((9o==-1)||(9n==-1)){C z.5m(1b.2G)}C z.5m(6N.21(9o+2,9n))},"2e-6M-9m":B(1b){A 6L=1b.2G;A 9l=6L.T("/*");A 9k=6L.31("*/");if((9l==-1)||(9k==-1)){1z.1K("kt en ks\'t 6M 9m!");C""}C z.5m(6L.21(9l+2,9k))},"kr":B(1b){C z.3u(1b.2G)},"kq":B(1b){if(z.1l&&!1b.el){z.1n(["ko","em","kn","km"],B(i){1u{A 1e=S 9j(kl[i]+".kk");1e.kj=U;1e.ki(1b.2G);C 1e}1y(e){}})}I{C 1b.el}}};(B(){z.e5=B(F,ej,ei,eh){A 2F={};2F.F=F;A 6J=L;if(F.3R){A 3R=z.1D(F.3R);A 9i=3R.kh("kg");2F.2E=F.2E||(9i?9i.1Z:L);6J=z.6K(3R)}I{2F.2E=F.2E}A 5l=[{}];if(6J){5l.Y(6J)}if(F.5g){5l.Y(F.5g)}if(F.ek){5l.Y({"z.ek":S 5d().8O()})}2F.1r=z.9h(z.1x.14(L,5l));2F.9d=F.9d||"9g";A d=S z.30(ej);d.5k(ei,B(eg){C eh(eg,d)});A ld=F.4E;if(ld&&z.1Y(ld)){d.ef(B(ee){C ld.2d(F,ee,2F)})}A 1G=F.9f;if(1G&&z.1Y(1G)){d.ed(B(e9){C 1G.2d(F,e9,2F)})}A 6I=F.kf;if(6I&&z.1Y(6I)){d.9e(B(e8){C 6I.2d(F,e8,2F)})}d.1F=2F;C d};A e4=B(O){O.e0=K;A 1b=O.1F.1b;if(V 1b.e7=="B"){1b.e7()}};A e3=B(O){C z.e6[O.1F.9d](O.1F.1b)};A e2=B(9c,O){1z.1K(9c);C 9c};A 3Q=B(F){A O=z.e5(F,e4,e3,e2);O.1F.1b=z.9b(O.1F.F);C O};A 5j=L;A 3t=[];A 94=B(){A dZ=(S 5d()).dU();if(!z.e1){z.1n(3t,B(4D,6H){if(!4D){C}A O=4D.O;1u{if(!O||O.e0||!4D.dT(O)){3t.3S(6H,1);C}if(4D.dR(O)){3t.3S(6H,1);4D.dP(O)}I{if(O.9a){if(O.9a+(O.1F.F.6G||0)<dZ){3t.3S(6H,1);A 1G=S 1O("6G ke");1G.dY="6G";O.5i(1G);O.4C()}}}}1y(e){1z.1K(e);O.5i(S 1O("kc!"))}})}if(!3t.G){dX(5j);5j=L;C}};z.dV=B(){1u{z.1n(3t,B(i){i.O.4C()})}1y(e){}};if(z.1l){z.dW(z.dV)}z.dH=B(O,dS,dQ,dO){if(O.1F.F.6G){O.9a=(S 5d()).dU()}3t.Y({O:O,dT:dS,dR:dQ,dP:dO});if(!5j){5j=dN(94,50)}94()};A dJ="8Z/x-kb-3R-ka";A dG=B(O){C O.1F.1b.6F};A dF=B(O){C 4==O.1F.1b.6F};A dE=B(O){if(z.8Y(O.1F.1b)){O.dM(O)}I{O.5i(S 1O("k9 k8 k7 5h:"+O.1F.1b.3N))}};A 3P=B(Z,O){A 3s=O.1F;A F=3s.F;3s.1b.dL(Z,3s.2E,(F.k6!==K),(F.8X?F.8X:1k),(F.8W?F.8W:1k));if(F.6E){R(A 5f in F.6E){if(5f.1M()==="5g-Z"&&!F.8V){F.8V=F.6E[5f]}I{3s.1b.dK(5f,F.6E[5f])}}}3s.1b.dK("k5-k4",(F.8V||dJ));1u{3s.1b.dI(3s.1r)}1y(e){O.4C()}z.dH(O,dG,dF,dE);C O};z.8T=B(4B){if(4B.1r.G){4B.2E+=(4B.2E.T("?")==-1?"?":"&")+4B.1r;4B.1r=L}};z.k3=B(F){A O=3Q(F);z.8T(O.1F);C 3P("dD",O)};z.k2=B(F){C 3P("dC",3Q(F))};z.k1=B(F){A O=3Q(F);O.1F.1r=F.k0;C 3P("dC",O)};z.jZ=B(F){C 3P("dA",3Q(F))};z.jY=B(F){A O=3Q(F);A dB=O.1F;if(F["8U"]){dB.1r=F.8U;F.8U=L}C 3P("dA",O)};z.jX=B(F){A O=3Q(F);z.8T(O.1F);C 3P("8S",O)};z.dz=B(jW){2m S 1O("z.dz 3O jV jU")}})()}if(!z.1h["z.X.fx"]){z.1h["z.X.fx"]=K;z.1Q("z.X.fx");z.dx=B(dy,1d){D.1w=dy;D.1d=1d;D.4x=B(n){C((D.1d-D.1w)*n)+D.1w}};z.2r("z.d6",L,{1P:B(F){z.1x(D,F);if(z.2l(D.2C)){D.2C=S z.dx(D.2C[0],D.2C[1])}},2C:L,8Q:jT,5a:L,4z:0,dj:10,du:L,6x:L,dt:L,8B:L,dh:L,ds:L,dr:L,dm:L,2D:U,2Z:U,4A:L,8N:L,3r:L,2o:0,4y:0,3q:B(H,F){if(D[H]){D[H].14(D,F||[])}C D},5b:B(dw,8R){if(8R){5e(D.3r);D.2D=D.2Z=U;D.2o=0}I{if(D.2D&&!D.2Z){C D}}D.3q("6x");A d=dw||D.du;if(d>0){5c(z.2p(D,B(){D.5b(L,8R)}),d);C D}D.4A=S 5d().8O();if(D.2Z){D.4A-=D.8Q*D.2o}D.8N=D.4A+D.8Q;D.2D=K;D.2Z=U;A 8P=D.2C.4x(D.2o);if(!D.2o){if(!D.4y){D.4y=D.4z}D.3q("dt",[8P])}D.3q("ds",[8P]);D.8M();C D},jS:B(){5e(D.3r);if(!D.2D){C D}D.2Z=K;D.3q("dr",[D.2C.4x(D.2o)]);C D},jR:B(dq,dp){5e(D.3r);D.2D=D.2Z=K;D.2o=dq*6D;if(dp){D.5b()}C D},jQ:B(dn){if(!D.3r){C}5e(D.3r);if(dn){D.2o=1}D.3q("dm",[D.2C.4x(D.2o)]);D.2D=D.2Z=U;C D},3N:B(){if(D.2D){C D.2Z?"3M":"jP"}C"jO"},8M:B(){5e(D.3r);if(D.2D){A dl=S 5d().8O();A 2q=(dl-D.4A)/(D.8N-D.4A);if(2q>=1){2q=1}D.2o=2q;if(D.5a){2q=D.5a(2q)}D.3q("8B",[D.2C.4x(2q)]);if(2q<1){D.3r=5c(z.2p(D,"8M"),D.dj)}I{D.2D=U;if(D.4z>0){D.4z--;D.5b(L,K)}I{if(D.4z==-1){D.5b(L,K)}I{if(D.4y){D.4z=D.4y;D.4y=0}}}D.2o=0;D.3q("dh")}}C D}});(B(){A df=B(E){if(z.1l){A ns=E.1c;if(!ns.8L.G&&z.1c(E,"8L")=="dg"){ns.8L="1"}if(!ns.3n.G&&z.1c(E,"3n")=="8K"){ns.3n="8K"}}};z.6C=B(F){if(V F.1d=="1k"){2m S 1O("z.6C jN an 1d 1Z")}F.E=z.1D(F.E);A 3p=z.1x({6w:{}},F);A 8J=(3p.6w.2W={});8J.1w=(V 3p.1w=="1k")?B(){C 2V(z.1c(3p.E,"2W"))}:3p.1w;8J.1d=3p.1d;A 2U=z.6y(3p);z.2c(2U,"6x",L,B(){df(3p.E)});C 2U};z.8I=B(F){C z.6C(z.1x({1d:1},F))};z.8H=B(F){C z.6C(z.1x({1d:0},F))};if(z.6B&&!z.3o){z.8E=B(n){C 2k("0.5")+((2Y.da((n+2k("1.5"))*2Y.d9))/2)}}I{z.8E=B(n){C 0.5+((2Y.da((n+1.5)*2Y.d9))/2)}}A d4=B(6A){D.8G=6A;R(A p in 6A){A 1a=6A[p];if(1a.1w 1N z.1J){1a.d7=S z.1J()}}D.4x=B(r){A J={};R(A p in D.8G){A 1a=D.8G[p];A 6z=L;if(1a.1w 1N z.1J){6z=z.d8(1a.1w,1a.1d,r,1a.d7).8F()}I{if(!z.2l(1a.1w)){6z=((1a.1d-1a.1w)*r)+1a.1w+(p!="2W"?1a.jM||"px":"")}}J[p]=6z}C J}};z.6y=B(F){F.E=z.1D(F.E);if(!F.5a){F.5a=z.8E}A 2U=S z.d6(F);z.2c(2U,"6x",2U,B(){A pm={};R(A p in D.6w){A 1a=pm[p]=z.1x({},D.6w[p]);if(z.1Y(1a.1w)){1a.1w=1a.1w()}if(z.1Y(1a.1d)){1a.1d=1a.1d()}A d5=(p.1M().T("jL")>=0);B 8C(E,p){4w(p){2X"58":C E.8D;2X"3n":C E.6v}A v=z.1c(E,p);C(p=="2W")?2V(v):2k(v)};if(V 1a.1d=="1k"){1a.1d=8C(D.E,p)}I{if(V 1a.1w=="1k"){1a.1w=8C(D.E,p)}}if(d5){1a.1w=S z.1J(1a.1w);1a.1d=S z.1J(1a.1d)}I{1a.1w=(p=="2W")?2V(1a.1w):2k(1a.1w)}}D.2C=S d4(pm)});z.2c(2U,"8B",2U,B(8A){R(A s in 8A){z.1c(D.E,s,8A[s])}});C 2U}})()}',62,1711,'|||||||||||||||||||||||||||||||||||dojo|var|function|return|this|node|args|length|evt|else|ret|true|null|obj|elem|dfd|arguments|arr|for|new|indexOf|false|typeof||_base|push|type||te|||apply|attr|||||prop|xhr|style|end|doc|match|uri|_hasResource|key|del|undefined|isIE|item|forEach|djConfig|name|document|query|while|_66|try|res|start|mixin|catch|console|split|root|prototype|byId|gcs|ioArgs|err|NodeList|_p|Color|debug|parentNode|toLowerCase|instanceof|Error|constructor|provide|isString|ta|255|val|_a|global|_69|isFunction|value||substring|join|map|tn||window||path|_343|_220|_listeners|connect|call|json|replace|left|_b|toString|128|parseFloat|isArray|throw||_percent|hitch|step|declare|charAt|nodeType|_3c3|nidx|slice|faux|fired|_c4|_7e|loc|curve|_active|url|_44c|responseText|str|_312|idx|tqp|isNaN|isOpera|_22d|callee|add|_18b|_f8|_e2|_41|anim|Number|opacity|case|Math|_paused|Deferred|lastIndexOf|||||||||shift|substr|string|_3e7|_3ce|break|_w|charCode|_listener|_d5|_c5|authority|_49|width|isSafari|_49e|fire|_timer|_47b|_465|eval|_in|_40c|_409|_362|_3d9|className|_3d5|_386|_37a|body|getComputedStyle|box|_221|keyCode|remove|_8d|_46|paused|status|not|_478|_461|form|splice|filter|concat|tret|childNodes|_38b|_367|_33d||||||||||_340|_348|keypress|appendChild|_toArray|Array|_2b0|_toPixelValue|ref|_fixEvent|_19f|_14c|_14a|_150|_141|declaredClass|_d4|_99|_Url|_83|scheme|_67|_3d|switch|getValue|_startRepeatCount|repeat|_startTime|_47e|cancel|tif|load|to|with|tf|getElementsByTagName|number|_34c|_342|extend|_1e3|_normalizeEventName|_14b|_14e|results|self|cbfn|_f9|_d8|_b2|src|_88|dav||baseUrl|fragment|_loadedModules|_44|_43|_loaders|mll|height||easing|play|setTimeout|Date|clearTimeout|hdr|content|code|errback|_464|addCallbacks|_450|fromJson|_413|_3fc|_3ee|max|_31e|cond|getAttribute|_3d4|obi|tagName|_360|_381|contains|firstChild|_368|_372|_320|place|_2fa|scrollTop|_299|scrollLeft|top|documentElement|_288|_287|_getBorderExtents|_23f|_23d|_239|_218|_216|_211|eles|target|keys|shiftKey|ctrlKey|event|192|iel|_1db|delete|_1cf||addEventListener|String|_1af|_157|array|_14d|continue|_14f|_137|_11f|_106|_findMethod|has|_delegate|_dc|_d3|loaded|_9a|_loadInit|_inFlightCount|getObject|tv|_4f|_postLoad|_2d|offsetWidth|properties|beforeBegin|animateProperty|_4ad|_4a6|isKhtml|_fade|100|headers|readyState|timeout|_469|_457|_44d|formToObject|_441|comment|_43d|_36f|_419|tp|_40a|_406|_407|_373|_403|_3e6|_31b|cbi|test|_3c7|nextSibling|last|_3a1|_38e|_365|_36b|ecn|_364|_363|_356|_35e|_35f|_34f|_34d|_349|trim|tci|_328|_32b|_31f|_31c|_anim|_300|_2ff|_2f5|_2e7|removeClass|addClass|func|_2c4|cls|_2a9|_2ae|_280|_27f|_getPadExtents|isMoz|none|_233|cssText|_214|_fixCallback|_synthesizeEvent|stopPropagation|preventDefault|_setKeyChar|_1e1|ieh|_1d7|_1be|colorFromArray|sanitize|bits|rgb|_156|_fire|_resback|_13d|partial|_13a|silentlyCancelled|_topics|_127|_f1|_f0|superclass|_ec|_e3|mct|setObject|_bf|_b3|object|require|_92|_khtmlTimer|location|XMLHTTP|locale|dua|_71|_modulePrefixes|_55|_loadModule|_51|_50|_4e|pop|_3f|_callLoaded|_unloaders|_loadNotifying|_loadedUrls|_27|_24|_1d|_5|_4b7|onAnimate|getStyle|offsetHeight|_defaultEasing|toCss|_properties|fadeOut|fadeIn|_49f|auto|zoom|_cycle|_endTime|valueOf|_494|duration|_492|DELETE|_ioAddQueryToUrl|putData|contentType|password|user|_isDocumentOk|application|||||_466||||||startTime|_xhrObj|_45f|handleAs|addBoth|error|text|objectToQuery|_44f|ActiveXObject|_443|_442|filtered|_43f|_43e|_437|file|tnl|_41c|_filterQueryResult|_zipIdx|_408|_402|evaluate|_3ed|_380|fHit|_361|_33b|_3da|_3ab|_3d6|RegExp|_327|_3cf|_3c9|child|innerHTML|first|tval|_391|class|pnc|_37e|_37c|_375|_366|_35c|_35a|_353|_33c|_336|_314|||_315|_oe|_307|_309|cloneNode|after|createElement||_2f8|_2ef|_2ee|unshift|coords|some|every||_2cb|script|_2c9|parent||a2p||_2c3|_2bd||abs|_getMarginBox|_2b3|_2a6|position|_2a7|_2ac|_2ab|_getIeDocumentElementOffset|getBoundingClientRect|ownerDocument|_2a3|clientWidth|_isBodyLtr|_fixIeBiDiScrollLeft|_bodyLtr|_29d|_getContentBox|_setBox|_getMarginExtents|_getPadBorderExtents|_usesBorderBox|boxModel|pcs|st|sl|_240|runtimeStyle|_dcm|BackCompat|compatMode|default|_21b|_d|html|_event_listener|handlers|PAGE_DOWN|PAGE_UP|RIGHT_ARROW|LEFT_ARROW|DOWN_ARROW|UP_ARROW|_preventDefault||_stopPropagation|returnValue||_trySetKeyCode|cancelBubble|currentTarget|106|_1ee|111||_1e8|_1e7|||se|srcElement|onkeydown||_1d0|_disconnect|lid|_1c0|_connect|_set|_195|_185|_183|_17d|_everyOrSome|_16b|_172|_15b|Function|_154|_escapeString|_140|chain|_check|canceller|_12d|_124|_11a|_10d|_107|inherited|_fa|_f2|_findMixin|_constructor|preamble|_de|clone|tmp|_c7|TMP|_be|_ba|_mixin|isBrowser|lang|firebug||param|modulePaths|_a7|_fireCallback|_a0|setContext||_9c|unloaded||||_96|_93|navigator|_90|_89||protocol|_84|_86|_XMLHTTP_PROGIDS|gears|google|setAttribute|_80|_77|cfg|_6f|_getModuleSymbols|_5a|_58|_53|_4d|_4c|_45|_40|_moduleHasPrefix|_loadUri|_28|_26|_21|_22|tests|doh|_20|_1f|_1c|version|_1b|_19|_getProp|_11|_4|_4a5|_4b3|_Animation|tempColor|blendColors|PI|sin|||||_49a|normal|onEnd||rate||curr|onStop|_497||_496|pct|onPause|onPlay|onBegin|delay||_491|_Line|_48b|wrapForm|PUT|_487|POST|GET|_476|_474|_472|_ioWatch|send|_471|setRequestHeader|open|callback|setInterval|_470|resHandle|_46f|ioCheck|_46e|validCheck|getTime|_ioCancelAll|addOnUnload|clearInterval|dojoType|now|canceled|_blockAsync|_45e|_45c|_459|_ioSetArgs|_contentHandlers|abort|_458|_456||||addErrback|_454|addCallback|_452|_44b|_44a|_449|preventCache|responseXML|Microsoft|JSON|usePlainJson|_431|toJson|_430|_42d|image|opt|ria|_421|_41b|_40b|_zip|_410|_40d|_357|sqf|_374|_3e5|_3df|_38f|clc|pred|parseInt|ntf|_3bf|_3bc|cnl|previousSibling|_3a9|_3a6|_39c|_399|_396|_392|__cachedIndex|__cachedLength|_376|iterateNext|_34a|_355|_354|_32c|_350|_34b|_33f|_33e|_33a|_338|_334|_332||_330|_32e||_322|_316|mousemove|mouseout|mouseover|_305|lastChild||_2f9||_2f2|_2f1|removeChild|_2ec|_2eb|_2ea|_2e6||_2e4|_2e2|_2d6|_2d5|_2d4|_2d3|_2d2|_2d1|_2cd|_2cc|scs|write|_2c8|hasClass|_2c0|_2bb|_2b5|_abs|_docScroll|offsetParent|offsetTop|offsetLeft|absolute|getBoxObjectFor|clientLeft|_setContentSize|_setMarginBox|_28d|_286|_285|_289|NaN|_281|border|_272|_26b|_260|_258|_253|_24c|_246|_23a|_getOpacity|_setOpacity|_238|td|tr|nodeName|FILTER|_22f|_22e|currentStyle|_22c|_22b|display|QuirksMode|unselectable|_217|isMozilla|getElementById|attributes|all|_ie_listener|_getIeDispatcher|_1fd|NUM_LOCK|SCROLL_LOCK|INSERT|END|HOME|PAUSE|F12|F11|F10|F9|F8|F7|F6|F5|F4|F3|F2|F1|63232|SHIFT_TAB|TAB|keyIdentifier|_1f3|stopEvent|_punctMap|222|219|186|onkeypress|_stealthKeyDown|_fixKeys|relatedTarget|_1e0|_1df|_stealthKeydown|_1d6|_1d5|_1d1|_1ca|_1c9|_1cb|_1c2|_1c1|_1c3|_1c4|_1bc|_1b3|_1b2|colorFromHex|colorFromRgb|named|colorFromString|mask|rgba|_19c|_197|_192|setColor|_180|_178|_177|_175|_174|_16d|_166|_164|_163|_162|_15c|_15d|_15e|index|__json__|toJsonIndentStr|_nextId|_12f|_12b|publish|_128|_126|_125|_122|_121|_123|_11c|_11b|_10c|_10b|_108|getDispatcher|argument|nom|_construct|_core|_makeCtor|_df|_db|deprecated|isObject|_cc||scope||_hitchArgs|_c2||pre|_c1|native|isDebug||registerModulePath|_a8||finally|||_a6|_a5|_a4|_a3|_a2|_a1|_9f|_9e|_9d|_9b|_98|_97|onbeforeunload|ipt|scr|complete|_95|userAgent|_modulesLoaded|initialized|_initFired|_8c|_8a|_getText|_87|ieForceActiveXXhr|Msxml2|isGears|_81|_gearsObject|googlegears|GearsFactory|isFF|_7d|Safari|_72|_name|_6c|ire|ore|_68|i18n|_5b|requireIf|_56|_52|loading|_4a|_loadPath|_47|_48|_global_omit_module_check|_getModulePrefix|_3c|_3a|_37|_30|Boolean|_loadUriAndCheck|_2e||cacheBust|_1e|_1a|_17|_16|_15|_14|_f|_10|_e|_9|_8|revision|flag|patch|minor|major|_6|color|units|needs|stopped|playing|stop|gotoPercent|pause|1000|implemented|yet|_48a|xhrDelete|rawXhrPut|xhrPut|postData|rawXhrPost|xhrPost|xhrGet|Type|Content|sync|response|http|bad|urlencoded|www|_watchInFlightError||exceeded|handle|action|getAttributeNode|loadXML|async|XMLDOM|prefixes|MSXML3|MSXML|MSXML2||xml|javascript|wasn|your|optional|message|off|turn|use|endpoints|issues|security|potential|avoid|mimetype|using|consider|please|decodeURIComponent|queryToObject|formToJson|formToQuery|encodeURIComponent|selected|option|multiple|checked|checkbox|radio|disabled|textarea|select|button|reset|submit|input|_3fb|hasAttribute|0n|even|odd|nth|_3b5|empty|_3b1|_3ad|htmlFor|_38a|under||exprssion|failure|ANY_TYPE|XPathResult|starts|keyup|keydown|mouseup|mousedown|blur|click|combine|span|addContent||adopt|orphan|_2de|_2dd|styles|_2da|_2d9|_2cf|_2ce|show|createPopup|toggleClass|scrollWidth|clientTop|ltr|direction|pageXOffset|pageYOffset|fixed|contentBox|marginBox|BUTTON|TABLE|_getBorderBox|clientHeight|visible|overflow|marginBottom|marginRight|marginTop|marginLeft|borderBottomWidth|borderBottomStyle|borderRightWidth|borderRightStyle|borderTopWidth|borderTopStyle|borderLeftWidth|borderLeftStyle|paddingBottom|paddingRight|paddingTop|paddingLeft|offset||min|padding||margin|Opacity|Alpha|alpha|filters|pixelLeft|medium|_22a|defaultView|before||insertBefore|KhtmlUserSelect|MozUserSelect|setSelectable|isDescendant|div|_destroyElement|BackgroundImageCache|execCommand|PageDown|PageUp|Right|Left|Down|Up|63289|63249|63248|PRINT_SCREEN|63302|63277|63276|63275|63273|63272|63250|63247|63246|63245|63244|63243|63242|63241|63240|63239|63238|63237|63236|63235|63234|63233|Enter|_1f9|which|_1f6|bubbledKeyCode|221|220||||191|190|189|188|187|toElement|fromElement|clientY|pageY||clientX|pageX|offsetY|||layerY|offsetX|layerX|parentWindow|_nop|_allow_leaks|145|144|126|F15|125|F14|124|F13|123|122|121|120|119|118|117|116|115|114|113|112|NUMPAD_DIVIDE|110|NUMPAD_PERIOD|109|NUMPAD_MINUS|108|NUMPAD_ENTER|107|NUMPAD_PLUS|NUMPAD_MULTIPLY|105|NUMPAD_9|104|NUMPAD_8|103|NUMPAD_7|102|NUMPAD_6|101|NUMPAD_5|NUMPAD_4||NUMPAD_3|NUMPAD_2|NUMPAD_1|NUMPAD_0||SELECT|RIGHT_WINDOW||LEFT_WINDOW||HELP|SPACE|ESCAPE|CAPS_LOCK|ALT|CTRL|SHIFT|ENTER|CLEAR|BACKSPACE|attachEvent|fixEvent|fromCharCode|keyChar|_1b9|removeEventListener|0x|round|toHex|toRgba|toRgb|aqua|teal|blue|navy|yellow|olive|lime|green|fuchsia|purple|red|maroon|white|gray|silver|black|boolean|called|already|Cancelled|connectPublisher|unsubscribe|subscribe|disconnect|_113|_112||_111|_110|||found|was||must|_|module|||required|likely|It|declaration|Mixin|separate|instead|property|initializer||pass|_c9|_bb|_b7|nfunction|isAlien|isFinite|isArrayLike|_firebug|withDoc|withGlobal|_writeIncludes|VML|behavior|addRule|createStyleSheet|vml|com|microsoft|schemas|urn|namespaces|onunload|onreadystatechange|defer|khtml|WebKit|DOMContentLoaded|enableMozDomContentLoaded|domcontentloaded|Unable|base|chrome|1223|304|300|200|available|XMLHttpRequest|_println|language|userLanguage|isQuirks|factory|mimeTypes|Factory|Gears|_7f|MSIE||Firefox|Gecko|Konqueror||Opera|appVersion|xd|browser|moduleUrl|port|host|hostenv|_requireLocalization|_5f|_5e|_5d|_5c|requireLocalization|requireAfterIf|_57|common|platformRequire|defined|symbol|_isXDomain|tried|Could|__package__|packageFileName|_42|useXDomain|flight|still|files|addOnLoad|failed|sourceURL|util|notice|without|change|subject|APIs|EXPERIMENTAL|experimental|removed|will|DEPRECATED|exists|10315|Rev|Mobile|Spidermonkey|Rhino||Browser|delayMozLoadingFix|preventBackButtonFix|libraryScriptUri|baseRelativePath|baseScriptUri|allowQueryConfig|warn|trace|timeEnd||time|profileEnd|profile|log|info|groupEnd|group|dirxml|dir|count|assert'.split('|'),0,{});
+
+
+/*
+
+Prototype 1.5 rc0
+ - Adapted from Ruby on Rails - http://dev.rubyonrails.org/browser/spinoffs/prototype/src
+ - By Lunarmedia, 06 August, 2006
+ - Available at (and packed with) JavascriptCompressor.com
+
+Please note this version is missing the selector.js component of the full Prototype library. 
+You can get the compressed version of selector at JavascriptCompressor.com
+
+*/
+
+var decompressedPrototype = function(p,a,c,k,e,d){e=function(c){return(c<a?"":e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[(function(e){return d[e]})];e=(function(){return'\\w+'});c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('d T={4l:\'1.5.8P\',3E:\'(?:<3G.*?>)((\\n|\\r|.)*?)(?:<\\/3G>)\',2v:7(){},K:7(x){c x}};d 1b={17:7(){c 7(){6.1I.2n(6,N)}}};d 1e=z q();q.u=7(5d,O){G(d 1G 2M O){5d[1G]=O[1G]}c 5d};q.1U=7(U){1j{f(U==1v)c\'1v\';f(U==1L)c\'1L\';c U.1U?U.1U():U.2C()}1s(e){f(e 8R 9l)c\'...\';25 e}};7j.v.1d=7(){d 43=6,23=$A(N),U=23.8S();c 7(){c 43.2n(U,23.3s($A(N)))}};7j.v.8U=7(U){d 43=6;c 7(C){c 43.8V(U,C||1W.C)}};q.u(8Q.v,{8W:7(){d 4Z=6.2C(16);f(6<16)c\'0\'+4Z;c 4Z},5j:7(){c 6+1},8Y:7(o){$R(0,6,11).V(o);c 6}});d 6s={6j:7(){d 48;G(d i=0;i<N.t;i++){d 6L=N[i];1j{48=6L();1y}1s(e){}}c 48}};d 6Q=1b.17();6Q.v={1I:7(1a,1J){6.1a=1a;6.1J=1J;6.41=Y;6.2A()},2A:7(){5Z(6.2D.1d(6),6.1J*4z)},2D:7(){f(!6.41){1j{6.41=11;6.1a()}8Z{6.41=Y}}}};q.u(4b.v,{2T:7(1A,1z){d L=\'\',O=6,I;1z=N.90.52(1z);1H(O.t>0){f(I=O.I(1A)){L+=O.47(0,I.w);L+=(1z(I)||\'\').2C();O=O.47(I.w+I[0].t)}1D{L+=O,O=\'\'}}c L},92:7(1A,1z,3i){1z=6.2T.52(1z);3i=3i===1v?1:3i;c 6.2T(1A,7(I){f(--3i<0)c I[0];c 1z(I)})},93:7(1A,o){6.2T(1A,o);c 6},94:7(t,2S){t=t||30;2S=2S===1v?\'...\':2S;c 6.t>t?6.47(0,t-2S.t)+2S:6},9F:7(){c 6.2y(/^\\s+/,\'\').2y(/\\s+$/,\'\')},71:7(){c 6.2y(/<\\/?[^>]+>/7Y,\'\')},2Q:7(){c 6.2y(z 3O(T.3E,\'5P\'),\'\')},70:7(){d 6Y=z 3O(T.3E,\'5P\');d 5p=z 3O(T.3E,\'98\');c(6.I(6Y)||[]).1C(7(5o){c(5o.I(5p)||[\'\',\'\'])[1]})},3q:7(){c 6.70().1C(7(3G){c 4q(3G)})},9E:7(){d 1q=J.4Y(\'1q\');d 1Y=J.9D(6);1q.75(1Y);c 1q.3h},9c:7(){d 1q=J.4Y(\'1q\');1q.3h=6.71();c 1q.2z[0]?1q.2z[0].6q:\'\'},78:7(){d 7i=6.I(/^\\??(.*)$/)[1].3j(\'&\');c 7i.36({},7(5b,72){d 1i=72.3j(\'=\');5b[1i[0]]=1i[1];c 5b})},1Z:7(){c 6.3j(\'\')},3P:7(){d 2l=6.3j(\'-\');f(2l.t==1)c 2l[0];d 54=6.5g(\'-\')==0?2l[0].7e(0).3Y()+2l[0].7g(1):2l[0];G(d i=1,73=2l.t;i<73;i++){d s=2l[i];54+=s.7e(0).3Y()+s.7g(1)}c 54},1U:7(){c"\'"+6.2y(/\\\\/g,\'\\\\\\\\\').2y(/\'/g,\'\\\\\\\'\')+"\'"}});4b.v.2T.52=7(1z){f(2i 1z==\'7\')c 1z;d 2U=z 3n(1z);c 7(I){c 2U.7a(I)}};4b.v.9h=4b.v.78;d 3n=1b.17();3n.79=/(^|.|\\r|\\n)(#\\{(.*?)\\})/;3n.v={1I:7(2U,1A){6.2U=2U.2C();6.1A=1A||3n.79},7a:7(U){c 6.2U.2T(6.1A,7(I){d 53=I[1];f(53==\'\\\\\')c I[2];c 53+(U[I[3]]||\'\').2C()})}};d $1y=z q();d $49=z q();d 1p={V:7(o){d w=0;1j{6.2m(7(h){1j{o(h,w++)}1s(e){f(e!=$49)25 e}})}1s(e){f(e!=$1y)25 e}},9n:7(o){d L=11;6.V(7(h,w){L=L&&!!(o||T.K)(h,w);f(!L)25 $1y});c L},9o:7(o){d L=11;6.V(7(h,w){f(L=!!(o||T.K)(h,w))25 $1y});c L},3e:7(o){d P=[];6.V(7(h,w){P.W(o(h,w))});c P},7n:7(o){d L;6.V(7(h,w){f(o(h,w)){L=h;25 $1y}});c L},7o:7(o){d P=[];6.V(7(h,w){f(o(h,w))P.W(h)});c P},9p:7(1A,o){d P=[];6.V(7(h,w){d 7c=h.2C();f(7c.I(1A))P.W((o||T.K)(h,w))});c P},1M:7(U){d 51=Y;6.V(7(h){f(h==U){51=11;25 $1y}});c 51},36:7(45,o){6.V(7(h,w){45=o(45,h,w)});c 45},9q:7(1F){d 23=$A(N).47(1);c 6.3e(7(h){c h[1F].2n(h,23)})},9s:7(o){d L;6.V(7(h,w){h=(o||T.K)(h,w);f(L==1v||h>=L)L=h});c L},9u:7(o){d L;6.V(7(h,w){h=(o||T.K)(h,w);f(L==1v||h<L)L=h});c L},9v:7(o){d 50=[],58=[];6.V(7(h,w){((o||T.K)(h,w)?50:58).W(h)});c[50,58]},3r:7(1G){d P=[];6.V(7(h,w){P.W(h[1G])});c P},9x:7(o){d P=[];6.V(7(h,w){f(!o(h,w))P.W(h)});c P},9y:7(o){c 6.3e(7(h,w){c{h:h,59:o(h,w)}}).9z(7(18,3U){d a=18.59,b=3U.59;c a<b?-1:a>b?1:0}).3r(\'h\')},1Z:7(){c 6.3e(T.K)},9B:7(){d o=T.K,23=$A(N);f(2i 23.5e()==\'7\')o=23.9C();d 7l=[6].3s(23).1C($A);c 6.1C(7(h,w){c o(7l.3r(w))})},1U:7(){c\'#<1p:\'+6.1Z().1U()+\'>\'}};q.u(1p,{1C:1p.3e,5v:1p.7n,1k:1p.7o,8M:1p.1M,7p:1p.1Z});d $A=1E.7q=7(2R){f(!2R)c[];f(2R.1Z){c 2R.1Z()}1D{d P=[];G(d i=0;i<2R.t;i++)P.W(2R[i]);c P}};q.u(1E.v,1p);f(!1E.v.4d)1E.v.4d=1E.v.4m;q.u(1E.v,{2m:7(o){G(d i=0;i<6.t;i++)o(6[i])},5i:7(){6.t=0;c 6},7r:7(){c 6[0]},5e:7(){c 6[6.t-1]},7s:7(){c 6.1k(7(h){c h!=1v||h!=1L})},6J:7(){c 6.36([],7(6H,h){c 6H.3s(h&&h.5D==1E?h.6J():[h])})},5s:7(){d 4N=$A(N);c 6.1k(7(h){c!4N.1M(h)})},5g:7(U){G(d i=0;i<6.t;i++)f(6[i]==U)c i;c-1},4m:7(5h){c(5h!==Y?6:6.1Z()).4d()},1U:7(){c\'[\'+6.1C(q.1U).1N(\', \')+\']\'}});d 4h={2m:7(o){G(d 1O 2M 6){d h=6[1O];f(2i h==\'7\')49;d 1i=[1O,h];1i.1O=1O;1i.h=h;o(1i)}},7t:7(){c 6.3r(\'1O\')},4N:7(){c 6.3r(\'h\')},7u:7(2N){c $H(2N).36($H(6),7(4Q,1i){4Q[1i.1O]=1i.h;c 4Q})},7w:7(){c 6.1C(7(1i){c 1i.1C(4n).1N(\'=\')}).1N(\'&\')},1U:7(){c\'#<4h:{\'+6.1C(7(1i){c 1i.1C(q.1U).1N(\': \')}).1N(\', \')+\'}>\'}};7 $H(U){d 2N=q.u({},U||{});q.u(2N,1p);q.u(2N,4h);c 2N};3L=1b.17();q.u(3L.v,1p);q.u(3L.v,{1I:7(22,2x,2H){6.22=22;6.2x=2x;6.2H=2H},2m:7(o){d h=6.22;2q{o(h);h=h.5j()}1H(6.1M(h))},1M:7(h){f(h<6.22)c Y;f(6.2H)c h<6.2x;c h<=6.2x}});d $R=7(22,2x,2H){c z 3L(22,2x,2H)};d M={4w:7(){c 6s.6j(7(){c z 5C()},7(){c z 5n(\'7y.6d\')},7(){c z 5n(\'7z.6d\')})||Y},4s:0};M.2W={3b:[],2m:7(o){6.3b.2m(o)},69:7(4F){f(!6.1M(4F))6.3b.W(4F)},7A:7(5t){6.3b=6.3b.5s(5t)},3y:7(1a,26,E,2Z){6.V(7(3o){f(3o[1a]&&2i 3o[1a]==\'7\'){1j{3o[1a].2n(3o,[26,E,2Z])}1s(e){}}})}};q.u(M.2W,1p);M.2W.69({5G:7(){M.4s++},1B:7(){M.4s--}});M.44=7(){};M.44.v={4a:7(m){6.m={1F:\'4j\',4p:11,5H:\'5E/x-86-Q-7C\',28:\'\'};q.u(6.m,m||{})},3l:7(){c 6.E.32==1v||6.E.32==0||(6.E.32>=84&&6.E.32<7E)},7G:7(){c!6.3l()}};M.3t=1b.17();M.3t.5L=[\'7H\',\'80\',\'7I\',\'7J\',\'4t\'];M.3t.v=q.u(z M.44(),{1I:7(1l,m){6.E=M.4w();6.4a(m);6.26(1l)},26:7(1l){d 28=6.m.28||\'\';f(28.t>0)28+=\'&7K=\';1j{6.1l=1l;f(6.m.1F==\'7L\'&&28.t>0)6.1l+=(6.1l.I(/\\?/)?\'&\':\'?\')+28;M.2W.3y(\'5G\',6,6.E);6.E.7N(6.m.1F,6.1l,6.m.4p);f(6.m.4p){6.E.5T=6.5J.1d(6);2Y((7(){6.4r(1)}).1d(6),10)}6.5A();d 1c=6.m.5V?6.m.5V:28;6.E.7O(6.m.1F==\'4j\'?1c:1L)}1s(e){6.3p(e)}},5A:7(){d 1P=[\'X-7P-7Q\',\'5C\',\'X-T-4l\',T.4l,\'7R\',\'1Y/7m, 1Y/2e, 5E/5F, 1Y/5F, */*\'];f(6.m.1F==\'4j\'){1P.W(\'5Q-2g\',6.m.5H);f(6.E.7S)1P.W(\'7T\',\'7U\')}f(6.m.1P)1P.W.2n(1P,6.m.1P);G(d i=0;i<1P.t;i+=2)6.E.7V(1P[i],1P[i+1])},5J:7(){d 2F=6.E.2F;f(2F!=1)6.4r(6.E.2F)},4A:7(B){1j{c 6.E.7W(B)}1s(e){}},5M:7(){1j{c 4q(\'(\'+6.4A(\'X-7X\')+\')\')}1s(e){}},5R:7(){1j{c 4q(6.E.3F)}1s(e){6.3p(e)}},4r:7(2F){d C=M.3t.5L[2F];d E=6.E,2Z=6.5M();f(C==\'4t\'){1j{(6.m[\'2I\'+6.E.32]||6.m[\'2I\'+(6.3l()?\'81\':\'82\')]||T.2v)(E,2Z)}1s(e){6.3p(e)}f((6.4A(\'5Q-2g\')||\'\').I(/^1Y\\/7m/i))6.5R()}1j{(6.m[\'2I\'+C]||T.2v)(E,2Z);M.2W.3y(\'2I\'+C,6,E,2Z)}1s(e){6.3p(e)}f(C==\'4t\')6.E.5T=T.2v},3p:7(57){(6.m.5W||T.2v)(6,57);M.2W.3y(\'5W\',6,57)}});M.4C=1b.17();q.u(q.u(M.4C.v,M.3t.v),{1I:7(1w,1l,m){6.4x={3m:1w.3m?$(1w.3m):$(1w),3z:1w.3z?$(1w.3z):(1w.3m?1L:$(1w))};6.E=M.4w();6.4a(m);d 1B=6.m.1B||T.2v;6.m.1B=(7(E,U){6.5Y();1B(E,U)}).1d(6);6.26(1l)},5Y:7(){d 3A=6.3l()?6.4x.3m:6.4x.3z;d 3k=6.E.3F;f(!6.m.3q)3k=3k.2Q();f(3A){f(6.m.60){z 6.m.60(3A,3k)}1D{k.6h(3A,3k)}}f(6.3l()){f(6.1B)2Y(6.1B.1d(6),10)}}});M.61=1b.17();M.61.v=q.u(z M.44(),{1I:7(1w,1l,m){6.4a(m);6.1B=6.m.1B;6.1J=(6.m.1J||2);6.2s=(6.m.2s||1);6.4B={};6.1w=1w;6.1l=1l;6.22()},22:7(){6.m.1B=6.63.1d(6);6.2D()},7b:7(){6.4B.1B=1v;89(6.65);(6.1B||T.2v).2n(6,N)},63:7(26){f(6.m.2s){6.2s=(26.3F==6.64?6.2s*6.m.2s:1);6.64=26.3F}6.65=2Y(6.2D.1d(6),6.2s*6.1J*4z)},2D:7(){6.4B=z M.4C(6.1w,6.1l,6.m)}});7 $(){d P=[],4;G(d i=0;i<N.t;i++){4=N[i];f(2i 4==\'8c\')4=J.8d(4);P.W(k.u(4))}c P.t<2?P[0]:P};J.8f=7(1f,6a){d 6b=($(6a)||J.1c).4D(\'*\');c $A(6b).36([],7(12,4E){f(4E.1f.I(z 3O("(^|\\\\s)"+1f+"(\\\\s|$)")))12.W(k.u(4E));c 12})};f(!1W.k)d k=z q();k.u=7(4){f(!4)c;f(4X)c 4;f(!4.6e&&4.1h&&4!=1W){d 2a=k.3d,2r=k.u.2r;G(d 1G 2M 2a){d h=2a[1G];f(2i h==\'7\')4[1G]=2r.4W(h)}}4.6e=11;c 4};k.u.2r={4W:7(h){c 6[h]=6[h]||7(){c h.2n(1L,[6].3s($A(N)))}}};k.3d={4U:7(4){c $(4).l.2B!=\'3Q\'},6N:7(){G(d i=0;i<N.t;i++){d 4=$(N[i]);k[k.4U(4)?\'6f\':\'6w\'](4)}},6f:7(){G(d i=0;i<N.t;i++){d 4=$(N[i]);4.l.2B=\'3Q\'}},6w:7(){G(d i=0;i<N.t;i++){d 4=$(N[i]);4.l.2B=\'\'}},42:7(4){4=$(4);4.1X.8h(4)},6h:7(4,2e){$(4).3h=2e.2Q();2Y(7(){2e.3q()},10)},2y:7(4,2e){4=$(4);f(4.6k){4.6k=2e.2Q()}1D{d 1K=4.6R.6S();1K.56(4);4.1X.8i(1K.6T(2e.2Q()),4)}2Y(7(){2e.3q()},10)},8k:7(4){4=$(4);c 4.2k},3K:7(4){c z k.3S(4)},8l:7(4,1f){f(!(4=$(4)))c;c k.3K(4).1M(1f)},8m:7(4,1f){f(!(4=$(4)))c;c k.3K(4).7k(1f)},8n:7(4,1f){f(!(4=$(4)))c;c k.3K(4).42(1f)},8p:7(4){4=$(4);G(d i=0;i<4.2z.t;i++){d 3M=4.2z[i];f(3M.8q==3&&!/\\S/.4v(3M.6q))k.42(3M)}},8r:7(4){c $(4).3h.I(/^\\s*$/)},8s:7(4,3I){4=$(4),3I=$(3I);1H(4=4.1X)f(4==3I)c 11;c Y},6t:7(4){4=$(4);d x=4.x?4.x:4.2f,y=4.y?4.y:4.29;1W.6t(x,y)},1R:7(4,l){4=$(4);d h=4.l[l.3P()];f(!h){f(J.4J&&J.4J.6v){d 4L=J.4J.6v(4,1L);h=4L?4L.8v(l):1L}1D f(4.6x){h=4.6x[l.3P()]}}f(1W.6E&&[\'18\',\'1n\',\'3U\',\'6G\'].1M(l))f(k.1R(4,\'14\')==\'4G\')h=\'6y\';c h==\'6y\'?1L:h},8x:7(4,l){4=$(4);G(d B 2M l)4.l[B.3P()]=l[B]},8y:7(4){4=$(4);f(k.1R(4,\'2B\')!=\'3Q\')c{21:4.2p,24:4.2k};d 20=4.l;d 6B=20.4O;d 6A=20.14;20.4O=\'31\';20.14=\'2o\';20.2B=\'\';d 6C=4.6m;d 6D=4.6p;20.2B=\'3Q\';20.14=6A;20.4O=6B;c{21:6C,24:6D}},8z:7(4){4=$(4);d 4R=k.1R(4,\'14\');f(4R==\'4G\'||!4R){4.4T=11;4.l.14=\'3T\';f(1W.6E){4.l.1n=0;4.l.18=0}}},8A:7(4){4=$(4);f(4.4T){4.4T=1v;4.l.14=4.l.1n=4.l.18=4.l.6G=4.l.3U=\'\'}},8B:7(4){4=$(4);f(4.3c)c;4.3c=4.l.3V;f((k.1R(4,\'3V\')||\'4U\')!=\'31\')4.l.3V=\'31\'},8D:7(4){4=$(4);f(4.3c)c;4.l.3V=4.3c;4.3c=1v}};q.u(k,k.3d);d 4X=Y;f(!3W&&/3x|3w|3u/.4v(33.62)){d 3W={}};k.6K=7(2a){q.u(k.3d,2a||{});f(2i 3W!=\'1v\'){d 2a=k.3d,2r=k.u.2r;G(d 1G 2M 2a){d h=2a[1G];f(2i h==\'7\')3W.v[1G]=2r.4W(h)}4X=11}};k.6K();d 6M=z q();6M.2B=k.6N;1e.1g=7(3f){6.3f=3f};1e.1g.v={1I:7(4,2t){6.4=$(4);6.2t=2t.2Q();f(6.3f&&6.4.6O){1j{6.4.6O(6.3f,6.2t)}1s(e){d 1h=6.4.1h.2w();f(1h==\'4V\'||1h==\'8N\'){6.2X(6.6U())}1D{25 e}}}1D{6.1K=6.4.6R.6S();f(6.2V)6.2V();6.2X([6.1K.6T(6.2t)])}2Y(7(){2t.3q()},10)},6U:7(){d 1q=J.4Y(\'1q\');1q.3h=\'<6V><4V>\'+6.2t+\'</4V></6V>\';c $A(1q.2z[0].2z[0].2z)}};d 1g=z q();1g.6W=1b.17();1g.6W.v=q.u(z 1e.1g(\'96\'),{2V:7(){6.1K.97(6.4)},2X:7(2h){2h.V((7(2j){6.4.1X.55(2j,6.4)}).1d(6))}});1g.5m=1b.17();1g.5m.v=q.u(z 1e.1g(\'99\'),{2V:7(){6.1K.56(6.4);6.1K.74(11)},2X:7(2h){2h.4m(Y).V((7(2j){6.4.55(2j,6.4.9a)}).1d(6))}});1g.7h=1b.17();1g.7h.v=q.u(z 1e.1g(\'9d\'),{2V:7(){6.1K.56(6.4);6.1K.74(6.4)},2X:7(2h){2h.V((7(2j){6.4.75(2j)}).1d(6))}});1g.76=1b.17();1g.76.v=q.u(z 1e.1g(\'9i\'),{2V:7(){6.1K.9m(6.4)},2X:7(2h){2h.V((7(2j){6.4.1X.55(2j,6.4.9t)}).1d(6))}});k.3S=1b.17();k.3S.v={1I:7(4){6.4=$(4)},2m:7(o){6.4.1f.3j(/\\s+/).1k(7(B){c B.t>0}).2m(o)},5c:7(1f){6.4.1f=1f},7k:7(5a){f(6.1M(5a))c;6.5c(6.1Z().3s(5a).1N(\' \'))},42:7(4c){f(!6.1M(4c))c;6.5c(6.1k(7(1f){c 1f!=4c}).1N(\' \'))},2C:7(){c 6.1Z().1N(\' \')}};q.u(k.3S.v,1p);d 5I={5i:7(){G(d i=0;i<N.t;i++)$(N[i]).h=\'\'},4f:7(4){$(4).4f()},7v:7(){G(d i=0;i<N.t;i++)f($(N[i]).h==\'\')c Y;c 11},1k:7(4){$(4).1k()},5y:7(4){4=$(4);4.4f();f(4.1k)4.1k()}};d D={3a:7(Q){d 12=D.2L($(Q));d 4I=z 1E();G(d i=0;i<12.t;i++){d 4g=D.k.3a(12[i]);f(4g)4I.W(4g)}c 4I.1N(\'&\')},2L:7(Q){Q=$(Q);d 12=z 1E();G(d 1h 2M D.k.2E){d 4H=Q.4D(1h);G(d j=0;j<4H.t;j++)12.W(4H[j])}c 12},7x:7(Q,3N,B){Q=$(Q);d 3H=Q.4D(\'2u\');f(!3N&&!B)c 3H;d 4y=z 1E();G(d i=0;i<3H.t;i++){d 2u=3H[i];f((3N&&2u.2g!=3N)||(B&&2u.B!=B))49;4y.W(2u)}c 4y},7B:7(Q){d 12=D.2L(Q);G(d i=0;i<12.t;i++){d 4=12[i];4.7D();4.4o=\'11\'}},7F:7(Q){d 12=D.2L(Q);G(d i=0;i<12.t;i++){d 4=12[i];4.4o=\'\'}},5z:7(Q){c D.2L(Q).5v(7(4){c 4.2g!=\'31\'&&!4.4o&&[\'2u\',\'1k\',\'3J\'].1M(4.1h.2w())})},7M:7(Q){5I.5y(D.5z(Q))},5w:7(Q){$(Q).5w()}};D.k={3a:7(4){4=$(4);d 1F=4.1h.2w();d 1S=D.k.2E[1F](4);f(1S){d 1O=4n(1S[0]);f(1O.t==0)c;f(1S[1].5D!=1E)1S[1]=[1S[1]];c 1S[1].1C(7(h){c 1O+\'=\'+4n(h)}).1N(\'&\')}},1x:7(4){4=$(4);d 1F=4.1h.2w();d 1S=D.k.2E[1F](4);f(1S)c 1S[1]}};D.k.2E={2u:7(4){6c(4.2g.2w()){1r\'7Z\':1r\'31\':1r\'6l\':1r\'1Y\':c D.k.2E.3J(4);1r\'6g\':1r\'6i\':c D.k.2E.5O(4)}c Y},5O:7(4){f(4.83)c[4.B,4.h]},3J:7(4){c[4.B,4.h]},1k:7(4){c D.k.2E[4.2g==\'1k-6n\'?\'5S\':\'5X\'](4)},5S:7(4){d h=\'\',2b,w=4.85;f(w>=0){2b=4.m[w];h=2b.h||2b.1Y}c[4.B,h]},5X:7(4){d h=[];G(d i=0;i<4.t;i++){d 2b=4.m[i];f(2b.87)h.W(2b.h||2b.1Y)}c[4.B,h]}};d $F=D.k.1x;1e.3D=7(){};1e.3D.v={1I:7(4,1J,1a){6.1J=1J;6.4=$(4);6.1a=1a;6.2K=6.1x();6.2A()},2A:7(){5Z(6.2D.1d(6),6.1J*4z)},2D:7(){d h=6.1x();f(6.2K!=h){6.1a(6.4,h);6.2K=h}}};D.k.3C=1b.17();D.k.3C.v=q.u(z 1e.3D(),{1x:7(){c D.k.1x(6.4)}});D.3C=1b.17();D.3C.v=q.u(z 1e.3D(),{1x:7(){c D.3a(6.4)}});1e.2c=7(){};1e.2c.v={1I:7(4,1a){6.4=$(4);6.1a=1a;6.2K=6.1x();f(6.4.1h.2w()==\'Q\')6.67();1D 6.2A(6.4)},4K:7(){d h=6.1x();f(6.2K!=h){6.1a(6.4,h);6.2K=h}},67:7(){d 12=D.2L(6.4);G(d i=0;i<12.t;i++)6.2A(12[i])},2A:7(4){f(4.2g){6c(4.2g.2w()){1r\'6g\':1r\'6i\':1o.3B(4,\'8j\',6.4K.1d(6));1y;1r\'6l\':1r\'1Y\':1r\'3J\':1r\'1k-6n\':1r\'1k-8t\':1o.3B(4,\'8u\',6.4K.1d(6));1y}}}};D.k.2c=1b.17();D.k.2c.v=q.u(z 1e.2c(),{1x:7(){c D.k.1x(6.4)}});D.2c=1b.17();D.2c.v=q.u(z 1e.2c(),{1x:7(){c D.3a(6.4)}});f(!1W.1o){d 1o=z q()}q.u(1o,{8C:8,8F:9,8H:13,8I:27,8J:37,8L:38,8O:39,8T:40,8X:46,4:7(C){c C.Z||C.91},95:7(C){c(((C.6X)&&(C.6X==1))||((C.6Z)&&(C.6Z==1)))},9b:7(C){c C.9e||(C.9f+(J.3R.2G||J.1c.2G))},9g:7(C){c C.9j||(C.9k+(J.3R.2O||J.1c.2O))},7b:7(C){f(C.7d){C.7d();C.9r()}1D{C.48=Y;C.9w=11}},9A:7(C,1h){d 4=1o.4(C);1H(4.1X&&(!4.1h||(4.1h.3Y()!=1h.3Y())))4=4.1X;c 4},1T:Y,5u:7(4,B,1V,1u){f(!6.1T)6.1T=[];f(4.5f){6.1T.W([4,B,1V,1u]);4.5f(B,1V,1u)}1D f(4.4i){6.1T.W([4,B,1V,1u]);4.4i(\'2I\'+B,1V)}},66:7(){f(!1o.1T)c;G(d i=0;i<1o.1T.t;i++){1o.5N.2n(6,1o.1T[i]);1o.1T[i][0]=1L}1o.1T=Y},3B:7(4,B,1V,1u){d 4=$(4);1u=1u||Y;f(B==\'5U\'&&(33.4u.I(/3x|3w|3u/)||4.4i))B=\'5K\';6.5u(4,B,1V,1u)},5N:7(4,B,1V,1u){d 4=$(4);1u=1u||Y;f(B==\'5U\'&&(33.4u.I(/3x|3w|3u/)||4.4k))B=\'5K\';f(4.5x){4.5x(B,1V,1u)}1D f(4.4k){1j{4.4k(\'2I\'+B,1V)}1s(e){}}}});f(33.4u.I(/\\88\\b/))1o.3B(1W,\'8a\',1o.66,Y);d 2d={6o:Y,4P:7(){6.6z=1W.8e||J.3R.2G||J.1c.2G||0;6.6F=1W.8g||J.3R.2O||J.1c.2O||0},6u:7(4){d 19=0,15=0;2q{19+=4.2O||0;15+=4.2G||0;4=4.1X}1H(4);c[15,19]},35:7(4){d 19=0,15=0;2q{19+=4.29||0;15+=4.2f||0;4=4.1Q}1H(4);c[15,19]},68:7(4){d 19=0,15=0;2q{19+=4.29||0;15+=4.2f||0;4=4.1Q;f(4){p=k.1R(4,\'14\');f(p==\'3T\'||p==\'2o\')1y}}1H(4);c[15,19]},1Q:7(4){f(4.1Q)c 4.1Q;f(4==J.1c)c 4;1H((4=4.1X)&&4!=J.1c)f(k.1R(4,\'14\')!=\'4G\')c 4;c J.1c},8o:7(4,x,y){f(6.6o)c 6.6r(4,x,y);6.3g=x;6.34=y;6.1t=6.35(4);c(y>=6.1t[1]&&y<6.1t[1]+4.2k&&x>=6.1t[0]&&x<6.1t[0]+4.2p)},6r:7(4,x,y){d 4S=6.6u(4);6.3g=x+4S[0]-6.6z;6.34=y+4S[1]-6.6F;6.1t=6.35(4);c(6.34>=6.1t[1]&&6.34<6.1t[1]+4.2k&&6.3g>=6.1t[0]&&6.3g<6.1t[0]+4.2p)},8E:7(3Z,4){f(!3Z)c 0;f(3Z==\'8G\')c((6.1t[1]+4.2k)-6.34)/4.2k;f(3Z==\'8K\')c((6.1t[0]+4.2p)-6.3g)/4.2p},77:7(O,Z){O=$(O);Z=$(Z);Z.l.14=\'2o\';d 2P=6.35(O);Z.l.1n=2P[1]+\'1m\';Z.l.18=2P[0]+\'1m\';Z.l.21=O.2p+\'1m\';Z.l.24=O.2k+\'1m\'},4e:7(4M){d 19=0,15=0;d 4=4M;2q{19+=4.29||0;15+=4.2f||0;f(4.1Q==J.1c)f(k.1R(4,\'14\')==\'2o\')1y}1H(4=4.1Q);4=4M;2q{19-=4.2O||0;15-=4.2G||0}1H(4=4.1X);c[15,19]},77:7(O,Z){d m=q.u({5l:11,5r:11,5B:11,5q:11,29:0,2f:0},N[2]||{});O=$(O);d p=2d.4e(O);Z=$(Z);d 2J=[0,0];d 3v=1L;f(k.1R(Z,\'14\')==\'2o\'){3v=2d.1Q(Z);2J=2d.4e(3v)}f(3v==J.1c){2J[0]-=J.1c.2f;2J[1]-=J.1c.29}f(m.5l)Z.l.18=(p[0]-2J[0]+m.2f)+\'1m\';f(m.5r)Z.l.1n=(p[1]-2J[1]+m.29)+\'1m\';f(m.5B)Z.l.21=O.2p+\'1m\';f(m.5q)Z.l.24=O.2k+\'1m\'},8b:7(4){4=$(4);f(4.l.14==\'2o\')c;2d.4P();d 2P=2d.68(4);d 1n=2P[1];d 18=2P[0];d 21=4.6m;d 24=4.6p;4.6P=18-3X(4.l.18||0);4.6I=1n-3X(4.l.1n||0);4.5k=4.l.21;4.7f=4.l.24;4.l.14=\'2o\';4.l.1n=1n+\'1m\';4.l.18=18+\'1m\';4.l.21=21+\'1m\';4.l.24=24+\'1m\'},8w:7(4){4=$(4);f(4.l.14==\'3T\')c;2d.4P();4.l.14=\'3T\';d 1n=3X(4.l.1n||0)-(4.6I||0);d 18=3X(4.l.18||0)-(4.6P||0);4.l.1n=1n+\'1m\';4.l.18=18+\'1m\';4.l.24=4.7f;4.l.21=4.5k}};f(/3x|3w|3u/.4v(33.62)){2d.35=7(4){d 19=0,15=0;2q{19+=4.29||0;15+=4.2f||0;f(4.1Q==J.1c)f(k.1R(4,\'14\')==\'2o\')1y;4=4.1Q}1H(4);c[15,19]}};',62,600,'||||element||this|function|||||return|var||if||value|||Element|style|options||iterator||Object|||length|extend|prototype|index|||new||name|event|Form|transport||for||match|document||result|Ajax|arguments|source|results|form|||Prototype|object|each|push||false|target||true|elements||position|valueL||create|left|valueT|callback|Class|body|bind|Abstract|className|Insertion|tagName|pair|try|select|url|px|top|Event|Enumerable|div|case|catch|offset|useCapture|undefined|container|getValue|break|replacement|pattern|onComplete|map|else|Array|method|property|while|initialize|frequency|range|null|include|join|key|requestHeaders|offsetParent|getStyle|parameter|observers|inspect|observer|window|parentNode|text|toArray|els|width|start|args|height|throw|request||parameters|offsetTop|methods|opt|EventObserver|Position|html|offsetLeft|type|fragments|typeof|fragment|offsetHeight|oStringList|_each|apply|absolute|offsetWidth|do|cache|decay|content|input|emptyFunction|toLowerCase|end|replace|childNodes|registerCallback|display|toString|onTimerEvent|Serializers|readyState|scrollLeft|exclusive|on|delta|lastValue|getElements|in|hash|scrollTop|offsets|stripScripts|iterable|truncation|gsub|template|initializeRange|Responders|insertContent|setTimeout|json||hidden|status|navigator|ycomp|cumulativeOffset|inject||||serialize|responders|_overflow|Methods|collect|adjacency|xcomp|innerHTML|count|split|response|responseIsSuccess|success|Template|responder|dispatchException|evalScripts|pluck|concat|Request|KHTML|parent|Safari|Konqueror|dispatch|failure|receiver|observe|Observer|TimedObserver|ScriptFragment|responseText|script|inputs|ancestor|textarea|classNames|ObjectRange|node|typeName|RegExp|camelize|none|documentElement|ClassNames|relative|right|overflow|HTMLElement|parseFloat|toUpperCase|mode||currentlyExecuting|remove|__method|Base|memo||slice|returnValue|continue|setOptions|String|classNameToRemove|_reverse|page|focus|queryComponent|Hash|attachEvent|post|detachEvent|Version|reverse|encodeURIComponent|disabled|asynchronous|eval|respondToReadyState|activeRequestCount|Complete|appVersion|test|getTransport|containers|matchingInputs|1000|header|updater|Updater|getElementsByTagName|child|responderToAdd|static|tagElements|queryComponents|defaultView|onElementEvent|css|forElement|values|visibility|prepare|mergedHash|pos|offsetcache|_madePositioned|visible|tbody|findOrStore|_nativeExtensions|createElement|digits|trues|found|prepareReplacement|before|camelizedString|insertBefore|selectNodeContents|exception|falses|criteria|classNameToAdd|params|set|destination|last|addEventListener|indexOf|inline|clear|succ|_originalWidth|setLeft|Top|ActiveXObject|scriptTag|matchOne|setHeight|setTop|without|responderToRemove|_observeAndCache|find|reset|removeEventListener|activate|findFirstElement|setRequestHeaders|setWidth|XMLHttpRequest|constructor|application|xml|onCreate|contentType|Field|onStateChange|keydown|Events|evalJSON|stopObserving|inputSelector|img|Content|evalResponse|selectOne|onreadystatechange|keypress|postBody|onException|selectMany|updateContent|setInterval|insertion|PeriodicalUpdater|userAgent|updateComplete|lastText|timer|unloadCache|registerFormCallbacks|positionedOffset|register|parentElement|children|switch|XMLHTTP|_extended|hide|checkbox|update|radio|these|outerHTML|password|clientWidth|one|includeScrollOffsets|clientHeight|nodeValue|withinIncludingScrolloffsets|Try|scrollTo|realOffset|getComputedStyle|show|currentStyle|auto|deltaX|originalPosition|originalVisibility|originalWidth|originalHeight|opera|deltaY|bottom|array|_originalTop|flatten|addMethods|lambda|Toggle|toggle|insertAdjacentHTML|_originalLeft|PeriodicalExecuter|ownerDocument|createRange|createContextualFragment|contentFromAnonymousTable|table|Before|which|matchAll|button|extractScripts|stripTags|pairString|len|collapse|appendChild|After|clone|toQueryParams|Pattern|evaluate|stop|stringValue|preventDefault|charAt|_originalHeight|substring|Bottom|pairs|Function|add|collections|javascript|detect|findAll|entries|from|first|compact|keys|merge|present|toQueryString|getInputs|Msxml2|Microsoft|unregister|disable|urlencoded|blur|300|enable|responseIsFailure|Uninitialized|Loaded|Interactive|_|get|focusFirstElement|open|send|Requested|With|Accept|overrideMimeType|Connection|close|setRequestHeader|getResponseHeader|JSON|gi|submit|Loading|Success|Failure|checked|200|selectedIndex|www|selected|bMSIE|clearTimeout|unload|absolutize|string|getElementById|pageXOffset|getElementsByClassName|pageYOffset|removeChild|replaceChild|click|getHeight|hasClassName|addClassName|removeClassName|within|cleanWhitespace|nodeType|empty|childOf|multiple|change|getPropertyValue|relativize|setStyle|getDimensions|makePositioned|undoPositioned|makeClipping|KEY_BACKSPACE|undoClipping|overlap|KEY_TAB|vertical|KEY_RETURN|KEY_ESC|KEY_LEFT|horizontal|KEY_UP|member|tr|KEY_RIGHT|0_RC_0|Number|instanceof|shift|KEY_DOWN|bindAsEventListener|call|toColorPart|KEY_DELETE|times|finally|callee|srcElement|sub|scan|truncate|isLeftClick|beforeBegin|setStartBefore|im|afterBegin|firstChild|pointerX|unescapeHTML|beforeEnd|pageX|clientX|pointerY|parseQuery|afterEnd|pageY|clientY|RangeError|setStartAfter|all|any|grep|invoke|stopPropagation|max|nextSibling|min|partition|cancelBubble|reject|sortBy|sort|findElement|zip|pop|createTextNode|escapeHTML|strip'.split('|'),0,{})
+
+}
+
+var _sunSpiderInterval = new Date() - _sunSpiderStartDate;
+
+document.getElementById("console").innerHTML = _sunSpiderInterval;
+</script>
+
+
+</body>
+</html>
diff --git a/src/third_party/mozjs-45/build/pgo/js-input/sunspider/string-validate-input.html b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/string-validate-input.html
new file mode 100644
index 0000000..72cf920
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/js-input/sunspider/string-validate-input.html
@@ -0,0 +1,139 @@
+<!DOCTYPE html>
+<head>
+<!--
+ Copyright (C) 2007 Apple Inc.  All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+-->
+
+<title>SunSpider string-validate-input</title>
+
+</head>
+
+<body>
+<h3>string-validate-input</h3>
+<div id="console">
+</div>
+
+<script>
+
+var _sunSpiderStartDate = new Date();
+
+letters = new Array("a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z");
+numbers = new Array(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26);
+colors  = new Array("FF","CC","99","66","33","00");
+
+var endResult;
+
+function doTest()
+{
+   endResult = "";
+
+   // make up email address
+   for (var k=0;k<4000;k++)
+   {
+      name = makeName(6);
+      (k%2)?email=name+"@mac.com":email=name+"(at)mac.com";
+
+      // validate the email address
+      var pattern = /^[a-zA-Z0-9\-\._]+@[a-zA-Z0-9\-_]+(\.?[a-zA-Z0-9\-_]*)\.[a-zA-Z]{2,3}$/;
+
+      if(pattern.test(email))
+      {
+         var r = email + " appears to be a valid email address.";
+         addResult(r);
+      }
+      else
+      {
+         r = email + " does NOT appear to be a valid email address.";
+         addResult(r);
+      }
+   }
+
+   // make up ZIP codes
+   for (var s=0;s<4000;s++)
+   {
+      var zipGood = true;
+      var zip = makeNumber(4);
+      (s%2)?zip=zip+"xyz":zip=zip.concat("7");
+
+      // validate the zip code
+      for (var i = 0; i < zip.length; i++) {
+          var ch = zip.charAt(i);
+          if (ch < "0" || ch > "9") {
+              zipGood = false;
+              r = zip + " contains letters.";
+              addResult(r);
+          }
+      }
+      if (zipGood && zip.length>5)
+      {
+         zipGood = false;
+         r = zip + " is longer than five characters.";
+         addResult(r);
+      }
+      if (zipGood)
+      {
+         r = zip + " appears to be a valid ZIP code.";
+         addResult(r);
+      }
+   }
+}
+
+function makeName(n)
+{
+   var tmp = "";
+   for (var i=0;i<n;i++)
+   {
+      var l = Math.floor(26*Math.random());
+      tmp += letters[l];
+   }
+   return tmp;
+}
+
+function makeNumber(n)
+{
+   var tmp = "";
+   for (var i=0;i<n;i++)
+   {
+      var l = Math.floor(9*Math.random());
+      tmp = tmp.concat(l);
+   }
+   return tmp;
+}
+
+function addResult(r)
+{
+   endResult += "\n" + r;
+}
+
+doTest();
+
+
+var _sunSpiderInterval = new Date() - _sunSpiderStartDate;
+
+document.getElementById("console").innerHTML = _sunSpiderInterval;
+</script>
+
+
+</body>
+</html>
diff --git a/src/third_party/mozjs-45/build/pgo/js-input/valid-xhtml10.png b/src/third_party/mozjs-45/build/pgo/js-input/valid-xhtml10.png
new file mode 100644
index 0000000..2275ee6
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/js-input/valid-xhtml10.png
Binary files differ
diff --git a/src/third_party/mozjs-45/build/pgo/profileserver.py b/src/third_party/mozjs-45/build/pgo/profileserver.py
new file mode 100644
index 0000000..473f707
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/profileserver.py
@@ -0,0 +1,80 @@
+#!/usr/bin/python
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+from mozprofile import FirefoxProfile, Profile, Preferences
+from mozprofile.permissions import ServerLocations
+from mozrunner import FirefoxRunner, CLI
+from mozhttpd import MozHttpd
+import json
+import socket
+import threading
+import os
+import sys
+import shutil
+import tempfile
+from datetime import datetime
+from mozbuild.base import MozbuildObject
+from buildconfig import substs
+
+PORT = 8888
+
+if __name__ == '__main__':
+  cli = CLI()
+  debug_args, interactive = cli.debugger_arguments()
+
+  build = MozbuildObject.from_environment()
+  httpd = MozHttpd(port=PORT,
+                   docroot=os.path.join(build.topsrcdir, "build", "pgo"))
+  httpd.start(block=False)
+
+  locations = ServerLocations()
+  locations.add_host(host='127.0.0.1',
+                     port=PORT,
+                     options='primary,privileged')
+
+  #TODO: mozfile.TemporaryDirectory
+  profilePath = tempfile.mkdtemp()
+  try:
+    #TODO: refactor this into mozprofile
+    prefpath = os.path.join(build.topsrcdir, "testing", "profiles", "prefs_general.js")
+    prefs = {}
+    prefs.update(Preferences.read_prefs(prefpath))
+    interpolation = { "server": "%s:%d" % httpd.httpd.server_address,
+                      "OOP": "false"}
+    prefs = json.loads(json.dumps(prefs) % interpolation)
+    for pref in prefs:
+      prefs[pref] = Preferences.cast(prefs[pref])
+    profile = FirefoxProfile(profile=profilePath,
+                             preferences=prefs,
+                             addons=[os.path.join(build.distdir, 'xpi-stage', 'quitter')],
+                             locations=locations)
+
+    env = os.environ.copy()
+    env["MOZ_CRASHREPORTER_NO_REPORT"] = "1"
+    env["XPCOM_DEBUG_BREAK"] = "warn"
+
+    # For VC12, make sure we can find the right bitness of pgort120.dll
+    if "VS120COMNTOOLS" in env and not substs["HAVE_64BIT_BUILD"]:
+      vc12dir = os.path.abspath(os.path.join(env["VS120COMNTOOLS"],
+                                             "../../VC/bin"))
+      if os.path.exists(vc12dir):
+        env["PATH"] = vc12dir + ";" + env["PATH"]
+
+    jarlog = os.getenv("JARLOG_FILE")
+    if jarlog:
+      env["MOZ_JAR_LOG_FILE"] = os.path.abspath(jarlog)
+      print "jarlog: %s" % env["MOZ_JAR_LOG_FILE"]
+
+    cmdargs = ["http://localhost:%d/index.html" % PORT]
+    runner = FirefoxRunner(profile=profile,
+                           binary=build.get_binary_path(where="staged-package"),
+                           cmdargs=cmdargs,
+                           env=env)
+    runner.start(debug_args=debug_args, interactive=interactive)
+    runner.wait()
+    httpd.stop()
+  finally:
+    shutil.rmtree(profilePath)
diff --git a/src/third_party/mozjs-45/build/pgo/server-locations.txt b/src/third_party/mozjs-45/build/pgo/server-locations.txt
new file mode 100644
index 0000000..9151151
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pgo/server-locations.txt
@@ -0,0 +1,260 @@
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#
+# This file defines the locations at which this HTTP server may be accessed.
+# It is referred to by the following page, so if this file moves, that page must
+# be modified accordingly:
+#
+# https://developer.mozilla.org/en/docs/Mochitest#How_do_I_test_issues_which_only_show_up_when_tests_are_run_across_domains.3F
+#
+# Empty lines and lines which begin with "#" are ignored and may be used for
+# storing comments.  All other lines consist of an origin followed by whitespace
+# and a comma-separated list of options (if indeed any options are needed).
+#
+# The format of an origin is, referring to RFC 2396, a scheme (either "http" or
+# "https"), followed by "://", followed by a host, followed by ":", followed by
+# a port number.  The colon and port number must be present even if the port
+# number is the default for the protocol.
+#
+# Unrecognized options are ignored.  Recognized options are "primary" and
+# "privileged", "nocert", "cert=some_cert_nickname", "redir=hostname" and
+# "failHandshake".
+#
+# "primary" denotes a location which is the canonical location of
+# the server; this location is the one assumed for requests which don't
+# otherwise identify a particular origin (e.g. HTTP/1.0 requests).  
+#
+# "privileged" denotes a location which should have the ability to request 
+# elevated privileges; the default is no privileges.
+#
+# "nocert" makes sense only for https:// hosts and means there is not
+# any certificate automatically generated for this host.
+#
+# "failHandshake" causes the tls handshake to fail (by sending a client hello to
+# the client).
+#
+# "cert=nickname" tells the pgo server to use a particular certificate
+# for this host. The certificate is referenced by its nickname that must
+# not contain any spaces. The certificate  key files (PKCS12 modules)
+# for custom certification are loaded from build/pgo/certs
+# directory. When new certificate is added to this dir pgo/ssltunnel
+# must be built then. This is only necessary for cases where we really do
+# want specific certs.
+#
+# "redir=hostname" tells the pgo server is only used for https://
+# hosts while processing the CONNECT tunnel request. It responds
+# to the CONNECT with a 302 and redirection to the hostname instead
+# of connecting to the real back end and replying with a 200. This
+# mode exists primarily to ensure we don't allow a proxy to do that.
+#
+
+#
+# This is the primary location from which tests run.
+#
+http://mochi.test:8888   primary,privileged
+
+#
+# These are a common set of prefixes scattered across one TLD with two ports and
+# another TLD on a single port.
+#
+http://127.0.0.1:80               privileged
+http://127.0.0.1:8888             privileged
+http://test:80                    privileged
+http://mochi.test:8888            privileged
+http://test1.mochi.test:8888
+http://sub1.test1.mochi.test:8888
+http://sub2.xn--lt-uia.mochi.test:8888
+http://test2.mochi.test:8888
+http://example.org:80                privileged
+http://test1.example.org:80          privileged
+http://test2.example.org:80          privileged
+http://sub1.test1.example.org:80     privileged
+http://sub1.test2.example.org:80     privileged
+http://sub2.test1.example.org:80     privileged
+http://sub2.test2.example.org:80     privileged
+http://example.org:8000              privileged
+http://test1.example.org:8000        privileged
+http://test2.example.org:8000        privileged
+http://sub1.test1.example.org:8000   privileged
+http://sub1.test2.example.org:8000   privileged
+http://sub2.test1.example.org:8000   privileged
+http://sub2.test2.example.org:8000   privileged
+http://example.com:80                privileged
+http://www.example.com:80            privileged
+http://test1.example.com:80          privileged
+http://test2.example.com:80          privileged
+http://sub1.test1.example.com:80     privileged
+http://sub1.test2.example.com:80     privileged
+http://sub2.test1.example.com:80     privileged
+http://sub2.test2.example.com:80     privileged
+http://noxul.example.com:80          privileged,noxul
+http://example.net:80                privileged
+# Used to test that clearing Service Workers for domain example.com, does not clear prefixexample.com
+http://prefixexample.com:80
+
+# The first HTTPS location is used to generate the Common Name (CN) value of the
+# certificate's Issued To field.
+https://example.com:443                privileged
+https://test1.example.com:443          privileged
+https://test2.example.com:443          privileged
+https://example.org:443                privileged
+https://test1.example.org:443          privileged
+https://test2.example.org:443          privileged
+https://sub1.test1.example.com:443     privileged
+https://sub1.test2.example.com:443     privileged
+https://sub2.test1.example.com:443     privileged
+https://sub2.test2.example.com:443     privileged
+https://nocert.example.com:443         privileged,nocert
+https://self-signed.example.com:443    privileged,cert=selfsigned
+https://untrusted.example.com:443      privileged,cert=untrusted
+https://expired.example.com:443        privileged,cert=expired
+https://requestclientcert.example.com:443         privileged,clientauth=request
+https://requireclientcert.example.com:443         privileged,clientauth=require
+https://mismatch.expired.example.com:443	privileged,cert=expired
+https://mismatch.untrusted.example.com:443	privileged,cert=untrusted
+https://untrusted-expired.example.com:443	privileged,cert=untrustedandexpired
+https://mismatch.untrusted-expired.example.com:443	privileged,cert=untrustedandexpired
+
+# This is here so that we don't load the default live bookmark over
+# the network in every test suite.
+http://fxfeeds.mozilla.com:80
+
+# Prevent safebrowsing tests from hitting the network for its-a-trap.html and
+# its-an-attack.html.
+http://www.itisatrap.org:80
+
+#
+# These are subdomains of <ält.example.org>.
+#
+http://sub1.xn--lt-uia.example.org:8000   privileged
+http://sub2.xn--lt-uia.example.org:80     privileged
+http://xn--exmple-cua.test:80             privileged
+http://sub1.xn--exmple-cua.test:80        privileged
+http://xn--exaple-kqf.test:80             privileged
+http://sub1.xn--exaple-kqf.test:80        privileged
+
+https://xn--hxajbheg2az3al.xn--jxalpdlp:443        privileged
+https://sub1.xn--hxajbheg2az3al.xn--jxalpdlp:443   privileged
+
+#
+# These are subdomains of <παράδειγμα.δοκιμή>, the Greek IDN for example.test.
+#
+http://xn--hxajbheg2az3al.xn--jxalpdlp:80        privileged
+http://sub1.xn--hxajbheg2az3al.xn--jxalpdlp:80   privileged
+
+# Bug 413909 test host
+https://bug413909.xn--hxajbheg2az3al.xn--jxalpdlp:443   privileged,cert=bug413909cert
+
+#
+# These hosts are used in tests which exercise privilege-granting functionality;
+# we could reuse some of the names above, but specific names make it easier to
+# distinguish one from the other in tests (as well as what functionality is
+# being tested).
+#
+http://sectest1.example.org:80       privileged
+http://sub.sectest2.example.org:80   privileged
+http://sectest2.example.org:80
+http://sub.sectest1.example.org:80
+
+https://sectest1.example.org:443       privileged
+https://sub.sectest2.example.org:443   privileged
+https://sectest2.example.org:443
+https://sub.sectest1.example.org:443
+
+#
+# Used while testing the url-classifier
+#
+http://malware.example.com:80
+http://tracking.example.com:80
+http://not-tracking.example.com:80
+http://tracking.example.org:80
+http://itisatracker.org:80
+http://trackertest.org:80
+
+https://malware.example.com:443
+https://tracking.example.com:443
+https://not-tracking.example.com:443
+https://tracking.example.org:443
+
+# Bug 483437, 484111
+https://www.bank1.com:443           privileged,cert=escapeattack1
+
+#
+# CONNECT for redirproxy results in a 302 redirect to
+# test1.example.com
+#
+https://redirproxy.example.com:443          privileged,redir=test1.example.com
+
+# Host used for IndexedDB Quota testing
+http://bug704464-1.example.com:80        privileged
+http://bug704464-2.example.com:80        privileged
+http://bug704464-3.example.com:80        privileged
+http://bug702292.example.com:80          privileged
+
+# W3C hosts.
+# See http://www.w3.org/wiki/Testing/Requirements#The_Web_test_server_must_be_available_through_different_domain_names
+http://w3c-test.org:80
+http://w3c-test.org:81
+http://w3c-test.org:82
+http://w3c-test.org:83
+http://www.w3c-test.org:80
+http://www.w3c-test.org:81
+http://www.w3c-test.org:82
+http://www.w3c-test.org:83
+http://www1.w3c-test.org:80
+http://www1.w3c-test.org:81
+http://www1.w3c-test.org:82
+http://www1.w3c-test.org:83
+http://www2.w3c-test.org:80
+http://www2.w3c-test.org:81
+http://www2.w3c-test.org:82
+http://www2.w3c-test.org:83
+# http://天気の良い日.w3c-test.org
+http://xn--n8j6ds53lwwkrqhv28a.w3c-test.org:80
+http://xn--n8j6ds53lwwkrqhv28a.w3c-test.org:81
+http://xn--n8j6ds53lwwkrqhv28a.w3c-test.org:82
+http://xn--n8j6ds53lwwkrqhv28a.w3c-test.org:83
+# http://élève.w3c-test.org
+http://xn--lve-6lad.w3c-test.org:80
+http://xn--lve-6lad.w3c-test.org:81
+http://xn--lve-6lad.w3c-test.org:82
+http://xn--lve-6lad.w3c-test.org:83
+# HTTPS versions of the above
+https://w3c-test.org:443
+https://www.w3c-test.org:443
+https://www1.w3c-test.org:443
+https://www2.w3c-test.org:443
+https://xn--n8j6ds53lwwkrqhv28a.w3c-test.org:443
+https://xn--lve-6lad.w3c-test.org:443
+http://test.w3.org:80
+
+# Hosts for testing TLD-based fallback encoding
+http://example.tw:80                privileged
+http://example.cn:80                privileged
+http://example.co.jp:80             privileged
+http://example.fi:80                privileged
+
+# Hosts for testing marketplace apps installations
+https://marketplace.firefox.com:443       privileged
+https://marketplace-dev.allizom.org:443   privileged
+https://marketplace.allizom.org:443       privileged
+
+# Host for HPKP
+https://include-subdomains.pinning-dynamic.example.com:443        privileged,cert=dynamicPinningGood
+https://bad.include-subdomains.pinning-dynamic.example.com:443    privileged,cert=dynamicPinningBad
+
+# Host for static pin tests
+https://badchain.include-subdomains.pinning.example.com:443       privileged,cert=staticPinningBad
+https://fail-handshake.example.com:443                            privileged,failHandshake
+
+# Hosts for sha1 console warning tests
+https://sha1ee.example.com:443                                    privileged,cert=sha1_end_entity
+https://sha256ee.example.com:443                                  privileged,cert=sha256_end_entity
+
+# Hosts for ssl3/rc4 console warning tests
+https://ssl3.example.com:443        privileged,ssl3
+https://rc4.example.com:443         privileged,rc4
+https://ssl3rc4.example.com:443     privileged,ssl3,rc4
diff --git a/src/third_party/mozjs-45/build/pymake/LICENSE b/src/third_party/mozjs-45/build/pymake/LICENSE
new file mode 100644
index 0000000..04a7d64
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/LICENSE
@@ -0,0 +1,21 @@
+The MIT License
+
+Copyright (c) 2009 The Mozilla Foundation <http://www.mozilla.org/>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/src/third_party/mozjs-45/build/pymake/README b/src/third_party/mozjs-45/build/pymake/README
new file mode 100644
index 0000000..4f0fdfe
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/README
@@ -0,0 +1,64 @@
+INTRODUCTION
+
+make.py (and the pymake modules that support it) are an implementation of the make tool
+which are mostly compatible with makefiles written for GNU make.
+
+PURPOSE
+
+The Mozilla project inspired this tool with several goals:
+
+* Improve build speeds, especially on Windows. This can be done by reducing the total number
+  of processes that are launched, especially MSYS shell processes which are expensive.
+
+* Allow writing some complicated build logic directly in Python instead of in shell.
+
+* Allow computing dependencies for special targets, such as members within ZIP files.
+
+* Enable experiments with build system. By writing a makefile parser, we can experiment
+  with converting in-tree makefiles to another build system, such as SCons, waf, ant, ...insert
+  your favorite build tool here. Or we could experiment along the lines of makepp, keeping
+  our existing makefiles, but change the engine to build a global dependency graph.
+
+KNOWN INCOMPATIBILITIES
+
+* Order-only prerequisites are not yet supported
+
+* Secondary expansion is not yet supported.
+
+* Target-specific variables behave differently than in GNU make: in pymake, the target-specific
+  variable only applies to the specific target that is mentioned, and does not apply recursively
+  to all dependencies which are remade. This is an intentional change: the behavior of GNU make
+  is neither deterministic nor intuitive.
+
+* $(eval) is only supported during the parse phase. Any attempt to recursively expand
+  an $(eval) function during command execution will fail. This is an intentional incompatibility.
+
+* There is a subtle difference in execution order that can cause unexpected changes in the
+  following circumstance:
+** A file `foo.c` exists on the VPATH
+** A rule for `foo.c` exists with a dependency on `tool` and no commands
+** `tool` is remade for some other reason earlier in the file
+  In this case, pymake resets the VPATH of `foo.c`, while GNU make does not. This shouldn't
+  happen in the real world, since a target found on the VPATH without commands is silly. But
+  mozilla/js/src happens to have a rule, which I'm patching.
+
+* pymake does not implement any of the builtin implicit rules or the related variables. Mozilla
+  only cares because pymake doesn't implicitly define $(RM), which I'm also fixing in the Mozilla
+  code.
+
+ISSUES
+
+* Speed is a problem.
+
+FUTURE WORK
+
+* implement a new type of command which is implemented in python. This would allow us
+to replace the current `nsinstall` binary (and execution costs for the shell and binary) with an
+in-process python solution.
+
+AUTHOR
+
+Initial code was written by Benjamin Smedberg <benjamin@smedbergs.us>. For future releases see
+http://benjamin.smedbergs.us/pymake/
+
+See the LICENSE file for license information (MIT license)
diff --git a/src/third_party/mozjs-45/build/pymake/make.py b/src/third_party/mozjs-45/build/pymake/make.py
new file mode 100755
index 0000000..0857f3f
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/make.py
@@ -0,0 +1,35 @@
+#!/usr/bin/env python
+
+"""
+make.py
+
+A drop-in or mostly drop-in replacement for GNU make.
+"""
+
+import sys, os
+import pymake.command, pymake.process
+
+import gc
+
+if __name__ == '__main__':
+  if 'TINDERBOX_OUTPUT' in os.environ:
+    # When building on mozilla build slaves, execute mozmake instead. Until bug
+    # 978211, this is the easiest, albeit hackish, way to do this.
+    import subprocess
+    mozmake = os.path.join(os.path.dirname(__file__), '..', '..',
+        'mozmake.exe')
+    cmd = [mozmake]
+    cmd.extend(sys.argv[1:])
+    shell = os.environ.get('SHELL')
+    if shell and not shell.lower().endswith('.exe'):
+        cmd += ['SHELL=%s.exe' % shell]
+    sys.exit(subprocess.call(cmd))
+
+  sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
+  sys.stderr = os.fdopen(sys.stderr.fileno(), 'w', 0)
+
+  gc.disable()
+
+  pymake.command.main(sys.argv[1:], os.environ, os.getcwd(), cb=sys.exit)
+  pymake.process.ParallelContext.spin()
+  assert False, "Not reached"
diff --git a/src/third_party/mozjs-45/build/pymake/mkformat.py b/src/third_party/mozjs-45/build/pymake/mkformat.py
new file mode 100755
index 0000000..41dd761
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/mkformat.py
@@ -0,0 +1,13 @@
+#!/usr/bin/env python
+
+import sys
+import pymake.parser
+
+filename = sys.argv[1]
+source = None
+
+with open(filename, 'rU') as fh:
+    source = fh.read()
+
+statements = pymake.parser.parsestring(source, filename)
+print statements.to_source()
diff --git a/src/third_party/mozjs-45/build/pymake/mkparse.py b/src/third_party/mozjs-45/build/pymake/mkparse.py
new file mode 100755
index 0000000..2536839
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/mkparse.py
@@ -0,0 +1,12 @@
+#!/usr/bin/env python
+
+import sys
+import pymake.parser
+
+for f in sys.argv[1:]:
+    print "Parsing %s" % f
+    fd = open(f, 'rU')
+    s = fd.read()
+    fd.close()
+    stmts = pymake.parser.parsestring(s, f)
+    print stmts
diff --git a/src/third_party/mozjs-45/build/pymake/pymake/__init__.py b/src/third_party/mozjs-45/build/pymake/pymake/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/pymake/__init__.py
diff --git a/src/third_party/mozjs-45/build/pymake/pymake/builtins.py b/src/third_party/mozjs-45/build/pymake/pymake/builtins.py
new file mode 100644
index 0000000..eb6f2e1
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/pymake/builtins.py
@@ -0,0 +1,120 @@
+# Basic commands implemented in Python
+import errno, sys, os, shutil, time
+from getopt import getopt, GetoptError
+
+from process import PythonException
+
+__all__ = ["mkdir", "rm", "sleep", "touch"]
+
+def mkdir(args):
+  """
+  Emulate some of the behavior of mkdir(1).
+  Only supports the -p (--parents) argument.
+  """
+  try:
+    opts, args = getopt(args, "p", ["parents"])
+  except GetoptError, e:
+    raise PythonException, ("mkdir: %s" % e, 1)
+  parents = False
+  for o, a in opts:
+    if o in ('-p', '--parents'):
+      parents = True
+  for f in args:
+    try:
+      if parents:
+        os.makedirs(f)
+      else:
+        os.mkdir(f)
+    except OSError, e:
+      if e.errno == errno.EEXIST and parents:
+        pass
+      else:
+        raise PythonException, ("mkdir: %s" % e, 1)
+
+def rm(args):
+  """
+  Emulate most of the behavior of rm(1).
+  Only supports the -r (--recursive) and -f (--force) arguments.
+  """
+  try:
+    opts, args = getopt(args, "rRf", ["force", "recursive"])
+  except GetoptError, e:
+    raise PythonException, ("rm: %s" % e, 1)
+  force = False
+  recursive = False
+  for o, a in opts:
+    if o in ('-f', '--force'):
+      force = True
+    elif o in ('-r', '-R', '--recursive'):
+      recursive = True
+  for f in args:
+    if os.path.isdir(f):
+      if not recursive:
+        raise PythonException, ("rm: cannot remove '%s': Is a directory" % f, 1)
+      else:
+        shutil.rmtree(f, force)
+    elif os.path.exists(f):
+      try:
+        os.unlink(f)
+      except:
+        if not force:
+          raise PythonException, ("rm: failed to remove '%s': %s" % (f, sys.exc_info()[0]), 1)
+    elif not force:
+      raise PythonException, ("rm: cannot remove '%s': No such file or directory" % f, 1)
+
+def sleep(args):
+    """
+    Emulate the behavior of sleep(1).
+    """
+    total = 0
+    values = {'s': 1, 'm': 60, 'h': 3600, 'd': 86400}
+    for a in args:
+        multiplier = 1
+        for k, v in values.iteritems():
+            if a.endswith(k):
+                a = a[:-1]
+                multiplier = v
+                break
+        try:
+            f = float(a)
+            total += f * multiplier
+        except ValueError:
+            raise PythonException, ("sleep: invalid time interval '%s'" % a, 1)
+    time.sleep(total)
+
+def touch(args):
+    """
+    Emulate the behavior of touch(1).
+    """
+    try:
+        opts, args = getopt(args, "t:")
+    except GetoptError, e:
+        raise PythonException, ("touch: %s" % e, 1)
+    opts = dict(opts)
+    times = None
+    if '-t' in opts:
+        import re
+        from time import mktime, localtime
+        m = re.match('^(?P<Y>(?:\d\d)?\d\d)?(?P<M>\d\d)(?P<D>\d\d)(?P<h>\d\d)(?P<m>\d\d)(?:\.(?P<s>\d\d))?$', opts['-t'])
+        if not m:
+            raise PythonException, ("touch: invalid date format '%s'" % opts['-t'], 1)
+        def normalized_field(m, f):
+            if f == 'Y':
+                if m.group(f) is None:
+                    return localtime()[0]
+                y = int(m.group(f))
+                if y < 69:
+                    y += 2000
+                elif y < 100:
+                    y += 1900
+                return y
+            if m.group(f) is None:
+                return localtime()[0] if f == 'Y' else 0
+            return int(m.group(f))
+        time = [normalized_field(m, f) for f in ['Y', 'M', 'D', 'h', 'm', 's']] + [0, 0, -1]
+        time = mktime(time)
+        times = (time, time)
+    for f in args:
+        if not os.path.exists(f):
+            open(f, 'a').close()
+        os.utime(f, times)
diff --git a/src/third_party/mozjs-45/build/pymake/pymake/command.py b/src/third_party/mozjs-45/build/pymake/pymake/command.py
new file mode 100644
index 0000000..cd68e4f
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/pymake/command.py
@@ -0,0 +1,278 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+"""
+Makefile execution.
+
+Multiple `makes` can be run within the same process. Each one has an entirely data.Makefile and .Target
+structure, environment, and working directory. Typically they will all share a parallel execution context,
+except when a submake specifies -j1 when the parent make is building in parallel.
+"""
+
+import os, subprocess, sys, logging, time, traceback, re
+from optparse import OptionParser
+import data, parserdata, process, util
+
+# TODO: If this ever goes from relocatable package to system-installed, this may need to be
+# a configured-in path.
+
+makepypath = util.normaljoin(os.path.dirname(__file__), '../make.py')
+
+_simpleopts = re.compile(r'^[a-zA-Z]+(\s|$)')
+def parsemakeflags(env):
+    """
+    Parse MAKEFLAGS from the environment into a sequence of command-line arguments.
+    """
+
+    makeflags = env.get('MAKEFLAGS', '')
+    makeflags = makeflags.strip()
+
+    if makeflags == '':
+        return []
+
+    if _simpleopts.match(makeflags):
+        makeflags = '-' + makeflags
+
+    opts = []
+    curopt = ''
+
+    i = 0
+    while i < len(makeflags):
+        c = makeflags[i]
+        if c.isspace():
+            opts.append(curopt)
+            curopt = ''
+            i += 1
+            while i < len(makeflags) and makeflags[i].isspace():
+                i += 1
+            continue
+
+        if c == '\\':
+            i += 1
+            if i == len(makeflags):
+                raise data.DataError("MAKEFLAGS has trailing backslash")
+            c = makeflags[i]
+            
+        curopt += c
+        i += 1
+
+    if curopt != '':
+        opts.append(curopt)
+
+    return opts
+
+def _version(*args):
+    print """pymake: GNU-compatible make program
+Copyright (C) 2009 The Mozilla Foundation <http://www.mozilla.org/>
+This is free software; see the source for copying conditions.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE."""
+
+_log = logging.getLogger('pymake.execution')
+
+class _MakeContext(object):
+    def __init__(self, makeflags, makelevel, workdir, context, env, targets, options, ostmts, overrides, cb):
+        self.makeflags = makeflags
+        self.makelevel = makelevel
+
+        self.workdir = workdir
+        self.context = context
+        self.env = env
+        self.targets = targets
+        self.options = options
+        self.ostmts = ostmts
+        self.overrides = overrides
+        self.cb = cb
+
+        self.restarts = 0
+
+        self.remakecb(True)
+
+    def remakecb(self, remade, error=None):
+        if error is not None:
+            print error
+            self.context.defer(self.cb, 2)
+            return
+
+        if remade:
+            if self.restarts > 0:
+                _log.info("make.py[%i]: Restarting makefile parsing", self.makelevel)
+
+            self.makefile = data.Makefile(restarts=self.restarts,
+                                          make='%s %s' % (sys.executable.replace('\\', '/'), makepypath.replace('\\', '/')),
+                                          makeflags=self.makeflags,
+                                          makeoverrides=self.overrides,
+                                          workdir=self.workdir,
+                                          context=self.context,
+                                          env=self.env,
+                                          makelevel=self.makelevel,
+                                          targets=self.targets,
+                                          keepgoing=self.options.keepgoing,
+                                          silent=self.options.silent,
+                                          justprint=self.options.justprint)
+
+            self.restarts += 1
+
+            try:
+                self.ostmts.execute(self.makefile)
+                for f in self.options.makefiles:
+                    self.makefile.include(f)
+                self.makefile.finishparsing()
+                self.makefile.remakemakefiles(self.remakecb)
+            except util.MakeError, e:
+                print e
+                self.context.defer(self.cb, 2)
+
+            return
+
+        if len(self.targets) == 0:
+            if self.makefile.defaulttarget is None:
+                print "No target specified and no default target found."
+                self.context.defer(self.cb, 2)
+                return
+
+            _log.info("Making default target %s", self.makefile.defaulttarget)
+            self.realtargets = [self.makefile.defaulttarget]
+            self.tstack = ['<default-target>']
+        else:
+            self.realtargets = self.targets
+            self.tstack = ['<command-line>']
+
+        self.makefile.gettarget(self.realtargets.pop(0)).make(self.makefile, self.tstack, cb=self.makecb)
+
+    def makecb(self, error, didanything):
+        assert error in (True, False)
+
+        if error:
+            self.context.defer(self.cb, 2)
+            return
+
+        if not len(self.realtargets):
+            if self.options.printdir:
+                print "make.py[%i]: Leaving directory '%s'" % (self.makelevel, self.workdir)
+            sys.stdout.flush()
+
+            self.context.defer(self.cb, 0)
+        else:
+            self.makefile.gettarget(self.realtargets.pop(0)).make(self.makefile, self.tstack, self.makecb)
+
+def main(args, env, cwd, cb):
+    """
+    Start a single makefile execution, given a command line, working directory, and environment.
+
+    @param cb a callback to notify with an exit code when make execution is finished.
+    """
+
+    try:
+        makelevel = int(env.get('MAKELEVEL', '0'))
+
+        op = OptionParser()
+        op.add_option('-f', '--file', '--makefile',
+                      action='append',
+                      dest='makefiles',
+                      default=[])
+        op.add_option('-d',
+                      action="store_true",
+                      dest="verbose", default=False)
+        op.add_option('-k', '--keep-going',
+                      action="store_true",
+                      dest="keepgoing", default=False)
+        op.add_option('--debug-log',
+                      dest="debuglog", default=None)
+        op.add_option('-C', '--directory',
+                      dest="directory", default=None)
+        op.add_option('-v', '--version', action="store_true",
+                      dest="printversion", default=False)
+        op.add_option('-j', '--jobs', type="int",
+                      dest="jobcount", default=1)
+        op.add_option('-w', '--print-directory', action="store_true",
+                      dest="printdir")
+        op.add_option('--no-print-directory', action="store_false",
+                      dest="printdir", default=True)
+        op.add_option('-s', '--silent', action="store_true",
+                      dest="silent", default=False)
+        op.add_option('-n', '--just-print', '--dry-run', '--recon',
+                      action="store_true",
+                      dest="justprint", default=False)
+
+        options, arguments1 = op.parse_args(parsemakeflags(env))
+        options, arguments2 = op.parse_args(args, values=options)
+
+        op.destroy()
+
+        arguments = arguments1 + arguments2
+
+        if options.printversion:
+            _version()
+            cb(0)
+            return
+
+        shortflags = []
+        longflags = []
+
+        if options.keepgoing:
+            shortflags.append('k')
+
+        if options.printdir:
+            shortflags.append('w')
+
+        if options.silent:
+            shortflags.append('s')
+            options.printdir = False
+
+        if options.justprint:
+            shortflags.append('n')
+
+        loglevel = logging.WARNING
+        if options.verbose:
+            loglevel = logging.DEBUG
+            shortflags.append('d')
+
+        logkwargs = {}
+        if options.debuglog:
+            logkwargs['filename'] = options.debuglog
+            longflags.append('--debug-log=%s' % options.debuglog)
+
+        if options.directory is None:
+            workdir = cwd
+        else:
+            workdir = util.normaljoin(cwd, options.directory)
+
+        if options.jobcount != 1:
+            longflags.append('-j%i' % (options.jobcount,))
+
+        makeflags = ''.join(shortflags)
+        if len(longflags):
+            makeflags += ' ' + ' '.join(longflags)
+
+        logging.basicConfig(level=loglevel, **logkwargs)
+
+        context = process.getcontext(options.jobcount)
+
+        if options.printdir:
+            print "make.py[%i]: Entering directory '%s'" % (makelevel, workdir)
+            sys.stdout.flush()
+
+        if len(options.makefiles) == 0:
+            if os.path.exists(util.normaljoin(workdir, 'Makefile')):
+                options.makefiles.append('Makefile')
+            else:
+                print "No makefile found"
+                cb(2)
+                return
+
+        ostmts, targets, overrides = parserdata.parsecommandlineargs(arguments)
+
+        _MakeContext(makeflags, makelevel, workdir, context, env, targets, options, ostmts, overrides, cb)
+    except (util.MakeError), e:
+        print e
+        if options.printdir:
+            print "make.py[%i]: Leaving directory '%s'" % (makelevel, workdir)
+        sys.stdout.flush()
+        cb(2)
+        return
diff --git a/src/third_party/mozjs-45/build/pymake/pymake/data.py b/src/third_party/mozjs-45/build/pymake/pymake/data.py
new file mode 100644
index 0000000..dcd7e92
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/pymake/data.py
@@ -0,0 +1,1842 @@
+"""
+A representation of makefile data structures.
+"""
+
+import logging, re, os, sys
+import parserdata, parser, functions, process, util, implicit
+from cStringIO import StringIO
+
+if sys.version_info[0] < 3:
+    str_type = basestring
+else:
+    str_type = str
+
+_log = logging.getLogger('pymake.data')
+
+class DataError(util.MakeError):
+    pass
+
+class ResolutionError(DataError):
+    """
+    Raised when dependency resolution fails, either due to recursion or to missing
+    prerequisites.This is separately catchable so that implicit rule search can try things
+    without having to commit.
+    """
+    pass
+
+def withoutdups(it):
+    r = set()
+    for i in it:
+        if not i in r:
+            r.add(i)
+            yield i
+
+def mtimeislater(deptime, targettime):
+    """
+    Is the mtime of the dependency later than the target?
+    """
+
+    if deptime is None:
+        return True
+    if targettime is None:
+        return False
+    # int(1000*x) because of http://bugs.python.org/issue10148
+    return int(1000 * deptime) > int(1000 * targettime)
+
+def getmtime(path):
+    try:
+        s = os.stat(path)
+        return s.st_mtime
+    except OSError:
+        return None
+
+def stripdotslash(s):
+    if s.startswith('./'):
+        st = s[2:]
+        return st if st != '' else '.'
+    return s
+
+def stripdotslashes(sl):
+    for s in sl:
+        yield stripdotslash(s)
+
+def getindent(stack):
+    return ''.ljust(len(stack) - 1)
+
+def _if_else(c, t, f):
+    if c:
+        return t()
+    return f()
+
+
+class BaseExpansion(object):
+    """Base class for expansions.
+
+    A make expansion is the parsed representation of a string, which may
+    contain references to other elements.
+    """
+
+    @property
+    def is_static_string(self):
+        """Returns whether the expansion is composed of static string content.
+
+        This is always True for StringExpansion. It will be True for Expansion
+        only if all elements of that Expansion are static strings.
+        """
+        raise Exception('Must be implemented in child class.')
+
+    def functions(self, descend=False):
+        """Obtain all functions inside this expansion.
+
+        This is a generator for pymake.functions.Function instances.
+
+        By default, this only returns functions existing as the primary
+        elements of this expansion. If `descend` is True, it will descend into
+        child expansions and extract all functions in the tree.
+        """
+        # An empty generator. Yeah, it's weird.
+        for x in []:
+            yield x
+
+    def variable_references(self, descend=False):
+        """Obtain all variable references in this expansion.
+
+        This is a generator for pymake.functionsVariableRef instances.
+
+        To retrieve the names of variables, simply query the `vname` field on
+        the returned instances. Most of the time these will be StringExpansion
+        instances.
+        """
+        for f in self.functions(descend=descend):
+            if not isinstance(f, functions.VariableRef):
+                continue
+
+            yield f
+
+    @property
+    def is_filesystem_dependent(self):
+        """Whether this expansion may query the filesystem for evaluation.
+
+        This effectively asks "is any function in this expansion dependent on
+        the filesystem.
+        """
+        for f in self.functions(descend=True):
+            if f.is_filesystem_dependent:
+                return True
+
+        return False
+
+    @property
+    def is_shell_dependent(self):
+        """Whether this expansion may invoke a shell for evaluation."""
+
+        for f in self.functions(descend=True):
+            if isinstance(f, functions.ShellFunction):
+                return True
+
+        return False
+
+
+class StringExpansion(BaseExpansion):
+    """An Expansion representing a static string.
+
+    This essentially wraps a single str instance.
+    """
+
+    __slots__ = ('loc', 's',)
+    simple = True
+
+    def __init__(self, s, loc):
+        assert isinstance(s, str_type)
+        self.s = s
+        self.loc = loc
+
+    def lstrip(self):
+        self.s = self.s.lstrip()
+
+    def rstrip(self):
+        self.s = self.s.rstrip()
+
+    def isempty(self):
+        return self.s == ''
+
+    def resolve(self, i, j, fd, k=None):
+        fd.write(self.s)
+
+    def resolvestr(self, i, j, k=None):
+        return self.s
+
+    def resolvesplit(self, i, j, k=None):
+        return self.s.split()
+
+    def clone(self):
+        e = Expansion(self.loc)
+        e.appendstr(self.s)
+        return e
+
+    @property
+    def is_static_string(self):
+        return True
+
+    def __len__(self):
+        return 1
+
+    def __getitem__(self, i):
+        assert i == 0
+        return self.s, False
+
+    def __repr__(self):
+        return "Exp<%s>(%r)" % (self.loc, self.s)
+
+    def __eq__(self, other):
+        """We only compare the string contents."""
+        return self.s == other
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def to_source(self, escape_variables=False, escape_comments=False):
+        s = self.s
+
+        if escape_comments:
+            s = s.replace('#', '\\#')
+
+        if escape_variables:
+            return s.replace('$', '$$')
+
+        return s
+
+
+class Expansion(BaseExpansion, list):
+    """A representation of expanded data.
+
+    This is effectively an ordered list of StringExpansion and
+    pymake.function.Function instances. Every item in the collection appears in
+    the same context in a make file.
+    """
+
+    __slots__ = ('loc',)
+    simple = False
+
+    def __init__(self, loc=None):
+        # A list of (element, isfunc) tuples
+        # element is either a string or a function
+        self.loc = loc
+
+    @staticmethod
+    def fromstring(s, path):
+        return StringExpansion(s, parserdata.Location(path, 1, 0))
+
+    def clone(self):
+        e = Expansion()
+        e.extend(self)
+        return e
+
+    def appendstr(self, s):
+        assert isinstance(s, str_type)
+        if s == '':
+            return
+
+        self.append((s, False))
+
+    def appendfunc(self, func):
+        assert isinstance(func, functions.Function)
+        self.append((func, True))
+
+    def concat(self, o):
+        """Concatenate the other expansion on to this one."""
+        if o.simple:
+            self.appendstr(o.s)
+        else:
+            self.extend(o)
+
+    def isempty(self):
+        return (not len(self)) or self[0] == ('', False)
+
+    def lstrip(self):
+        """Strip leading literal whitespace from this expansion."""
+        while True:
+            i, isfunc = self[0]
+            if isfunc:
+                return
+
+            i = i.lstrip()
+            if i != '':
+                self[0] = i, False
+                return
+
+            del self[0]
+
+    def rstrip(self):
+        """Strip trailing literal whitespace from this expansion."""
+        while True:
+            i, isfunc = self[-1]
+            if isfunc:
+                return
+
+            i = i.rstrip()
+            if i != '':
+                self[-1] = i, False
+                return
+
+            del self[-1]
+
+    def finish(self):
+        # Merge any adjacent literal strings:
+        strings = []
+        elements = []
+        for (e, isfunc) in self:
+            if isfunc:
+                if strings:
+                    s = ''.join(strings)
+                    if s:
+                        elements.append((s, False))
+                    strings = []
+                elements.append((e, True))
+            else:
+                strings.append(e)
+
+        if not elements:
+            # This can only happen if there were no function elements.
+            return StringExpansion(''.join(strings), self.loc)
+
+        if strings:
+            s = ''.join(strings)
+            if s:
+                elements.append((s, False))
+
+        if len(elements) < len(self):
+            self[:] = elements
+
+        return self
+
+    def resolve(self, makefile, variables, fd, setting=[]):
+        """
+        Resolve this variable into a value, by interpolating the value
+        of other variables.
+
+        @param setting (Variable instance) the variable currently
+               being set, if any. Setting variables must avoid self-referential
+               loops.
+        """
+        assert isinstance(makefile, Makefile)
+        assert isinstance(variables, Variables)
+        assert isinstance(setting, list)
+
+        for e, isfunc in self:
+            if isfunc:
+                e.resolve(makefile, variables, fd, setting)
+            else:
+                assert isinstance(e, str_type)
+                fd.write(e)
+
+    def resolvestr(self, makefile, variables, setting=[]):
+        fd = StringIO()
+        self.resolve(makefile, variables, fd, setting)
+        return fd.getvalue()
+
+    def resolvesplit(self, makefile, variables, setting=[]):
+        return self.resolvestr(makefile, variables, setting).split()
+
+    @property
+    def is_static_string(self):
+        """An Expansion is static if all its components are strings, not
+        functions."""
+        for e, is_func in self:
+            if is_func:
+                return False
+
+        return True
+
+    def functions(self, descend=False):
+        for e, is_func in self:
+            if is_func:
+                yield e
+
+            if descend:
+                for exp in e.expansions(descend=True):
+                    for f in exp.functions(descend=True):
+                        yield f
+
+    def __repr__(self):
+        return "<Expansion with elements: %r>" % ([e for e, isfunc in self],)
+
+    def to_source(self, escape_variables=False, escape_comments=False):
+        parts = []
+        for e, is_func in self:
+            if is_func:
+                parts.append(e.to_source())
+                continue
+
+            if escape_variables:
+                parts.append(e.replace('$', '$$'))
+                continue
+
+            parts.append(e)
+
+        return ''.join(parts)
+
+    def __eq__(self, other):
+        if not isinstance(other, (Expansion, StringExpansion)):
+            return False
+
+        # Expansions are equivalent if adjacent string literals normalize to
+        # the same value. So, we must normalize before any comparisons are
+        # made.
+        a = self.clone().finish()
+
+        if isinstance(other, StringExpansion):
+            if isinstance(a, StringExpansion):
+                return a == other
+
+            # A normalized Expansion != StringExpansion.
+            return False
+
+        b = other.clone().finish()
+
+        # b could be a StringExpansion now.
+        if isinstance(b, StringExpansion):
+            if isinstance(a, StringExpansion):
+                return a == b
+
+            # Our normalized Expansion != normalized StringExpansion.
+            return False
+
+        if len(a) != len(b):
+            return False
+
+        for i in xrange(len(self)):
+            e1, is_func1 = a[i]
+            e2, is_func2 = b[i]
+
+            if is_func1 != is_func2:
+                return False
+
+            if type(e1) != type(e2):
+                return False
+
+            if e1 != e2:
+                return False
+
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+class Variables(object):
+    """
+    A mapping from variable names to variables. Variables have flavor, source, and value. The value is an 
+    expansion object.
+    """
+
+    __slots__ = ('parent', '_map')
+
+    FLAVOR_RECURSIVE = 0
+    FLAVOR_SIMPLE = 1
+    FLAVOR_APPEND = 2
+
+    SOURCE_OVERRIDE = 0
+    SOURCE_COMMANDLINE = 1
+    SOURCE_MAKEFILE = 2
+    SOURCE_ENVIRONMENT = 3
+    SOURCE_AUTOMATIC = 4
+    SOURCE_IMPLICIT = 5
+
+    def __init__(self, parent=None):
+        self._map = {} # vname -> flavor, source, valuestr, valueexp
+        self.parent = parent
+
+    def readfromenvironment(self, env):
+        for k, v in env.iteritems():
+            self.set(k, self.FLAVOR_RECURSIVE, self.SOURCE_ENVIRONMENT, v)
+
+    def get(self, name, expand=True):
+        """
+        Get the value of a named variable. Returns a tuple (flavor, source, value)
+
+        If the variable is not present, returns (None, None, None)
+
+        @param expand If true, the value will be returned as an expansion. If false,
+        it will be returned as an unexpanded string.
+        """
+        flavor, source, valuestr, valueexp = self._map.get(name, (None, None, None, None))
+        if flavor is not None:
+            if expand and flavor != self.FLAVOR_SIMPLE and valueexp is None:
+                d = parser.Data.fromstring(valuestr, parserdata.Location("Expansion of variables '%s'" % (name,), 1, 0))
+                valueexp, t, o = parser.parsemakesyntax(d, 0, (), parser.iterdata)
+                self._map[name] = flavor, source, valuestr, valueexp
+
+            if flavor == self.FLAVOR_APPEND:
+                if self.parent:
+                    pflavor, psource, pvalue = self.parent.get(name, expand)
+                else:
+                    pflavor, psource, pvalue = None, None, None
+
+                if pvalue is None:
+                    flavor = self.FLAVOR_RECURSIVE
+                    # fall through
+                else:
+                    if source > psource:
+                        # TODO: log a warning?
+                        return pflavor, psource, pvalue
+
+                    if not expand:
+                        return pflavor, psource, pvalue + ' ' + valuestr
+
+                    pvalue = pvalue.clone()
+                    pvalue.appendstr(' ')
+                    pvalue.concat(valueexp)
+
+                    return pflavor, psource, pvalue
+                    
+            if not expand:
+                return flavor, source, valuestr
+
+            if flavor == self.FLAVOR_RECURSIVE:
+                val = valueexp
+            else:
+                val = Expansion.fromstring(valuestr, "Expansion of variable '%s'" % (name,))
+
+            return flavor, source, val
+
+        if self.parent is not None:
+            return self.parent.get(name, expand)
+
+        return (None, None, None)
+
+    def set(self, name, flavor, source, value, force=False):
+        assert flavor in (self.FLAVOR_RECURSIVE, self.FLAVOR_SIMPLE)
+        assert source in (self.SOURCE_OVERRIDE, self.SOURCE_COMMANDLINE, self.SOURCE_MAKEFILE, self.SOURCE_ENVIRONMENT, self.SOURCE_AUTOMATIC, self.SOURCE_IMPLICIT)
+        assert isinstance(value, str_type), "expected str, got %s" % type(value)
+
+        prevflavor, prevsource, prevvalue = self.get(name)
+        if prevsource is not None and source > prevsource and not force:
+            # TODO: give a location for this warning
+            _log.info("not setting variable '%s', set by higher-priority source to value '%s'" % (name, prevvalue))
+            return
+
+        self._map[name] = flavor, source, value, None
+
+    def append(self, name, source, value, variables, makefile):
+        assert source in (self.SOURCE_OVERRIDE, self.SOURCE_MAKEFILE, self.SOURCE_AUTOMATIC)
+        assert isinstance(value, str_type)
+
+        if name not in self._map:
+            self._map[name] = self.FLAVOR_APPEND, source, value, None
+            return
+
+        prevflavor, prevsource, prevvalue, valueexp = self._map[name]
+        if source > prevsource:
+            # TODO: log a warning?
+            return
+
+        if prevflavor == self.FLAVOR_SIMPLE:
+            d = parser.Data.fromstring(value, parserdata.Location("Expansion of variables '%s'" % (name,), 1, 0))
+            valueexp, t, o = parser.parsemakesyntax(d, 0, (), parser.iterdata)
+
+            val = valueexp.resolvestr(makefile, variables, [name])
+            self._map[name] = prevflavor, prevsource, prevvalue + ' ' + val, None
+            return
+
+        newvalue = prevvalue + ' ' + value
+        self._map[name] = prevflavor, prevsource, newvalue, None
+
+    def merge(self, other):
+        assert isinstance(other, Variables)
+        for k, flavor, source, value in other:
+            self.set(k, flavor, source, value)
+
+    def __iter__(self):
+        for k, (flavor, source, value, valueexp) in self._map.iteritems():
+            yield k, flavor, source, value
+
+    def __contains__(self, item):
+        return item in self._map
+
+class Pattern(object):
+    """
+    A pattern is a string, possibly with a % substitution character. From the GNU make manual:
+
+    '%' characters in pattern rules can be quoted with precending backslashes ('\'). Backslashes that
+    would otherwise quote '%' charcters can be quoted with more backslashes. Backslashes that
+    quote '%' characters or other backslashes are removed from the pattern before it is compared t
+    file names or has a stem substituted into it. Backslashes that are not in danger of quoting '%'
+    characters go unmolested. For example, the pattern the\%weird\\%pattern\\ has `the%weird\' preceding
+    the operative '%' character, and 'pattern\\' following it. The final two backslashes are left alone
+    because they cannot affect any '%' character.
+
+    This insane behavior probably doesn't matter, but we're compatible just for shits and giggles.
+    """
+
+    __slots__ = ('data')
+
+    def __init__(self, s):
+        r = []
+        i = 0
+        slen = len(s)
+        while i < slen:
+            c = s[i]
+            if c == '\\':
+                nc = s[i + 1]
+                if nc == '%':
+                    r.append('%')
+                    i += 1
+                elif nc == '\\':
+                    r.append('\\')
+                    i += 1
+                else:
+                    r.append(c)
+            elif c == '%':
+                self.data = (''.join(r), s[i+1:])
+                return
+            else:
+                r.append(c)
+            i += 1
+
+        # This is different than (s,) because \% and \\ have been unescaped. Parsing patterns is
+        # context-sensitive!
+        self.data = (''.join(r),)
+
+    def ismatchany(self):
+        return self.data == ('','')
+
+    def ispattern(self):
+        return len(self.data) == 2
+
+    def __hash__(self):
+        return self.data.__hash__()
+
+    def __eq__(self, o):
+        assert isinstance(o, Pattern)
+        return self.data == o.data
+
+    def gettarget(self):
+        assert not self.ispattern()
+        return self.data[0]
+
+    def hasslash(self):
+        return self.data[0].find('/') != -1 or self.data[1].find('/') != -1
+
+    def match(self, word):
+        """
+        Match this search pattern against a word (string).
+
+        @returns None if the word doesn't match, or the matching stem.
+                      If this is a %-less pattern, the stem will always be ''
+        """
+        d = self.data
+        if len(d) == 1:
+            if word == d[0]:
+                return word
+            return None
+
+        d0, d1 = d
+        l1 = len(d0)
+        l2 = len(d1)
+        if len(word) >= l1 + l2 and word.startswith(d0) and word.endswith(d1):
+            if l2 == 0:
+                return word[l1:]
+            return word[l1:-l2]
+
+        return None
+
+    def resolve(self, dir, stem):
+        if self.ispattern():
+            return dir + self.data[0] + stem + self.data[1]
+
+        return self.data[0]
+
+    def subst(self, replacement, word, mustmatch):
+        """
+        Given a word, replace the current pattern with the replacement pattern, a la 'patsubst'
+
+        @param mustmatch If true and this pattern doesn't match the word, throw a DataError. Otherwise
+                         return word unchanged.
+        """
+        assert isinstance(replacement, str_type)
+
+        stem = self.match(word)
+        if stem is None:
+            if mustmatch:
+                raise DataError("target '%s' doesn't match pattern" % (word,))
+            return word
+
+        if not self.ispattern():
+            # if we're not a pattern, the replacement is not parsed as a pattern either
+            return replacement
+
+        return Pattern(replacement).resolve('', stem)
+
+    def __repr__(self):
+        return "<Pattern with data %r>" % (self.data,)
+
+    _backre = re.compile(r'[%\\]')
+    def __str__(self):
+        if not self.ispattern():
+            return self._backre.sub(r'\\\1', self.data[0])
+
+        return self._backre.sub(r'\\\1', self.data[0]) + '%' + self.data[1]
+
+class RemakeTargetSerially(object):
+    __slots__ = ('target', 'makefile', 'indent', 'rlist')
+
+    def __init__(self, target, makefile, indent, rlist):
+        self.target = target
+        self.makefile = makefile
+        self.indent = indent
+        self.rlist = rlist
+        self.commandscb(False)
+
+    def resolvecb(self, error, didanything):
+        assert error in (True, False)
+
+        if didanything:
+            self.target.didanything = True
+
+        if error:
+            self.target.error = True
+            self.makefile.error = True
+            if not self.makefile.keepgoing:
+                self.target.notifydone(self.makefile)
+                return
+            else:
+                # don't run the commands!
+                del self.rlist[0]
+                self.commandscb(error=False)
+        else:
+            self.rlist.pop(0).runcommands(self.indent, self.commandscb)
+
+    def commandscb(self, error):
+        assert error in (True, False)
+
+        if error:
+            self.target.error = True
+            self.makefile.error = True
+
+        if self.target.error and not self.makefile.keepgoing:
+            self.target.notifydone(self.makefile)
+            return
+
+        if not len(self.rlist):
+            self.target.notifydone(self.makefile)
+        else:
+            self.rlist[0].resolvedeps(True, self.resolvecb)
+
+class RemakeTargetParallel(object):
+    __slots__ = ('target', 'makefile', 'indent', 'rlist', 'rulesremaining', 'currunning')
+
+    def __init__(self, target, makefile, indent, rlist):
+        self.target = target
+        self.makefile = makefile
+        self.indent = indent
+        self.rlist = rlist
+
+        self.rulesremaining = len(rlist)
+        self.currunning = False
+
+        for r in rlist:
+            makefile.context.defer(self.doresolve, r)
+
+    def doresolve(self, r):
+        if self.makefile.error and not self.makefile.keepgoing:
+            r.error = True
+            self.resolvecb(True, False)
+        else:
+            r.resolvedeps(False, self.resolvecb)
+
+    def resolvecb(self, error, didanything):
+        assert error in (True, False)
+
+        if error:
+            self.target.error = True
+
+        if didanything:
+            self.target.didanything = True
+
+        self.rulesremaining -= 1
+
+        # commandscb takes care of the details if we're currently building
+        # something
+        if self.currunning:
+            return
+
+        self.runnext()
+
+    def runnext(self):
+        assert not self.currunning
+
+        if self.makefile.error and not self.makefile.keepgoing:
+            self.rlist = []
+        else:
+            while len(self.rlist) and self.rlist[0].error:
+                del self.rlist[0]
+
+        if not len(self.rlist):
+            if not self.rulesremaining:
+                self.target.notifydone(self.makefile)
+            return
+
+        if self.rlist[0].depsremaining != 0:
+            return
+
+        self.currunning = True
+        rule = self.rlist.pop(0)
+        self.makefile.context.defer(rule.runcommands, self.indent, self.commandscb)
+
+    def commandscb(self, error):
+        assert error in (True, False)
+        if error:
+            self.target.error = True
+            self.makefile.error = True
+
+        assert self.currunning
+        self.currunning = False
+        self.runnext()
+
+class RemakeRuleContext(object):
+    def __init__(self, target, makefile, rule, deps,
+                 targetstack, avoidremakeloop):
+        self.target = target
+        self.makefile = makefile
+        self.rule = rule
+        self.deps = deps
+        self.targetstack = targetstack
+        self.avoidremakeloop = avoidremakeloop
+
+        self.running = False
+        self.error = False
+        self.depsremaining = len(deps) + 1
+        self.remake = False
+
+    def resolvedeps(self, serial, cb):
+        self.resolvecb = cb
+        self.didanything = False
+        if serial:
+            self._resolvedepsserial()
+        else:
+            self._resolvedepsparallel()
+
+    def _weakdepfinishedserial(self, error, didanything):
+        if error:
+            self.remake = True
+        self._depfinishedserial(False, didanything)
+
+    def _depfinishedserial(self, error, didanything):
+        assert error in (True, False)
+
+        if didanything:
+            self.didanything = True
+
+        if error:
+            self.error = True
+            if not self.makefile.keepgoing:
+                self.resolvecb(error=True, didanything=self.didanything)
+                return
+        
+        if len(self.resolvelist):
+            dep, weak = self.resolvelist.pop(0)
+            self.makefile.context.defer(dep.make,
+                                        self.makefile, self.targetstack, weak and self._weakdepfinishedserial or self._depfinishedserial)
+        else:
+            self.resolvecb(error=self.error, didanything=self.didanything)
+
+    def _resolvedepsserial(self):
+        self.resolvelist = list(self.deps)
+        self._depfinishedserial(False, False)
+
+    def _startdepparallel(self, d):
+        dep, weak = d
+        if weak:
+            depfinished = self._weakdepfinishedparallel
+        else:
+            depfinished = self._depfinishedparallel
+        if self.makefile.error:
+            depfinished(True, False)
+        else:
+            dep.make(self.makefile, self.targetstack, depfinished)
+
+    def _weakdepfinishedparallel(self, error, didanything):
+        if error:
+            self.remake = True
+        self._depfinishedparallel(False, didanything)
+
+    def _depfinishedparallel(self, error, didanything):
+        assert error in (True, False)
+
+        if error:
+            print "<%s>: Found error" % self.target.target
+            self.error = True
+        if didanything:
+            self.didanything = True
+
+        self.depsremaining -= 1
+        if self.depsremaining == 0:
+            self.resolvecb(error=self.error, didanything=self.didanything)
+
+    def _resolvedepsparallel(self):
+        self.depsremaining -= 1
+        if self.depsremaining == 0:
+            self.resolvecb(error=self.error, didanything=self.didanything)
+            return
+
+        self.didanything = False
+
+        for d in self.deps:
+            self.makefile.context.defer(self._startdepparallel, d)
+
+    def _commandcb(self, error):
+        assert error in (True, False)
+
+        if error:
+            self.runcb(error=True)
+            return
+
+        if len(self.commands):
+            self.commands.pop(0)(self._commandcb)
+        else:
+            self.runcb(error=False)
+
+    def runcommands(self, indent, cb):
+        assert not self.running
+        self.running = True
+
+        self.runcb = cb
+
+        if self.rule is None or not len(self.rule.commands):
+            if self.target.mtime is None:
+                self.target.beingremade()
+            else:
+                for d, weak in self.deps:
+                    if mtimeislater(d.mtime, self.target.mtime):
+                        if d.mtime is None:
+                            self.target.beingremade()
+                        else:
+                            _log.info("%sNot remaking %s ubecause it would have no effect, even though %s is newer.", indent, self.target.target, d.target)
+                        break
+            cb(error=False)
+            return
+
+        if self.rule.doublecolon:
+            if len(self.deps) == 0:
+                if self.avoidremakeloop:
+                    _log.info("%sNot remaking %s using rule at %s because it would introduce an infinite loop.", indent, self.target.target, self.rule.loc)
+                    cb(error=False)
+                    return
+
+        remake = self.remake
+        if remake:
+            _log.info("%sRemaking %s using rule at %s: weak dependency was not found.", indent, self.target.target, self.rule.loc)
+        else:
+            if self.target.mtime is None:
+                remake = True
+                _log.info("%sRemaking %s using rule at %s: target doesn't exist or is a forced target", indent, self.target.target, self.rule.loc)
+
+        if not remake:
+            if self.rule.doublecolon:
+                if len(self.deps) == 0:
+                    _log.info("%sRemaking %s using rule at %s because there are no prerequisites listed for a double-colon rule.", indent, self.target.target, self.rule.loc)
+                    remake = True
+
+        if not remake:
+            for d, weak in self.deps:
+                if mtimeislater(d.mtime, self.target.mtime):
+                    _log.info("%sRemaking %s using rule at %s because %s is newer.", indent, self.target.target, self.rule.loc, d.target)
+                    remake = True
+                    break
+
+        if remake:
+            self.target.beingremade()
+            self.target.didanything = True
+            try:
+                self.commands = [c for c in self.rule.getcommands(self.target, self.makefile)]
+            except util.MakeError, e:
+                print e
+                sys.stdout.flush()
+                cb(error=True)
+                return
+
+            self._commandcb(False)
+        else:
+            cb(error=False)
+
+MAKESTATE_NONE = 0
+MAKESTATE_FINISHED = 1
+MAKESTATE_WORKING = 2
+
+class Target(object):
+    """
+    An actual (non-pattern) target.
+
+    It holds target-specific variables and a list of rules. It may also point to a parent
+    PatternTarget, if this target is being created by an implicit rule.
+
+    The rules associated with this target may be Rule instances or, in the case of static pattern
+    rules, PatternRule instances.
+    """
+
+    wasremade = False
+
+    def __init__(self, target, makefile):
+        assert isinstance(target, str_type)
+        self.target = target
+        self.vpathtarget = None
+        self.rules = []
+        self.variables = Variables(makefile.variables)
+        self.explicit = False
+        self._state = MAKESTATE_NONE
+
+    def addrule(self, rule):
+        assert isinstance(rule, (Rule, PatternRuleInstance))
+        if len(self.rules) and rule.doublecolon != self.rules[0].doublecolon:
+            raise DataError("Cannot have single- and double-colon rules for the same target. Prior rule location: %s" % self.rules[0].loc, rule.loc)
+
+        if isinstance(rule, PatternRuleInstance):
+            if len(rule.prule.targetpatterns) != 1:
+                raise DataError("Static pattern rules must only have one target pattern", rule.prule.loc)
+            if rule.prule.targetpatterns[0].match(self.target) is None:
+                raise DataError("Static pattern rule doesn't match target '%s'" % self.target, rule.loc)
+
+        self.rules.append(rule)
+
+    def isdoublecolon(self):
+        return self.rules[0].doublecolon
+
+    def isphony(self, makefile):
+        """Is this a phony target? We don't check for existence of phony targets."""
+        return makefile.gettarget('.PHONY').hasdependency(self.target)
+
+    def hasdependency(self, t):
+        for rule in self.rules:
+            if t in rule.prerequisites:
+                return True
+
+        return False
+
+    def resolveimplicitrule(self, makefile, targetstack, rulestack):
+        """
+        Try to resolve an implicit rule to build this target.
+        """
+        # The steps in the GNU make manual Implicit-Rule-Search.html are very detailed. I hope they can be trusted.
+
+        indent = getindent(targetstack)
+
+        _log.info("%sSearching for implicit rule to make '%s'", indent, self.target)
+
+        dir, s, file = util.strrpartition(self.target, '/')
+        dir = dir + s
+
+        candidates = [] # list of PatternRuleInstance
+
+        hasmatch = util.any((r.hasspecificmatch(file) for r in makefile.implicitrules))
+
+        for r in makefile.implicitrules:
+            if r in rulestack:
+                _log.info("%s %s: Avoiding implicit rule recursion", indent, r.loc)
+                continue
+
+            if not len(r.commands):
+                continue
+
+            for ri in r.matchesfor(dir, file, hasmatch):
+                candidates.append(ri)
+            
+        newcandidates = []
+
+        for r in candidates:
+            depfailed = None
+            for p in r.prerequisites:
+                t = makefile.gettarget(p)
+                t.resolvevpath(makefile)
+                if not t.explicit and t.mtime is None:
+                    depfailed = p
+                    break
+
+            if depfailed is not None:
+                if r.doublecolon:
+                    _log.info("%s Terminal rule at %s doesn't match: prerequisite '%s' not mentioned and doesn't exist.", indent, r.loc, depfailed)
+                else:
+                    newcandidates.append(r)
+                continue
+
+            _log.info("%sFound implicit rule at %s for target '%s'", indent, r.loc, self.target)
+            self.rules.append(r)
+            return
+
+        # Try again, but this time with chaining and without terminal (double-colon) rules
+
+        for r in newcandidates:
+            newrulestack = rulestack + [r.prule]
+
+            depfailed = None
+            for p in r.prerequisites:
+                t = makefile.gettarget(p)
+                try:
+                    t.resolvedeps(makefile, targetstack, newrulestack, True)
+                except ResolutionError:
+                    depfailed = p
+                    break
+
+            if depfailed is not None:
+                _log.info("%s Rule at %s doesn't match: prerequisite '%s' could not be made.", indent, r.loc, depfailed)
+                continue
+
+            _log.info("%sFound implicit rule at %s for target '%s'", indent, r.loc, self.target)
+            self.rules.append(r)
+            return
+
+        _log.info("%sCouldn't find implicit rule to remake '%s'", indent, self.target)
+
+    def ruleswithcommands(self):
+        "The number of rules with commands"
+        return reduce(lambda i, rule: i + (len(rule.commands) > 0), self.rules, 0)
+
+    def resolvedeps(self, makefile, targetstack, rulestack, recursive):
+        """
+        Resolve the actual path of this target, using vpath if necessary.
+
+        Recursively resolve dependencies of this target. This means finding implicit
+        rules which match the target, if appropriate.
+
+        Figure out whether this target needs to be rebuild, and set self.outofdate
+        appropriately.
+
+        @param targetstack is the current stack of dependencies being resolved. If
+               this target is already in targetstack, bail to prevent infinite
+               recursion.
+        @param rulestack is the current stack of implicit rules being used to resolve
+               dependencies. A rule chain cannot use the same implicit rule twice.
+        """
+        assert makefile.parsingfinished
+
+        if self.target in targetstack:
+            raise ResolutionError("Recursive dependency: %s -> %s" % (
+                    " -> ".join(targetstack), self.target))
+
+        targetstack = targetstack + [self.target]
+        
+        indent = getindent(targetstack)
+
+        _log.info("%sConsidering target '%s'", indent, self.target)
+
+        self.resolvevpath(makefile)
+
+        # Sanity-check our rules. If we're single-colon, only one rule should have commands
+        ruleswithcommands = self.ruleswithcommands()
+        if len(self.rules) and not self.isdoublecolon():
+            if ruleswithcommands > 1:
+                # In GNU make this is a warning, not an error. I'm going to be stricter.
+                # TODO: provide locations
+                raise DataError("Target '%s' has multiple rules with commands." % self.target)
+
+        if ruleswithcommands == 0:
+            self.resolveimplicitrule(makefile, targetstack, rulestack)
+
+        # If a target is mentioned, but doesn't exist, has no commands and no
+        # prerequisites, it is special and exists just to say that targets which
+        # depend on it are always out of date. This is like .FORCE but more
+        # compatible with other makes.
+        # Otherwise, we don't know how to make it.
+        if not len(self.rules) and self.mtime is None and not util.any((len(rule.prerequisites) > 0
+                                                                        for rule in self.rules)):
+            raise ResolutionError("No rule to make target '%s' needed by %r" % (self.target,
+                                                                                targetstack))
+
+        if recursive:
+            for r in self.rules:
+                newrulestack = rulestack + [r]
+                for d in r.prerequisites:
+                    dt = makefile.gettarget(d)
+                    if dt.explicit:
+                        continue
+
+                    dt.resolvedeps(makefile, targetstack, newrulestack, True)
+
+        for v in makefile.getpatternvariablesfor(self.target):
+            self.variables.merge(v)
+
+    def resolvevpath(self, makefile):
+        if self.vpathtarget is not None:
+            return
+
+        if self.isphony(makefile):
+            self.vpathtarget = self.target
+            self.mtime = None
+            return
+
+        if self.target.startswith('-l'):
+            stem = self.target[2:]
+            f, s, e = makefile.variables.get('.LIBPATTERNS')
+            if e is not None:
+                libpatterns = [Pattern(stripdotslash(s)) for s in e.resolvesplit(makefile, makefile.variables)]
+                if len(libpatterns):
+                    searchdirs = ['']
+                    searchdirs.extend(makefile.getvpath(self.target))
+
+                    for lp in libpatterns:
+                        if not lp.ispattern():
+                            raise DataError('.LIBPATTERNS contains a non-pattern')
+
+                        libname = lp.resolve('', stem)
+
+                        for dir in searchdirs:
+                            libpath = util.normaljoin(dir, libname).replace('\\', '/')
+                            fspath = util.normaljoin(makefile.workdir, libpath)
+                            mtime = getmtime(fspath)
+                            if mtime is not None:
+                                self.vpathtarget = libpath
+                                self.mtime = mtime
+                                return
+
+                    self.vpathtarget = self.target
+                    self.mtime = None
+                    return
+
+        search = [self.target]
+        if not os.path.isabs(self.target):
+            search += [util.normaljoin(dir, self.target).replace('\\', '/')
+                       for dir in makefile.getvpath(self.target)]
+
+        targetandtime = self.searchinlocs(makefile, search)
+        if targetandtime is not None:
+            (self.vpathtarget, self.mtime) = targetandtime
+            return
+
+        self.vpathtarget = self.target
+        self.mtime = None
+
+    def searchinlocs(self, makefile, locs):
+        """
+        Look in the given locations relative to the makefile working directory
+        for a file. Return a pair of the target and the mtime if found, None
+        if not.
+        """
+        for t in locs:
+            fspath = util.normaljoin(makefile.workdir, t).replace('\\', '/')
+            mtime = getmtime(fspath)
+#            _log.info("Searching %s ... checking %s ... mtime %r" % (t, fspath, mtime))
+            if mtime is not None:
+                return (t, mtime)
+
+        return None
+        
+    def beingremade(self):
+        """
+        When we remake ourself, we have to drop any vpath prefixes.
+        """
+        self.vpathtarget = self.target
+        self.wasremade = True
+
+    def notifydone(self, makefile):
+        assert self._state == MAKESTATE_WORKING, "State was %s" % self._state
+        # If we were remade then resolve mtime again
+        if self.wasremade:
+            targetandtime = self.searchinlocs(makefile, [self.target])
+            if targetandtime is not None:
+                (_, self.mtime) = targetandtime
+            else:
+                self.mtime = None
+
+        self._state = MAKESTATE_FINISHED
+        for cb in self._callbacks:
+            makefile.context.defer(cb, error=self.error, didanything=self.didanything)
+        del self._callbacks 
+
+    def make(self, makefile, targetstack, cb, avoidremakeloop=False, printerror=True):
+        """
+        If we are out of date, asynchronously make ourself. This is a multi-stage process, mostly handled
+        by the helper objects RemakeTargetSerially, RemakeTargetParallel,
+        RemakeRuleContext. These helper objects should keep us from developing
+        any cyclical dependencies.
+
+        * resolve dependencies (synchronous)
+        * gather a list of rules to execute and related dependencies (synchronous)
+        * for each rule (in parallel)
+        ** remake dependencies (asynchronous)
+        ** build list of commands to execute (synchronous)
+        ** execute each command (asynchronous)
+        * asynchronously notify when all rules are complete
+
+        @param cb A callback function to notify when remaking is finished. It is called
+               thusly: callback(error=True/False, didanything=True/False)
+               If there is no asynchronous activity to perform, the callback may be called directly.
+        """
+
+        serial = makefile.context.jcount == 1
+        
+        if self._state == MAKESTATE_FINISHED:
+            cb(error=self.error, didanything=self.didanything)
+            return
+            
+        if self._state == MAKESTATE_WORKING:
+            assert not serial
+            self._callbacks.append(cb)
+            return
+
+        assert self._state == MAKESTATE_NONE
+
+        self._state = MAKESTATE_WORKING
+        self._callbacks = [cb]
+        self.error = False
+        self.didanything = False
+
+        indent = getindent(targetstack)
+
+        try:
+            self.resolvedeps(makefile, targetstack, [], False)
+        except util.MakeError, e:
+            if printerror:
+                print e
+            self.error = True
+            self.notifydone(makefile)
+            return
+
+        assert self.vpathtarget is not None, "Target was never resolved!"
+        if not len(self.rules):
+            self.notifydone(makefile)
+            return
+
+        if self.isdoublecolon():
+            rulelist = [RemakeRuleContext(self, makefile, r, [(makefile.gettarget(p), False) for p in r.prerequisites], targetstack, avoidremakeloop) for r in self.rules]
+        else:
+            alldeps = []
+
+            commandrule = None
+            for r in self.rules:
+                rdeps = [(makefile.gettarget(p), r.weakdeps) for p in r.prerequisites]
+                if len(r.commands):
+                    assert commandrule is None
+                    commandrule = r
+                    # The dependencies of the command rule are resolved before other dependencies,
+                    # no matter the ordering of the other no-command rules
+                    alldeps[0:0] = rdeps
+                else:
+                    alldeps.extend(rdeps)
+
+            rulelist = [RemakeRuleContext(self, makefile, commandrule, alldeps, targetstack, avoidremakeloop)]
+
+        targetstack = targetstack + [self.target]
+
+        if serial:
+            RemakeTargetSerially(self, makefile, indent, rulelist)
+        else:
+            RemakeTargetParallel(self, makefile, indent, rulelist)
+
+def dirpart(p):
+    d, s, f = util.strrpartition(p, '/')
+    if d == '':
+        return '.'
+
+    return d
+
+def filepart(p):
+    d, s, f = util.strrpartition(p, '/')
+    return f
+
+def setautomatic(v, name, plist):
+    v.set(name, Variables.FLAVOR_SIMPLE, Variables.SOURCE_AUTOMATIC, ' '.join(plist))
+    v.set(name + 'D', Variables.FLAVOR_SIMPLE, Variables.SOURCE_AUTOMATIC, ' '.join((dirpart(p) for p in plist)))
+    v.set(name + 'F', Variables.FLAVOR_SIMPLE, Variables.SOURCE_AUTOMATIC, ' '.join((filepart(p) for p in plist)))
+
+def setautomaticvariables(v, makefile, target, prerequisites):
+    prtargets = [makefile.gettarget(p) for p in prerequisites]
+    prall = [pt.vpathtarget for pt in prtargets]
+    proutofdate = [pt.vpathtarget for pt in withoutdups(prtargets)
+                   if target.mtime is None or mtimeislater(pt.mtime, target.mtime)]
+    
+    setautomatic(v, '@', [target.vpathtarget])
+    if len(prall):
+        setautomatic(v, '<', [prall[0]])
+
+    setautomatic(v, '?', proutofdate)
+    setautomatic(v, '^', list(withoutdups(prall)))
+    setautomatic(v, '+', prall)
+
+def splitcommand(command):
+    """
+    Using the esoteric rules, split command lines by unescaped newlines.
+    """
+    start = 0
+    i = 0
+    while i < len(command):
+        c = command[i]
+        if c == '\\':
+            i += 1
+        elif c == '\n':
+            yield command[start:i]
+            i += 1
+            start = i
+            continue
+
+        i += 1
+
+    if i > start:
+        yield command[start:i]
+
+def findmodifiers(command):
+    """
+    Find any of +-@% prefixed on the command.
+    @returns (command, isHidden, isRecursive, ignoreErrors, isNative)
+    """
+
+    isHidden = False
+    isRecursive = False
+    ignoreErrors = False
+    isNative = False
+
+    realcommand = command.lstrip(' \t\n@+-%')
+    modset = set(command[:-len(realcommand)])
+    return realcommand, '@' in modset, '+' in modset, '-' in modset, '%' in modset
+
+class _CommandWrapper(object):
+    def __init__(self, cline, ignoreErrors, loc, context, **kwargs):
+        self.ignoreErrors = ignoreErrors
+        self.loc = loc
+        self.cline = cline
+        self.kwargs = kwargs
+        self.context = context
+
+    def _cb(self, res):
+        if res != 0 and not self.ignoreErrors:
+            print "%s: command '%s' failed, return code %i" % (self.loc, self.cline, res)
+            self.usercb(error=True)
+        else:
+            self.usercb(error=False)
+
+    def __call__(self, cb):
+        self.usercb = cb
+        process.call(self.cline, loc=self.loc, cb=self._cb, context=self.context, **self.kwargs)
+
+class _NativeWrapper(_CommandWrapper):
+    def __init__(self, cline, ignoreErrors, loc, context,
+                 pycommandpath, **kwargs):
+        _CommandWrapper.__init__(self, cline, ignoreErrors, loc, context,
+                                 **kwargs)
+        if pycommandpath:
+            self.pycommandpath = re.split('[%s\s]+' % os.pathsep,
+                                          pycommandpath)
+        else:
+            self.pycommandpath = None
+
+    def __call__(self, cb):
+        # get the module and method to call
+        parts, badchar = process.clinetoargv(self.cline, self.kwargs['cwd'])
+        if parts is None:
+            raise DataError("native command '%s': shell metacharacter '%s' in command line" % (self.cline, badchar), self.loc)
+        if len(parts) < 2:
+            raise DataError("native command '%s': no method name specified" % self.cline, self.loc)
+        module = parts[0]
+        method = parts[1]
+        cline_list = parts[2:]
+        self.usercb = cb
+        process.call_native(module, method, cline_list,
+                            loc=self.loc, cb=self._cb, context=self.context,
+                            pycommandpath=self.pycommandpath, **self.kwargs)
+
+def getcommandsforrule(rule, target, makefile, prerequisites, stem):
+    v = Variables(parent=target.variables)
+    setautomaticvariables(v, makefile, target, prerequisites)
+    if stem is not None:
+        setautomatic(v, '*', [stem])
+
+    env = makefile.getsubenvironment(v)
+
+    for c in rule.commands:
+        cstring = c.resolvestr(makefile, v)
+        for cline in splitcommand(cstring):
+            cline, isHidden, isRecursive, ignoreErrors, isNative = findmodifiers(cline)
+            if (isHidden or makefile.silent) and not makefile.justprint:
+                echo = None
+            else:
+                echo = "%s$ %s" % (c.loc, cline)
+            if not isNative:
+                yield _CommandWrapper(cline, ignoreErrors=ignoreErrors, env=env, cwd=makefile.workdir, loc=c.loc, context=makefile.context,
+                                      echo=echo, justprint=makefile.justprint)
+            else:
+                f, s, e = v.get("PYCOMMANDPATH", True)
+                if e:
+                    e = e.resolvestr(makefile, v, ["PYCOMMANDPATH"])
+                yield _NativeWrapper(cline, ignoreErrors=ignoreErrors,
+                                     env=env, cwd=makefile.workdir,
+                                     loc=c.loc, context=makefile.context,
+                                     echo=echo, justprint=makefile.justprint,
+                                     pycommandpath=e)
+
+class Rule(object):
+    """
+    A rule contains a list of prerequisites and a list of commands. It may also
+    contain rule-specific variables. This rule may be associated with multiple targets.
+    """
+
+    def __init__(self, prereqs, doublecolon, loc, weakdeps):
+        self.prerequisites = prereqs
+        self.doublecolon = doublecolon
+        self.commands = []
+        self.loc = loc
+        self.weakdeps = weakdeps
+
+    def addcommand(self, c):
+        assert isinstance(c, (Expansion, StringExpansion))
+        self.commands.append(c)
+
+    def getcommands(self, target, makefile):
+        assert isinstance(target, Target)
+        # Prerequisites are merged if the target contains multiple rules and is
+        # not a terminal (double colon) rule. See
+        # https://www.gnu.org/software/make/manual/make.html#Multiple-Targets.
+        prereqs = []
+        prereqs.extend(self.prerequisites)
+
+        if not self.doublecolon:
+            for rule in target.rules:
+                # The current rule comes first, which is already in prereqs so
+                # we don't need to add it again.
+                if rule != self:
+                    prereqs.extend(rule.prerequisites)
+
+        return getcommandsforrule(self, target, makefile, prereqs, stem=None)
+        # TODO: $* in non-pattern rules?
+
+class PatternRuleInstance(object):
+    weakdeps = False
+
+    """
+    A pattern rule instantiated for a particular target. It has the same API as Rule, but
+    different internals, forwarding most information on to the PatternRule.
+    """
+    def __init__(self, prule, dir, stem, ismatchany):
+        assert isinstance(prule, PatternRule)
+
+        self.dir = dir
+        self.stem = stem
+        self.prule = prule
+        self.prerequisites = prule.prerequisitesforstem(dir, stem)
+        self.doublecolon = prule.doublecolon
+        self.loc = prule.loc
+        self.ismatchany = ismatchany
+        self.commands = prule.commands
+
+    def getcommands(self, target, makefile):
+        assert isinstance(target, Target)
+        return getcommandsforrule(self, target, makefile, self.prerequisites, stem=self.dir + self.stem)
+
+    def __str__(self):
+        return "Pattern rule at %s with stem '%s', matchany: %s doublecolon: %s" % (self.loc,
+                                                                                    self.dir + self.stem,
+                                                                                    self.ismatchany,
+                                                                                    self.doublecolon)
+
+class PatternRule(object):
+    """
+    An implicit rule or static pattern rule containing target patterns, prerequisite patterns,
+    and a list of commands.
+    """
+
+    def __init__(self, targetpatterns, prerequisites, doublecolon, loc):
+        self.targetpatterns = targetpatterns
+        self.prerequisites = prerequisites
+        self.doublecolon = doublecolon
+        self.loc = loc
+        self.commands = []
+
+    def addcommand(self, c):
+        assert isinstance(c, (Expansion, StringExpansion))
+        self.commands.append(c)
+
+    def ismatchany(self):
+        return util.any((t.ismatchany() for t in self.targetpatterns))
+
+    def hasspecificmatch(self, file):
+        for p in self.targetpatterns:
+            if not p.ismatchany() and p.match(file) is not None:
+                return True
+
+        return False
+
+    def matchesfor(self, dir, file, skipsinglecolonmatchany):
+        """
+        Determine all the target patterns of this rule that might match target t.
+        @yields a PatternRuleInstance for each.
+        """
+
+        for p in self.targetpatterns:
+            matchany = p.ismatchany()
+            if matchany:
+                if skipsinglecolonmatchany and not self.doublecolon:
+                    continue
+
+                yield PatternRuleInstance(self, dir, file, True)
+            else:
+                stem = p.match(dir + file)
+                if stem is not None:
+                    yield PatternRuleInstance(self, '', stem, False)
+                else:
+                    stem = p.match(file)
+                    if stem is not None:
+                        yield PatternRuleInstance(self, dir, stem, False)
+
+    def prerequisitesforstem(self, dir, stem):
+        return [p.resolve(dir, stem) for p in self.prerequisites]
+
+class _RemakeContext(object):
+    def __init__(self, makefile, cb):
+        self.makefile = makefile
+        self.included = [(makefile.gettarget(f), required)
+                         for f, required in makefile.included]
+        self.toremake = list(self.included)
+        self.cb = cb
+
+        self.remakecb(error=False, didanything=False)
+
+    def remakecb(self, error, didanything):
+        assert error in (True, False)
+
+        if error and self.required:
+            print "Error remaking makefiles (ignored)"
+
+        if len(self.toremake):
+            target, self.required = self.toremake.pop(0)
+            target.make(self.makefile, [], avoidremakeloop=True, cb=self.remakecb, printerror=False)
+        else:
+            for t, required in self.included:
+                if t.wasremade:
+                    _log.info("Included file %s was remade, restarting make", t.target)
+                    self.cb(remade=True)
+                    return
+                elif required and t.mtime is None:
+                    self.cb(remade=False, error=DataError("No rule to remake missing include file %s" % t.target))
+                    return
+
+            self.cb(remade=False)
+
+class Makefile(object):
+    """
+    The top-level data structure for makefile execution. It holds Targets, implicit rules, and other
+    state data.
+    """
+
+    def __init__(self, workdir=None, env=None, restarts=0, make=None,
+                 makeflags='', makeoverrides='',
+                 makelevel=0, context=None, targets=(), keepgoing=False,
+                 silent=False, justprint=False):
+        self.defaulttarget = None
+
+        if env is None:
+            env = os.environ
+        self.env = env
+
+        self.variables = Variables()
+        self.variables.readfromenvironment(env)
+
+        self.context = context
+        self.exportedvars = {}
+        self._targets = {}
+        self.keepgoing = keepgoing
+        self.silent = silent
+        self.justprint = justprint
+        self._patternvariables = [] # of (pattern, variables)
+        self.implicitrules = []
+        self.parsingfinished = False
+
+        self._patternvpaths = [] # of (pattern, [dir, ...])
+
+        if workdir is None:
+            workdir = os.getcwd()
+        workdir = os.path.realpath(workdir)
+        self.workdir = workdir
+        self.variables.set('CURDIR', Variables.FLAVOR_SIMPLE,
+                           Variables.SOURCE_AUTOMATIC, workdir.replace('\\','/'))
+
+        # the list of included makefiles, whether or not they existed
+        self.included = []
+
+        self.variables.set('MAKE_RESTARTS', Variables.FLAVOR_SIMPLE,
+                           Variables.SOURCE_AUTOMATIC, restarts > 0 and str(restarts) or '')
+
+        self.variables.set('.PYMAKE', Variables.FLAVOR_SIMPLE,
+                           Variables.SOURCE_MAKEFILE, "1")
+        if make is not None:
+            self.variables.set('MAKE', Variables.FLAVOR_SIMPLE,
+                               Variables.SOURCE_MAKEFILE, make)
+
+        if makeoverrides != '':
+            self.variables.set('-*-command-variables-*-', Variables.FLAVOR_SIMPLE,
+                               Variables.SOURCE_AUTOMATIC, makeoverrides)
+            makeflags += ' -- $(MAKEOVERRIDES)'
+
+        self.variables.set('MAKEOVERRIDES', Variables.FLAVOR_RECURSIVE,
+                           Variables.SOURCE_ENVIRONMENT,
+                           '${-*-command-variables-*-}')
+
+        self.variables.set('MAKEFLAGS', Variables.FLAVOR_RECURSIVE,
+                           Variables.SOURCE_MAKEFILE, makeflags)
+        self.exportedvars['MAKEFLAGS'] = True
+
+        self.makelevel = makelevel
+        self.variables.set('MAKELEVEL', Variables.FLAVOR_SIMPLE,
+                           Variables.SOURCE_MAKEFILE, str(makelevel))
+
+        self.variables.set('MAKECMDGOALS', Variables.FLAVOR_SIMPLE,
+                           Variables.SOURCE_AUTOMATIC, ' '.join(targets))
+
+        for vname, val in implicit.variables.iteritems():
+            self.variables.set(vname,
+                               Variables.FLAVOR_SIMPLE,
+                               Variables.SOURCE_IMPLICIT, val)
+
+    def foundtarget(self, t):
+        """
+        Inform the makefile of a target which is a candidate for being the default target,
+        if there isn't already a default target.
+        """
+        flavor, source, value = self.variables.get('.DEFAULT_GOAL')
+        if self.defaulttarget is None and t != '.PHONY' and value is None:
+            self.defaulttarget = t
+            self.variables.set('.DEFAULT_GOAL', Variables.FLAVOR_SIMPLE,
+                               Variables.SOURCE_AUTOMATIC, t)
+
+    def getpatternvariables(self, pattern):
+        assert isinstance(pattern, Pattern)
+
+        for p, v in self._patternvariables:
+            if p == pattern:
+                return v
+
+        v = Variables()
+        self._patternvariables.append( (pattern, v) )
+        return v
+
+    def getpatternvariablesfor(self, target):
+        for p, v in self._patternvariables:
+            if p.match(target):
+                yield v
+
+    def hastarget(self, target):
+        return target in self._targets
+
+    _globcheck = re.compile('[[*?]')
+    def gettarget(self, target):
+        assert isinstance(target, str_type)
+
+        target = target.rstrip('/')
+
+        assert target != '', "empty target?"
+
+        assert not self._globcheck.match(target)
+
+        t = self._targets.get(target, None)
+        if t is None:
+            t = Target(target, self)
+            self._targets[target] = t
+        return t
+
+    def appendimplicitrule(self, rule):
+        assert isinstance(rule, PatternRule)
+        self.implicitrules.append(rule)
+
+    def finishparsing(self):
+        """
+        Various activities, such as "eval", are not allowed after parsing is
+        finished. In addition, various warnings and errors can only be issued
+        after the parsing data model is complete. All dependency resolution
+        and rule execution requires that parsing be finished.
+        """
+        self.parsingfinished = True
+
+        flavor, source, value = self.variables.get('GPATH')
+        if value is not None and value.resolvestr(self, self.variables, ['GPATH']).strip() != '':
+            raise DataError('GPATH was set: pymake does not support GPATH semantics')
+
+        flavor, source, value = self.variables.get('VPATH')
+        if value is None:
+            self._vpath = []
+        else:
+            self._vpath = filter(lambda e: e != '',
+                                 re.split('[%s\s]+' % os.pathsep,
+                                          value.resolvestr(self, self.variables, ['VPATH'])))
+
+        targets = list(self._targets.itervalues())
+        for t in targets:
+            t.explicit = True
+            for r in t.rules:
+                for p in r.prerequisites:
+                    self.gettarget(p).explicit = True
+
+        np = self.gettarget('.NOTPARALLEL')
+        if len(np.rules):
+            self.context = process.getcontext(1)
+
+        flavor, source, value = self.variables.get('.DEFAULT_GOAL')
+        if value is not None:
+            self.defaulttarget = value.resolvestr(self, self.variables, ['.DEFAULT_GOAL']).strip()
+
+        self.error = False
+
+    def include(self, path, required=True, weak=False, loc=None):
+        """
+        Include the makefile at `path`.
+        """
+        self.included.append((path, required))
+        fspath = util.normaljoin(self.workdir, path)
+        if os.path.exists(fspath):
+            if weak:
+                stmts = parser.parsedepfile(fspath)
+            else:
+                stmts = parser.parsefile(fspath)
+            self.variables.append('MAKEFILE_LIST', Variables.SOURCE_AUTOMATIC, path, None, self)
+            stmts.execute(self, weak=weak)
+            self.gettarget(path).explicit = True
+
+    def addvpath(self, pattern, dirs):
+        """
+        Add a directory to the vpath search for the given pattern.
+        """
+        self._patternvpaths.append((pattern, dirs))
+
+    def clearvpath(self, pattern):
+        """
+        Clear vpaths for the given pattern.
+        """
+        self._patternvpaths = [(p, dirs)
+                               for p, dirs in self._patternvpaths
+                               if not p.match(pattern)]
+
+    def clearallvpaths(self):
+        self._patternvpaths = []
+
+    def getvpath(self, target):
+        vp = list(self._vpath)
+        for p, dirs in self._patternvpaths:
+            if p.match(target):
+                vp.extend(dirs)
+
+        return withoutdups(vp)
+
+    def remakemakefiles(self, cb):
+        mlist = []
+        for f, required in self.included:
+            t = self.gettarget(f)
+            t.explicit = True
+            t.resolvevpath(self)
+            oldmtime = t.mtime
+
+            mlist.append((t, oldmtime))
+
+        _RemakeContext(self, cb)
+
+    def getsubenvironment(self, variables):
+        env = dict(self.env)
+        for vname, v in self.exportedvars.iteritems():
+            if v:
+                flavor, source, val = variables.get(vname)
+                if val is None:
+                    strval = ''
+                else:
+                    strval = val.resolvestr(self, variables, [vname])
+                env[vname] = strval
+            else:
+                env.pop(vname, None)
+
+        makeflags = ''
+
+        env['MAKELEVEL'] = str(self.makelevel + 1)
+        return env
diff --git a/src/third_party/mozjs-45/build/pymake/pymake/functions.py b/src/third_party/mozjs-45/build/pymake/pymake/functions.py
new file mode 100644
index 0000000..e53fb54
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/pymake/functions.py
@@ -0,0 +1,873 @@
+"""
+Makefile functions.
+"""
+
+import parser, util
+import subprocess, os, logging, sys
+from globrelative import glob
+from cStringIO import StringIO
+
+log = logging.getLogger('pymake.data')
+
+def emit_expansions(descend, *expansions):
+    """Helper function to emit all expansions within an input set."""
+    for expansion in expansions:
+        yield expansion
+
+        if not descend or not isinstance(expansion, list):
+            continue
+
+        for e, is_func in expansion:
+            if is_func:
+                for exp in e.expansions(True):
+                    yield exp
+            else:
+                yield e
+
+class Function(object):
+    """
+    An object that represents a function call. This class is always subclassed
+    with the following methods and attributes:
+
+    minargs = minimum # of arguments
+    maxargs = maximum # of arguments (0 means unlimited)
+
+    def resolve(self, makefile, variables, fd, setting)
+        Calls the function
+        calls fd.write() with strings
+    """
+
+    __slots__ = ('_arguments', 'loc')
+
+    def __init__(self, loc):
+        self._arguments = []
+        self.loc = loc
+        assert self.minargs > 0
+
+    def __getitem__(self, key):
+        return self._arguments[key]
+
+    def setup(self):
+        argc = len(self._arguments)
+
+        if argc < self.minargs:
+            raise data.DataError("Not enough arguments to function %s, requires %s" % (self.name, self.minargs), self.loc)
+
+        assert self.maxargs == 0 or argc <= self.maxargs, "Parser screwed up, gave us too many args"
+
+    def append(self, arg):
+        assert isinstance(arg, (data.Expansion, data.StringExpansion))
+        self._arguments.append(arg)
+
+    def to_source(self):
+        """Convert the function back to make file "source" code."""
+        if not hasattr(self, 'name'):
+            raise Exception("%s must implement to_source()." % self.__class__)
+
+        # The default implementation simply prints the function name and all
+        # the arguments joined by a comma.
+        # According to the GNU make manual Section 8.1, whitespace around
+        # arguments is *not* part of the argument's value. So, we trim excess
+        # white space so we have consistent behavior.
+        args = []
+        curly = False
+        for i, arg in enumerate(self._arguments):
+            arg = arg.to_source()
+
+            if i == 0:
+                arg = arg.lstrip()
+
+            # Are balanced parens even OK?
+            if arg.count('(') != arg.count(')'):
+                curly = True
+
+            args.append(arg)
+
+        if curly:
+            return '${%s %s}' % (self.name, ','.join(args))
+
+        return '$(%s %s)' % (self.name, ','.join(args))
+
+    def expansions(self, descend=False):
+        """Obtain all expansions contained within this function.
+
+        By default, only expansions directly part of this function are
+        returned. If descend is True, we will descend into child expansions and
+        return all of the composite parts.
+
+        This is a generator for pymake.data.BaseExpansion instances.
+        """
+        # Our default implementation simply returns arguments. More advanced
+        # functions like variable references may need their own implementation.
+        return emit_expansions(descend, *self._arguments)
+
+    @property
+    def is_filesystem_dependent(self):
+        """Exposes whether this function depends on the filesystem for results.
+
+        If True, the function touches the filesystem as part of evaluation.
+
+        This only tests whether the function itself uses the filesystem. If
+        this function has arguments that are functions that touch the
+        filesystem, this will return False.
+        """
+        return False
+
+    def __len__(self):
+        return len(self._arguments)
+
+    def __repr__(self):
+        return "%s<%s>(%r)" % (
+            self.__class__.__name__, self.loc,
+            ','.join([repr(a) for a in self._arguments]),
+            )
+
+    def __eq__(self, other):
+        if not hasattr(self, 'name'):
+            raise Exception("%s must implement __eq__." % self.__class__)
+
+        if type(self) != type(other):
+            return False
+
+        if self.name != other.name:
+            return False
+
+        if len(self._arguments) != len(other._arguments):
+            return False
+
+        for i in xrange(len(self._arguments)):
+            # According to the GNU make manual Section 8.1, whitespace around
+            # arguments is *not* part of the argument's value. So, we do a
+            # whitespace-agnostic comparison.
+            if i == 0:
+                a = self._arguments[i]
+                a.lstrip()
+
+                b = other._arguments[i]
+                b.lstrip()
+
+                if a != b:
+                    return False
+
+                continue
+
+            if self._arguments[i] != other._arguments[i]:
+                return False
+
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+class VariableRef(Function):
+    AUTOMATIC_VARIABLES = set(['@', '%', '<', '?', '^', '+', '|', '*'])
+
+    __slots__ = ('vname', 'loc')
+
+    def __init__(self, loc, vname):
+        self.loc = loc
+        assert isinstance(vname, (data.Expansion, data.StringExpansion))
+        self.vname = vname
+
+    def setup(self):
+        assert False, "Shouldn't get here"
+
+    def resolve(self, makefile, variables, fd, setting):
+        vname = self.vname.resolvestr(makefile, variables, setting)
+        if vname in setting:
+            raise data.DataError("Setting variable '%s' recursively references itself." % (vname,), self.loc)
+
+        flavor, source, value = variables.get(vname)
+        if value is None:
+            log.debug("%s: variable '%s' was not set" % (self.loc, vname))
+            return
+
+        value.resolve(makefile, variables, fd, setting + [vname])
+
+    def to_source(self):
+        if isinstance(self.vname, data.StringExpansion):
+            if self.vname.s in self.AUTOMATIC_VARIABLES:
+                return '$%s' % self.vname.s
+
+            return '$(%s)' % self.vname.s
+
+        return '$(%s)' % self.vname.to_source()
+
+    def expansions(self, descend=False):
+        return emit_expansions(descend, self.vname)
+
+    def __repr__(self):
+        return "VariableRef<%s>(%r)" % (self.loc, self.vname)
+
+    def __eq__(self, other):
+        if not isinstance(other, VariableRef):
+            return False
+
+        return self.vname == other.vname
+
+class SubstitutionRef(Function):
+    """$(VARNAME:.c=.o) and $(VARNAME:%.c=%.o)"""
+
+    __slots__ = ('loc', 'vname', 'substfrom', 'substto')
+
+    def __init__(self, loc, varname, substfrom, substto):
+        self.loc = loc
+        self.vname = varname
+        self.substfrom = substfrom
+        self.substto = substto
+
+    def setup(self):
+        assert False, "Shouldn't get here"
+
+    def resolve(self, makefile, variables, fd, setting):
+        vname = self.vname.resolvestr(makefile, variables, setting)
+        if vname in setting:
+            raise data.DataError("Setting variable '%s' recursively references itself." % (vname,), self.loc)
+
+        substfrom = self.substfrom.resolvestr(makefile, variables, setting)
+        substto = self.substto.resolvestr(makefile, variables, setting)
+
+        flavor, source, value = variables.get(vname)
+        if value is None:
+            log.debug("%s: variable '%s' was not set" % (self.loc, vname))
+            return
+
+        f = data.Pattern(substfrom)
+        if not f.ispattern():
+            f = data.Pattern('%' + substfrom)
+            substto = '%' + substto
+
+        fd.write(' '.join([f.subst(substto, word, False)
+                           for word in value.resolvesplit(makefile, variables, setting + [vname])]))
+
+    def to_source(self):
+        return '$(%s:%s=%s)' % (
+            self.vname.to_source(),
+            self.substfrom.to_source(),
+            self.substto.to_source())
+
+    def expansions(self, descend=False):
+        return emit_expansions(descend, self.vname, self.substfrom,
+                self.substto)
+
+    def __repr__(self):
+        return "SubstitutionRef<%s>(%r:%r=%r)" % (
+            self.loc, self.vname, self.substfrom, self.substto,)
+
+    def __eq__(self, other):
+        if not isinstance(other, SubstitutionRef):
+            return False
+
+        return self.vname == other.vname and self.substfrom == other.substfrom \
+                and self.substto == other.substto
+
+class SubstFunction(Function):
+    name = 'subst'
+    minargs = 3
+    maxargs = 3
+
+    __slots__ = Function.__slots__
+
+    def resolve(self, makefile, variables, fd, setting):
+        s = self._arguments[0].resolvestr(makefile, variables, setting)
+        r = self._arguments[1].resolvestr(makefile, variables, setting)
+        d = self._arguments[2].resolvestr(makefile, variables, setting)
+        fd.write(d.replace(s, r))
+
+class PatSubstFunction(Function):
+    name = 'patsubst'
+    minargs = 3
+    maxargs = 3
+
+    __slots__ = Function.__slots__
+
+    def resolve(self, makefile, variables, fd, setting):
+        s = self._arguments[0].resolvestr(makefile, variables, setting)
+        r = self._arguments[1].resolvestr(makefile, variables, setting)
+
+        p = data.Pattern(s)
+        fd.write(' '.join([p.subst(r, word, False)
+                           for word in self._arguments[2].resolvesplit(makefile, variables, setting)]))
+
+class StripFunction(Function):
+    name = 'strip'
+    minargs = 1
+    maxargs = 1
+
+    __slots__ = Function.__slots__
+
+    def resolve(self, makefile, variables, fd, setting):
+        util.joiniter(fd, self._arguments[0].resolvesplit(makefile, variables, setting))
+
+class FindstringFunction(Function):
+    name = 'findstring'
+    minargs = 2
+    maxargs = 2
+
+    __slots__ = Function.__slots__
+
+    def resolve(self, makefile, variables, fd, setting):
+        s = self._arguments[0].resolvestr(makefile, variables, setting)
+        r = self._arguments[1].resolvestr(makefile, variables, setting)
+        if r.find(s) == -1:
+            return
+        fd.write(s)
+
+class FilterFunction(Function):
+    name = 'filter'
+    minargs = 2
+    maxargs = 2
+
+    __slots__ = Function.__slots__
+
+    def resolve(self, makefile, variables, fd, setting):
+        plist = [data.Pattern(p)
+                 for p in self._arguments[0].resolvesplit(makefile, variables, setting)]
+
+        fd.write(' '.join([w for w in self._arguments[1].resolvesplit(makefile, variables, setting)
+                           if util.any((p.match(w) for p in plist))]))
+
+class FilteroutFunction(Function):
+    name = 'filter-out'
+    minargs = 2
+    maxargs = 2
+
+    __slots__ = Function.__slots__
+
+    def resolve(self, makefile, variables, fd, setting):
+        plist = [data.Pattern(p)
+                 for p in self._arguments[0].resolvesplit(makefile, variables, setting)]
+
+        fd.write(' '.join([w for w in self._arguments[1].resolvesplit(makefile, variables, setting)
+                           if not util.any((p.match(w) for p in plist))]))
+
+class SortFunction(Function):
+    name = 'sort'
+    minargs = 1
+    maxargs = 1
+
+    __slots__ = Function.__slots__
+
+    def resolve(self, makefile, variables, fd, setting):
+        d = set(self._arguments[0].resolvesplit(makefile, variables, setting))
+        util.joiniter(fd, sorted(d))
+
+class WordFunction(Function):
+    name = 'word'
+    minargs = 2
+    maxargs = 2
+
+    __slots__ = Function.__slots__
+
+    def resolve(self, makefile, variables, fd, setting):
+        n = self._arguments[0].resolvestr(makefile, variables, setting)
+        # TODO: provide better error if this doesn't convert
+        n = int(n)
+        words = list(self._arguments[1].resolvesplit(makefile, variables, setting))
+        if n < 1 or n > len(words):
+            return
+        fd.write(words[n - 1])
+
+class WordlistFunction(Function):
+    name = 'wordlist'
+    minargs = 3
+    maxargs = 3
+
+    __slots__ = Function.__slots__
+
+    def resolve(self, makefile, variables, fd, setting):
+        nfrom = self._arguments[0].resolvestr(makefile, variables, setting)
+        nto = self._arguments[1].resolvestr(makefile, variables, setting)
+        # TODO: provide better errors if this doesn't convert
+        nfrom = int(nfrom)
+        nto = int(nto)
+
+        words = list(self._arguments[2].resolvesplit(makefile, variables, setting))
+
+        if nfrom < 1:
+            nfrom = 1
+        if nto < 1:
+            nto = 1
+
+        util.joiniter(fd, words[nfrom - 1:nto])
+
+class WordsFunction(Function):
+    name = 'words'
+    minargs = 1
+    maxargs = 1
+
+    __slots__ = Function.__slots__
+
+    def resolve(self, makefile, variables, fd, setting):
+        fd.write(str(len(self._arguments[0].resolvesplit(makefile, variables, setting))))
+
+class FirstWordFunction(Function):
+    name = 'firstword'
+    minargs = 1
+    maxargs = 1
+
+    __slots__ = Function.__slots__
+
+    def resolve(self, makefile, variables, fd, setting):
+        l = self._arguments[0].resolvesplit(makefile, variables, setting)
+        if len(l):
+            fd.write(l[0])
+
+class LastWordFunction(Function):
+    name = 'lastword'
+    minargs = 1
+    maxargs = 1
+
+    __slots__ = Function.__slots__
+
+    def resolve(self, makefile, variables, fd, setting):
+        l = self._arguments[0].resolvesplit(makefile, variables, setting)
+        if len(l):
+            fd.write(l[-1])
+
+def pathsplit(path, default='./'):
+    """
+    Splits a path into dirpart, filepart on the last slash. If there is no slash, dirpart
+    is ./
+    """
+    dir, slash, file = util.strrpartition(path, '/')
+    if dir == '':
+        return default, file
+
+    return dir + slash, file
+
+class DirFunction(Function):
+    name = 'dir'
+    minargs = 1
+    maxargs = 1
+
+    def resolve(self, makefile, variables, fd, setting):
+        fd.write(' '.join([pathsplit(path)[0]
+                           for path in self._arguments[0].resolvesplit(makefile, variables, setting)]))
+
+class NotDirFunction(Function):
+    name = 'notdir'
+    minargs = 1
+    maxargs = 1
+
+    __slots__ = Function.__slots__
+
+    def resolve(self, makefile, variables, fd, setting):
+        fd.write(' '.join([pathsplit(path)[1]
+                           for path in self._arguments[0].resolvesplit(makefile, variables, setting)]))
+
+class SuffixFunction(Function):
+    name = 'suffix'
+    minargs = 1
+    maxargs = 1
+
+    __slots__ = Function.__slots__
+
+    @staticmethod
+    def suffixes(words):
+        for w in words:
+            dir, file = pathsplit(w)
+            base, dot, suffix = util.strrpartition(file, '.')
+            if base != '':
+                yield dot + suffix
+
+    def resolve(self, makefile, variables, fd, setting):
+        util.joiniter(fd, self.suffixes(self._arguments[0].resolvesplit(makefile, variables, setting)))
+
+class BasenameFunction(Function):
+    name = 'basename'
+    minargs = 1
+    maxargs = 1
+
+    __slots__ = Function.__slots__
+
+    @staticmethod
+    def basenames(words):
+        for w in words:
+            dir, file = pathsplit(w, '')
+            base, dot, suffix = util.strrpartition(file, '.')
+            if dot == '':
+                base = suffix
+
+            yield dir + base
+
+    def resolve(self, makefile, variables, fd, setting):
+        util.joiniter(fd, self.basenames(self._arguments[0].resolvesplit(makefile, variables, setting)))
+
+class AddSuffixFunction(Function):
+    name = 'addsuffix'
+    minargs = 2
+    maxargs = 2
+
+    __slots__ = Function.__slots__
+
+    def resolve(self, makefile, variables, fd, setting):
+        suffix = self._arguments[0].resolvestr(makefile, variables, setting)
+
+        fd.write(' '.join([w + suffix for w in self._arguments[1].resolvesplit(makefile, variables, setting)]))
+
+class AddPrefixFunction(Function):
+    name = 'addprefix'
+    minargs = 2
+    maxargs = 2
+
+    def resolve(self, makefile, variables, fd, setting):
+        prefix = self._arguments[0].resolvestr(makefile, variables, setting)
+
+        fd.write(' '.join([prefix + w for w in self._arguments[1].resolvesplit(makefile, variables, setting)]))
+
+class JoinFunction(Function):
+    name = 'join'
+    minargs = 2
+    maxargs = 2
+
+    __slots__ = Function.__slots__
+
+    @staticmethod
+    def iterjoin(l1, l2):
+        for i in xrange(0, max(len(l1), len(l2))):
+            i1 = i < len(l1) and l1[i] or ''
+            i2 = i < len(l2) and l2[i] or ''
+            yield i1 + i2
+
+    def resolve(self, makefile, variables, fd, setting):
+        list1 = list(self._arguments[0].resolvesplit(makefile, variables, setting))
+        list2 = list(self._arguments[1].resolvesplit(makefile, variables, setting))
+
+        util.joiniter(fd, self.iterjoin(list1, list2))
+
+class WildcardFunction(Function):
+    name = 'wildcard'
+    minargs = 1
+    maxargs = 1
+
+    __slots__ = Function.__slots__
+
+    def resolve(self, makefile, variables, fd, setting):
+        patterns = self._arguments[0].resolvesplit(makefile, variables, setting)
+
+        fd.write(' '.join([x.replace('\\','/')
+                           for p in patterns
+                           for x in glob(makefile.workdir, p)]))
+
+    @property
+    def is_filesystem_dependent(self):
+        return True
+
+class RealpathFunction(Function):
+    name = 'realpath'
+    minargs = 1
+    maxargs = 1
+
+    def resolve(self, makefile, variables, fd, setting):
+        fd.write(' '.join([os.path.realpath(os.path.join(makefile.workdir, path)).replace('\\', '/')
+                           for path in self._arguments[0].resolvesplit(makefile, variables, setting)]))
+
+    def is_filesystem_dependent(self):
+        return True
+
+class AbspathFunction(Function):
+    name = 'abspath'
+    minargs = 1
+    maxargs = 1
+
+    __slots__ = Function.__slots__
+
+    def resolve(self, makefile, variables, fd, setting):
+        assert os.path.isabs(makefile.workdir)
+        fd.write(' '.join([util.normaljoin(makefile.workdir, path).replace('\\', '/')
+                           for path in self._arguments[0].resolvesplit(makefile, variables, setting)]))
+
+class IfFunction(Function):
+    name = 'if'
+    minargs = 1
+    maxargs = 3
+
+    __slots__ = Function.__slots__
+
+    def setup(self):
+        Function.setup(self)
+        self._arguments[0].lstrip()
+        self._arguments[0].rstrip()
+
+    def resolve(self, makefile, variables, fd, setting):
+        condition = self._arguments[0].resolvestr(makefile, variables, setting)
+
+        if len(condition):
+            self._arguments[1].resolve(makefile, variables, fd, setting)
+        elif len(self._arguments) > 2:
+            return self._arguments[2].resolve(makefile, variables, fd, setting)
+
+class OrFunction(Function):
+    name = 'or'
+    minargs = 1
+    maxargs = 0
+
+    __slots__ = Function.__slots__
+
+    def resolve(self, makefile, variables, fd, setting):
+        for arg in self._arguments:
+            r = arg.resolvestr(makefile, variables, setting)
+            if r != '':
+                fd.write(r)
+                return
+
+class AndFunction(Function):
+    name = 'and'
+    minargs = 1
+    maxargs = 0
+
+    __slots__ = Function.__slots__
+
+    def resolve(self, makefile, variables, fd, setting):
+        r = ''
+
+        for arg in self._arguments:
+            r = arg.resolvestr(makefile, variables, setting)
+            if r == '':
+                return
+
+        fd.write(r)
+
+class ForEachFunction(Function):
+    name = 'foreach'
+    minargs = 3
+    maxargs = 3
+
+    __slots__ = Function.__slots__
+
+    def resolve(self, makefile, variables, fd, setting):
+        vname = self._arguments[0].resolvestr(makefile, variables, setting)
+        e = self._arguments[2]
+
+        v = data.Variables(parent=variables)
+        firstword = True
+
+        for w in self._arguments[1].resolvesplit(makefile, variables, setting):
+            if firstword:
+                firstword = False
+            else:
+                fd.write(' ')
+
+            # The $(origin) of the local variable must be "automatic" to
+            # conform with GNU make. However, automatic variables have low
+            # priority. So, we must force its assignment to occur.
+            v.set(vname, data.Variables.FLAVOR_SIMPLE,
+                    data.Variables.SOURCE_AUTOMATIC, w, force=True)
+            e.resolve(makefile, v, fd, setting)
+
+class CallFunction(Function):
+    name = 'call'
+    minargs = 1
+    maxargs = 0
+
+    __slots__ = Function.__slots__
+
+    def resolve(self, makefile, variables, fd, setting):
+        vname = self._arguments[0].resolvestr(makefile, variables, setting)
+        if vname in setting:
+            raise data.DataError("Recursively setting variable '%s'" % (vname,))
+
+        v = data.Variables(parent=variables)
+        v.set('0', data.Variables.FLAVOR_SIMPLE, data.Variables.SOURCE_AUTOMATIC, vname)
+        for i in xrange(1, len(self._arguments)):
+            param = self._arguments[i].resolvestr(makefile, variables, setting)
+            v.set(str(i), data.Variables.FLAVOR_SIMPLE, data.Variables.SOURCE_AUTOMATIC, param)
+
+        flavor, source, e = variables.get(vname)
+
+        if e is None:
+            return
+
+        if flavor == data.Variables.FLAVOR_SIMPLE:
+            log.warning("%s: calling variable '%s' which is simply-expanded" % (self.loc, vname))
+
+        # but we'll do it anyway
+        e.resolve(makefile, v, fd, setting + [vname])
+
+class ValueFunction(Function):
+    name = 'value'
+    minargs = 1
+    maxargs = 1
+
+    __slots__ = Function.__slots__
+
+    def resolve(self, makefile, variables, fd, setting):
+        varname = self._arguments[0].resolvestr(makefile, variables, setting)
+
+        flavor, source, value = variables.get(varname, expand=False)
+        if value is not None:
+            fd.write(value)
+
+class EvalFunction(Function):
+    name = 'eval'
+    minargs = 1
+    maxargs = 1
+
+    def resolve(self, makefile, variables, fd, setting):
+        if makefile.parsingfinished:
+            # GNU make allows variables to be set by recursive expansion during
+            # command execution. This seems really dumb to me, so I don't!
+            raise data.DataError("$(eval) not allowed via recursive expansion after parsing is finished", self.loc)
+
+        stmts = parser.parsestring(self._arguments[0].resolvestr(makefile, variables, setting),
+                                   'evaluation from %s' % self.loc)
+        stmts.execute(makefile)
+
+class OriginFunction(Function):
+    name = 'origin'
+    minargs = 1
+    maxargs = 1
+
+    __slots__ = Function.__slots__
+
+    def resolve(self, makefile, variables, fd, setting):
+        vname = self._arguments[0].resolvestr(makefile, variables, setting)
+
+        flavor, source, value = variables.get(vname)
+        if source is None:
+            r = 'undefined'
+        elif source == data.Variables.SOURCE_OVERRIDE:
+            r = 'override'
+
+        elif source == data.Variables.SOURCE_MAKEFILE:
+            r = 'file'
+        elif source == data.Variables.SOURCE_ENVIRONMENT:
+            r = 'environment'
+        elif source == data.Variables.SOURCE_COMMANDLINE:
+            r = 'command line'
+        elif source == data.Variables.SOURCE_AUTOMATIC:
+            r = 'automatic'
+        elif source == data.Variables.SOURCE_IMPLICIT:
+            r = 'default'
+
+        fd.write(r)
+
+class FlavorFunction(Function):
+    name = 'flavor'
+    minargs = 1
+    maxargs = 1
+
+    __slots__ = Function.__slots__
+
+    def resolve(self, makefile, variables, fd, setting):
+        varname = self._arguments[0].resolvestr(makefile, variables, setting)
+        
+        flavor, source, value = variables.get(varname)
+        if flavor is None:
+            r = 'undefined'
+        elif flavor == data.Variables.FLAVOR_RECURSIVE:
+            r = 'recursive'
+        elif flavor == data.Variables.FLAVOR_SIMPLE:
+            r = 'simple'
+        fd.write(r)
+
+class ShellFunction(Function):
+    name = 'shell'
+    minargs = 1
+    maxargs = 1
+
+    __slots__ = Function.__slots__
+
+    def resolve(self, makefile, variables, fd, setting):
+        from process import prepare_command
+        cline = self._arguments[0].resolvestr(makefile, variables, setting)
+        executable, cline = prepare_command(cline, makefile.workdir, self.loc)
+
+        # subprocess.Popen doesn't use the PATH set in the env argument for
+        # finding the executable on some platforms (but strangely it does on
+        # others!), so set os.environ['PATH'] explicitly.
+        oldpath = os.environ['PATH']
+        if makefile.env is not None and 'PATH' in makefile.env:
+            os.environ['PATH'] = makefile.env['PATH']
+
+        log.debug("%s: running command '%s'" % (self.loc, ' '.join(cline)))
+        try:
+            p = subprocess.Popen(cline, executable=executable, env=makefile.env, shell=False,
+                                 stdout=subprocess.PIPE, cwd=makefile.workdir)
+        except OSError, e:
+            print >>sys.stderr, "Error executing command %s" % cline[0], e
+            return
+        finally:
+            os.environ['PATH'] = oldpath
+
+        stdout, stderr = p.communicate()
+        stdout = stdout.replace('\r\n', '\n')
+        if stdout.endswith('\n'):
+            stdout = stdout[:-1]
+        stdout = stdout.replace('\n', ' ')
+
+        fd.write(stdout)
+
+class ErrorFunction(Function):
+    name = 'error'
+    minargs = 1
+    maxargs = 1
+
+    __slots__ = Function.__slots__
+
+    def resolve(self, makefile, variables, fd, setting):
+        v = self._arguments[0].resolvestr(makefile, variables, setting)
+        raise data.DataError(v, self.loc)
+
+class WarningFunction(Function):
+    name = 'warning'
+    minargs = 1
+    maxargs = 1
+
+    __slots__ = Function.__slots__
+
+    def resolve(self, makefile, variables, fd, setting):
+        v = self._arguments[0].resolvestr(makefile, variables, setting)
+        log.warning(v)
+
+class InfoFunction(Function):
+    name = 'info'
+    minargs = 1
+    maxargs = 1
+
+    __slots__ = Function.__slots__
+
+    def resolve(self, makefile, variables, fd, setting):
+        v = self._arguments[0].resolvestr(makefile, variables, setting)
+        print v
+
+functionmap = {
+    'subst': SubstFunction,
+    'patsubst': PatSubstFunction,
+    'strip': StripFunction,
+    'findstring': FindstringFunction,
+    'filter': FilterFunction,
+    'filter-out': FilteroutFunction,
+    'sort': SortFunction,
+    'word': WordFunction,
+    'wordlist': WordlistFunction,
+    'words': WordsFunction,
+    'firstword': FirstWordFunction,
+    'lastword': LastWordFunction,
+    'dir': DirFunction,
+    'notdir': NotDirFunction,
+    'suffix': SuffixFunction,
+    'basename': BasenameFunction,
+    'addsuffix': AddSuffixFunction,
+    'addprefix': AddPrefixFunction,
+    'join': JoinFunction,
+    'wildcard': WildcardFunction,
+    'realpath': RealpathFunction,
+    'abspath': AbspathFunction,
+    'if': IfFunction,
+    'or': OrFunction,
+    'and': AndFunction,
+    'foreach': ForEachFunction,
+    'call': CallFunction,
+    'value': ValueFunction,
+    'eval': EvalFunction,
+    'origin': OriginFunction,
+    'flavor': FlavorFunction,
+    'shell': ShellFunction,
+    'error': ErrorFunction,
+    'warning': WarningFunction,
+    'info': InfoFunction,
+}
+
+import data
diff --git a/src/third_party/mozjs-45/build/pymake/pymake/globrelative.py b/src/third_party/mozjs-45/build/pymake/pymake/globrelative.py
new file mode 100644
index 0000000..37ca28e
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/pymake/globrelative.py
@@ -0,0 +1,68 @@
+"""
+Filename globbing like the python glob module with minor differences:
+
+* glob relative to an arbitrary directory
+* include . and ..
+* check that link targets exist, not just links
+"""
+
+import os, re, fnmatch
+import util
+
+_globcheck = re.compile('[[*?]')
+
+def hasglob(p):
+    return _globcheck.search(p) is not None
+
+def glob(fsdir, path):
+    """
+    Yield paths matching the path glob. Sorts as a bonus. Excludes '.' and '..'
+    """
+
+    dir, leaf = os.path.split(path)
+    if dir == '':
+        return globpattern(fsdir, leaf)
+
+    if hasglob(dir):
+        dirsfound = glob(fsdir, dir)
+    else:
+        dirsfound = [dir]
+
+    r = []
+
+    for dir in dirsfound:
+        fspath = util.normaljoin(fsdir, dir)
+        if not os.path.isdir(fspath):
+            continue
+
+        r.extend((util.normaljoin(dir, found) for found in globpattern(fspath, leaf)))
+
+    return r
+
+def globpattern(dir, pattern):
+    """
+    Return leaf names in the specified directory which match the pattern.
+    """
+
+    if not hasglob(pattern):
+        if pattern == '':
+            if os.path.isdir(dir):
+                return ['']
+            return []
+
+        if os.path.exists(util.normaljoin(dir, pattern)):
+            return [pattern]
+        return []
+
+    leaves = os.listdir(dir) + ['.', '..']
+
+    # "hidden" filenames are a bit special
+    if not pattern.startswith('.'):
+        leaves = [leaf for leaf in leaves
+                  if not leaf.startswith('.')]
+
+    leaves = fnmatch.filter(leaves, pattern)
+    leaves = filter(lambda l: os.path.exists(util.normaljoin(dir, l)), leaves)
+
+    leaves.sort()
+    return leaves
diff --git a/src/third_party/mozjs-45/build/pymake/pymake/implicit.py b/src/third_party/mozjs-45/build/pymake/pymake/implicit.py
new file mode 100644
index 0000000..d73895c
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/pymake/implicit.py
@@ -0,0 +1,14 @@
+"""

+Implicit variables; perhaps in the future this will also include some implicit

+rules, at least match-anything cancellation rules.

+"""

+

+variables = {

+    'MKDIR': '%pymake.builtins mkdir',

+    'RM': '%pymake.builtins rm -f',

+    'SLEEP': '%pymake.builtins sleep',

+    'TOUCH': '%pymake.builtins touch',

+    '.LIBPATTERNS': 'lib%.so lib%.a',

+    '.PYMAKE': '1',

+    }

+

diff --git a/src/third_party/mozjs-45/build/pymake/pymake/parser.py b/src/third_party/mozjs-45/build/pymake/pymake/parser.py
new file mode 100644
index 0000000..4bff533
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/pymake/parser.py
@@ -0,0 +1,822 @@
+"""
+Module for parsing Makefile syntax.
+
+Makefiles use a line-based parsing system. Continuations and substitutions are handled differently based on the
+type of line being parsed:
+
+Lines with makefile syntax condense continuations to a single space, no matter the actual trailing whitespace
+of the first line or the leading whitespace of the continuation. In other situations, trailing whitespace is
+relevant.
+
+Lines with command syntax do not condense continuations: the backslash and newline are part of the command.
+(GNU Make is buggy in this regard, at least on mac).
+
+Lines with an initial tab are commands if they can be (there is a rule or a command immediately preceding).
+Otherwise, they are parsed as makefile syntax.
+
+This file parses into the data structures defined in the parserdata module. Those classes are what actually
+do the dirty work of "executing" the parsed data into a data.Makefile.
+
+Four iterator functions are available:
+* iterdata
+* itermakefilechars
+* itercommandchars
+
+The iterators handle line continuations and comments in different ways, but share a common calling
+convention:
+
+Called with (data, startoffset, tokenlist, finditer)
+
+yield 4-tuples (flatstr, token, tokenoffset, afteroffset)
+flatstr is data, guaranteed to have no tokens (may be '')
+token, tokenoffset, afteroffset *may be None*. That means there is more text
+coming.
+"""
+
+import logging, re, os, sys
+import data, functions, util, parserdata
+
+_log = logging.getLogger('pymake.parser')
+
+class SyntaxError(util.MakeError):
+    pass
+
+_skipws = re.compile('\S')
+class Data(object):
+    """
+    A single virtual "line", which can be multiple source lines joined with
+    continuations.
+    """
+
+    __slots__ = ('s', 'lstart', 'lend', 'loc')
+
+    def __init__(self, s, lstart, lend, loc):
+        self.s = s
+        self.lstart = lstart
+        self.lend = lend
+        self.loc = loc
+
+    @staticmethod
+    def fromstring(s, path):
+        return Data(s, 0, len(s), parserdata.Location(path, 1, 0))
+
+    def getloc(self, offset):
+        assert offset >= self.lstart and offset <= self.lend
+        return self.loc.offset(self.s, self.lstart, offset)
+
+    def skipwhitespace(self, offset):
+        """
+        Return the offset of the first non-whitespace character in data starting at offset, or None if there are
+        only whitespace characters remaining.
+        """
+        m = _skipws.search(self.s, offset, self.lend)
+        if m is None:
+            return self.lend
+
+        return m.start(0)
+
+_linere = re.compile(r'\\*\n')
+def enumeratelines(s, filename):
+    """
+    Enumerate lines in a string as Data objects, joining line
+    continuations.
+    """
+
+    off = 0
+    lineno = 1
+    curlines = 0
+    for m in _linere.finditer(s):
+        curlines += 1
+        start, end = m.span(0)
+
+        if (start - end) % 2 == 0:
+            # odd number of backslashes is a continuation
+            continue
+
+        yield Data(s, off, end - 1, parserdata.Location(filename, lineno, 0))
+
+        lineno += curlines
+        curlines = 0
+        off = end
+
+    yield Data(s, off, len(s), parserdata.Location(filename, lineno, 0))
+
+_alltokens = re.compile(r'''\\*\# | # hash mark preceeded by any number of backslashes
+                            := |
+                            \+= |
+                            \?= |
+                            :: |
+                            (?:\$(?:$|[\(\{](?:%s)\s+|.)) | # dollar sign followed by EOF, a function keyword with whitespace, or any character
+                            :(?![\\/]) | # colon followed by anything except a slash (Windows path detection)
+                            [=#{}();,|'"]''' % '|'.join(functions.functionmap.iterkeys()), re.VERBOSE)
+
+def iterdata(d, offset, tokenlist, it):
+    """
+    Iterate over flat data without line continuations, comments, or any special escaped characters.
+
+    Typically used to parse recursively-expanded variables.
+    """
+
+    assert len(tokenlist), "Empty tokenlist passed to iterdata is meaningless!"
+    assert offset >= d.lstart and offset <= d.lend, "offset %i should be between %i and %i" % (offset, d.lstart, d.lend)
+
+    if offset == d.lend:
+        return
+
+    s = d.s
+    for m in it:
+        mstart, mend = m.span(0)
+        token = s[mstart:mend]
+        if token in tokenlist or (token[0] == '$' and '$' in tokenlist):
+            yield s[offset:mstart], token, mstart, mend
+        else:
+            yield s[offset:mend], None, None, mend
+        offset = mend
+
+    yield s[offset:d.lend], None, None, None
+
+# multiple backslashes before a newline are unescaped, halving their total number
+_makecontinuations = re.compile(r'(?:\s*|((?:\\\\)+))\\\n\s*')
+def _replacemakecontinuations(m):
+    start, end = m.span(1)
+    if start == -1:
+        return ' '
+    return ' '.rjust((end - start) / 2 + 1, '\\')
+
+def itermakefilechars(d, offset, tokenlist, it, ignorecomments=False):
+    """
+    Iterate over data in makefile syntax. Comments are found at unescaped # characters, and escaped newlines
+    are converted to single-space continuations.
+    """
+
+    assert offset >= d.lstart and offset <= d.lend, "offset %i should be between %i and %i" % (offset, d.lstart, d.lend)
+
+    if offset == d.lend:
+        return
+
+    s = d.s
+    for m in it:
+        mstart, mend = m.span(0)
+        token = s[mstart:mend]
+
+        starttext = _makecontinuations.sub(_replacemakecontinuations, s[offset:mstart])
+
+        if token[-1] == '#' and not ignorecomments:
+            l = mend - mstart
+            # multiple backslashes before a hash are unescaped, halving their total number
+            if l % 2:
+                # found a comment
+                yield starttext + token[:(l - 1) / 2], None, None, None
+                return
+            else:
+                yield starttext + token[-l / 2:], None, None, mend
+        elif token in tokenlist or (token[0] == '$' and '$' in tokenlist):
+            yield starttext, token, mstart, mend
+        else:
+            yield starttext + token, None, None, mend
+        offset = mend
+
+    yield _makecontinuations.sub(_replacemakecontinuations, s[offset:d.lend]), None, None, None
+
+_findcomment = re.compile(r'\\*\#')
+def flattenmakesyntax(d, offset):
+    """
+    A shortcut method for flattening line continuations and comments in makefile syntax without
+    looking for other tokens.
+    """
+
+    assert offset >= d.lstart and offset <= d.lend, "offset %i should be between %i and %i" % (offset, d.lstart, d.lend)
+    if offset == d.lend:
+        return ''
+
+    s = _makecontinuations.sub(_replacemakecontinuations, d.s[offset:d.lend])
+
+    elements = []
+    offset = 0
+    for m in _findcomment.finditer(s):
+        mstart, mend = m.span(0)
+        elements.append(s[offset:mstart])
+        if (mend - mstart) % 2:
+            # even number of backslashes... it's a comment
+            elements.append(''.ljust((mend - mstart - 1) / 2, '\\'))
+            return ''.join(elements)
+
+        # odd number of backslashes
+        elements.append(''.ljust((mend - mstart - 2) / 2, '\\') + '#')
+        offset = mend
+
+    elements.append(s[offset:])
+    return ''.join(elements)
+
+def itercommandchars(d, offset, tokenlist, it):
+    """
+    Iterate over command syntax. # comment markers are not special, and escaped newlines are included
+    in the output text.
+    """
+
+    assert offset >= d.lstart and offset <= d.lend, "offset %i should be between %i and %i" % (offset, d.lstart, d.lend)
+
+    if offset == d.lend:
+        return
+
+    s = d.s
+    for m in it:
+        mstart, mend = m.span(0)
+        token = s[mstart:mend]
+        starttext = s[offset:mstart].replace('\n\t', '\n')
+
+        if token in tokenlist or (token[0] == '$' and '$' in tokenlist):
+            yield starttext, token, mstart, mend
+        else:
+            yield starttext + token, None, None, mend
+        offset = mend
+
+    yield s[offset:d.lend].replace('\n\t', '\n'), None, None, None
+
+_redefines = re.compile('\s*define|\s*endef')
+def iterdefinelines(it, startloc):
+    """
+    Process the insides of a define. Most characters are included literally. Escaped newlines are treated
+    as they would be in makefile syntax. Internal define/endef pairs are ignored.
+    """
+
+    results = []
+
+    definecount = 1
+    for d in it:
+        m = _redefines.match(d.s, d.lstart, d.lend)
+        if m is not None:
+            directive = m.group(0).strip()
+            if directive == 'endef':
+                definecount -= 1
+                if definecount == 0:
+                    return _makecontinuations.sub(_replacemakecontinuations, '\n'.join(results))
+            else:
+                definecount += 1
+
+        results.append(d.s[d.lstart:d.lend])
+
+    # Falling off the end is an unterminated define!
+    raise SyntaxError("define without matching endef", startloc)
+
+def _ensureend(d, offset, msg):
+    """
+    Ensure that only whitespace remains in this data.
+    """
+
+    s = flattenmakesyntax(d, offset)
+    if s != '' and not s.isspace():
+        raise SyntaxError(msg, d.getloc(offset))
+
+_eqargstokenlist = ('(', "'", '"')
+
+def ifeq(d, offset):
+    if offset > d.lend - 1:
+        raise SyntaxError("No arguments after conditional", d.getloc(offset))
+
+    # the variety of formats for this directive is rather maddening
+    token = d.s[offset]
+    if token not in _eqargstokenlist:
+        raise SyntaxError("No arguments after conditional", d.getloc(offset))
+
+    offset += 1
+
+    if token == '(':
+        arg1, t, offset = parsemakesyntax(d, offset, (',',), itermakefilechars)
+        if t is None:
+            raise SyntaxError("Expected two arguments in conditional", d.getloc(d.lend))
+
+        arg1.rstrip()
+
+        offset = d.skipwhitespace(offset)
+        arg2, t, offset = parsemakesyntax(d, offset, (')',), itermakefilechars)
+        if t is None:
+            raise SyntaxError("Unexpected text in conditional", d.getloc(offset))
+
+        _ensureend(d, offset, "Unexpected text after conditional")
+    else:
+        arg1, t, offset = parsemakesyntax(d, offset, (token,), itermakefilechars)
+        if t is None:
+            raise SyntaxError("Unexpected text in conditional", d.getloc(d.lend))
+
+        offset = d.skipwhitespace(offset)
+        if offset == d.lend:
+            raise SyntaxError("Expected two arguments in conditional", d.getloc(offset))
+
+        token = d.s[offset]
+        if token not in '\'"':
+            raise SyntaxError("Unexpected text in conditional", d.getloc(offset))
+
+        arg2, t, offset = parsemakesyntax(d, offset + 1, (token,), itermakefilechars)
+
+        _ensureend(d, offset, "Unexpected text after conditional")
+
+    return parserdata.EqCondition(arg1, arg2)
+
+def ifneq(d, offset):
+    c = ifeq(d, offset)
+    c.expected = False
+    return c
+
+def ifdef(d, offset):
+    e, t, offset = parsemakesyntax(d, offset, (), itermakefilechars)
+    e.rstrip()
+
+    return parserdata.IfdefCondition(e)
+
+def ifndef(d, offset):
+    c = ifdef(d, offset)
+    c.expected = False
+    return c
+
+_conditionkeywords = {
+    'ifeq': ifeq,
+    'ifneq': ifneq,
+    'ifdef': ifdef,
+    'ifndef': ifndef
+    }
+
+_conditiontokens = tuple(_conditionkeywords.iterkeys())
+_conditionre = re.compile(r'(%s)(?:$|\s+)' % '|'.join(_conditiontokens))
+
+_directivestokenlist = _conditiontokens + \
+    ('else', 'endif', 'define', 'endef', 'override', 'include', '-include', 'includedeps', '-includedeps', 'vpath', 'export', 'unexport')
+
+_directivesre = re.compile(r'(%s)(?:$|\s+)' % '|'.join(_directivestokenlist))
+
+_varsettokens = (':=', '+=', '?=', '=')
+
+def _parsefile(pathname):
+    fd = open(pathname, "rU")
+    stmts = parsestring(fd.read(), pathname)
+    stmts.mtime = os.fstat(fd.fileno()).st_mtime
+    fd.close()
+    return stmts
+
+def _checktime(path, stmts):
+    mtime = os.path.getmtime(path)
+    if mtime != stmts.mtime:
+        _log.debug("Re-parsing makefile '%s': mtimes differ", path)
+        return False
+
+    return True
+
+_parsecache = util.MostUsedCache(50, _parsefile, _checktime)
+
+def parsefile(pathname):
+    """
+    Parse a filename into a parserdata.StatementList. A cache is used to avoid re-parsing
+    makefiles that have already been parsed and have not changed.
+    """
+
+    pathname = os.path.realpath(pathname)
+    return _parsecache.get(pathname)
+
+# colon followed by anything except a slash (Windows path detection)
+_depfilesplitter = re.compile(r':(?![\\/])')
+# simple variable references
+_vars = re.compile('\$\((\w+)\)')
+
+def parsedepfile(pathname):
+    """
+    Parse a filename listing only depencencies into a parserdata.StatementList.
+    Simple variable references are allowed in such files.
+    """
+    def continuation_iter(lines):
+        current_line = []
+        for line in lines:
+            line = line.rstrip()
+            if line.endswith("\\"):
+                current_line.append(line.rstrip("\\"))
+                continue
+            if not len(line):
+                continue
+            current_line.append(line)
+            yield ''.join(current_line)
+            current_line = []
+        if current_line:
+            yield ''.join(current_line)
+
+    def get_expansion(s):
+        if '$' in s:
+            expansion = data.Expansion()
+            # for an input like e.g. "foo $(bar) baz",
+            # _vars.split returns ["foo", "bar", "baz"]
+            # every other element is a variable name.
+            for i, element in enumerate(_vars.split(s)):
+                if i % 2:
+                    expansion.appendfunc(functions.VariableRef(None,
+                        data.StringExpansion(element, None)))
+                elif element:
+                    expansion.appendstr(element)
+
+            return expansion
+
+        return data.StringExpansion(s, None)
+
+    pathname = os.path.realpath(pathname)
+    stmts = parserdata.StatementList()
+    for line in continuation_iter(open(pathname).readlines()):
+        target, deps = _depfilesplitter.split(line, 1)
+        stmts.append(parserdata.Rule(get_expansion(target),
+                                     get_expansion(deps), False))
+    return stmts
+
+def parsestring(s, filename):
+    """
+    Parse a string containing makefile data into a parserdata.StatementList.
+    """
+
+    currule = False
+    condstack = [parserdata.StatementList()]
+
+    fdlines = enumeratelines(s, filename)
+    for d in fdlines:
+        assert len(condstack) > 0
+
+        offset = d.lstart
+
+        if currule and offset < d.lend and d.s[offset] == '\t':
+            e, token, offset = parsemakesyntax(d, offset + 1, (), itercommandchars)
+            assert token is None
+            assert offset is None
+            condstack[-1].append(parserdata.Command(e))
+            continue
+
+        # To parse Makefile syntax, we first strip leading whitespace and
+        # look for initial keywords. If there are no keywords, it's either
+        # setting a variable or writing a rule.
+
+        offset = d.skipwhitespace(offset)
+        if offset is None:
+            continue
+
+        m = _directivesre.match(d.s, offset, d.lend)
+        if m is not None:
+            kword = m.group(1)
+            offset = m.end(0)
+
+            if kword == 'endif':
+                _ensureend(d, offset, "Unexpected data after 'endif' directive")
+                if len(condstack) == 1:
+                    raise SyntaxError("unmatched 'endif' directive",
+                                      d.getloc(offset))
+
+                condstack.pop().endloc = d.getloc(offset)
+                continue
+            
+            if kword == 'else':
+                if len(condstack) == 1:
+                    raise SyntaxError("unmatched 'else' directive",
+                                      d.getloc(offset))
+
+                m = _conditionre.match(d.s, offset, d.lend)
+                if m is None:
+                    _ensureend(d, offset, "Unexpected data after 'else' directive.")
+                    condstack[-1].addcondition(d.getloc(offset), parserdata.ElseCondition())
+                else:
+                    kword = m.group(1)
+                    if kword not in _conditionkeywords:
+                        raise SyntaxError("Unexpected condition after 'else' directive.",
+                                          d.getloc(offset))
+
+                    startoffset = offset
+                    offset = d.skipwhitespace(m.end(1))
+                    c = _conditionkeywords[kword](d, offset)
+                    condstack[-1].addcondition(d.getloc(startoffset), c)
+                continue
+
+            if kword in _conditionkeywords:
+                c = _conditionkeywords[kword](d, offset)
+                cb = parserdata.ConditionBlock(d.getloc(d.lstart), c)
+                condstack[-1].append(cb)
+                condstack.append(cb)
+                continue
+
+            if kword == 'endef':
+                raise SyntaxError("endef without matching define", d.getloc(offset))
+
+            if kword == 'define':
+                currule = False
+                vname, t, i = parsemakesyntax(d, offset, (), itermakefilechars)
+                vname.rstrip()
+
+                startloc = d.getloc(d.lstart)
+                value = iterdefinelines(fdlines, startloc)
+                condstack[-1].append(parserdata.SetVariable(vname, value=value, valueloc=startloc, token='=', targetexp=None))
+                continue
+
+            if kword in ('include', '-include', 'includedeps', '-includedeps'):
+                if kword.startswith('-'):
+                    required = False
+                    kword = kword[1:]
+                else:
+                    required = True
+
+                deps = kword == 'includedeps'
+
+                currule = False
+                incfile, t, offset = parsemakesyntax(d, offset, (), itermakefilechars)
+                condstack[-1].append(parserdata.Include(incfile, required, deps))
+
+                continue
+
+            if kword == 'vpath':
+                currule = False
+                e, t, offset = parsemakesyntax(d, offset, (), itermakefilechars)
+                condstack[-1].append(parserdata.VPathDirective(e))
+                continue
+
+            if kword == 'override':
+                currule = False
+                vname, token, offset = parsemakesyntax(d, offset, _varsettokens, itermakefilechars)
+                vname.lstrip()
+                vname.rstrip()
+
+                if token is None:
+                    raise SyntaxError("Malformed override directive, need =", d.getloc(d.lstart))
+
+                value = flattenmakesyntax(d, offset).lstrip()
+
+                condstack[-1].append(parserdata.SetVariable(vname, value=value, valueloc=d.getloc(offset), token=token, targetexp=None, source=data.Variables.SOURCE_OVERRIDE))
+                continue
+
+            if kword == 'export':
+                currule = False
+                e, token, offset = parsemakesyntax(d, offset, _varsettokens, itermakefilechars)
+                e.lstrip()
+                e.rstrip()
+
+                if token is None:
+                    condstack[-1].append(parserdata.ExportDirective(e, concurrent_set=False))
+                else:
+                    condstack[-1].append(parserdata.ExportDirective(e, concurrent_set=True))
+
+                    value = flattenmakesyntax(d, offset).lstrip()
+                    condstack[-1].append(parserdata.SetVariable(e, value=value, valueloc=d.getloc(offset), token=token, targetexp=None))
+
+                continue
+
+            if kword == 'unexport':
+                e, token, offset = parsemakesyntax(d, offset, (), itermakefilechars)
+                condstack[-1].append(parserdata.UnexportDirective(e))
+                continue
+
+        e, token, offset = parsemakesyntax(d, offset, _varsettokens + ('::', ':'), itermakefilechars)
+        if token is None:
+            e.rstrip()
+            e.lstrip()
+            if not e.isempty():
+                condstack[-1].append(parserdata.EmptyDirective(e))
+            continue
+
+        # if we encountered real makefile syntax, the current rule is over
+        currule = False
+
+        if token in _varsettokens:
+            e.lstrip()
+            e.rstrip()
+
+            value = flattenmakesyntax(d, offset).lstrip()
+
+            condstack[-1].append(parserdata.SetVariable(e, value=value, valueloc=d.getloc(offset), token=token, targetexp=None))
+        else:
+            doublecolon = token == '::'
+
+            # `e` is targets or target patterns, which can end up as
+            # * a rule
+            # * an implicit rule
+            # * a static pattern rule
+            # * a target-specific variable definition
+            # * a pattern-specific variable definition
+            # any of the rules may have order-only prerequisites
+            # delimited by |, and a command delimited by ;
+            targets = e
+
+            e, token, offset = parsemakesyntax(d, offset,
+                                               _varsettokens + (':', '|', ';'),
+                                               itermakefilechars)
+            if token in (None, ';'):
+                condstack[-1].append(parserdata.Rule(targets, e, doublecolon))
+                currule = True
+
+                if token == ';':
+                    offset = d.skipwhitespace(offset)
+                    e, t, offset = parsemakesyntax(d, offset, (), itercommandchars)
+                    condstack[-1].append(parserdata.Command(e))
+
+            elif token in _varsettokens:
+                e.lstrip()
+                e.rstrip()
+
+                value = flattenmakesyntax(d, offset).lstrip()
+                condstack[-1].append(parserdata.SetVariable(e, value=value, valueloc=d.getloc(offset), token=token, targetexp=targets))
+            elif token == '|':
+                raise SyntaxError('order-only prerequisites not implemented', d.getloc(offset))
+            else:
+                assert token == ':'
+                # static pattern rule
+
+                pattern = e
+
+                deps, token, offset = parsemakesyntax(d, offset, (';',), itermakefilechars)
+
+                condstack[-1].append(parserdata.StaticPatternRule(targets, pattern, deps, doublecolon))
+                currule = True
+
+                if token == ';':
+                    offset = d.skipwhitespace(offset)
+                    e, token, offset = parsemakesyntax(d, offset, (), itercommandchars)
+                    condstack[-1].append(parserdata.Command(e))
+
+    if len(condstack) != 1:
+        raise SyntaxError("Condition never terminated with endif", condstack[-1].loc)
+
+    return condstack[0]
+
+_PARSESTATE_TOPLEVEL = 0    # at the top level
+_PARSESTATE_FUNCTION = 1    # expanding a function call
+_PARSESTATE_VARNAME = 2     # expanding a variable expansion.
+_PARSESTATE_SUBSTFROM = 3   # expanding a variable expansion substitution "from" value
+_PARSESTATE_SUBSTTO = 4     # expanding a variable expansion substitution "to" value
+_PARSESTATE_PARENMATCH = 5  # inside nested parentheses/braces that must be matched
+
+class ParseStackFrame(object):
+    __slots__ = ('parsestate', 'parent', 'expansion', 'tokenlist', 'openbrace', 'closebrace', 'function', 'loc', 'varname', 'substfrom')
+
+    def __init__(self, parsestate, parent, expansion, tokenlist, openbrace, closebrace, function=None, loc=None):
+        self.parsestate = parsestate
+        self.parent = parent
+        self.expansion = expansion
+        self.tokenlist = tokenlist
+        self.openbrace = openbrace
+        self.closebrace = closebrace
+        self.function = function
+        self.loc = loc
+
+    def __str__(self):
+        return "<state=%i expansion=%s tokenlist=%s openbrace=%s closebrace=%s>" % (self.parsestate, self.expansion, self.tokenlist, self.openbrace, self.closebrace)
+
+_matchingbrace = {
+    '(': ')',
+    '{': '}',
+    }
+
+def parsemakesyntax(d, offset, stopon, iterfunc):
+    """
+    Given Data, parse it into a data.Expansion.
+
+    @param stopon (sequence)
+        Indicate characters where toplevel parsing should stop.
+
+    @param iterfunc (generator function)
+        A function which is used to iterate over d, yielding (char, offset, loc)
+        @see iterdata
+        @see itermakefilechars
+        @see itercommandchars
+ 
+    @return a tuple (expansion, token, offset). If all the data is consumed,
+    token and offset will be None
+    """
+
+    assert callable(iterfunc)
+
+    stacktop = ParseStackFrame(_PARSESTATE_TOPLEVEL, None, data.Expansion(loc=d.getloc(d.lstart)),
+                               tokenlist=stopon + ('$',),
+                               openbrace=None, closebrace=None)
+
+    tokeniterator = _alltokens.finditer(d.s, offset, d.lend)
+
+    di = iterfunc(d, offset, stacktop.tokenlist, tokeniterator)
+    while True: # this is not a for loop because `di` changes during the function
+        assert stacktop is not None
+        try:
+            s, token, tokenoffset, offset = di.next()
+        except StopIteration:
+            break
+
+        stacktop.expansion.appendstr(s)
+        if token is None:
+            continue
+
+        parsestate = stacktop.parsestate
+
+        if token[0] == '$':
+            if tokenoffset + 1 == d.lend:
+                # an unterminated $ expands to nothing
+                break
+
+            loc = d.getloc(tokenoffset)
+            c = token[1]
+            if c == '$':
+                assert len(token) == 2
+                stacktop.expansion.appendstr('$')
+            elif c in ('(', '{'):
+                closebrace = _matchingbrace[c]
+
+                if len(token) > 2:
+                    fname = token[2:].rstrip()
+                    fn = functions.functionmap[fname](loc)
+                    e = data.Expansion()
+                    if len(fn) + 1 == fn.maxargs:
+                        tokenlist = (c, closebrace, '$')
+                    else:
+                        tokenlist = (',', c, closebrace, '$')
+
+                    stacktop = ParseStackFrame(_PARSESTATE_FUNCTION, stacktop,
+                                               e, tokenlist, function=fn,
+                                               openbrace=c, closebrace=closebrace)
+                else:
+                    e = data.Expansion()
+                    tokenlist = (':', c, closebrace, '$')
+                    stacktop = ParseStackFrame(_PARSESTATE_VARNAME, stacktop,
+                                               e, tokenlist,
+                                               openbrace=c, closebrace=closebrace, loc=loc)
+            else:
+                assert len(token) == 2
+                e = data.Expansion.fromstring(c, loc)
+                stacktop.expansion.appendfunc(functions.VariableRef(loc, e))
+        elif token in ('(', '{'):
+            assert token == stacktop.openbrace
+
+            stacktop.expansion.appendstr(token)
+            stacktop = ParseStackFrame(_PARSESTATE_PARENMATCH, stacktop,
+                                       stacktop.expansion,
+                                       (token, stacktop.closebrace, '$'),
+                                       openbrace=token, closebrace=stacktop.closebrace, loc=d.getloc(tokenoffset))
+        elif parsestate == _PARSESTATE_PARENMATCH:
+            assert token == stacktop.closebrace
+            stacktop.expansion.appendstr(token)
+            stacktop = stacktop.parent
+        elif parsestate == _PARSESTATE_TOPLEVEL:
+            assert stacktop.parent is None
+            return stacktop.expansion.finish(), token, offset
+        elif parsestate == _PARSESTATE_FUNCTION:
+            if token == ',':
+                stacktop.function.append(stacktop.expansion.finish())
+
+                stacktop.expansion = data.Expansion()
+                if len(stacktop.function) + 1 == stacktop.function.maxargs:
+                    tokenlist = (stacktop.openbrace, stacktop.closebrace, '$')
+                    stacktop.tokenlist = tokenlist
+            elif token in (')', '}'):
+                fn = stacktop.function
+                fn.append(stacktop.expansion.finish())
+                fn.setup()
+                
+                stacktop = stacktop.parent
+                stacktop.expansion.appendfunc(fn)
+            else:
+                assert False, "Not reached, _PARSESTATE_FUNCTION"
+        elif parsestate == _PARSESTATE_VARNAME:
+            if token == ':':
+                stacktop.varname = stacktop.expansion
+                stacktop.parsestate = _PARSESTATE_SUBSTFROM
+                stacktop.expansion = data.Expansion()
+                stacktop.tokenlist = ('=', stacktop.openbrace, stacktop.closebrace, '$')
+            elif token in (')', '}'):
+                fn = functions.VariableRef(stacktop.loc, stacktop.expansion.finish())
+                stacktop = stacktop.parent
+                stacktop.expansion.appendfunc(fn)
+            else:
+                assert False, "Not reached, _PARSESTATE_VARNAME"
+        elif parsestate == _PARSESTATE_SUBSTFROM:
+            if token == '=':
+                stacktop.substfrom = stacktop.expansion
+                stacktop.parsestate = _PARSESTATE_SUBSTTO
+                stacktop.expansion = data.Expansion()
+                stacktop.tokenlist = (stacktop.openbrace, stacktop.closebrace, '$')
+            elif token in (')', '}'):
+                # A substitution of the form $(VARNAME:.ee) is probably a mistake, but make
+                # parses it. Issue a warning. Combine the varname and substfrom expansions to
+                # make the compatible varname. See tests/var-substitutions.mk SIMPLE3SUBSTNAME
+                _log.warning("%s: Variable reference looks like substitution without =", stacktop.loc)
+                stacktop.varname.appendstr(':')
+                stacktop.varname.concat(stacktop.expansion)
+                fn = functions.VariableRef(stacktop.loc, stacktop.varname.finish())
+                stacktop = stacktop.parent
+                stacktop.expansion.appendfunc(fn)
+            else:
+                assert False, "Not reached, _PARSESTATE_SUBSTFROM"
+        elif parsestate == _PARSESTATE_SUBSTTO:
+            assert token in  (')','}'), "Not reached, _PARSESTATE_SUBSTTO"
+
+            fn = functions.SubstitutionRef(stacktop.loc, stacktop.varname.finish(),
+                                           stacktop.substfrom.finish(), stacktop.expansion.finish())
+            stacktop = stacktop.parent
+            stacktop.expansion.appendfunc(fn)
+        else:
+            assert False, "Unexpected parse state %s" % stacktop.parsestate
+
+        if stacktop.parent is not None and iterfunc == itercommandchars:
+            di = itermakefilechars(d, offset, stacktop.tokenlist, tokeniterator,
+                                   ignorecomments=True)
+        else:
+            di = iterfunc(d, offset, stacktop.tokenlist, tokeniterator)
+
+    if stacktop.parent is not None:
+        raise SyntaxError("Unterminated function call", d.getloc(offset))
+
+    assert stacktop.parsestate == _PARSESTATE_TOPLEVEL
+
+    return stacktop.expansion.finish(), None, None
diff --git a/src/third_party/mozjs-45/build/pymake/pymake/parserdata.py b/src/third_party/mozjs-45/build/pymake/pymake/parserdata.py
new file mode 100644
index 0000000..7b2e544
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/pymake/parserdata.py
@@ -0,0 +1,1006 @@
+import logging, re, os
+import data, parser, functions, util
+from cStringIO import StringIO
+from pymake.globrelative import hasglob, glob
+
+_log = logging.getLogger('pymake.data')
+_tabwidth = 4
+
+class Location(object):
+    """
+    A location within a makefile.
+
+    For the moment, locations are just path/line/column, but in the future
+    they may reference parent locations for more accurate "included from"
+    or "evaled at" error reporting.
+    """
+    __slots__ = ('path', 'line', 'column')
+
+    def __init__(self, path, line, column):
+        self.path = path
+        self.line = line
+        self.column = column
+
+    def offset(self, s, start, end):
+        """
+        Returns a new location offset by
+        the specified string.
+        """
+
+        if start == end:
+            return self
+
+        skiplines = s.count('\n', start, end)
+        line = self.line + skiplines
+        if skiplines:
+            lastnl = s.rfind('\n', start, end)
+            assert lastnl != -1
+            start = lastnl + 1
+            column = 0
+        else:
+            column = self.column
+
+        while True:
+            j = s.find('\t', start, end)
+            if j == -1:
+                column += end - start
+                break
+
+            column += j - start
+            column += _tabwidth
+            column -= column % _tabwidth
+            start = j + 1
+
+        return Location(self.path, line, column)
+
+    def __str__(self):
+        return "%s:%s:%s" % (self.path, self.line, self.column)
+
+def _expandwildcards(makefile, tlist):
+    for t in tlist:
+        if not hasglob(t):
+            yield t
+        else:
+            l = glob(makefile.workdir, t)
+            for r in l:
+                yield r
+
+_flagescape = re.compile(r'([\s\\])')
+
+def parsecommandlineargs(args):
+    """
+    Given a set of arguments from a command-line invocation of make,
+    parse out the variable definitions and return (stmts, arglist, overridestr)
+    """
+
+    overrides = []
+    stmts = StatementList()
+    r = []
+    for i in xrange(0, len(args)):
+        a = args[i]
+
+        vname, t, val = util.strpartition(a, ':=')
+        if t == '':
+            vname, t, val = util.strpartition(a, '=')
+        if t != '':
+            overrides.append(_flagescape.sub(r'\\\1', a))
+
+            vname = vname.strip()
+            vnameexp = data.Expansion.fromstring(vname, "Command-line argument")
+
+            stmts.append(ExportDirective(vnameexp, concurrent_set=True))
+            stmts.append(SetVariable(vnameexp, token=t,
+                                     value=val, valueloc=Location('<command-line>', i, len(vname) + len(t)),
+                                     targetexp=None, source=data.Variables.SOURCE_COMMANDLINE))
+        else:
+            r.append(data.stripdotslash(a))
+
+    return stmts, r, ' '.join(overrides)
+
+class Statement(object):
+    """
+    Represents parsed make file syntax.
+
+    This is an abstract base class. Child classes are expected to implement
+    basic methods defined below.
+    """
+
+    def execute(self, makefile, context):
+        """Executes this Statement within a make file execution context."""
+        raise Exception("%s must implement execute()." % self.__class__)
+
+    def to_source(self):
+        """Obtain the make file "source" representation of the Statement.
+
+        This converts an individual Statement back to a string that can again
+        be parsed into this Statement.
+        """
+        raise Exception("%s must implement to_source()." % self.__class__)
+
+    def __eq__(self, other):
+        raise Exception("%s must implement __eq__." % self.__class__)
+
+    def __ne__(self, other):
+        return self.__eq__(other)
+
+class DummyRule(object):
+    __slots__ = ()
+
+    def addcommand(self, r):
+        pass
+
+class Rule(Statement):
+    """
+    Rules represent how to make specific targets.
+
+    See https://www.gnu.org/software/make/manual/make.html#Rules.
+
+    An individual rule is composed of a target, dependencies, and a recipe.
+    This class only contains references to the first 2. The recipe will be
+    contained in Command classes which follow this one in a stream of Statement
+    instances.
+
+    Instances also contain a boolean property `doublecolon` which says whether
+    this is a doublecolon rule. Doublecolon rules are rules that are always
+    executed, if they are evaluated. Normally, rules are only executed if their
+    target is out of date.
+    """
+    __slots__ = ('targetexp', 'depexp', 'doublecolon')
+
+    def __init__(self, targetexp, depexp, doublecolon):
+        assert isinstance(targetexp, (data.Expansion, data.StringExpansion))
+        assert isinstance(depexp, (data.Expansion, data.StringExpansion))
+
+        self.targetexp = targetexp
+        self.depexp = depexp
+        self.doublecolon = doublecolon
+
+    def execute(self, makefile, context):
+        if context.weak:
+            self._executeweak(makefile, context)
+        else:
+            self._execute(makefile, context)
+
+    def _executeweak(self, makefile, context):
+        """
+        If the context is weak (we're just handling dependencies) we can make a number of assumptions here.
+        This lets us go really fast and is generally good.
+        """
+        assert context.weak
+        deps = self.depexp.resolvesplit(makefile, makefile.variables)
+        # Skip targets with no rules and no dependencies
+        if not deps:
+            return
+        targets = data.stripdotslashes(self.targetexp.resolvesplit(makefile, makefile.variables))
+        rule = data.Rule(list(data.stripdotslashes(deps)), self.doublecolon, loc=self.targetexp.loc, weakdeps=True)
+        for target in targets:
+            makefile.gettarget(target).addrule(rule)
+            makefile.foundtarget(target)
+        context.currule = rule
+
+    def _execute(self, makefile, context):
+        assert not context.weak
+
+        atargets = data.stripdotslashes(self.targetexp.resolvesplit(makefile, makefile.variables))
+        targets = [data.Pattern(p) for p in _expandwildcards(makefile, atargets)]
+
+        if not len(targets):
+            context.currule = DummyRule()
+            return
+
+        ispatterns = set((t.ispattern() for t in targets))
+        if len(ispatterns) == 2:
+            raise data.DataError("Mixed implicit and normal rule", self.targetexp.loc)
+        ispattern, = ispatterns
+
+        deps = list(_expandwildcards(makefile, data.stripdotslashes(self.depexp.resolvesplit(makefile, makefile.variables))))
+        if ispattern:
+            rule = data.PatternRule(targets, map(data.Pattern, deps), self.doublecolon, loc=self.targetexp.loc)
+            makefile.appendimplicitrule(rule)
+        else:
+            rule = data.Rule(deps, self.doublecolon, loc=self.targetexp.loc, weakdeps=False)
+            for t in targets:
+                makefile.gettarget(t.gettarget()).addrule(rule)
+
+            makefile.foundtarget(targets[0].gettarget())
+
+        context.currule = rule
+
+    def dump(self, fd, indent):
+        print >>fd, "%sRule %s: %s" % (indent, self.targetexp, self.depexp)
+
+    def to_source(self):
+        sep = ':'
+
+        if self.doublecolon:
+            sep = '::'
+
+        deps = self.depexp.to_source()
+        if len(deps) > 0 and not deps[0].isspace():
+            sep += ' '
+
+        return '\n%s%s%s' % (
+            self.targetexp.to_source(escape_variables=True),
+            sep,
+            deps)
+
+    def __eq__(self, other):
+        if not isinstance(other, Rule):
+            return False
+
+        return self.targetexp == other.targetexp \
+                and self.depexp == other.depexp \
+                and self.doublecolon == other.doublecolon
+
+class StaticPatternRule(Statement):
+    """
+    Static pattern rules are rules which specify multiple targets based on a
+    string pattern.
+
+    See https://www.gnu.org/software/make/manual/make.html#Static-Pattern
+
+    They are like `Rule` instances except an added property, `patternexp` is
+    present. It contains the Expansion which represents the rule pattern.
+    """
+    __slots__ = ('targetexp', 'patternexp', 'depexp', 'doublecolon')
+
+    def __init__(self, targetexp, patternexp, depexp, doublecolon):
+        assert isinstance(targetexp, (data.Expansion, data.StringExpansion))
+        assert isinstance(patternexp, (data.Expansion, data.StringExpansion))
+        assert isinstance(depexp, (data.Expansion, data.StringExpansion))
+
+        self.targetexp = targetexp
+        self.patternexp = patternexp
+        self.depexp = depexp
+        self.doublecolon = doublecolon
+
+    def execute(self, makefile, context):
+        if context.weak:
+            raise data.DataError("Static pattern rules not allowed in includedeps", self.targetexp.loc)
+
+        targets = list(_expandwildcards(makefile, data.stripdotslashes(self.targetexp.resolvesplit(makefile, makefile.variables))))
+
+        if not len(targets):
+            context.currule = DummyRule()
+            return
+
+        patterns = list(data.stripdotslashes(self.patternexp.resolvesplit(makefile, makefile.variables)))
+        if len(patterns) != 1:
+            raise data.DataError("Static pattern rules must have a single pattern", self.patternexp.loc)
+        pattern = data.Pattern(patterns[0])
+
+        deps = [data.Pattern(p) for p in _expandwildcards(makefile, data.stripdotslashes(self.depexp.resolvesplit(makefile, makefile.variables)))]
+
+        rule = data.PatternRule([pattern], deps, self.doublecolon, loc=self.targetexp.loc)
+
+        for t in targets:
+            if data.Pattern(t).ispattern():
+                raise data.DataError("Target '%s' of a static pattern rule must not be a pattern" % (t,), self.targetexp.loc)
+            stem = pattern.match(t)
+            if stem is None:
+                raise data.DataError("Target '%s' does not match the static pattern '%s'" % (t, pattern), self.targetexp.loc)
+            makefile.gettarget(t).addrule(data.PatternRuleInstance(rule, '', stem, pattern.ismatchany()))
+
+        makefile.foundtarget(targets[0])
+        context.currule = rule
+
+    def dump(self, fd, indent):
+        print >>fd, "%sStaticPatternRule %s: %s: %s" % (indent, self.targetexp, self.patternexp, self.depexp)
+
+    def to_source(self):
+        sep = ':'
+
+        if self.doublecolon:
+            sep = '::'
+
+        pattern = self.patternexp.to_source()
+        deps = self.depexp.to_source()
+
+        if len(pattern) > 0 and pattern[0] not in (' ', '\t'):
+            sep += ' '
+
+        return '\n%s%s%s:%s' % (
+            self.targetexp.to_source(escape_variables=True),
+            sep,
+            pattern,
+            deps)
+
+    def __eq__(self, other):
+        if not isinstance(other, StaticPatternRule):
+            return False
+
+        return self.targetexp == other.targetexp \
+                and self.patternexp == other.patternexp \
+                and self.depexp == other.depexp \
+                and self.doublecolon == other.doublecolon
+
+class Command(Statement):
+    """
+    Commands are things that get executed by a rule.
+
+    A rule's recipe is composed of 0 or more Commands.
+
+    A command is simply an expansion. Commands typically represent strings to
+    be executed in a shell (e.g. via system()). Although, since make files
+    allow arbitrary shells to be used for command execution, this isn't a
+    guarantee.
+    """
+    __slots__ = ('exp',)
+
+    def __init__(self, exp):
+        assert isinstance(exp, (data.Expansion, data.StringExpansion))
+        self.exp = exp
+
+    def execute(self, makefile, context):
+        assert context.currule is not None
+        if context.weak:
+            raise data.DataError("rules not allowed in includedeps", self.exp.loc)
+
+        context.currule.addcommand(self.exp)
+
+    def dump(self, fd, indent):
+        print >>fd, "%sCommand %s" % (indent, self.exp,)
+
+    def to_source(self):
+        # Commands have some interesting quirks when it comes to source
+        # formatting. First, they can be multi-line. Second, a tab needs to be
+        # inserted at the beginning of every line. Finally, there might be
+        # variable references inside the command. This means we need to escape
+        # variable references inside command strings. Luckily, this is handled
+        # by the Expansion.
+        s = self.exp.to_source(escape_variables=True)
+
+        return '\n'.join(['\t%s' % line for line in s.split('\n')])
+
+    def __eq__(self, other):
+        if not isinstance(other, Command):
+            return False
+
+        return self.exp == other.exp
+
+class SetVariable(Statement):
+    """
+    Represents a variable assignment.
+
+    Variable assignment comes in two different flavors.
+
+    Simple assignment has the form:
+
+      <Expansion> <Assignment Token> <string>
+
+    e.g. FOO := bar
+
+    These correspond to the fields `vnameexp`, `token`, and `value`. In
+    addition, `valueloc` will be a Location and `source` will be a
+    pymake.data.Variables.SOURCE_* constant.
+
+    There are also target-specific variables. These are variables that only
+    apply in the context of a specific target. They are like the aforementioned
+    assignment except the `targetexp` field is set to an Expansion representing
+    the target they apply to.
+    """
+    __slots__ = ('vnameexp', 'token', 'value', 'valueloc', 'targetexp', 'source')
+
+    def __init__(self, vnameexp, token, value, valueloc, targetexp, source=None):
+        assert isinstance(vnameexp, (data.Expansion, data.StringExpansion))
+        assert isinstance(value, str)
+        assert targetexp is None or isinstance(targetexp, (data.Expansion, data.StringExpansion))
+
+        if source is None:
+            source = data.Variables.SOURCE_MAKEFILE
+
+        self.vnameexp = vnameexp
+        self.token = token
+        self.value = value
+        self.valueloc = valueloc
+        self.targetexp = targetexp
+        self.source = source
+
+    def execute(self, makefile, context):
+        vname = self.vnameexp.resolvestr(makefile, makefile.variables)
+        if len(vname) == 0:
+            raise data.DataError("Empty variable name", self.vnameexp.loc)
+
+        if self.targetexp is None:
+            setvariables = [makefile.variables]
+        else:
+            setvariables = []
+
+            targets = [data.Pattern(t) for t in data.stripdotslashes(self.targetexp.resolvesplit(makefile, makefile.variables))]
+            for t in targets:
+                if t.ispattern():
+                    setvariables.append(makefile.getpatternvariables(t))
+                else:
+                    setvariables.append(makefile.gettarget(t.gettarget()).variables)
+
+        for v in setvariables:
+            if self.token == '+=':
+                v.append(vname, self.source, self.value, makefile.variables, makefile)
+                continue
+
+            if self.token == '?=':
+                flavor = data.Variables.FLAVOR_RECURSIVE
+                oldflavor, oldsource, oldval = v.get(vname, expand=False)
+                if oldval is not None:
+                    continue
+                value = self.value
+            elif self.token == '=':
+                flavor = data.Variables.FLAVOR_RECURSIVE
+                value = self.value
+            else:
+                assert self.token == ':='
+
+                flavor = data.Variables.FLAVOR_SIMPLE
+                d = parser.Data.fromstring(self.value, self.valueloc)
+                e, t, o = parser.parsemakesyntax(d, 0, (), parser.iterdata)
+                value = e.resolvestr(makefile, makefile.variables)
+
+            v.set(vname, flavor, self.source, value)
+
+    def dump(self, fd, indent):
+        print >>fd, "%sSetVariable<%s> %s %s\n%s %r" % (indent, self.valueloc, self.vnameexp, self.token, indent, self.value)
+
+    def __eq__(self, other):
+        if not isinstance(other, SetVariable):
+            return False
+
+        return self.vnameexp == other.vnameexp \
+                and self.token == other.token \
+                and self.value == other.value \
+                and self.targetexp == other.targetexp \
+                and self.source == other.source
+
+    def to_source(self):
+        chars = []
+        for i in xrange(0, len(self.value)):
+            c = self.value[i]
+
+            # Literal # is escaped in variable assignment otherwise it would be
+            # a comment.
+            if c == '#':
+                # If a backslash precedes this, we need to escape it as well.
+                if i > 0 and self.value[i-1] == '\\':
+                    chars.append('\\')
+
+                chars.append('\\#')
+                continue
+
+            chars.append(c)
+
+        value = ''.join(chars)
+
+        prefix = ''
+        if self.source == data.Variables.SOURCE_OVERRIDE:
+            prefix = 'override '
+
+        # SetVariable come in two flavors: simple and target-specific.
+
+        # We handle the target-specific syntax first.
+        if self.targetexp is not None:
+            return '%s: %s %s %s' % (
+                self.targetexp.to_source(),
+                self.vnameexp.to_source(),
+                self.token,
+                value)
+
+        # The variable could be multi-line or have leading whitespace. For
+        # regular variable assignment, whitespace after the token but before
+        # the value is ignored. If we see leading whitespace in the value here,
+        # the variable must have come from a define.
+        if value.count('\n') > 0 or (len(value) and value[0].isspace()):
+            # The parser holds the token in vnameexp for whatever reason.
+            return '%sdefine %s\n%s\nendef' % (
+                prefix,
+                self.vnameexp.to_source(),
+                value)
+
+        return '%s%s %s %s' % (
+                prefix,
+                self.vnameexp.to_source(),
+                self.token,
+                value)
+
+class Condition(object):
+    """
+    An abstract "condition", either ifeq or ifdef, perhaps negated.
+
+    See https://www.gnu.org/software/make/manual/make.html#Conditional-Syntax
+
+    Subclasses must implement:
+
+    def evaluate(self, makefile)
+    """
+
+    def __eq__(self, other):
+        raise Exception("%s must implement __eq__." % __class__)
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+class EqCondition(Condition):
+    """
+    Represents an ifeq or ifneq conditional directive.
+
+    This directive consists of two Expansions which are compared for equality.
+
+    The `expected` field is a bool indicating what the condition must evaluate
+    to in order for its body to be executed. If True, this is an "ifeq"
+    conditional directive. If False, an "ifneq."
+    """
+    __slots__ = ('exp1', 'exp2', 'expected')
+
+    def __init__(self, exp1, exp2):
+        assert isinstance(exp1, (data.Expansion, data.StringExpansion))
+        assert isinstance(exp2, (data.Expansion, data.StringExpansion))
+
+        self.expected = True
+        self.exp1 = exp1
+        self.exp2 = exp2
+
+    def evaluate(self, makefile):
+        r1 = self.exp1.resolvestr(makefile, makefile.variables)
+        r2 = self.exp2.resolvestr(makefile, makefile.variables)
+        return (r1 == r2) == self.expected
+
+    def __str__(self):
+        return "ifeq (expected=%s) %s %s" % (self.expected, self.exp1, self.exp2)
+
+    def __eq__(self, other):
+        if not isinstance(other, EqCondition):
+            return False
+
+        return self.exp1 == other.exp1 \
+                and self.exp2 == other.exp2 \
+                and self.expected == other.expected
+
+class IfdefCondition(Condition):
+    """
+    Represents an ifdef or ifndef conditional directive.
+
+    This directive consists of a single expansion which represents the name of
+    a variable (without the leading '$') which will be checked for definition.
+
+    The `expected` field is a bool and has the same behavior as EqCondition.
+    If it is True, this represents a "ifdef" conditional. If False, "ifndef."
+    """
+    __slots__ = ('exp', 'expected')
+
+    def __init__(self, exp):
+        assert isinstance(exp, (data.Expansion, data.StringExpansion))
+        self.exp = exp
+        self.expected = True
+
+    def evaluate(self, makefile):
+        vname = self.exp.resolvestr(makefile, makefile.variables)
+        flavor, source, value = makefile.variables.get(vname, expand=False)
+
+        if value is None:
+            return not self.expected
+
+        return (len(value) > 0) == self.expected
+
+    def __str__(self):
+        return "ifdef (expected=%s) %s" % (self.expected, self.exp)
+
+    def __eq__(self, other):
+        if not isinstance(other, IfdefCondition):
+            return False
+
+        return self.exp == other.exp and self.expected == other.expected
+
+class ElseCondition(Condition):
+    """
+    Represents the transition between branches in a ConditionBlock.
+    """
+    __slots__ = ()
+
+    def evaluate(self, makefile):
+        return True
+
+    def __str__(self):
+        return "else"
+
+    def __eq__(self, other):
+        return isinstance(other, ElseCondition)
+
+class ConditionBlock(Statement):
+    """
+    A set of related Conditions.
+
+    This is essentially a list of 2-tuples of (Condition, list(Statement)).
+
+    The parser creates a ConditionBlock for all statements related to the same
+    conditional group. If iterating over the parser's output, where you think
+    you would see an ifeq, you will see a ConditionBlock containing an IfEq. In
+    other words, the parser collapses separate statements into this container
+    class.
+
+    ConditionBlock instances may exist within other ConditionBlock if the
+    conditional logic is multiple levels deep.
+    """
+    __slots__ = ('loc', '_groups')
+
+    def __init__(self, loc, condition):
+        self.loc = loc
+        self._groups = []
+        self.addcondition(loc, condition)
+
+    def getloc(self):
+        return self.loc
+
+    def addcondition(self, loc, condition):
+        assert isinstance(condition, Condition)
+        condition.loc = loc
+
+        if len(self._groups) and isinstance(self._groups[-1][0], ElseCondition):
+            raise parser.SyntaxError("Multiple else conditions for block starting at %s" % self.loc, loc)
+
+        self._groups.append((condition, StatementList()))
+
+    def append(self, statement):
+        self._groups[-1][1].append(statement)
+
+    def execute(self, makefile, context):
+        i = 0
+        for c, statements in self._groups:
+            if c.evaluate(makefile):
+                _log.debug("Condition at %s met by clause #%i", self.loc, i)
+                statements.execute(makefile, context)
+                return
+
+            i += 1
+
+    def dump(self, fd, indent):
+        print >>fd, "%sConditionBlock" % (indent,)
+
+        indent2 = indent + '  '
+        for c, statements in self._groups:
+            print >>fd, "%s Condition %s" % (indent, c)
+            statements.dump(fd, indent2)
+            print >>fd, "%s ~Condition" % (indent,)
+        print >>fd, "%s~ConditionBlock" % (indent,)
+
+    def to_source(self):
+        lines = []
+        index = 0
+        for condition, statements in self:
+            lines.append(ConditionBlock.condition_source(condition, index))
+            index += 1
+
+            for statement in statements:
+                lines.append(statement.to_source())
+
+        lines.append('endif')
+
+        return '\n'.join(lines)
+
+    def __eq__(self, other):
+        if not isinstance(other, ConditionBlock):
+            return False
+
+        if len(self) != len(other):
+            return False
+
+        for i in xrange(0, len(self)):
+            our_condition, our_statements = self[i]
+            other_condition, other_statements = other[i]
+
+            if our_condition != other_condition:
+                return False
+
+            if our_statements != other_statements:
+                return False
+
+        return True
+
+    @staticmethod
+    def condition_source(statement, index):
+        """Convert a condition to its source representation.
+
+        The index argument defines the index of this condition inside a
+        ConditionBlock. If it is greater than 0, an "else" will be prepended
+        to the result, if necessary.
+        """
+        prefix = ''
+        if isinstance(statement, (EqCondition, IfdefCondition)) and index > 0:
+            prefix = 'else '
+
+        if isinstance(statement, IfdefCondition):
+            s = statement.exp.s
+
+            if statement.expected:
+                return '%sifdef %s' % (prefix, s)
+
+            return '%sifndef %s' % (prefix, s)
+
+        if isinstance(statement, EqCondition):
+            args = [
+                statement.exp1.to_source(escape_comments=True),
+                statement.exp2.to_source(escape_comments=True)]
+
+            use_quotes = False
+            single_quote_present = False
+            double_quote_present = False
+            for i, arg in enumerate(args):
+                if len(arg) > 0 and (arg[0].isspace() or arg[-1].isspace()):
+                    use_quotes = True
+
+                    if "'" in arg:
+                        single_quote_present = True
+
+                    if '"' in arg:
+                        double_quote_present = True
+
+            # Quote everything if needed.
+            if single_quote_present and double_quote_present:
+                raise Exception('Cannot format condition with multiple quotes.')
+
+            if use_quotes:
+                for i, arg in enumerate(args):
+                    # Double to single quotes.
+                    if single_quote_present:
+                        args[i] = '"' + arg + '"'
+                    else:
+                        args[i] = "'" + arg + "'"
+
+            body = None
+            if use_quotes:
+                body = ' '.join(args)
+            else:
+                body = '(%s)' % ','.join(args)
+
+            if statement.expected:
+                return '%sifeq %s' % (prefix, body)
+
+            return '%sifneq %s' % (prefix, body)
+
+        if isinstance(statement, ElseCondition):
+            return 'else'
+
+        raise Exception('Unhandled Condition statement: %s' %
+                statement.__class__)
+
+    def __iter__(self):
+        return iter(self._groups)
+
+    def __len__(self):
+        return len(self._groups)
+
+    def __getitem__(self, i):
+        return self._groups[i]
+
+class Include(Statement):
+    """
+    Represents the include directive.
+
+    See https://www.gnu.org/software/make/manual/make.html#Include
+
+    The file to be included is represented by the Expansion defined in the
+    field `exp`. `required` is a bool indicating whether execution should fail
+    if the specified file could not be processed.
+    """
+    __slots__ = ('exp', 'required', 'deps')
+
+    def __init__(self, exp, required, weak):
+        assert isinstance(exp, (data.Expansion, data.StringExpansion))
+        self.exp = exp
+        self.required = required
+        self.weak = weak
+
+    def execute(self, makefile, context):
+        files = self.exp.resolvesplit(makefile, makefile.variables)
+        for f in files:
+            makefile.include(f, self.required, loc=self.exp.loc, weak=self.weak)
+
+    def dump(self, fd, indent):
+        print >>fd, "%sInclude %s" % (indent, self.exp)
+
+    def to_source(self):
+        prefix = ''
+
+        if not self.required:
+            prefix = '-'
+
+        return '%sinclude %s' % (prefix, self.exp.to_source())
+
+    def __eq__(self, other):
+        if not isinstance(other, Include):
+            return False
+
+        return self.exp == other.exp and self.required == other.required
+
+class VPathDirective(Statement):
+    """
+    Represents the vpath directive.
+
+    See https://www.gnu.org/software/make/manual/make.html#Selective-Search
+    """
+    __slots__ = ('exp',)
+
+    def __init__(self, exp):
+        assert isinstance(exp, (data.Expansion, data.StringExpansion))
+        self.exp = exp
+
+    def execute(self, makefile, context):
+        words = list(data.stripdotslashes(self.exp.resolvesplit(makefile, makefile.variables)))
+        if len(words) == 0:
+            makefile.clearallvpaths()
+        else:
+            pattern = data.Pattern(words[0])
+            mpaths = words[1:]
+
+            if len(mpaths) == 0:
+                makefile.clearvpath(pattern)
+            else:
+                dirs = []
+                for mpath in mpaths:
+                    dirs.extend((dir for dir in mpath.split(os.pathsep)
+                                 if dir != ''))
+                if len(dirs):
+                    makefile.addvpath(pattern, dirs)
+
+    def dump(self, fd, indent):
+        print >>fd, "%sVPath %s" % (indent, self.exp)
+
+    def to_source(self):
+        return 'vpath %s' % self.exp.to_source()
+
+    def __eq__(self, other):
+        if not isinstance(other, VPathDirective):
+            return False
+
+        return self.exp == other.exp
+
+class ExportDirective(Statement):
+    """
+    Represents the "export" directive.
+
+    This is used to control exporting variables to sub makes.
+
+    See https://www.gnu.org/software/make/manual/make.html#Variables_002fRecursion
+
+    The `concurrent_set` field defines whether this statement occurred with or
+    without a variable assignment. If False, no variable assignment was
+    present. If True, the SetVariable immediately following this statement
+    originally came from this export directive (the parser splits it into
+    multiple statements).
+    """
+
+    __slots__ = ('exp', 'concurrent_set')
+
+    def __init__(self, exp, concurrent_set):
+        assert isinstance(exp, (data.Expansion, data.StringExpansion))
+        self.exp = exp
+        self.concurrent_set = concurrent_set
+
+    def execute(self, makefile, context):
+        if self.concurrent_set:
+            vlist = [self.exp.resolvestr(makefile, makefile.variables)]
+        else:
+            vlist = list(self.exp.resolvesplit(makefile, makefile.variables))
+            if not len(vlist):
+                raise data.DataError("Exporting all variables is not supported", self.exp.loc)
+
+        for v in vlist:
+            makefile.exportedvars[v] = True
+
+    def dump(self, fd, indent):
+        print >>fd, "%sExport (single=%s) %s" % (indent, self.single, self.exp)
+
+    def to_source(self):
+        return ('export %s' % self.exp.to_source()).rstrip()
+
+    def __eq__(self, other):
+        if not isinstance(other, ExportDirective):
+            return False
+
+        # single is irrelevant because it just says whether the next Statement
+        # contains a variable definition.
+        return self.exp == other.exp
+
+class UnexportDirective(Statement):
+    """
+    Represents the "unexport" directive.
+
+    This is the opposite of ExportDirective.
+    """
+    __slots__ = ('exp',)
+
+    def __init__(self, exp):
+        self.exp = exp
+
+    def execute(self, makefile, context):
+        vlist = list(self.exp.resolvesplit(makefile, makefile.variables))
+        for v in vlist:
+            makefile.exportedvars[v] = False
+
+    def dump(self, fd, indent):
+        print >>fd, "%sUnexport %s" % (indent, self.exp)
+
+    def to_source(self):
+        return 'unexport %s' % self.exp.to_source()
+
+    def __eq__(self, other):
+        if not isinstance(other, UnexportDirective):
+            return False
+
+        return self.exp == other.exp
+
+class EmptyDirective(Statement):
+    """
+    Represents a standalone statement, usually an Expansion.
+
+    You will encounter EmptyDirective instances if there is a function
+    or similar at the top-level of a make file (e.g. outside of a rule or
+    variable assignment). You can also find them as the bodies of
+    ConditionBlock branches.
+    """
+    __slots__ = ('exp',)
+
+    def __init__(self, exp):
+        assert isinstance(exp, (data.Expansion, data.StringExpansion))
+        self.exp = exp
+
+    def execute(self, makefile, context):
+        v = self.exp.resolvestr(makefile, makefile.variables)
+        if v.strip() != '':
+            raise data.DataError("Line expands to non-empty value", self.exp.loc)
+
+    def dump(self, fd, indent):
+        print >>fd, "%sEmptyDirective: %s" % (indent, self.exp)
+
+    def to_source(self):
+        return self.exp.to_source()
+
+    def __eq__(self, other):
+        if not isinstance(other, EmptyDirective):
+            return False
+
+        return self.exp == other.exp
+
+class _EvalContext(object):
+    __slots__ = ('currule', 'weak')
+
+    def __init__(self, weak):
+        self.weak = weak
+
+class StatementList(list):
+    """
+    A list of Statement instances.
+
+    This is what is generated by the parser when a make file is parsed.
+
+    Consumers can iterate over all Statement instances in this collection to
+    statically inspect (and even modify) make files before they are executed.
+    """
+    __slots__ = ('mtime',)
+
+    def append(self, statement):
+        assert isinstance(statement, Statement)
+        list.append(self, statement)
+
+    def execute(self, makefile, context=None, weak=False):
+        if context is None:
+            context = _EvalContext(weak=weak)
+
+        for s in self:
+            s.execute(makefile, context)
+
+    def dump(self, fd, indent):
+        for s in self:
+            s.dump(fd, indent)
+
+    def __str__(self):
+        fd = StringIO()
+        self.dump(fd, '')
+        return fd.getvalue()
+
+    def to_source(self):
+        return '\n'.join([s.to_source() for s in self])
+
+def iterstatements(stmts):
+    for s in stmts:
+        yield s
+        if isinstance(s, ConditionBlock):
+            for c, sl in s:
+                for s2 in iterstatments(sl): yield s2
diff --git a/src/third_party/mozjs-45/build/pymake/pymake/process.py b/src/third_party/mozjs-45/build/pymake/pymake/process.py
new file mode 100644
index 0000000..01cadf5
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/pymake/process.py
@@ -0,0 +1,556 @@
+"""
+Skipping shell invocations is good, when possible. This wrapper around subprocess does dirty work of
+parsing command lines into argv and making sure that no shell magic is being used.
+"""
+
+#TODO: ship pyprocessing?
+import multiprocessing
+import subprocess, shlex, re, logging, sys, traceback, os, imp, glob
+import site
+from collections import deque
+# XXXkhuey Work around http://bugs.python.org/issue1731717
+subprocess._cleanup = lambda: None
+import command, util
+if sys.platform=='win32':
+    import win32process
+
+_log = logging.getLogger('pymake.process')
+
+_escapednewlines = re.compile(r'\\\n')
+
+def tokens2re(tokens):
+    # Create a pattern for non-escaped tokens, in the form:
+    #   (?<!\\)(?:a|b|c...)
+    # This is meant to match patterns a, b, or c, or ... if they are not
+    # preceded by a backslash.
+    # where a, b, c... are in the form
+    #   (?P<name>pattern)
+    # which matches the pattern and captures it in a named match group.
+    # The group names and patterns come are given as a dict in the function
+    # argument.
+    nonescaped = r'(?<!\\)(?:%s)' % '|'.join('(?P<%s>%s)' % (name, value) for name, value in tokens.iteritems())
+    # The final pattern matches either the above pattern, or an escaped
+    # backslash, captured in the "escape" match group.
+    return re.compile('(?:%s|%s)' % (nonescaped, r'(?P<escape>\\\\)'))
+
+_unquoted_tokens = tokens2re({
+  'whitespace': r'[\t\r\n ]+',
+  'quote': r'[\'"]',
+  'comment': '#',
+  'special': r'[<>&|`~(){}$;]',
+  'backslashed': r'\\[^\\]',
+  'glob': r'[\*\?]',
+})
+
+_doubly_quoted_tokens = tokens2re({
+  'quote': '"',
+  'backslashedquote': r'\\"',
+  'special': '\$',
+  'backslashed': r'\\[^\\"]',
+})
+
+class MetaCharacterException(Exception):
+    def __init__(self, char):
+        self.char = char
+
+class ClineSplitter(list):
+    """
+    Parses a given command line string and creates a list of command
+    and arguments, with wildcard expansion.
+    """
+    def __init__(self, cline, cwd):
+        self.cwd = cwd
+        self.arg = None
+        self.cline = cline
+        self.glob = False
+        self._parse_unquoted()
+
+    def _push(self, str):
+        """
+        Push the given string as part of the current argument
+        """
+        if self.arg is None:
+            self.arg = ''
+        self.arg += str
+
+    def _next(self):
+        """
+        Finalize current argument, effectively adding it to the list.
+        Perform globbing if needed.
+        """
+        if self.arg is None:
+            return
+        if self.glob:
+            if os.path.isabs(self.arg):
+                path = self.arg
+            else:
+                path = os.path.join(self.cwd, self.arg)
+            globbed = glob.glob(path)
+            if not globbed:
+                # If globbing doesn't find anything, the literal string is
+                # used.
+                self.append(self.arg)
+            else:
+                self.extend(f[len(path)-len(self.arg):] for f in globbed)
+            self.glob = False
+        else:
+            self.append(self.arg)
+        self.arg = None
+
+    def _parse_unquoted(self):
+        """
+        Parse command line remainder in the context of an unquoted string.
+        """
+        while self.cline:
+            # Find the next token
+            m = _unquoted_tokens.search(self.cline)
+            # If we find none, the remainder of the string can be pushed to
+            # the current argument and the argument finalized
+            if not m:
+                self._push(self.cline)
+                break
+            # The beginning of the string, up to the found token, is part of
+            # the current argument
+            if m.start():
+                self._push(self.cline[:m.start()])
+            self.cline = self.cline[m.end():]
+
+            match = dict([(name, value) for name, value in m.groupdict().items() if value])
+            if 'quote' in match:
+                # " or ' start a quoted string
+                if match['quote'] == '"':
+                    self._parse_doubly_quoted()
+                else:
+                    self._parse_quoted()
+            elif 'comment' in match:
+                # Comments are ignored. The current argument can be finalized,
+                # and parsing stopped.
+                break
+            elif 'special' in match:
+                # Unquoted, non-escaped special characters need to be sent to a
+                # shell.
+                raise MetaCharacterException, match['special']
+            elif 'whitespace' in match:
+                # Whitespaces terminate current argument.
+                self._next()
+            elif 'escape' in match:
+                # Escaped backslashes turn into a single backslash
+                self._push('\\')
+            elif 'backslashed' in match:
+                # Backslashed characters are unbackslashed
+                # e.g. echo \a -> a
+                self._push(match['backslashed'][1])
+            elif 'glob' in match:
+                # ? or * will need globbing
+                self.glob = True
+                self._push(m.group(0))
+            else:
+                raise Exception, "Shouldn't reach here"
+        if self.arg:
+            self._next()
+
+    def _parse_quoted(self):
+        # Single quoted strings are preserved, except for the final quote
+        index = self.cline.find("'")
+        if index == -1:
+            raise Exception, 'Unterminated quoted string in command'
+        self._push(self.cline[:index])
+        self.cline = self.cline[index+1:]
+
+    def _parse_doubly_quoted(self):
+        if not self.cline:
+            raise Exception, 'Unterminated quoted string in command'
+        while self.cline:
+            m = _doubly_quoted_tokens.search(self.cline)
+            if not m:
+                raise Exception, 'Unterminated quoted string in command'
+            self._push(self.cline[:m.start()])
+            self.cline = self.cline[m.end():]
+            match = dict([(name, value) for name, value in m.groupdict().items() if value])
+            if 'quote' in match:
+                # a double quote ends the quoted string, so go back to
+                # unquoted parsing
+                return
+            elif 'special' in match:
+                # Unquoted, non-escaped special characters in a doubly quoted
+                # string still have a special meaning and need to be sent to a
+                # shell.
+                raise MetaCharacterException, match['special']
+            elif 'escape' in match:
+                # Escaped backslashes turn into a single backslash
+                self._push('\\')
+            elif 'backslashedquote' in match:
+                # Backslashed double quotes are un-backslashed
+                self._push('"')
+            elif 'backslashed' in match:
+                # Backslashed characters are kept backslashed
+                self._push(match['backslashed'])
+
+def clinetoargv(cline, cwd):
+    """
+    If this command line can safely skip the shell, return an argv array.
+    @returns argv, badchar
+    """
+    str = _escapednewlines.sub('', cline)
+    try:
+        args = ClineSplitter(str, cwd)
+    except MetaCharacterException, e:
+        return None, e.char
+
+    if len(args) and args[0].find('=') != -1:
+        return None, '='
+
+    return args, None
+
+# shellwords contains a set of shell builtin commands that need to be
+# executed within a shell. It also contains a set of commands that are known
+# to be giving problems when run directly instead of through the msys shell.
+shellwords = (':', '.', 'break', 'cd', 'continue', 'exec', 'exit', 'export',
+              'getopts', 'hash', 'pwd', 'readonly', 'return', 'shift', 
+              'test', 'times', 'trap', 'umask', 'unset', 'alias',
+              'set', 'bind', 'builtin', 'caller', 'command', 'declare',
+              'echo', 'enable', 'help', 'let', 'local', 'logout', 
+              'printf', 'read', 'shopt', 'source', 'type', 'typeset',
+              'ulimit', 'unalias', 'set', 'find')
+
+def prepare_command(cline, cwd, loc):
+    """
+    Returns a list of command and arguments for the given command line string.
+    If the command needs to be run through a shell for some reason, the
+    returned list contains the shell invocation.
+    """
+
+    #TODO: call this once up-front somewhere and save the result?
+    shell, msys = util.checkmsyscompat()
+
+    shellreason = None
+    executable = None
+    if msys and cline.startswith('/'):
+        shellreason = "command starts with /"
+    else:
+        argv, badchar = clinetoargv(cline, cwd)
+        if argv is None:
+            shellreason = "command contains shell-special character '%s'" % (badchar,)
+        elif len(argv) and argv[0] in shellwords:
+            shellreason = "command starts with shell primitive '%s'" % (argv[0],)
+        elif argv and (os.sep in argv[0] or os.altsep and os.altsep in argv[0]):
+            executable = util.normaljoin(cwd, argv[0])
+            # Avoid "%1 is not a valid Win32 application" errors, assuming
+            # that if the executable path is to be resolved with PATH, it will
+            # be a Win32 executable.
+            if sys.platform == 'win32' and os.path.isfile(executable) and open(executable, 'rb').read(2) == "#!":
+                shellreason = "command executable starts with a hashbang"
+
+    if shellreason is not None:
+        _log.debug("%s: using shell: %s: '%s'", loc, shellreason, cline)
+        if msys:
+            if len(cline) > 3 and cline[1] == ':' and cline[2] == '/':
+                cline = '/' + cline[0] + cline[2:]
+        argv = [shell, "-c", cline]
+        executable = None
+
+    return executable, argv
+
+def call(cline, env, cwd, loc, cb, context, echo, justprint=False):
+    executable, argv = prepare_command(cline, cwd, loc)
+
+    if not len(argv):
+        cb(res=0)
+        return
+
+    if argv[0] == command.makepypath:
+        command.main(argv[1:], env, cwd, cb)
+        return
+
+    if argv[0:2] == [sys.executable.replace('\\', '/'),
+                     command.makepypath.replace('\\', '/')]:
+        command.main(argv[2:], env, cwd, cb)
+        return
+
+    context.call(argv, executable=executable, shell=False, env=env, cwd=cwd, cb=cb,
+                 echo=echo, justprint=justprint)
+
+def call_native(module, method, argv, env, cwd, loc, cb, context, echo, justprint=False,
+                pycommandpath=None):
+    context.call_native(module, method, argv, env=env, cwd=cwd, cb=cb,
+                        echo=echo, justprint=justprint, pycommandpath=pycommandpath)
+
+def statustoresult(status):
+    """
+    Convert the status returned from waitpid into a prettier numeric result.
+    """
+    sig = status & 0xFF
+    if sig:
+        return -sig
+
+    return status >>8
+
+class Job(object):
+    """
+    A single job to be executed on the process pool.
+    """
+    done = False # set to true when the job completes
+
+    def __init__(self):
+        self.exitcode = -127
+
+    def notify(self, condition, result):
+        condition.acquire()
+        self.done = True
+        self.exitcode = result
+        condition.notify()
+        condition.release()
+
+    def get_callback(self, condition):
+        return lambda result: self.notify(condition, result)
+
+class PopenJob(Job):
+    """
+    A job that executes a command using subprocess.Popen.
+    """
+    def __init__(self, argv, executable, shell, env, cwd):
+        Job.__init__(self)
+        self.argv = argv
+        self.executable = executable
+        self.shell = shell
+        self.env = env
+        self.cwd = cwd
+        self.parentpid = os.getpid()
+
+    def run(self):
+        assert os.getpid() != self.parentpid
+        # subprocess.Popen doesn't use the PATH set in the env argument for
+        # finding the executable on some platforms (but strangely it does on
+        # others!), so set os.environ['PATH'] explicitly. This is parallel-
+        # safe because pymake uses separate processes for parallelism, and
+        # each process is serial. See http://bugs.python.org/issue8557 for a
+        # general overview of "subprocess PATH semantics and portability".
+        oldpath = os.environ['PATH']
+        try:
+            if self.env is not None and self.env.has_key('PATH'):
+                os.environ['PATH'] = self.env['PATH']
+            p = subprocess.Popen(self.argv, executable=self.executable, shell=self.shell, env=self.env, cwd=self.cwd)
+            return p.wait()
+        except OSError, e:
+            print >>sys.stderr, e
+            return -127
+        finally:
+            os.environ['PATH'] = oldpath
+
+class PythonException(Exception):
+    def __init__(self, message, exitcode):
+        Exception.__init__(self)
+        self.message = message
+        self.exitcode = exitcode
+
+    def __str__(self):
+        return self.message
+
+
+class PythonJob(Job):
+    """
+    A job that calls a Python method.
+    """
+    def __init__(self, module, method, argv, env, cwd, pycommandpath=None):
+        self.module = module
+        self.method = method
+        self.argv = argv
+        self.env = env
+        self.cwd = cwd
+        self.pycommandpath = pycommandpath or []
+        self.parentpid = os.getpid()
+
+    def run(self):
+        assert os.getpid() != self.parentpid
+        # os.environ is a magic dictionary. Setting it to something else
+        # doesn't affect the environment of subprocesses, so use clear/update
+        oldenv = dict(os.environ)
+
+        # sys.path is adjusted for the entire lifetime of the command
+        # execution. This ensures any delayed imports will still work.
+        oldsyspath = list(sys.path)
+        try:
+            os.chdir(self.cwd)
+            os.environ.clear()
+            os.environ.update(self.env)
+
+            sys.path = []
+            for p in sys.path + self.pycommandpath:
+                site.addsitedir(p)
+            sys.path.extend(oldsyspath)
+
+            if self.module not in sys.modules:
+                try:
+                    __import__(self.module)
+                except Exception as e:
+                    print >>sys.stderr, 'Error importing %s: %s' % (
+                        self.module, e)
+                    return -127
+
+            m = sys.modules[self.module]
+            if self.method not in m.__dict__:
+                print >>sys.stderr, "No method named '%s' in module %s" % (self.method, self.module)
+                return -127
+            rv = m.__dict__[self.method](self.argv)
+            if rv != 0 and rv is not None:
+                print >>sys.stderr, (
+                    "Native command '%s %s' returned value '%s'" %
+                    (self.module, self.method, rv))
+                return (rv if isinstance(rv, int) else 1)
+
+        except PythonException, e:
+            print >>sys.stderr, e
+            return e.exitcode
+        except:
+            e = sys.exc_info()[1]
+            if isinstance(e, SystemExit) and (e.code == 0 or e.code is None):
+                pass # sys.exit(0) is not a failure
+            else:
+                print >>sys.stderr, e
+                traceback.print_exc()
+                return -127
+        finally:
+            os.environ.clear()
+            os.environ.update(oldenv)
+            sys.path = oldsyspath
+            # multiprocessing exits via os._exit, make sure that all output
+            # from command gets written out before that happens.
+            sys.stdout.flush()
+            sys.stderr.flush()
+
+        return 0
+
+def job_runner(job):
+    """
+    Run a job. Called in a Process pool.
+    """
+    return job.run()
+
+class ParallelContext(object):
+    """
+    Manages the parallel execution of processes.
+    """
+
+    _allcontexts = set()
+    _condition = multiprocessing.Condition()
+
+    def __init__(self, jcount):
+        self.jcount = jcount
+        self.exit = False
+
+        self.processpool = multiprocessing.Pool(processes=jcount)
+        self.pending = deque() # deque of (cb, args, kwargs)
+        self.running = [] # list of (subprocess, cb)
+
+        self._allcontexts.add(self)
+
+    def finish(self):
+        assert len(self.pending) == 0 and len(self.running) == 0, "pending: %i running: %i" % (len(self.pending), len(self.running))
+        self.processpool.close()
+        self.processpool.join()
+        self._allcontexts.remove(self)
+
+    def run(self):
+        while len(self.pending) and len(self.running) < self.jcount:
+            cb, args, kwargs = self.pending.popleft()
+            cb(*args, **kwargs)
+
+    def defer(self, cb, *args, **kwargs):
+        assert self.jcount > 1 or not len(self.pending), "Serial execution error defering %r %r %r: currently pending %r" % (cb, args, kwargs, self.pending)
+        self.pending.append((cb, args, kwargs))
+
+    def _docall_generic(self, pool, job, cb, echo, justprint):
+        if echo is not None:
+            print echo
+        processcb = job.get_callback(ParallelContext._condition)
+        if justprint:
+            processcb(0)
+        else:
+            pool.apply_async(job_runner, args=(job,), callback=processcb)
+        self.running.append((job, cb))
+
+    def call(self, argv, shell, env, cwd, cb, echo, justprint=False, executable=None):
+        """
+        Asynchronously call the process
+        """
+
+        job = PopenJob(argv, executable=executable, shell=shell, env=env, cwd=cwd)
+        self.defer(self._docall_generic, self.processpool, job, cb, echo, justprint)
+
+    def call_native(self, module, method, argv, env, cwd, cb,
+                    echo, justprint=False, pycommandpath=None):
+        """
+        Asynchronously call the native function
+        """
+
+        job = PythonJob(module, method, argv, env, cwd, pycommandpath)
+        self.defer(self._docall_generic, self.processpool, job, cb, echo, justprint)
+
+    @staticmethod
+    def _waitany(condition):
+        def _checkdone():
+            jobs = []
+            for c in ParallelContext._allcontexts:
+                for i in xrange(0, len(c.running)):
+                    if c.running[i][0].done:
+                        jobs.append(c.running[i])
+                for j in jobs:
+                    if j in c.running:
+                        c.running.remove(j)
+            return jobs
+
+        # We must acquire the lock, and then check to see if any jobs have
+        # finished.  If we don't check after acquiring the lock it's possible
+        # that all outstanding jobs will have completed before we wait and we'll
+        # wait for notifications that have already occurred.
+        condition.acquire()
+        jobs = _checkdone()
+
+        if jobs == []:
+            condition.wait()
+            jobs = _checkdone()
+
+        condition.release()
+
+        return jobs
+        
+    @staticmethod
+    def spin():
+        """
+        Spin the 'event loop', and never return.
+        """
+
+        while True:
+            clist = list(ParallelContext._allcontexts)
+            for c in clist:
+                c.run()
+
+            dowait = util.any((len(c.running) for c in ParallelContext._allcontexts))
+            if dowait:
+                # Wait on local jobs first for perf
+                for job, cb in ParallelContext._waitany(ParallelContext._condition):
+                    cb(job.exitcode)
+            else:
+                assert any(len(c.pending) for c in ParallelContext._allcontexts)
+
+def makedeferrable(usercb, **userkwargs):
+    def cb(*args, **kwargs):
+        kwargs.update(userkwargs)
+        return usercb(*args, **kwargs)
+
+    return cb
+
+_serialContext = None
+_parallelContext = None
+
+def getcontext(jcount):
+    global _serialContext, _parallelContext
+    if jcount == 1:
+        if _serialContext is None:
+            _serialContext = ParallelContext(1)
+        return _serialContext
+    else:
+        if _parallelContext is None:
+            _parallelContext = ParallelContext(jcount)
+        return _parallelContext
+
diff --git a/src/third_party/mozjs-45/build/pymake/pymake/util.py b/src/third_party/mozjs-45/build/pymake/pymake/util.py
new file mode 100644
index 0000000..c63f930
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/pymake/util.py
@@ -0,0 +1,150 @@
+import os
+
+class MakeError(Exception):
+    def __init__(self, message, loc=None):
+        self.msg = message
+        self.loc = loc
+
+    def __str__(self):
+        locstr = ''
+        if self.loc is not None:
+            locstr = "%s:" % (self.loc,)
+
+        return "%s%s" % (locstr, self.msg)
+
+def normaljoin(path, suffix):
+    """
+    Combine the given path with the suffix, and normalize if necessary to shrink the path to avoid hitting path length limits
+    """
+    result = os.path.join(path, suffix)
+    if len(result) > 255:
+        result = os.path.normpath(result)
+    return result
+
+def joiniter(fd, it):
+    """
+    Given an iterator that returns strings, write the words with a space in between each.
+    """
+    
+    it = iter(it)
+    for i in it:
+        fd.write(i)
+        break
+
+    for i in it:
+        fd.write(' ')
+        fd.write(i)
+
+def checkmsyscompat():
+    """For msys compatibility on windows, honor the SHELL environment variable,
+    and if $MSYSTEM == MINGW32, run commands through $SHELL -c instead of
+    letting Python use the system shell."""
+    if 'SHELL' in os.environ:
+        shell = os.environ['SHELL']
+    elif 'MOZILLABUILD' in os.environ:
+        shell = os.environ['MOZILLABUILD'] + '/msys/bin/sh.exe'
+    elif 'COMSPEC' in os.environ:
+        shell = os.environ['COMSPEC']
+    else:
+        raise DataError("Can't find a suitable shell!")
+
+    msys = False
+    if 'MSYSTEM' in os.environ and os.environ['MSYSTEM'] == 'MINGW32':
+        msys = True
+        if not shell.lower().endswith(".exe"):
+            shell += ".exe"
+    return (shell, msys)
+
+if hasattr(str, 'partition'):
+    def strpartition(str, token):
+        return str.partition(token)
+
+    def strrpartition(str, token):
+        return str.rpartition(token)
+
+else:
+    def strpartition(str, token):
+        """Python 2.4 compatible str.partition"""
+
+        offset = str.find(token)
+        if offset == -1:
+            return str, '', ''
+
+        return str[:offset], token, str[offset + len(token):]
+
+    def strrpartition(str, token):
+        """Python 2.4 compatible str.rpartition"""
+
+        offset = str.rfind(token)
+        if offset == -1:
+            return '', '', str
+
+        return str[:offset], token, str[offset + len(token):]
+
+try:
+    from __builtin__ import any
+except ImportError:
+    def any(it):
+        for i in it:
+            if i:
+                return True
+        return False
+
+class _MostUsedItem(object):
+    __slots__ = ('key', 'o', 'count')
+
+    def __init__(self, key):
+        self.key = key
+        self.o = None
+        self.count = 1
+
+    def __repr__(self):
+        return "MostUsedItem(key=%r, count=%i, o=%r)" % (self.key, self.count, self.o)
+
+class MostUsedCache(object):
+    def __init__(self, capacity, creationfunc, verifyfunc):
+        self.capacity = capacity
+        self.cfunc = creationfunc
+        self.vfunc = verifyfunc
+
+        self.d = {}
+        self.active = [] # lazily sorted!
+
+    def setactive(self, item):
+        if item in self.active:
+            return
+
+        if len(self.active) == self.capacity:
+            self.active.sort(key=lambda i: i.count)
+            old = self.active.pop(0)
+            old.o = None
+            # print "Evicting %s" % old.key
+
+        self.active.append(item)
+
+    def get(self, key):
+        item = self.d.get(key, None)
+        if item is None:
+            item = _MostUsedItem(key)
+            self.d[key] = item
+        else:
+            item.count += 1
+
+        if item.o is not None and self.vfunc(key, item.o):
+            return item.o
+
+        item.o = self.cfunc(key)
+        self.setactive(item)
+        return item.o
+
+    def verify(self):
+        for k, v in self.d.iteritems():
+            if v.o:
+                assert v in self.active
+            else:
+                assert v not in self.active
+
+    def debugitems(self):
+        l = [i.key for i in self.active]
+        l.sort()
+        return l
diff --git a/src/third_party/mozjs-45/build/pymake/pymake/win32process.py b/src/third_party/mozjs-45/build/pymake/pymake/win32process.py
new file mode 100644
index 0000000..880a26a
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/pymake/win32process.py
@@ -0,0 +1,28 @@
+from ctypes import windll, POINTER, byref, WinError
+from ctypes.wintypes import WINFUNCTYPE, HANDLE, DWORD, BOOL
+
+INFINITE = -1
+WAIT_FAILED = 0xFFFFFFFF
+
+LPDWORD = POINTER(DWORD)
+_GetExitCodeProcessProto = WINFUNCTYPE(BOOL, HANDLE, LPDWORD)
+_GetExitCodeProcess = _GetExitCodeProcessProto(("GetExitCodeProcess", windll.kernel32))
+def GetExitCodeProcess(h):
+    exitcode = DWORD()
+    r = _GetExitCodeProcess(h, byref(exitcode))
+    if r is 0:
+        raise WinError()
+    return exitcode.value
+
+_WaitForMultipleObjectsProto = WINFUNCTYPE(DWORD, DWORD, POINTER(HANDLE), BOOL, DWORD)
+_WaitForMultipleObjects = _WaitForMultipleObjectsProto(("WaitForMultipleObjects", windll.kernel32))
+
+def WaitForAnyProcess(processes):
+    arrtype = HANDLE * len(processes)
+    harray = arrtype(*(int(p._handle) for p in processes))
+
+    r = _WaitForMultipleObjects(len(processes), harray, False, INFINITE)
+    if r == WAIT_FAILED:
+        raise WinError()
+
+    return processes[r], GetExitCodeProcess(int(processes[r]._handle)) <<8
diff --git a/src/third_party/mozjs-45/build/pymake/tests/automatic-variables.mk b/src/third_party/mozjs-45/build/pymake/tests/automatic-variables.mk
new file mode 100644
index 0000000..5302c08
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/automatic-variables.mk
@@ -0,0 +1,79 @@
+$(shell \
+mkdir -p src/subd; \
+mkdir subd; \
+touch dummy; \
+sleep 2; \
+touch subd/test.out src/subd/test.in2; \
+sleep 2; \
+touch subd/test.out2 src/subd/test.in; \
+sleep 2; \
+touch subd/host_test.out subd/host_test.out2; \
+sleep 2; \
+touch host_prog; \
+)
+
+VPATH = src
+
+all: prog host_prog prog dir/
+	test "$@" = "all"
+	test "$<" = "prog"
+	test "$^" = "prog host_prog dir"
+	test "$?" = "prog host_prog dir"
+	test "$+" = "prog host_prog prog dir"
+	test "$(@D)" = "."
+	test "$(@F)" = "all"
+	test "$(<D)" = "."
+	test "$(<F)" = "prog"
+	test "$(^D)" = ". . ."
+	test "$(^F)" = "prog host_prog dir"
+	test "$(?D)" = ". . ."
+	test "$(?F)" = "prog host_prog dir"
+	test "$(+D)" = ". . . ."
+	test "$(+F)" = "prog host_prog prog dir"
+	@echo TEST-PASS
+
+dir/:
+	test "$@" = "dir"
+	test "$<" = ""
+	test "$^" = ""
+	test "$(@D)" = "."
+	test "$(@F)" = "dir"
+	mkdir $@
+
+prog: subd/test.out subd/test.out2
+	test "$@" = "prog"
+	test "$<" = "subd/test.out"
+	test "$^" = "subd/test.out subd/test.out2" # ^
+	test "$?" = "subd/test.out subd/test.out2" # ?
+	cat $<
+	test "$$(cat $<)" = "remade"
+	test "$$(cat $(word 2,$^))" = ""
+
+host_prog: subd/host_test.out subd/host_test.out2
+	@echo TEST-FAIL No need to remake
+
+%.out: %.in dummy
+	test "$@" = "subd/test.out"
+	test "$*" = "subd/test"              # *
+	test "$<" = "src/subd/test.in"       # <
+	test "$^" = "src/subd/test.in dummy" # ^
+	test "$?" = "src/subd/test.in"       # ?
+	test "$+" = "src/subd/test.in dummy" # +
+	test "$(@D)" = "subd"
+	test "$(@F)" = "test.out"
+	test "$(*D)" = "subd"
+	test "$(*F)" = "test"
+	test "$(<D)" = "src/subd"
+	test "$(<F)" = "test.in"
+	test "$(^D)" = "src/subd ."          # ^D
+	test "$(^F)" = "test.in dummy"
+	test "$(?D)" = "src/subd"
+	test "$(?F)" = "test.in"
+	test "$(+D)" = "src/subd ."          # +D
+	test "$(+F)" = "test.in dummy"
+	printf "remade" >$@
+
+%.out2: %.in2 dummy
+	@echo TEST_FAIL No need to remake
+
+.PHONY: all
diff --git a/src/third_party/mozjs-45/build/pymake/tests/bad-command-continuation.mk b/src/third_party/mozjs-45/build/pymake/tests/bad-command-continuation.mk
new file mode 100644
index 0000000..d9ceccf
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/bad-command-continuation.mk
@@ -0,0 +1,3 @@
+all:
+	echo 'hello'\
+TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/call.mk b/src/third_party/mozjs-45/build/pymake/tests/call.mk
new file mode 100644
index 0000000..9eeb7e0
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/call.mk
@@ -0,0 +1,12 @@
+test = $0
+reverse = $2 $1
+twice = $1$1
+sideeffect = $(shell echo "called$1:" >>dummyfile)
+
+all:
+	test "$(call test)" = "test"
+	test "$(call reverse,1,2)" = "2 1"
+# expansion happens *before* substitution, thank sanity
+	test "$(call twice,$(sideeffect))" = ""
+	test `cat dummyfile` = "called:"
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/cmd-stripdotslash.mk b/src/third_party/mozjs-45/build/pymake/tests/cmd-stripdotslash.mk
new file mode 100644
index 0000000..ce5ed42
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/cmd-stripdotslash.mk
@@ -0,0 +1,5 @@
+all:
+	$(MAKE) -f $(TESTPATH)/cmd-stripdotslash.mk ./foo
+
+./foo:
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/cmdgoals.mk b/src/third_party/mozjs-45/build/pymake/tests/cmdgoals.mk
new file mode 100644
index 0000000..a3b25e7
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/cmdgoals.mk
@@ -0,0 +1,9 @@
+default:
+	test "$(MAKECMDGOALS)" = ""
+	$(MAKE) -f $(TESTPATH)/cmdgoals.mk t1   t2
+	@echo TEST-PASS
+
+t1:
+	test "$(MAKECMDGOALS)" = "t1 t2"
+
+t2:
diff --git a/src/third_party/mozjs-45/build/pymake/tests/commandmodifiers.mk b/src/third_party/mozjs-45/build/pymake/tests/commandmodifiers.mk
new file mode 100644
index 0000000..8440462
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/commandmodifiers.mk
@@ -0,0 +1,21 @@
+define COMMAND
+$(1)
+ 	$(1)
+
+endef
+
+all:
+	$(call COMMAND,@true #TEST-FAIL)
+	$(call COMMAND,-exit 4)
+	$(call COMMAND,@-exit 1 # TEST-FAIL)
+	$(call COMMAND,-@exit 1 # TEST-FAIL)
+	$(call COMMAND,+exit 0)
+	$(call COMMAND,+-exit 1)
+	$(call COMMAND,@+exit 0 # TEST-FAIL)
+	$(call COMMAND,+@exit 0 # TEST-FAIL)
+	$(call COMMAND,-+@exit 1 # TEST-FAIL)
+	$(call COMMAND,+-@exit 1 # TEST-FAIL)
+	$(call COMMAND,@+-exit 1 # TEST-FAIL)
+	$(call COMMAND,@+-@+-exit 1 # TEST-FAIL)
+	$(call COMMAND,@@++exit 0 # TEST-FAIL)
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/comment-parsing.mk b/src/third_party/mozjs-45/build/pymake/tests/comment-parsing.mk
new file mode 100644
index 0000000..d469e1a
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/comment-parsing.mk
@@ -0,0 +1,29 @@
+# where do comments take effect?
+
+VAR = val1 # comment
+VAR2 = lit2\#hash
+VAR2_1 = lit2.1\\\#hash
+VAR3 = val3
+VAR4 = lit4\\#backslash
+VAR4_1 = lit4\\\\#backslash
+VAR5 = lit5\char
+VAR6 = lit6\\char
+VAR7 = lit7\\
+VAR8 = lit8\\\\
+VAR9 = lit9\\\\extra
+# This comment extends to the next line \
+VAR3 = ignored
+
+all:
+	test "$(VAR)" = "val1 "
+	test "$(VAR2)" = "lit2#hash"
+	test '$(VAR2_1)' = 'lit2.1\#hash'
+	test "$(VAR3)" = "val3"
+	test '$(VAR4)' = 'lit4\'
+	test '$(VAR4_1)' = 'lit4\\'
+	test '$(VAR5)' = 'lit5\char'
+	test '$(VAR6)' = 'lit6\\char'
+	test '$(VAR7)' = 'lit7\\'
+	test '$(VAR8)' = 'lit8\\\\'
+	test '$(VAR9)' = 'lit9\\\\extra'
+	@echo "TEST-PASS"
diff --git a/src/third_party/mozjs-45/build/pymake/tests/continuations-in-functions.mk b/src/third_party/mozjs-45/build/pymake/tests/continuations-in-functions.mk
new file mode 100644
index 0000000..533df61
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/continuations-in-functions.mk
@@ -0,0 +1,6 @@
+all:
+	test 'Hello world.' = '$(if 1,Hello \
+	  world.)'
+	test '(Hello world.)' != '(Hello \
+	  world.)'
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/datatests.py b/src/third_party/mozjs-45/build/pymake/tests/datatests.py
new file mode 100644
index 0000000..513028b
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/datatests.py
@@ -0,0 +1,237 @@
+import pymake.data, pymake.functions, pymake.util
+import unittest
+import re
+from cStringIO import StringIO
+
+def multitest(cls):
+    for name in cls.testdata.iterkeys():
+        def m(self, name=name):
+            return self.runSingle(*self.testdata[name])
+
+        setattr(cls, 'test_%s' % name, m)
+    return cls
+
+class SplitWordsTest(unittest.TestCase):
+    testdata = (
+        (' test test.c test.o ', ['test', 'test.c', 'test.o']),
+        ('\ttest\t  test.c \ntest.o', ['test', 'test.c', 'test.o']),
+    )
+
+    def runTest(self):
+        for s, e in self.testdata:
+            w = s.split()
+            self.assertEqual(w, e, 'splitwords(%r)' % (s,))
+
+class GetPatSubstTest(unittest.TestCase):
+    testdata = (
+        ('%.c', '%.o', ' test test.c test.o ', 'test test.o test.o'),
+        ('%', '%.o', ' test.c test.o ', 'test.c.o test.o.o'),
+        ('foo', 'bar', 'test foo bar', 'test bar bar'),
+        ('foo', '%bar', 'test foo bar', 'test %bar bar'),
+        ('%', 'perc_%', 'path', 'perc_path'),
+        ('\\%', 'sub%', 'p %', 'p sub%'),
+        ('%.c', '\\%%.o', 'foo.c bar.o baz.cpp', '%foo.o bar.o baz.cpp'),
+    )
+
+    def runTest(self):
+        for s, r, d, e in self.testdata:
+            words = d.split()
+            p = pymake.data.Pattern(s)
+            a = ' '.join((p.subst(r, word, False)
+                          for word in words))
+            self.assertEqual(a, e, 'Pattern(%r).subst(%r, %r)' % (s, r, d))
+
+class LRUTest(unittest.TestCase):
+    # getkey, expected, funccount, debugitems
+    expected = (
+        (0, '', 1, (0,)),
+        (0, '', 2, (0,)),
+        (1, ' ', 3, (1, 0)),
+        (1, ' ', 3, (1, 0)),
+        (0, '', 4, (0, 1)),
+        (2, '  ', 5, (2, 0, 1)),
+        (1, ' ', 5, (1, 2, 0)),
+        (3, '   ', 6, (3, 1, 2)),
+    )
+
+    def spaceFunc(self, l):
+        self.funccount += 1
+        return ''.ljust(l)
+
+    def runTest(self):
+        self.funccount = 0
+        c = pymake.util.LRUCache(3, self.spaceFunc, lambda k, v: k % 2)
+        self.assertEqual(tuple(c.debugitems()), ())
+
+        for i in xrange(0, len(self.expected)):
+            k, e, fc, di = self.expected[i]
+
+            v = c.get(k)
+            self.assertEqual(v, e)
+            self.assertEqual(self.funccount, fc,
+                             "funccount, iteration %i, got %i expected %i" % (i, self.funccount, fc))
+            goti = tuple(c.debugitems())
+            self.assertEqual(goti, di,
+                             "debugitems, iteration %i, got %r expected %r" % (i, goti, di))
+
+class EqualityTest(unittest.TestCase):
+    def test_string_expansion(self):
+        s1 = pymake.data.StringExpansion('foo bar', None)
+        s2 = pymake.data.StringExpansion('foo bar', None)
+
+        self.assertEqual(s1, s2)
+
+    def test_expansion_simple(self):
+        s1 = pymake.data.Expansion(None)
+        s2 = pymake.data.Expansion(None)
+
+        self.assertEqual(s1, s2)
+
+        s1.appendstr('foo')
+        s2.appendstr('foo')
+        self.assertEqual(s1, s2)
+
+    def test_expansion_string_finish(self):
+        """Adjacent strings should normalize to same value."""
+        s1 = pymake.data.Expansion(None)
+        s2 = pymake.data.Expansion(None)
+
+        s1.appendstr('foo')
+        s2.appendstr('foo')
+
+        s1.appendstr(' bar')
+        s1.appendstr(' baz')
+        s2.appendstr(' bar baz')
+
+        self.assertEqual(s1, s2)
+
+    def test_function(self):
+        s1 = pymake.data.Expansion(None)
+        s2 = pymake.data.Expansion(None)
+
+        n1 = pymake.data.StringExpansion('FOO', None)
+        n2 = pymake.data.StringExpansion('FOO', None)
+
+        v1 = pymake.functions.VariableRef(None, n1)
+        v2 = pymake.functions.VariableRef(None, n2)
+
+        s1.appendfunc(v1)
+        s2.appendfunc(v2)
+
+        self.assertEqual(s1, s2)
+
+
+class StringExpansionTest(unittest.TestCase):
+    def test_base_expansion_interface(self):
+        s1 = pymake.data.StringExpansion('FOO', None)
+
+        self.assertTrue(s1.is_static_string)
+
+        funcs = list(s1.functions())
+        self.assertEqual(len(funcs), 0)
+
+        funcs = list(s1.functions(True))
+        self.assertEqual(len(funcs), 0)
+
+        refs = list(s1.variable_references())
+        self.assertEqual(len(refs), 0)
+
+
+class ExpansionTest(unittest.TestCase):
+    def test_is_static_string(self):
+        e1 = pymake.data.Expansion()
+        e1.appendstr('foo')
+
+        self.assertTrue(e1.is_static_string)
+
+        e1.appendstr('bar')
+        self.assertTrue(e1.is_static_string)
+
+        vname = pymake.data.StringExpansion('FOO', None)
+        func = pymake.functions.VariableRef(None, vname)
+
+        e1.appendfunc(func)
+
+        self.assertFalse(e1.is_static_string)
+
+    def test_get_functions(self):
+        e1 = pymake.data.Expansion()
+        e1.appendstr('foo')
+
+        vname1 = pymake.data.StringExpansion('FOO', None)
+        vname2 = pymake.data.StringExpansion('BAR', None)
+
+        func1 = pymake.functions.VariableRef(None, vname1)
+        func2 = pymake.functions.VariableRef(None, vname2)
+
+        e1.appendfunc(func1)
+        e1.appendfunc(func2)
+
+        funcs = list(e1.functions())
+        self.assertEqual(len(funcs), 2)
+
+        func3 = pymake.functions.SortFunction(None)
+        func3.append(vname1)
+
+        e1.appendfunc(func3)
+
+        funcs = list(e1.functions())
+        self.assertEqual(len(funcs), 3)
+
+        refs = list(e1.variable_references())
+        self.assertEqual(len(refs), 2)
+
+    def test_get_functions_descend(self):
+        e1 = pymake.data.Expansion()
+        vname1 = pymake.data.StringExpansion('FOO', None)
+        func1 = pymake.functions.VariableRef(None, vname1)
+        e2 = pymake.data.Expansion()
+        e2.appendfunc(func1)
+
+        func2 = pymake.functions.SortFunction(None)
+        func2.append(e2)
+
+        e1.appendfunc(func2)
+
+        funcs = list(e1.functions())
+        self.assertEqual(len(funcs), 1)
+
+        funcs = list(e1.functions(True))
+        self.assertEqual(len(funcs), 2)
+
+        self.assertTrue(isinstance(funcs[0], pymake.functions.SortFunction))
+
+    def test_is_filesystem_dependent(self):
+        e = pymake.data.Expansion()
+        vname1 = pymake.data.StringExpansion('FOO', None)
+        func1 = pymake.functions.VariableRef(None, vname1)
+        e.appendfunc(func1)
+
+        self.assertFalse(e.is_filesystem_dependent)
+
+        func2 = pymake.functions.WildcardFunction(None)
+        func2.append(vname1)
+        e.appendfunc(func2)
+
+        self.assertTrue(e.is_filesystem_dependent)
+
+    def test_is_filesystem_dependent_descend(self):
+        sort = pymake.functions.SortFunction(None)
+        wildcard = pymake.functions.WildcardFunction(None)
+
+        e = pymake.data.StringExpansion('foo/*', None)
+        wildcard.append(e)
+
+        e = pymake.data.Expansion(None)
+        e.appendfunc(wildcard)
+
+        sort.append(e)
+
+        e = pymake.data.Expansion(None)
+        e.appendfunc(sort)
+
+        self.assertTrue(e.is_filesystem_dependent)
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/src/third_party/mozjs-45/build/pymake/tests/default-goal-set-first.mk b/src/third_party/mozjs-45/build/pymake/tests/default-goal-set-first.mk
new file mode 100644
index 0000000..00a5b53
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/default-goal-set-first.mk
@@ -0,0 +1,7 @@
+.DEFAULT_GOAL := default
+
+not-default:
+	@echo TEST-FAIL did not run default rule
+
+default:
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/default-goal.mk b/src/third_party/mozjs-45/build/pymake/tests/default-goal.mk
new file mode 100644
index 0000000..699d6c0
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/default-goal.mk
@@ -0,0 +1,8 @@
+not-default:
+	@echo TEST-FAIL did not run default rule
+
+default:
+	@echo $(if $(filter not-default,$(INTERMEDIATE_DEFAULT_GOAL)),TEST-PASS,TEST-FAIL .DEFAULT_GOAL not set by $(MAKE))
+
+INTERMEDIATE_DEFAULT_GOAL := $(.DEFAULT_GOAL)
+.DEFAULT_GOAL := default
diff --git a/src/third_party/mozjs-45/build/pymake/tests/default-target.mk b/src/third_party/mozjs-45/build/pymake/tests/default-target.mk
new file mode 100644
index 0000000..701ac69
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/default-target.mk
@@ -0,0 +1,14 @@
+test: VAR = value
+
+%.do:
+	@echo TEST-FAIL: ran target "$@", should have run "all"
+
+.PHONY: test
+
+all:
+	@echo TEST-PASS: the default target is all
+
+test:
+	@echo TEST-FAIL: ran target "$@", should have run "all"
+
+test.do:
diff --git a/src/third_party/mozjs-45/build/pymake/tests/default-target2.mk b/src/third_party/mozjs-45/build/pymake/tests/default-target2.mk
new file mode 100644
index 0000000..b5a4b1b
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/default-target2.mk
@@ -0,0 +1,6 @@
+test.foo: %.foo:
+	test "$@" = "test.foo"
+	@echo TEST-PASS made test.foo by default
+
+all:
+	@echo TEST-FAIL made $@, should have made test.foo
diff --git a/src/third_party/mozjs-45/build/pymake/tests/define-directive.mk b/src/third_party/mozjs-45/build/pymake/tests/define-directive.mk
new file mode 100644
index 0000000..7899886
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/define-directive.mk
@@ -0,0 +1,69 @@
+define COMMANDS
+shellvar=hello
+test "$$shellvar" != "hello"
+endef
+
+define COMMANDS2
+shellvar=hello; \
+  test "$$shellvar" = "hello"
+endef
+
+define VARWITHCOMMENT # comment
+value
+endef
+
+define TEST3
+  whitespace
+endef
+
+define TEST4
+define TEST5
+random
+endef
+  endef
+
+ifdef TEST5
+$(error TEST5 should not be set)
+endif
+
+define TEST6
+  define TEST7
+random
+endef
+endef
+
+ifdef TEST7
+$(error TEST7 should not be set)
+endif
+
+define TEST8
+is this # a comment?
+endef
+
+ifneq ($(TEST8),is this \# a comment?)
+$(error TEST8 value not expected: $(TEST8))
+endif
+
+# A backslash continuation "hides" the endef
+define TEST9
+value \
+endef
+endef
+
+# Test ridiculous spacing
+ define TEST10
+  	define TEST11
+      baz
+endef
+define TEST12
+  foo
+  endef
+    	endef
+
+all:
+	$(COMMANDS)
+	$(COMMANDS2)
+	test '$(VARWITHCOMMENT)' = 'value'
+	test '$(COMMANDS2)' = 'shellvar=hello; test "$$shellvar" = "hello"'
+	test "$(TEST3)" = "  whitespace"
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/depfailed.mk b/src/third_party/mozjs-45/build/pymake/tests/depfailed.mk
new file mode 100644
index 0000000..ce4137c
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/depfailed.mk
@@ -0,0 +1,4 @@
+#T returncode: 2
+
+all: foo.out foo.in
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/depfailedj.mk b/src/third_party/mozjs-45/build/pymake/tests/depfailedj.mk
new file mode 100644
index 0000000..a94c74f
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/depfailedj.mk
@@ -0,0 +1,10 @@
+#T returncode: 2
+#T commandline: ['-j4']
+
+$(shell touch foo.in)
+
+all: foo.in foo.out missing
+	@echo TEST-PASS
+
+%.out: %.in
+	cp $< $@
diff --git a/src/third_party/mozjs-45/build/pymake/tests/diamond-deps.mk b/src/third_party/mozjs-45/build/pymake/tests/diamond-deps.mk
new file mode 100644
index 0000000..40a4176
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/diamond-deps.mk
@@ -0,0 +1,13 @@
+# If the dependency graph includes a diamond dependency, we should only remake
+# once!
+
+all: depA depB
+	cat testfile
+	test `cat testfile` = "data";
+	@echo TEST-PASS
+
+depA: testfile
+depB: testfile
+
+testfile:
+	printf "data" >>$@
diff --git a/src/third_party/mozjs-45/build/pymake/tests/dotslash-dir.mk b/src/third_party/mozjs-45/build/pymake/tests/dotslash-dir.mk
new file mode 100644
index 0000000..8b30d1e
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/dotslash-dir.mk
@@ -0,0 +1,8 @@
+#T grep-for: "dotslash-built"
+.PHONY: $(dir foo)
+
+all: $(dir foo)
+	@echo TEST-PASS
+
+$(dir foo):
+	@echo dotslash-built
diff --git a/src/third_party/mozjs-45/build/pymake/tests/dotslash-parse.mk b/src/third_party/mozjs-45/build/pymake/tests/dotslash-parse.mk
new file mode 100644
index 0000000..91461be
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/dotslash-parse.mk
@@ -0,0 +1,4 @@
+./:
+
+# This is merely a test to see that pymake doesn't choke on parsing ./
+$(info TEST-PASS)
diff --git a/src/third_party/mozjs-45/build/pymake/tests/dotslash-phony.mk b/src/third_party/mozjs-45/build/pymake/tests/dotslash-phony.mk
new file mode 100644
index 0000000..06b6ae7
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/dotslash-phony.mk
@@ -0,0 +1,3 @@
+.PHONY: ./
+./:
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/dotslash.mk b/src/third_party/mozjs-45/build/pymake/tests/dotslash.mk
new file mode 100644
index 0000000..585db96
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/dotslash.mk
@@ -0,0 +1,9 @@
+$(shell touch foo.in)
+
+all: foo.out
+	test "$(wildcard ./*.in)" = "./foo.in"
+	@echo TEST-PASS
+
+./%.out: %.in
+	test "$@" = "foo.out"
+	cp $< $@
diff --git a/src/third_party/mozjs-45/build/pymake/tests/doublecolon-exists.mk b/src/third_party/mozjs-45/build/pymake/tests/doublecolon-exists.mk
new file mode 100644
index 0000000..5d99a1f
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/doublecolon-exists.mk
@@ -0,0 +1,16 @@
+$(shell touch foo.testfile1 foo.testfile2)
+
+# when a rule has commands and no prerequisites, should it be executed?
+# double-colon: yes
+# single-colon: no
+
+all: foo.testfile1 foo.testfile2
+	test "$$(cat foo.testfile1)" = ""
+	test "$$(cat foo.testfile2)" = "remade:foo.testfile2"
+	@echo TEST-PASS
+
+foo.testfile1:
+	@echo TEST-FAIL
+
+foo.testfile2::
+	printf "remade:$@"> $@
diff --git a/src/third_party/mozjs-45/build/pymake/tests/doublecolon-priordeps.mk b/src/third_party/mozjs-45/build/pymake/tests/doublecolon-priordeps.mk
new file mode 100644
index 0000000..6cdf3a8
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/doublecolon-priordeps.mk
@@ -0,0 +1,19 @@
+#T commandline: ['-j3']
+
+# All *prior* dependencies of a doublecolon rule must be satisfied before
+# subsequent commands are run.
+
+all:: target1
+
+all:: target2
+	test -f target1
+	@echo TEST-PASS
+
+target1:
+	touch starting-$@
+	sleep 1
+	touch $@
+
+target2:
+	sleep 0.1
+	test -f starting-target1
diff --git a/src/third_party/mozjs-45/build/pymake/tests/doublecolon-remake.mk b/src/third_party/mozjs-45/build/pymake/tests/doublecolon-remake.mk
new file mode 100644
index 0000000..52aa926
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/doublecolon-remake.mk
@@ -0,0 +1,4 @@
+$(shell touch somefile)
+
+all:: somefile
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/dynamic-var.mk b/src/third_party/mozjs-45/build/pymake/tests/dynamic-var.mk
new file mode 100644
index 0000000..0993b9c
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/dynamic-var.mk
@@ -0,0 +1,18 @@
+# The *name* of variables can be constructed dynamically.
+
+VARNAME = FOOBAR
+
+$(VARNAME) = foovalue
+$(VARNAME)2 = foo2value
+
+$(VARNAME:%BAR=%BAM) = foobam
+
+all:
+	test "$(FOOBAR)" = "foovalue"
+	test "$(flavor FOOBAZ)" = "undefined"
+	test "$(FOOBAR2)" = "bazvalue"
+	test "$(FOOBAM)" = "foobam"
+	@echo TEST-PASS
+
+VARNAME = FOOBAZ
+FOOBAR2 = bazvalue
diff --git a/src/third_party/mozjs-45/build/pymake/tests/empty-arg.mk b/src/third_party/mozjs-45/build/pymake/tests/empty-arg.mk
new file mode 100644
index 0000000..616e5b6
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/empty-arg.mk
@@ -0,0 +1,2 @@
+all:
+	@  sh -c 'if [ $$# = 3 ] ; then echo TEST-PASS; else echo TEST-FAIL; fi' -- a "" b  
diff --git a/src/third_party/mozjs-45/build/pymake/tests/empty-command-semicolon.mk b/src/third_party/mozjs-45/build/pymake/tests/empty-command-semicolon.mk
new file mode 100644
index 0000000..07789f3
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/empty-command-semicolon.mk
@@ -0,0 +1,5 @@
+all:
+	@echo TEST-PASS
+
+foo: ;
+
diff --git a/src/third_party/mozjs-45/build/pymake/tests/empty-with-deps.mk b/src/third_party/mozjs-45/build/pymake/tests/empty-with-deps.mk
new file mode 100644
index 0000000..284e5a1
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/empty-with-deps.mk
@@ -0,0 +1,4 @@
+default.test: default.c
+
+default.c:
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/env-var-append.mk b/src/third_party/mozjs-45/build/pymake/tests/env-var-append.mk
new file mode 100644
index 0000000..4db39c4
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/env-var-append.mk
@@ -0,0 +1,7 @@
+#T environment: {'FOO': 'TEST'}
+
+FOO += $(BAR)
+BAR := PASS
+
+all:
+	@echo $(subst $(NULL) ,-,$(FOO))
diff --git a/src/third_party/mozjs-45/build/pymake/tests/env-var-append2.mk b/src/third_party/mozjs-45/build/pymake/tests/env-var-append2.mk
new file mode 100644
index 0000000..fc0735d
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/env-var-append2.mk
@@ -0,0 +1,8 @@
+#T environment: {'FOO': '$(BAZ)'}
+
+FOO += $(BAR)
+BAR := PASS
+BAZ := TEST
+
+all:
+	@echo $(subst $(NULL) ,-,$(FOO))
diff --git a/src/third_party/mozjs-45/build/pymake/tests/eof-continuation.mk b/src/third_party/mozjs-45/build/pymake/tests/eof-continuation.mk
new file mode 100644
index 0000000..daeaabc
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/eof-continuation.mk
@@ -0,0 +1,5 @@
+all:
+	test '$(TESTVAR)' = 'testval\'
+	@echo TEST-PASS
+
+TESTVAR = testval\
\ No newline at end of file
diff --git a/src/third_party/mozjs-45/build/pymake/tests/escape-chars.mk b/src/third_party/mozjs-45/build/pymake/tests/escape-chars.mk
new file mode 100644
index 0000000..ebea330
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/escape-chars.mk
@@ -0,0 +1,26 @@
+space = $(NULL) $(NULL)
+hello$(space)world$(space) = hellovalue
+
+A = aval
+
+VAR = value1\\
+VARAWFUL = value1\\#comment
+VAR2 = value2
+VAR3 = test\$A
+VAR4 = value4\\value5
+
+VAR5 = value1\\ \  \
+	value2
+
+EPERCENT = \%
+
+all:
+	test "$(hello world )" = "hellovalue"
+	test "$(VAR)" = "value1\\"
+	test '$(VARAWFUL)' = 'value1\'
+	test "$(VAR2)" = "value2"
+	test "$(VAR3)" = "test\aval"
+	test "$(VAR4)" = "value4\\value5"
+	test "$(VAR5)" = "value1\\ \ value2"
+	test "$(EPERCENT)" = "\%"
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/escaped-continuation.mk b/src/third_party/mozjs-45/build/pymake/tests/escaped-continuation.mk
new file mode 100644
index 0000000..537f754
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/escaped-continuation.mk
@@ -0,0 +1,6 @@
+#T returncode: 2
+
+all:
+	echo "Hello" \\
+	test "world" = "not!"
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/eval-duringexecute.mk b/src/third_party/mozjs-45/build/pymake/tests/eval-duringexecute.mk
new file mode 100644
index 0000000..dff8480
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/eval-duringexecute.mk
@@ -0,0 +1,12 @@
+#T returncode: 2
+
+# Once parsing is finished, recursive expansion in commands are not allowed to create any new rules (it may only set variables)
+
+define MORERULE
+all:
+	@echo TEST-FAIL
+endef
+
+all:
+	$(eval $(MORERULE))
+	@echo done
diff --git a/src/third_party/mozjs-45/build/pymake/tests/eval.mk b/src/third_party/mozjs-45/build/pymake/tests/eval.mk
new file mode 100644
index 0000000..de9759f
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/eval.mk
@@ -0,0 +1,7 @@
+TESTVAR = val1
+
+$(eval TESTVAR = val2)
+
+all:
+	test "$(TESTVAR)" = "val2"
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/exit-code.mk b/src/third_party/mozjs-45/build/pymake/tests/exit-code.mk
new file mode 100644
index 0000000..84dcffc
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/exit-code.mk
@@ -0,0 +1,5 @@
+#T returncode: 2
+
+all:
+	exit 1
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/file-functions-symlinks.mk b/src/third_party/mozjs-45/build/pymake/tests/file-functions-symlinks.mk
new file mode 100644
index 0000000..dcc0f6e
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/file-functions-symlinks.mk
@@ -0,0 +1,22 @@
+#T returncode-on: {'win32': 2}
+$(shell \
+touch test.file; \
+ln -s test.file test.symlink; \
+ln -s test.missing missing.symlink; \
+touch .testhidden; \
+mkdir foo; \
+touch foo/testfile; \
+ln -s foo symdir; \
+)
+
+all:
+	test "$(abspath test.file test.symlink)" = "$(CURDIR)/test.file $(CURDIR)/test.symlink"
+	test "$(realpath test.file test.symlink)" = "$(CURDIR)/test.file $(CURDIR)/test.file"
+	test "$(sort $(wildcard *))" = "foo symdir test.file test.symlink"
+	test "$(sort $(wildcard .*))" = ". .. .testhidden"
+	test "$(sort $(wildcard test*))" = "test.file test.symlink"
+	test "$(sort $(wildcard foo/*))" = "foo/testfile"
+	test "$(sort $(wildcard ./*))" = "./foo ./symdir ./test.file ./test.symlink"
+	test "$(sort $(wildcard f?o/*))" = "foo/testfile"
+	test "$(sort $(wildcard */*))" = "foo/testfile symdir/testfile"
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/file-functions.mk b/src/third_party/mozjs-45/build/pymake/tests/file-functions.mk
new file mode 100644
index 0000000..7e4c68e
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/file-functions.mk
@@ -0,0 +1,19 @@
+$(shell \
+touch test.file; \
+touch .testhidden; \
+mkdir foo; \
+touch foo/testfile; \
+)
+
+all:
+	test "$(abspath test.file)" = "$(CURDIR)/test.file"
+	test "$(realpath test.file)" = "$(CURDIR)/test.file"
+	test "$(sort $(wildcard *))" = "foo test.file"
+# commented out because GNU make matches . and .. while python doesn't, and I don't
+# care enough
+#	test "$(sort $(wildcard .*))" = ". .. .testhidden"
+	test "$(sort $(wildcard test*))" = "test.file"
+	test "$(sort $(wildcard foo/*))" = "foo/testfile"
+	test "$(sort $(wildcard ./*))" = "./foo ./test.file"
+	test "$(sort $(wildcard f?o/*))" = "foo/testfile"
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/foreach-local-variable.mk b/src/third_party/mozjs-45/build/pymake/tests/foreach-local-variable.mk
new file mode 100644
index 0000000..2551621
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/foreach-local-variable.mk
@@ -0,0 +1,8 @@
+# This test ensures that a local variable in a $(foreach) is bound to
+# the local value, not a global value.
+i := dummy
+
+all:
+	test "$(foreach i,foo bar,found:$(i))" = "found:foo found:bar"
+	test "$(i)" = "dummy"
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/formattingtests.py b/src/third_party/mozjs-45/build/pymake/tests/formattingtests.py
new file mode 100644
index 0000000..7aad6d4
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/formattingtests.py
@@ -0,0 +1,289 @@
+# This file contains test code for the formatting of parsed statements back to
+# make file "source." It essentially verifies to to_source() functions
+# scattered across the tree.
+
+import glob
+import logging
+import os.path
+import unittest
+
+from pymake.data import Expansion
+from pymake.data import StringExpansion
+from pymake.functions import BasenameFunction
+from pymake.functions import SubstitutionRef
+from pymake.functions import VariableRef
+from pymake.functions import WordlistFunction
+from pymake.parserdata import Include
+from pymake.parserdata import SetVariable
+from pymake.parser import parsestring
+from pymake.parser import SyntaxError
+
+class TestBase(unittest.TestCase):
+    pass
+
+class VariableRefTest(TestBase):
+    def test_string_name(self):
+        e = StringExpansion('foo', None)
+        v = VariableRef(None, e)
+
+        self.assertEqual(v.to_source(), '$(foo)')
+
+    def test_special_variable(self):
+        e = StringExpansion('<', None)
+        v = VariableRef(None, e)
+
+        self.assertEqual(v.to_source(), '$<')
+
+    def test_expansion_simple(self):
+        e = Expansion()
+        e.appendstr('foo')
+        e.appendstr('bar')
+
+        v = VariableRef(None, e)
+
+        self.assertEqual(v.to_source(), '$(foobar)')
+
+class StandardFunctionTest(TestBase):
+    def test_basename(self):
+        e1 = StringExpansion('foo', None)
+        v = VariableRef(None, e1)
+        e2 = Expansion(None)
+        e2.appendfunc(v)
+
+        b = BasenameFunction(None)
+        b.append(e2)
+
+        self.assertEqual(b.to_source(), '$(basename $(foo))')
+
+    def test_wordlist(self):
+        e1 = StringExpansion('foo', None)
+        e2 = StringExpansion('bar ', None)
+        e3 = StringExpansion(' baz', None)
+
+        w = WordlistFunction(None)
+        w.append(e1)
+        w.append(e2)
+        w.append(e3)
+
+        self.assertEqual(w.to_source(), '$(wordlist foo,bar , baz)')
+
+    def test_curly_brackets(self):
+        e1 = Expansion(None)
+        e1.appendstr('foo')
+
+        e2 = Expansion(None)
+        e2.appendstr('foo ( bar')
+
+        f = WordlistFunction(None)
+        f.append(e1)
+        f.append(e2)
+
+        self.assertEqual(f.to_source(), '${wordlist foo,foo ( bar}')
+
+class StringExpansionTest(TestBase):
+    def test_simple(self):
+        e = StringExpansion('foobar', None)
+        self.assertEqual(e.to_source(), 'foobar')
+
+        e = StringExpansion('$var', None)
+        self.assertEqual(e.to_source(), '$var')
+
+    def test_escaping(self):
+        e = StringExpansion('$var', None)
+        self.assertEqual(e.to_source(escape_variables=True), '$$var')
+
+        e = StringExpansion('this is # not a comment', None)
+        self.assertEqual(e.to_source(escape_comments=True),
+                         'this is \# not a comment')
+
+    def test_empty(self):
+        e = StringExpansion('', None)
+        self.assertEqual(e.to_source(), '')
+
+        e = StringExpansion(' ', None)
+        self.assertEqual(e.to_source(), ' ')
+
+class ExpansionTest(TestBase):
+    def test_single_string(self):
+        e = Expansion()
+        e.appendstr('foo')
+
+        self.assertEqual(e.to_source(), 'foo')
+
+    def test_multiple_strings(self):
+        e = Expansion()
+        e.appendstr('hello')
+        e.appendstr('world')
+
+        self.assertEqual(e.to_source(), 'helloworld')
+
+    def test_string_escape(self):
+        e = Expansion()
+        e.appendstr('$var')
+        self.assertEqual(e.to_source(), '$var')
+        self.assertEqual(e.to_source(escape_variables=True), '$$var')
+
+        e = Expansion()
+        e.appendstr('foo')
+        e.appendstr(' $bar')
+        self.assertEqual(e.to_source(escape_variables=True), 'foo $$bar')
+
+class SubstitutionRefTest(TestBase):
+    def test_simple(self):
+        name = StringExpansion('foo', None)
+        c = StringExpansion('%.c', None)
+        o = StringExpansion('%.o', None)
+        s = SubstitutionRef(None, name, c, o)
+
+        self.assertEqual(s.to_source(), '$(foo:%.c=%.o)')
+
+class SetVariableTest(TestBase):
+    def test_simple(self):
+        v = SetVariable(StringExpansion('foo', None), '=', 'bar', None, None)
+        self.assertEqual(v.to_source(), 'foo = bar')
+
+    def test_multiline(self):
+        s = 'hello\nworld'
+        foo = StringExpansion('FOO', None)
+
+        v = SetVariable(foo, '=', s, None, None)
+
+        self.assertEqual(v.to_source(), 'define FOO\nhello\nworld\nendef')
+
+    def test_multiline_immediate(self):
+        source = 'define FOO :=\nhello\nworld\nendef'
+
+        statements = parsestring(source, 'foo.mk')
+        self.assertEqual(statements.to_source(), source)
+
+    def test_target_specific(self):
+        foo = StringExpansion('FOO', None)
+        bar = StringExpansion('BAR', None)
+
+        v = SetVariable(foo, '+=', 'value', None, bar)
+
+        self.assertEqual(v.to_source(), 'BAR: FOO += value')
+
+class IncludeTest(TestBase):
+    def test_include(self):
+        e = StringExpansion('rules.mk', None)
+        i = Include(e, True, False)
+        self.assertEqual(i.to_source(), 'include rules.mk')
+
+        i = Include(e, False, False)
+        self.assertEqual(i.to_source(), '-include rules.mk')
+
+class IfdefTest(TestBase):
+    def test_simple(self):
+        source = 'ifdef FOO\nbar := $(value)\nendif'
+
+        statements = parsestring(source, 'foo.mk')
+        self.assertEqual(statements[0].to_source(), source)
+
+    def test_nested(self):
+        source = 'ifdef FOO\nifdef BAR\nhello = world\nendif\nendif'
+
+        statements = parsestring(source, 'foo.mk')
+        self.assertEqual(statements[0].to_source(), source)
+
+    def test_negation(self):
+        source = 'ifndef FOO\nbar += value\nendif'
+
+        statements = parsestring(source, 'foo.mk')
+        self.assertEqual(statements[0].to_source(), source)
+
+class IfeqTest(TestBase):
+    def test_simple(self):
+        source = 'ifeq ($(foo),bar)\nhello = $(world)\nendif'
+
+        statements = parsestring(source, 'foo.mk')
+        self.assertEqual(statements[0].to_source(), source)
+
+    def test_negation(self):
+        source = 'ifneq (foo,bar)\nhello = world\nendif'
+
+        statements = parsestring(source, 'foo.mk')
+        self.assertEqual(statements.to_source(), source)
+
+class ConditionBlocksTest(TestBase):
+    def test_mixed_conditions(self):
+        source = 'ifdef FOO\nifeq ($(FOO),bar)\nvar += $(value)\nendif\nendif'
+
+        statements = parsestring(source, 'foo.mk')
+        self.assertEqual(statements.to_source(), source)
+
+    def test_extra_statements(self):
+        source = 'ifdef FOO\nF := 1\nifdef BAR\nB += 1\nendif\nC = 1\nendif'
+
+        statements = parsestring(source, 'foo.mk')
+        self.assertEqual(statements.to_source(), source)
+
+    def test_whitespace_preservation(self):
+        source = "ifeq ' x' 'x '\n$(error stripping)\nendif"
+
+        statements = parsestring(source, 'foo.mk')
+        self.assertEqual(statements.to_source(), source)
+
+        source = 'ifneq (x , x)\n$(error stripping)\nendif'
+        statements = parsestring(source, 'foo.mk')
+        self.assertEqual(statements.to_source(),
+                'ifneq (x,x)\n$(error stripping)\nendif')
+
+class MakefileCorupusTest(TestBase):
+    """Runs the make files from the pymake corpus through the formatter.
+
+    All the above tests are child's play compared to this.
+    """
+
+    # Our reformatting isn't perfect. We ignore files with known failures until
+    # we make them work.
+    # TODO Address these formatting corner cases.
+    _IGNORE_FILES = [
+        # We are thrown off by backslashes at end of lines.
+        'comment-parsing.mk',
+        'escape-chars.mk',
+        'include-notfound.mk',
+    ]
+
+    def _get_test_files(self):
+        ourdir = os.path.dirname(os.path.abspath(__file__))
+
+        for makefile in glob.glob(os.path.join(ourdir, '*.mk')):
+            if os.path.basename(makefile) in self._IGNORE_FILES:
+                continue
+
+            source = None
+            with open(makefile, 'rU') as fh:
+                source = fh.read()
+
+            try:
+                yield (makefile, source, parsestring(source, makefile))
+            except SyntaxError:
+                continue
+
+    def test_reparse_consistency(self):
+        for filename, source, statements in self._get_test_files():
+            reformatted = statements.to_source()
+
+            # We should be able to parse the reformatted source fine.
+            new_statements = parsestring(reformatted, filename)
+
+            # If we do the formatting again, the representation shouldn't
+            # change. i.e. the only lossy change should be the original
+            # (whitespace and some semantics aren't preserved).
+            reformatted_again = new_statements.to_source()
+            self.assertEqual(reformatted, reformatted_again,
+                '%s has lossless reformat.' % filename)
+
+            self.assertEqual(len(statements), len(new_statements))
+
+            for i in xrange(0, len(statements)):
+                original = statements[i]
+                formatted = new_statements[i]
+
+                self.assertEqual(original, formatted, '%s %d: %s != %s' % (filename,
+                    i, original, formatted))
+
+if __name__ == '__main__':
+    logging.basicConfig(level=logging.DEBUG)
+    unittest.main()
diff --git a/src/third_party/mozjs-45/build/pymake/tests/func-refs.mk b/src/third_party/mozjs-45/build/pymake/tests/func-refs.mk
new file mode 100644
index 0000000..82ab17b
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/func-refs.mk
@@ -0,0 +1,11 @@
+unknown var = uval
+
+all:
+	test "$(subst a,b,value)" = "vblue"
+	test "${subst a,b,va)lue}" = "vb)lue"
+	test "$(subst /,\,ab/c)" = "ab\c"
+	test '$(subst a,b,\\#)' = '\\#'
+	test "$( subst a,b,value)" = ""
+	test "$(Subst a,b,value)" = ""
+	test "$(unknown var)" = "uval"
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/functions.mk b/src/third_party/mozjs-45/build/pymake/tests/functions.mk
new file mode 100644
index 0000000..817be07
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/functions.mk
@@ -0,0 +1,36 @@
+all:
+	test "$(subst e,EE,hello)" = "hEEllo"
+	test "$(strip $(NULL)  test data  )" = "test data"
+	test "$(findstring hell,hello)" = "hell"
+	test "$(findstring heaven,hello)" = ""
+	test "$(filter foo/%.c b%,foo/a.c b.c foo/a.o)" = "foo/a.c b.c"
+	test "$(filter foo,foo bar)" = "foo"
+	test "$(filter-out foo/%.c b%,foo/a.c b.c foo/a.o)" = "foo/a.o"
+	test "$(filter-out %.c,foo,bar.c foo,bar.o)" = "foo,bar.o"
+	test "$(sort .go a b aa A c cc)" = ".go A a aa b c cc"
+	test "$(word 1, hello )" = "hello"
+	test "$(word 2, hello )" = ""
+	test "$(wordlist 1, 2, foo bar baz )" = "foo bar"
+	test "$(words 1 2 3)" = "3"
+	test "$(words )" = "0"
+	test "$(firstword $(NULL) foo bar baz)" = "foo"
+	test "$(firstword )" = ""
+	test "$(dir foo.c path/foo.o dir/dir2/)" = "./ path/ dir/dir2/"
+	test "$(notdir foo.c path/foo.o dir/dir2/)" = "foo.c foo.o "
+	test "$(suffix src/foo.c dir/my.dir/foo foo.o)" = ".c .o"
+	test "$(basename src/foo.c dir/my.dir/foo foo.c .c)" = "src/foo dir/my.dir/foo foo "
+	test "$(addprefix src/,foo bar.c dir/foo)" = "src/foo src/bar.c src/dir/foo"
+	test "$(addsuffix .c,foo dir/bar)" = "foo.c dir/bar.c"
+	test "$(join a b c, 1 2 3)" = "a1 b2 c3"
+	test "$(join a b, 1 2 3)" = "a1 b2 3"
+	test "$(join a b c, 1 2)" = "a1 b2 c"
+	test "$(if $(NULL) ,yes)" = ""
+	test "$(if 1,yes,no)" = "yes"
+	test "$(if ,yes,no )" = "no "
+	test "$(if ,$(error Short-circuit problem))" = ""
+	test "$(or $(NULL),1)" = "1"
+	test "$(or $(NULL),2,$(warning TEST-FAIL bad or short-circuit))" = "2"
+	test "$(and ,$(warning TEST-FAIL bad and short-circuit))" = ""
+	test "$(and 1,2)" = "2"
+	test "$(foreach i,foo bar,found:$(i))" = "found:foo found:bar"
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/functiontests.py b/src/third_party/mozjs-45/build/pymake/tests/functiontests.py
new file mode 100644
index 0000000..43a344a
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/functiontests.py
@@ -0,0 +1,54 @@
+import unittest
+
+import pymake.data
+import pymake.functions
+
+class VariableRefTest(unittest.TestCase):
+    def test_get_expansions(self):
+        e = pymake.data.StringExpansion('FOO', None)
+        f = pymake.functions.VariableRef(None, e)
+
+        exps = list(f.expansions())
+        self.assertEqual(len(exps), 1)
+
+class GetExpansionsTest(unittest.TestCase):
+    def test_get_arguments(self):
+        f = pymake.functions.SubstFunction(None)
+
+        e1 = pymake.data.StringExpansion('FOO', None)
+        e2 = pymake.data.StringExpansion('BAR', None)
+        e3 = pymake.data.StringExpansion('BAZ', None)
+
+        f.append(e1)
+        f.append(e2)
+        f.append(e3)
+
+        exps = list(f.expansions())
+        self.assertEqual(len(exps), 3)
+
+    def test_descend(self):
+        f = pymake.functions.StripFunction(None)
+
+        e = pymake.data.Expansion(None)
+
+        e1 = pymake.data.StringExpansion('FOO', None)
+        f1 = pymake.functions.VariableRef(None, e1)
+        e.appendfunc(f1)
+
+        f2 = pymake.functions.WildcardFunction(None)
+        e2 = pymake.data.StringExpansion('foo/*', None)
+        f2.append(e2)
+        e.appendfunc(f2)
+
+        f.append(e)
+
+        exps = list(f.expansions())
+        self.assertEqual(len(exps), 1)
+
+        exps = list(f.expansions(True))
+        self.assertEqual(len(exps), 3)
+
+        self.assertFalse(f.is_filesystem_dependent)
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/src/third_party/mozjs-45/build/pymake/tests/if-syntaxerr.mk b/src/third_party/mozjs-45/build/pymake/tests/if-syntaxerr.mk
new file mode 100644
index 0000000..c172492
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/if-syntaxerr.mk
@@ -0,0 +1,6 @@
+#T returncode: 2
+
+ifeq ($(FOO,VAR))
+all:
+	@echo TEST_FAIL
+endif
diff --git a/src/third_party/mozjs-45/build/pymake/tests/ifdefs-nesting.mk b/src/third_party/mozjs-45/build/pymake/tests/ifdefs-nesting.mk
new file mode 100644
index 0000000..340530f
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/ifdefs-nesting.mk
@@ -0,0 +1,13 @@
+ifdef RANDOM
+ifeq (,$(error Not evaluated!))
+endif
+endif
+
+ifdef RANDOM
+ifeq (,)
+else ifeq (,$(error Not evaluated!))
+endif
+endif
+
+all:
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/ifdefs.mk b/src/third_party/mozjs-45/build/pymake/tests/ifdefs.mk
new file mode 100644
index 0000000..a779d19
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/ifdefs.mk
@@ -0,0 +1,127 @@
+ifdef FOO
+$(error FOO is not defined!)
+endif
+
+FOO = foo
+FOOFOUND = false
+BARFOUND = false
+BAZFOUND = false
+
+ifdef FOO
+FOOFOUND = true
+else ifdef BAR
+BARFOUND = true
+else
+BAZFOUND = true
+endif
+
+BAR2 = bar2
+FOO2FOUND = false
+BAR2FOUND = false
+BAZ2FOUND = false
+
+ifdef FOO2
+FOO2FOUND = true
+else ifdef BAR2
+BAR2FOUND = true
+else
+BAZ2FOUND = true
+endif
+
+FOO3FOUND = false
+BAR3FOUND = false
+BAZ3FOUND = false
+
+ifdef FOO3
+FOO3FOUND = true
+else ifdef BAR3
+BAR3FOUND = true
+else
+BAZ3FOUND = true
+endif
+
+ifdef RANDOM
+CONTINUATION = \
+else           \
+endif
+endif
+
+ifndef ASDFJK
+else
+$(error ASFDJK was not set)
+endif
+
+TESTSET =
+
+ifdef TESTSET
+$(error TESTSET was not set)
+endif
+
+TESTEMPTY = $(NULL)
+ifndef TESTEMPTY
+$(error TEST-FAIL TESTEMPTY was probably expanded!)
+endif
+
+# ifneq ( a,a)
+# $(error Arguments to ifeq should be stripped before evaluation)
+# endif
+
+XSPACE = x # trick
+
+ifneq ($(NULL),$(NULL))
+$(error TEST-FAIL ifneq)
+endif
+
+ifneq (x , x)
+$(error argument-stripping1)
+endif
+
+ifeq ( x,x )
+$(error argument-stripping2)
+endif
+
+ifneq ($(XSPACE), x )
+$(error argument-stripping3)
+endif
+
+ifeq 'x ' ' x'
+$(error TEST-FAIL argument-stripping4)
+endif
+
+all:
+	test $(FOOFOUND) = true   # FOOFOUND
+	test $(BARFOUND) = false  # BARFOUND
+	test $(BAZFOUND) = false  # BAZFOUND
+	test $(FOO2FOUND) = false # FOO2FOUND
+	test $(BAR2FOUND) = true  # BAR2FOUND
+	test $(BAZ2FOUND) = false # BAZ2FOUND
+	test $(FOO3FOUND) = false # FOO3FOUND
+	test $(BAR3FOUND) = false # BAR3FOUND
+	test $(BAZ3FOUND) = true  # BAZ3FOUND
+ifneq ($(FOO),foo)
+	echo TEST-FAIL 'FOO neq foo: "$(FOO)"'
+endif
+ifneq ($(FOO), foo) # Whitespace after the comma is stripped
+	echo TEST-FAIL 'FOO plus whitespace'
+endif
+ifeq ($(FOO), foo ) # But not trailing whitespace
+	echo TEST-FAIL 'FOO plus trailing whitespace'
+endif
+ifeq ( $(FOO),foo) # Not whitespace after the paren
+	echo TEST-FAIL 'FOO with leading whitespace'
+endif
+ifeq ($(FOO),$(NULL) foo) # Nor whitespace after expansion
+	echo TEST-FAIL 'FOO with embedded ws'
+endif
+ifeq ($(BAR2),bar)
+	echo TEST-FAIL 'BAR2 eq bar'
+endif
+ifeq '$(BAR3FOUND)' 'false'
+	echo BAR3FOUND is ok
+else
+	echo TEST-FAIL BAR3FOUND is not ok
+endif
+ifndef FOO
+	echo TEST-FAIL "foo not defined?"
+endif
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/ignore-error.mk b/src/third_party/mozjs-45/build/pymake/tests/ignore-error.mk
new file mode 100644
index 0000000..dc8d3a7
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/ignore-error.mk
@@ -0,0 +1,13 @@
+all:
+	-rm foo
+	+-rm bar
+	-+rm baz
+	@-rm bah
+	-@rm humbug
+	+-@rm sincere
+	+@-rm flattery
+	@+-rm will
+	@-+rm not
+	-+@rm save
+	-@+rm you
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/implicit-chain.mk b/src/third_party/mozjs-45/build/pymake/tests/implicit-chain.mk
new file mode 100644
index 0000000..16288b3
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/implicit-chain.mk
@@ -0,0 +1,12 @@
+all: test.prog
+	test "$$(cat $<)" = "Program: Object: Source: test.source"
+	@echo TEST-PASS
+
+%.prog: %.object
+	printf "Program: %s" "$$(cat $<)" > $@
+
+%.object: %.source
+	printf "Object: %s" "$$(cat $<)" > $@
+
+%.source:
+	printf "Source: %s" $@ > $@
diff --git a/src/third_party/mozjs-45/build/pymake/tests/implicit-dir.mk b/src/third_party/mozjs-45/build/pymake/tests/implicit-dir.mk
new file mode 100644
index 0000000..c7f75e8
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/implicit-dir.mk
@@ -0,0 +1,16 @@
+# Implicit rules have special instructions to deal with directories, so that a pattern rule which doesn't directly apply
+# may still be used.
+
+all: dir/host_test.otest
+
+host_%.otest: %.osource extra.file
+	@echo making $@ from $<
+
+test.osource:
+	@echo TEST-FAIL should have made dir/test.osource
+
+dir/test.osource:
+	@echo TEST-PASS made the correct dependency
+
+extra.file:
+	@echo building $@
diff --git a/src/third_party/mozjs-45/build/pymake/tests/implicit-terminal.mk b/src/third_party/mozjs-45/build/pymake/tests/implicit-terminal.mk
new file mode 100644
index 0000000..db2e244
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/implicit-terminal.mk
@@ -0,0 +1,16 @@
+#T returncode: 2
+
+# the %.object rule is "terminal". This means that additional implicit rules cannot be chained to it.
+
+all: test.prog
+	test "$$(cat $<)" = "Program: Object: Source: test.source"
+	@echo TEST-FAIL
+
+%.prog: %.object
+	printf "Program: %s" "$$(cat $<)" > $@
+
+%.object:: %.source
+	printf "Object: %s" "$$(cat $<)" > $@
+
+%.source:
+	printf "Source: %s" $@ > $@
diff --git a/src/third_party/mozjs-45/build/pymake/tests/implicitsubdir.mk b/src/third_party/mozjs-45/build/pymake/tests/implicitsubdir.mk
new file mode 100644
index 0000000..b9d854a
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/implicitsubdir.mk
@@ -0,0 +1,12 @@
+$(shell \
+mkdir foo; \
+touch test.in \
+)
+
+all: foo/test.out
+	@echo TEST-PASS
+
+foo/%.out: %.in
+	cp $< $@
+
+
diff --git a/src/third_party/mozjs-45/build/pymake/tests/include-dynamic.mk b/src/third_party/mozjs-45/build/pymake/tests/include-dynamic.mk
new file mode 100644
index 0000000..571895d
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/include-dynamic.mk
@@ -0,0 +1,21 @@
+$(shell \
+if ! test -f include-dynamic.inc; then \
+  echo "TESTVAR = oldval" > include-dynamic.inc; \
+  sleep 2; \
+  echo "TESTVAR = newval" > include-dynamic.inc.in; \
+fi \
+)
+
+# before running the 'all' rule, we should be rebuilding include-dynamic.inc,
+# because there is a rule to do so
+
+all:
+	test $(TESTVAR) = newval
+	test "$(MAKE_RESTARTS)" = 1
+	@echo TEST-PASS
+
+include-dynamic.inc: include-dynamic.inc.in
+	test "$(MAKE_RESTARTS)" = ""
+	cp $< $@
+
+include include-dynamic.inc
diff --git a/src/third_party/mozjs-45/build/pymake/tests/include-file.inc b/src/third_party/mozjs-45/build/pymake/tests/include-file.inc
new file mode 100644
index 0000000..d5d495d
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/include-file.inc
@@ -0,0 +1 @@
+INCLUDED = yes
diff --git a/src/third_party/mozjs-45/build/pymake/tests/include-missing.mk b/src/third_party/mozjs-45/build/pymake/tests/include-missing.mk
new file mode 100644
index 0000000..583d0a0
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/include-missing.mk
@@ -0,0 +1,9 @@
+#T returncode: 2
+
+# If an include file isn't present and doesn't have a rule to remake it, make
+# should fail.
+
+include notfound.mk
+
+all:
+	@echo TEST-FAIL
diff --git a/src/third_party/mozjs-45/build/pymake/tests/include-notfound.mk b/src/third_party/mozjs-45/build/pymake/tests/include-notfound.mk
new file mode 100644
index 0000000..1ee7e05
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/include-notfound.mk
@@ -0,0 +1,19 @@
+ifdef __WIN32__
+PS:=\\#
+else
+PS:=/
+endif
+
+ifneq ($(strip $(MAKEFILE_LIST)),$(NATIVE_TESTPATH)$(PS)include-notfound.mk)
+$(error MAKEFILE_LIST incorrect: '$(MAKEFILE_LIST)' (expected '$(NATIVE_TESTPATH)$(PS)include-notfound.mk'))
+endif
+
+-include notfound.inc-dummy
+
+ifneq ($(strip $(MAKEFILE_LIST)),$(NATIVE_TESTPATH)$(PS)include-notfound.mk)
+$(error MAKEFILE_LIST incorrect: '$(MAKEFILE_LIST)' (expected '$(NATIVE_TESTPATH)$(PS)include-notfound.mk'))
+endif
+
+all:
+	@echo TEST-PASS
+
diff --git a/src/third_party/mozjs-45/build/pymake/tests/include-optional-warning.mk b/src/third_party/mozjs-45/build/pymake/tests/include-optional-warning.mk
new file mode 100644
index 0000000..901938d
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/include-optional-warning.mk
@@ -0,0 +1,4 @@
+-include TEST-FAIL.mk
+
+all:
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/include-regen.mk b/src/third_party/mozjs-45/build/pymake/tests/include-regen.mk
new file mode 100644
index 0000000..c86e0c7
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/include-regen.mk
@@ -0,0 +1,10 @@
+# avoid infinite loops by not remaking makefiles with
+# double-colon no-dependency rules
+# http://www.gnu.org/software/make/manual/make.html#Remaking-Makefiles
+-include notfound.mk
+
+all:
+	@echo TEST-PASS
+
+notfound.mk::
+	@echo TEST-FAIL
diff --git a/src/third_party/mozjs-45/build/pymake/tests/include-regen2.mk b/src/third_party/mozjs-45/build/pymake/tests/include-regen2.mk
new file mode 100644
index 0000000..fc7fef0
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/include-regen2.mk
@@ -0,0 +1,10 @@
+# make should make makefiles that it has rules for if they are

+# included

+include test.mk

+

+all:

+	test "$(X)" = "1"

+	@echo "TEST-PASS"

+

+test.mk:

+	@echo "X = 1" > $@

diff --git a/src/third_party/mozjs-45/build/pymake/tests/include-regen3.mk b/src/third_party/mozjs-45/build/pymake/tests/include-regen3.mk
new file mode 100644
index 0000000..878ce0a
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/include-regen3.mk
@@ -0,0 +1,10 @@
+# make should make makefiles that it has rules for if they are

+# included

+-include test.mk

+

+all:

+	test "$(X)" = "1"

+	@echo "TEST-PASS"

+

+test.mk:

+	@echo "X = 1" > $@

diff --git a/src/third_party/mozjs-45/build/pymake/tests/include-test.mk b/src/third_party/mozjs-45/build/pymake/tests/include-test.mk
new file mode 100644
index 0000000..3608fc2
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/include-test.mk
@@ -0,0 +1,8 @@
+$(shell echo "INCLUDED2 = yes" >local-include.inc)
+
+include $(TESTPATH)/include-file.inc local-include.inc
+
+all:
+	test "$(INCLUDED)" = "yes"
+	test "$(INCLUDED2)" = "yes"
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/includedeps-norebuild.mk b/src/third_party/mozjs-45/build/pymake/tests/includedeps-norebuild.mk
new file mode 100644
index 0000000..e30abd4
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/includedeps-norebuild.mk
@@ -0,0 +1,15 @@
+#T gmake skip
+
+$(shell \
+touch filemissing; \
+sleep 2; \
+touch file1; \
+)
+
+all: file1
+	@echo TEST-PASS
+
+includedeps $(TESTPATH)/includedeps.deps
+
+file1:
+	@echo TEST-FAIL
diff --git a/src/third_party/mozjs-45/build/pymake/tests/includedeps-sideeffects.mk b/src/third_party/mozjs-45/build/pymake/tests/includedeps-sideeffects.mk
new file mode 100644
index 0000000..7e4ea30
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/includedeps-sideeffects.mk
@@ -0,0 +1,10 @@
+#T gmake skip
+#T returncode: 2
+
+all: file1 filemissing
+	@echo TEST-PASS
+
+includedeps $(TESTPATH)/includedeps.deps
+
+file:
+	touch $@
diff --git a/src/third_party/mozjs-45/build/pymake/tests/includedeps-stripdotslash.deps b/src/third_party/mozjs-45/build/pymake/tests/includedeps-stripdotslash.deps
new file mode 100644
index 0000000..352fca1
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/includedeps-stripdotslash.deps
@@ -0,0 +1 @@
+./test: TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/includedeps-stripdotslash.mk b/src/third_party/mozjs-45/build/pymake/tests/includedeps-stripdotslash.mk
new file mode 100644
index 0000000..ee942e6
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/includedeps-stripdotslash.mk
@@ -0,0 +1,8 @@
+#T gmake skip
+
+test:
+	@echo $<
+
+includedeps $(TESTPATH)/includedeps-stripdotslash.deps
+
+TEST-PASS:
diff --git a/src/third_party/mozjs-45/build/pymake/tests/includedeps-variables.deps b/src/third_party/mozjs-45/build/pymake/tests/includedeps-variables.deps
new file mode 100644
index 0000000..ba69e9b
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/includedeps-variables.deps
@@ -0,0 +1 @@
+$(FILE)1: filemissing
diff --git a/src/third_party/mozjs-45/build/pymake/tests/includedeps-variables.mk b/src/third_party/mozjs-45/build/pymake/tests/includedeps-variables.mk
new file mode 100644
index 0000000..314618d
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/includedeps-variables.mk
@@ -0,0 +1,10 @@
+#T gmake skip
+
+FILE = includedeps-variables
+
+all: $(FILE)1
+
+includedeps $(TESTPATH)/includedeps-variables.deps
+
+filemissing:
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/includedeps.deps b/src/third_party/mozjs-45/build/pymake/tests/includedeps.deps
new file mode 100644
index 0000000..d3017c0
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/includedeps.deps
@@ -0,0 +1 @@
+file1: filemissing
diff --git a/src/third_party/mozjs-45/build/pymake/tests/includedeps.mk b/src/third_party/mozjs-45/build/pymake/tests/includedeps.mk
new file mode 100644
index 0000000..deaa71f
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/includedeps.mk
@@ -0,0 +1,9 @@
+#T gmake skip
+
+all: file1
+	@echo TEST-PASS
+
+includedeps $(TESTPATH)/includedeps.deps
+
+file1:
+	touch $@
diff --git a/src/third_party/mozjs-45/build/pymake/tests/info.mk b/src/third_party/mozjs-45/build/pymake/tests/info.mk
new file mode 100644
index 0000000..8dddfd8
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/info.mk
@@ -0,0 +1,8 @@
+#T grep-for: "info-printed\ninfo-nth"
+all:
+
+INFO = info-printed
+
+$(info $(INFO))
+$(info $(subst second,nth,info-second))
+$(info TEST-PASS)
diff --git a/src/third_party/mozjs-45/build/pymake/tests/justprint-native.mk b/src/third_party/mozjs-45/build/pymake/tests/justprint-native.mk
new file mode 100644
index 0000000..580e402
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/justprint-native.mk
@@ -0,0 +1,28 @@
+## $(TOUCH) and $(RM) are native commands in pymake.

+## Test that pymake --just-print just prints them.

+

+ifndef TOUCH

+TOUCH = touch

+endif

+

+all: 

+	$(RM) justprint-native-file1.txt

+	$(TOUCH) justprint-native-file2.txt

+	$(MAKE) --just-print -f $(TESTPATH)/justprint-native.mk justprint_target > justprint.log

+#       make --just-print shouldn't have actually done anything.

+	test ! -f justprint-native-file1.txt

+	test -f justprint-native-file2.txt

+#	but it should have printed each command

+	grep -q 'touch justprint-native-file1.txt' justprint.log

+	grep -q 'rm -f justprint-native-file2.txt' justprint.log

+	grep -q 'this string is "unlikely to appear in the log by chance"' justprint.log

+#	tidy up

+	$(RM) justprint-native-file2.txt

+	@echo TEST-PASS

+

+justprint_target:

+	$(TOUCH) justprint-native-file1.txt

+	$(RM) justprint-native-file2.txt

+	this string is "unlikely to appear in the log by chance"

+

+.PHONY: justprint_target

diff --git a/src/third_party/mozjs-45/build/pymake/tests/justprint.mk b/src/third_party/mozjs-45/build/pymake/tests/justprint.mk
new file mode 100644
index 0000000..be11ba8
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/justprint.mk
@@ -0,0 +1,5 @@
+#T commandline: ['-n']

+

+all: 

+	false   # without -n, we wouldn't get past this

+	TEST-PASS  # heh

diff --git a/src/third_party/mozjs-45/build/pymake/tests/keep-going-doublecolon.mk b/src/third_party/mozjs-45/build/pymake/tests/keep-going-doublecolon.mk
new file mode 100644
index 0000000..fa5b31d
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/keep-going-doublecolon.mk
@@ -0,0 +1,16 @@
+#T commandline: ['-k']
+#T returncode: 2
+#T grep-for: "TEST-PASS"
+
+all:: t1
+	@echo TEST-FAIL "(t1)"
+
+all:: t2
+	@echo TEST-PASS
+
+t1:
+	@false
+
+t2:
+	touch $@
+
diff --git a/src/third_party/mozjs-45/build/pymake/tests/keep-going-parallel.mk b/src/third_party/mozjs-45/build/pymake/tests/keep-going-parallel.mk
new file mode 100644
index 0000000..a91d1a6
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/keep-going-parallel.mk
@@ -0,0 +1,11 @@
+#T commandline: ['-k', '-j2']
+#T returncode: 2
+#T grep-for: "TEST-PASS"
+
+all: t1 slow1 slow2 slow3 t2
+
+t2:
+	@echo TEST-PASS
+
+slow%:
+	sleep 1
diff --git a/src/third_party/mozjs-45/build/pymake/tests/keep-going.mk b/src/third_party/mozjs-45/build/pymake/tests/keep-going.mk
new file mode 100644
index 0000000..4c70928
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/keep-going.mk
@@ -0,0 +1,14 @@
+#T commandline: ['-k']
+#T returncode: 2
+#T grep-for: "TEST-PASS"
+
+all: t2 t3
+
+t1:
+	@false
+
+t2: t1
+	@echo TEST-FAIL
+
+t3:
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/line-continuations.mk b/src/third_party/mozjs-45/build/pymake/tests/line-continuations.mk
new file mode 100644
index 0000000..8b44480
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/line-continuations.mk
@@ -0,0 +1,24 @@
+VAR = val1 	 \
+  	  val2  
+
+VAR2 = val1space\
+val2
+
+VAR3 = val3 \\\
+	cont3
+
+all: otarget test.target
+	test "$(VAR)" = "val1 val2  "
+	test "$(VAR2)" = "val1space val2"
+	test '$(VAR3)' = 'val3 \ cont3'
+	test "hello \
+	  world" = "hello   world"
+	test "hello" = \
+"hello"
+	@echo TEST-PASS
+
+otarget: ; test "hello\
+	world" = "helloworld"
+
+test.target: %.target: ; test "hello\
+	world" = "helloworld"
diff --git a/src/third_party/mozjs-45/build/pymake/tests/link-search.mk b/src/third_party/mozjs-45/build/pymake/tests/link-search.mk
new file mode 100644
index 0000000..ea827f3
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/link-search.mk
@@ -0,0 +1,7 @@
+$(shell \
+touch libfoo.so \
+)
+
+all: -lfoo
+	test "$<" = "libfoo.so"
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/makeflags.mk b/src/third_party/mozjs-45/build/pymake/tests/makeflags.mk
new file mode 100644
index 0000000..288ff78
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/makeflags.mk
@@ -0,0 +1,7 @@
+#T environment: {'MAKEFLAGS': 'OVAR=oval'}
+
+all:
+	test "$(OVAR)" = "oval"
+	test "$$OVAR" = "oval"
+	@echo TEST-PASS
+
diff --git a/src/third_party/mozjs-45/build/pymake/tests/matchany.mk b/src/third_party/mozjs-45/build/pymake/tests/matchany.mk
new file mode 100644
index 0000000..7876c90
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/matchany.mk
@@ -0,0 +1,14 @@
+#T returncode: 2
+
+# we should fail to make foo.ooo from foo.ooo.test
+all: foo.ooo
+	@echo TEST-FAIL
+
+%.ooo:
+
+# this match-anything pattern should not apply to %.ooo
+%: %.test
+	cp $< $@
+
+foo.ooo.test:
+	touch $@
diff --git a/src/third_party/mozjs-45/build/pymake/tests/matchany2.mk b/src/third_party/mozjs-45/build/pymake/tests/matchany2.mk
new file mode 100644
index 0000000..d21d970
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/matchany2.mk
@@ -0,0 +1,13 @@
+# we should succeed in making foo.ooo from foo.ooo.test
+all: foo.ooo
+	@echo TEST-PASS
+
+%.ooo: %.ccc
+	exit 1
+
+# this match-anything rule is terminal, and therefore applies
+%:: %.test
+	cp $< $@
+
+foo.ooo.test:
+	touch $@
diff --git a/src/third_party/mozjs-45/build/pymake/tests/matchany3.mk b/src/third_party/mozjs-45/build/pymake/tests/matchany3.mk
new file mode 100644
index 0000000..83de8af
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/matchany3.mk
@@ -0,0 +1,10 @@
+$(shell \
+echo "target" > target.in; \
+)
+
+all: target
+	test "$$(cat $^)" = "target"
+	@echo TEST-PASS
+
+%: %.in
+	cp $< $@
diff --git a/src/third_party/mozjs-45/build/pymake/tests/mkdir-fail.mk b/src/third_party/mozjs-45/build/pymake/tests/mkdir-fail.mk
new file mode 100644
index 0000000..b05734a
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/mkdir-fail.mk
@@ -0,0 +1,7 @@
+#T returncode: 2
+all:
+	mkdir newdir/subdir
+	test ! -d newdir/subdir
+	test ! -d newdir
+	rm -r newdir
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/mkdir.mk b/src/third_party/mozjs-45/build/pymake/tests/mkdir.mk
new file mode 100644
index 0000000..413348f
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/mkdir.mk
@@ -0,0 +1,27 @@
+MKDIR ?= mkdir
+
+all:
+	$(MKDIR) newdir
+	test -d newdir
+	# subdir, parent exists
+	$(MKDIR) newdir/subdir
+	test -d newdir/subdir
+	# -p, existing dir
+	$(MKDIR) -p newdir
+	# -p, existing subdir
+	$(MKDIR) -p newdir/subdir
+	# multiple subdirs, existing parent
+	$(MKDIR) newdir/subdir1 newdir/subdir2
+	test -d newdir/subdir1 -a -d newdir/subdir2
+	rm -r newdir
+	# -p, subdir, no existing parent
+	$(MKDIR) -p newdir/subdir
+	test -d newdir/subdir
+	rm -r newdir
+	# -p, multiple subdirs, no existing parent
+	$(MKDIR) -p newdir/subdir1 newdir/subdir2
+	test -d newdir/subdir1 -a -d newdir/subdir2
+	# -p, multiple existing subdirs
+	$(MKDIR) -p newdir/subdir1 newdir/subdir2
+	rm -r newdir
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/multiple-rules-prerequisite-merge.mk b/src/third_party/mozjs-45/build/pymake/tests/multiple-rules-prerequisite-merge.mk
new file mode 100644
index 0000000..480d3b5
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/multiple-rules-prerequisite-merge.mk
@@ -0,0 +1,25 @@
+# When a target is defined multiple times, the prerequisites should get
+# merged.
+
+default: foo bar baz
+
+foo:
+	test "$<" = "foo.in1"
+	@echo TEST-PASS
+
+foo: foo.in1
+
+bar: bar.in1
+	test "$<" = "bar.in1"
+	test "$^" = "bar.in1 bar.in2"
+	@echo TEST-PASS
+
+bar: bar.in2
+
+baz: baz.in2
+baz: baz.in1
+	test "$<" = "baz.in1"
+	test "$^" = "baz.in1 baz.in2"
+	@echo TEST-PASS
+
+foo.in1 bar.in1 bar.in2 baz.in1 baz.in2:
diff --git a/src/third_party/mozjs-45/build/pymake/tests/native-command-delay-load.mk b/src/third_party/mozjs-45/build/pymake/tests/native-command-delay-load.mk
new file mode 100644
index 0000000..a9f3774
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/native-command-delay-load.mk
@@ -0,0 +1,12 @@
+#T gmake skip
+
+# This test exists to verify that sys.path is adjusted during command
+# execution and that delay importing a module will work.
+
+CMD = %pycmd delayloadfn
+PYCOMMANDPATH = $(TESTPATH) $(TESTPATH)/subdir
+
+all:
+	$(CMD)
+	@echo TEST-PASS
+
diff --git a/src/third_party/mozjs-45/build/pymake/tests/native-command-raise.mk b/src/third_party/mozjs-45/build/pymake/tests/native-command-raise.mk
new file mode 100644
index 0000000..d1b28b3
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/native-command-raise.mk
@@ -0,0 +1,9 @@
+#T gmake skip
+#T returncode: 2
+#T grep-for: "Exception: info-exception"
+
+CMD = %pycmd asplode_raise
+PYCOMMANDPATH = $(TESTPATH) $(TESTPATH)/subdir
+
+all:
+	@$(CMD) info-exception
diff --git a/src/third_party/mozjs-45/build/pymake/tests/native-command-return-fail1.mk b/src/third_party/mozjs-45/build/pymake/tests/native-command-return-fail1.mk
new file mode 100644
index 0000000..0cf085a
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/native-command-return-fail1.mk
@@ -0,0 +1,8 @@
+#T gmake skip
+#T returncode: 2
+
+CMD = %pycmd asplode_return
+PYCOMMANDPATH = $(TESTPATH) $(TESTPATH)/subdir
+
+all:
+	$(CMD) 1
diff --git a/src/third_party/mozjs-45/build/pymake/tests/native-command-return-fail2.mk b/src/third_party/mozjs-45/build/pymake/tests/native-command-return-fail2.mk
new file mode 100644
index 0000000..c071fc8
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/native-command-return-fail2.mk
@@ -0,0 +1,8 @@
+#T gmake skip
+#T returncode: 2
+
+CMD = %pycmd asplode_return
+PYCOMMANDPATH = $(TESTPATH) $(TESTPATH)/subdir
+
+all:
+	$(CMD) not-an-integer
diff --git a/src/third_party/mozjs-45/build/pymake/tests/native-command-return.mk b/src/third_party/mozjs-45/build/pymake/tests/native-command-return.mk
new file mode 100644
index 0000000..3e4d2e0
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/native-command-return.mk
@@ -0,0 +1,11 @@
+#T gmake skip
+
+CMD = %pycmd asplode_return
+PYCOMMANDPATH = $(TESTPATH) $(TESTPATH)/subdir
+
+all:
+	$(CMD) 0
+	-$(CMD) 1
+	$(CMD) None
+	-$(CMD) not-an-integer
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/native-command-shell-glob.mk b/src/third_party/mozjs-45/build/pymake/tests/native-command-shell-glob.mk
new file mode 100644
index 0000000..4bcdad8
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/native-command-shell-glob.mk
@@ -0,0 +1,11 @@
+#T gmake skip
+all:
+	mkdir shell-glob-test
+	touch shell-glob-test/foo.txt
+	touch shell-glob-test/bar.txt
+	touch shell-glob-test/a.foo
+	touch shell-glob-test/b.foo
+	$(RM) shell-glob-test/*.txt
+	$(RM) shell-glob-test/?.foo
+	rmdir shell-glob-test
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/native-command-sys-exit-fail1.mk b/src/third_party/mozjs-45/build/pymake/tests/native-command-sys-exit-fail1.mk
new file mode 100644
index 0000000..8e74800
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/native-command-sys-exit-fail1.mk
@@ -0,0 +1,8 @@
+#T gmake skip
+#T returncode: 2
+
+CMD = %pycmd asplode
+PYCOMMANDPATH = $(TESTPATH) $(TESTPATH)/subdir
+
+all:
+	$(CMD) 1
diff --git a/src/third_party/mozjs-45/build/pymake/tests/native-command-sys-exit-fail2.mk b/src/third_party/mozjs-45/build/pymake/tests/native-command-sys-exit-fail2.mk
new file mode 100644
index 0000000..0a04395
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/native-command-sys-exit-fail2.mk
@@ -0,0 +1,8 @@
+#T gmake skip
+#T returncode: 2
+
+CMD = %pycmd asplode
+PYCOMMANDPATH = $(TESTPATH) $(TESTPATH)/subdir
+
+all:
+	$(CMD) not-an-integer
diff --git a/src/third_party/mozjs-45/build/pymake/tests/native-command-sys-exit.mk b/src/third_party/mozjs-45/build/pymake/tests/native-command-sys-exit.mk
new file mode 100644
index 0000000..c04913a
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/native-command-sys-exit.mk
@@ -0,0 +1,11 @@
+#T gmake skip
+
+CMD = %pycmd asplode
+PYCOMMANDPATH = $(TESTPATH) $(TESTPATH)/subdir
+
+all:
+	$(CMD) 0
+	-$(CMD) 1
+	$(CMD) None
+	-$(CMD) not-an-integer
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/native-environment.mk b/src/third_party/mozjs-45/build/pymake/tests/native-environment.mk
new file mode 100644
index 0000000..36bd589
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/native-environment.mk
@@ -0,0 +1,11 @@
+#T gmake skip
+export EXPECTED := some data
+
+PYCOMMANDPATH = $(TESTPATH)
+
+all:
+	%pycmd writeenvtofile results EXPECTED
+	test "$$(cat results)" = "$(EXPECTED)"
+	%pycmd writesubprocessenvtofile results EXPECTED
+	test "$$(cat results)" = "$(EXPECTED)"
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/native-pycommandpath-sep.mk b/src/third_party/mozjs-45/build/pymake/tests/native-pycommandpath-sep.mk
new file mode 100644
index 0000000..b1c2c2b
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/native-pycommandpath-sep.mk
@@ -0,0 +1,21 @@
+#T gmake skip
+EXPECTED := some data
+
+# verify that we can load native command modules from
+# multiple directories in PYCOMMANDPATH separated by the native
+# path separator
+ifdef __WIN32__
+PS:=;
+else
+PS:=:
+endif
+CMD = %pycmd writetofile
+CMD2 = %pymod writetofile
+PYCOMMANDPATH = $(TESTPATH)$(PS)$(TESTPATH)/subdir
+
+all:
+	$(CMD) results $(EXPECTED)
+	test "$$(cat results)" = "$(EXPECTED)"
+	$(CMD2) results2 $(EXPECTED)
+	test "$$(cat results2)" = "$(EXPECTED)"
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/native-pycommandpath.mk b/src/third_party/mozjs-45/build/pymake/tests/native-pycommandpath.mk
new file mode 100644
index 0000000..dd0fbc9
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/native-pycommandpath.mk
@@ -0,0 +1,15 @@
+#T gmake skip
+EXPECTED := some data
+
+# verify that we can load native command modules from
+# multiple space-separated directories in PYCOMMANDPATH
+CMD = %pycmd writetofile
+CMD2 = %pymod writetofile
+PYCOMMANDPATH = $(TESTPATH) $(TESTPATH)/subdir
+
+all:
+	$(CMD) results $(EXPECTED)
+	test "$$(cat results)" = "$(EXPECTED)"
+	$(CMD2) results2 $(EXPECTED)
+	test "$$(cat results2)" = "$(EXPECTED)"
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/native-simple.mk b/src/third_party/mozjs-45/build/pymake/tests/native-simple.mk
new file mode 100644
index 0000000..626a586
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/native-simple.mk
@@ -0,0 +1,12 @@
+ifndef TOUCH

+TOUCH = touch

+endif

+

+all: testfile {testfile2} (testfile3)

+	test -f testfile

+	test -f {testfile2}

+	test -f "(testfile3)"

+	@echo TEST-PASS

+

+testfile {testfile2} (testfile3):

+	$(TOUCH) "$@"

diff --git a/src/third_party/mozjs-45/build/pymake/tests/native-touch.mk b/src/third_party/mozjs-45/build/pymake/tests/native-touch.mk
new file mode 100644
index 0000000..811161e
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/native-touch.mk
@@ -0,0 +1,15 @@
+TOUCH ?= touch
+
+foo:
+	$(TOUCH) bar
+	$(TOUCH) baz
+	$(MAKE) -f $(TESTPATH)/native-touch.mk baz
+	$(TOUCH) -t 198007040802 baz
+	$(MAKE) -f $(TESTPATH)/native-touch.mk baz
+
+bar:
+	$(TOUCH) $@
+
+baz: bar
+	echo TEST-PASS
+	$(TOUCH) $@
diff --git a/src/third_party/mozjs-45/build/pymake/tests/newlines.mk b/src/third_party/mozjs-45/build/pymake/tests/newlines.mk
new file mode 100644
index 0000000..5d8195c
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/newlines.mk
@@ -0,0 +1,30 @@
+#T gmake skip
+
+# Test that we handle \\\n properly
+
+all: dep1 dep2 dep3
+	cat testfile
+	test `cat testfile` = "data";
+	test "$$(cat results)" = "$(EXPECTED)";
+	@echo TEST-PASS
+
+# Test that something that still needs to go to the shell works
+testfile:
+	printf "data" \
+	  >>$@
+
+dep1: testfile
+
+# Test that something that does not need to go to the shell works
+dep2:
+	$(echo foo) \
+	$(echo bar)
+
+export EXPECTED := some data
+
+CMD = %pycmd writeenvtofile
+PYCOMMANDPATH = $(TESTPATH)
+
+dep3:
+	$(CMD) \
+	results EXPECTED
diff --git a/src/third_party/mozjs-45/build/pymake/tests/no-remake.mk b/src/third_party/mozjs-45/build/pymake/tests/no-remake.mk
new file mode 100644
index 0000000..c8df81b
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/no-remake.mk
@@ -0,0 +1,7 @@
+$(shell date >testfile)
+
+all: testfile
+	@echo TEST-PASS
+
+testfile:
+	@echo TEST-FAIL "We shouldn't have remade this!"
diff --git a/src/third_party/mozjs-45/build/pymake/tests/nosuchfile.mk b/src/third_party/mozjs-45/build/pymake/tests/nosuchfile.mk
new file mode 100644
index 0000000..cca9ce1
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/nosuchfile.mk
@@ -0,0 +1,4 @@
+#T returncode: 2
+
+all:
+	reallythereisnosuchcommand
diff --git a/src/third_party/mozjs-45/build/pymake/tests/notargets.mk b/src/third_party/mozjs-45/build/pymake/tests/notargets.mk
new file mode 100644
index 0000000..8e55d94
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/notargets.mk
@@ -0,0 +1,5 @@
+$(NULL): foo.c
+	@echo TEST-FAIL
+
+all:
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/notparallel.mk b/src/third_party/mozjs-45/build/pymake/tests/notparallel.mk
new file mode 100644
index 0000000..4fd8b1a
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/notparallel.mk
@@ -0,0 +1,8 @@
+#T commandline: ['-j3']
+
+include $(TESTPATH)/serial-rule-execution.mk
+
+all::
+	$(MAKE) -f $(TESTPATH)/parallel-simple.mk
+
+.NOTPARALLEL:
diff --git a/src/third_party/mozjs-45/build/pymake/tests/oneline-command-continuations.mk b/src/third_party/mozjs-45/build/pymake/tests/oneline-command-continuations.mk
new file mode 100644
index 0000000..c11f3df
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/oneline-command-continuations.mk
@@ -0,0 +1,5 @@
+all: test
+	@echo TEST-PASS
+
+test: ; test "Hello \
+	  world" = "Hello   world"
diff --git a/src/third_party/mozjs-45/build/pymake/tests/override-propagate.mk b/src/third_party/mozjs-45/build/pymake/tests/override-propagate.mk
new file mode 100644
index 0000000..a1663ff
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/override-propagate.mk
@@ -0,0 +1,37 @@
+#T commandline: ['-w', 'OVAR=oval']
+
+OVAR=mval
+
+all: vartest run-override
+	$(MAKE) -f $(TESTPATH)/override-propagate.mk vartest
+	@echo TEST-PASS
+
+CLINE := OVAR=oval TESTPATH=$(TESTPATH) NATIVE_TESTPATH=$(NATIVE_TESTPATH)
+ifdef __WIN32__
+CLINE += __WIN32__=1
+endif
+
+SORTED_CLINE := $(subst \,\\,$(sort $(CLINE)))
+
+vartest:
+	@echo MAKELEVEL: '$(MAKELEVEL)'
+	test '$(value MAKEFLAGS)' = 'w -- $$(MAKEOVERRIDES)'
+	test '$(origin MAKEFLAGS)' = 'file'
+	test '$(value MAKEOVERRIDES)' = '$${-*-command-variables-*-}'
+	test "$(sort $(MAKEOVERRIDES))" = "$(SORTED_CLINE)"
+	test '$(origin MAKEOVERRIDES)' = 'environment'
+	test '$(origin -*-command-variables-*-)' = 'automatic'
+	test "$(origin OVAR)" = "command line"
+	test "$(OVAR)" = "oval"
+
+run-override: MAKEOVERRIDES=
+run-override:
+	test "$(OVAR)" = "oval"
+	$(MAKE) -f $(TESTPATH)/override-propagate.mk otest
+
+otest:
+	test '$(value MAKEFLAGS)' = 'w'
+	test '$(value MAKEOVERRIDES)' = '$${-*-command-variables-*-}'
+	test '$(MAKEOVERRIDES)' = ''
+	test '$(origin -*-command-variables-*-)' = 'undefined'
+	test "$(OVAR)" = "mval"
diff --git a/src/third_party/mozjs-45/build/pymake/tests/parallel-dep-resolution.mk b/src/third_party/mozjs-45/build/pymake/tests/parallel-dep-resolution.mk
new file mode 100644
index 0000000..7967eba
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/parallel-dep-resolution.mk
@@ -0,0 +1,8 @@
+#T commandline: ['-j3']
+#T returncode: 2
+
+all: t1 t2
+
+t1:
+	sleep 1
+	touch t1 t2
diff --git a/src/third_party/mozjs-45/build/pymake/tests/parallel-dep-resolution2.mk b/src/third_party/mozjs-45/build/pymake/tests/parallel-dep-resolution2.mk
new file mode 100644
index 0000000..7d61e6b
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/parallel-dep-resolution2.mk
@@ -0,0 +1,9 @@
+#T commandline: ['-j3']
+#T returncode: 2
+
+all::
+	sleep 1
+	touch somefile
+
+all:: somefile
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/parallel-native.mk b/src/third_party/mozjs-45/build/pymake/tests/parallel-native.mk
new file mode 100644
index 0000000..d50cfbd
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/parallel-native.mk
@@ -0,0 +1,21 @@
+#T commandline: ['-j2']
+
+# ensure that calling python commands doesn't block other targets
+ifndef SLEEP
+SLEEP := sleep
+endif
+
+PRINTF = printf "$@:0:" >>results
+EXPECTED = target2:0:target1:0:
+
+all:: target1 target2
+	cat results
+	test "$$(cat results)" = "$(EXPECTED)"
+	@echo TEST-PASS
+
+target1:
+	$(SLEEP) 0.1
+	$(PRINTF)
+
+target2:
+	$(PRINTF)
diff --git a/src/third_party/mozjs-45/build/pymake/tests/parallel-simple.mk b/src/third_party/mozjs-45/build/pymake/tests/parallel-simple.mk
new file mode 100644
index 0000000..f1aafc5
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/parallel-simple.mk
@@ -0,0 +1,27 @@
+#T commandline: ['-j2']
+
+# CAUTION: this makefile is also used by serial-toparallel.mk
+
+define SLOWMAKE
+printf "$@:0:" >>results
+sleep 0.5
+printf "$@:1:" >>results
+sleep 0.5
+printf "$@:2:" >>results
+endef
+
+EXPECTED = target1:0:target2:0:target1:1:target2:1:target1:2:target2:2:
+
+all:: target1 target2
+	cat results
+	test "$$(cat results)" = "$(EXPECTED)"
+	@echo TEST-PASS
+
+target1:
+	$(SLOWMAKE)
+
+target2:
+	sleep 0.1
+	$(SLOWMAKE)
+
+.PHONY: all
diff --git a/src/third_party/mozjs-45/build/pymake/tests/parallel-submake.mk b/src/third_party/mozjs-45/build/pymake/tests/parallel-submake.mk
new file mode 100644
index 0000000..65cb2cf
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/parallel-submake.mk
@@ -0,0 +1,17 @@
+#T commandline: ['-j2']
+
+# A submake shouldn't return control to the parent until it has actually finished doing everything.
+
+all:
+	-$(MAKE) -f $(TESTPATH)/parallel-submake.mk subtarget
+	cat results
+	test "$$(cat results)" = "0123"
+	@echo TEST-PASS
+
+subtarget: succeed-slowly fail-quickly
+
+succeed-slowly:
+	printf 0 >>results; sleep 1; printf 1 >>results; sleep 1; printf 2 >>results; sleep 1; printf 3 >>results
+
+fail-quickly:
+	exit 1
diff --git a/src/third_party/mozjs-45/build/pymake/tests/parallel-toserial.mk b/src/third_party/mozjs-45/build/pymake/tests/parallel-toserial.mk
new file mode 100644
index 0000000..9a355eb
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/parallel-toserial.mk
@@ -0,0 +1,31 @@
+#T commandline: ['-j4']
+
+# Test that -j1 in a submake has the proper effect.
+
+define SLOWCMD
+printf "$@:0:" >>$(RFILE)
+sleep 0.5
+printf "$@:1:" >>$(RFILE)
+endef
+
+all: p1 p2
+subtarget: s1 s2
+
+p1 p2: RFILE = presult
+s1 s2: RFILE = sresult
+
+p1 s1:
+	$(SLOWCMD)
+
+p2 s2:
+	sleep 0.1
+	$(SLOWCMD)
+
+all:
+	$(MAKE) -j1 -f $(TESTPATH)/parallel-toserial.mk subtarget
+	printf "presult: %s\n" "$$(cat presult)"
+	test "$$(cat presult)" = "p1:0:p2:0:p1:1:p2:1:"
+	printf "sresult: %s\n" "$$(cat sresult)"
+	test "$$(cat sresult)" = "s1:0:s1:1:s2:0:s2:1:"
+	@echo TEST-PASS
+
diff --git a/src/third_party/mozjs-45/build/pymake/tests/parallel-waiting.mk b/src/third_party/mozjs-45/build/pymake/tests/parallel-waiting.mk
new file mode 100644
index 0000000..40a6e0d
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/parallel-waiting.mk
@@ -0,0 +1,21 @@
+#T commandline: ['-j2']
+
+EXPECTED = target1:before:target2:1:target2:2:target2:3:target1:after
+
+all:: target1 target2
+	cat results
+	test "$$(cat results)" = "$(EXPECTED)"
+	@echo TEST-PASS
+
+target1:
+	printf "$@:before:" >>results
+	sleep 4
+	printf "$@:after" >>results
+
+target2:
+	sleep 0.2
+	printf "$@:1:" >>results
+	sleep 0.1
+	printf "$@:2:" >>results
+	sleep 0.1
+	printf "$@:3:" >>results
diff --git a/src/third_party/mozjs-45/build/pymake/tests/parentheses.mk b/src/third_party/mozjs-45/build/pymake/tests/parentheses.mk
new file mode 100644
index 0000000..f207234
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/parentheses.mk
@@ -0,0 +1,2 @@
+all:
+	@(echo TEST-PASS)
diff --git a/src/third_party/mozjs-45/build/pymake/tests/parsertests.py b/src/third_party/mozjs-45/build/pymake/tests/parsertests.py
new file mode 100644
index 0000000..ab6406b
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/parsertests.py
@@ -0,0 +1,314 @@
+import pymake.data, pymake.parser, pymake.parserdata, pymake.functions
+import unittest
+import logging
+
+from cStringIO import StringIO
+
+def multitest(cls):
+    for name in cls.testdata.iterkeys():
+        def m(self, name=name):
+            return self.runSingle(*self.testdata[name])
+
+        setattr(cls, 'test_%s' % name, m)
+    return cls
+
+class TestBase(unittest.TestCase):
+    def assertEqual(self, a, b, msg=""):
+        """Actually print the values which weren't equal, if things don't work out!"""
+        unittest.TestCase.assertEqual(self, a, b, "%s got %r expected %r" % (msg, a, b))
+
+class DataTest(TestBase):
+    testdata = {
+        'oneline':
+            ("He\tllo", "f", 1, 0,
+             ((0, "f", 1, 0), (2, "f", 1, 2), (3, "f", 1, 4))),
+        'twoline':
+            ("line1 \n\tl\tine2", "f", 1, 4,
+             ((0, "f", 1, 4), (5, "f", 1, 9), (6, "f", 1, 10), (7, "f", 2, 0), (8, "f", 2, 4), (10, "f", 2, 8), (13, "f", 2, 11))),
+    }
+
+    def runSingle(self, data, filename, line, col, results):
+        d = pymake.parser.Data(data, 0, len(data), pymake.parserdata.Location(filename, line, col))
+        for pos, file, lineno, col in results:
+            loc = d.getloc(pos)
+            self.assertEqual(loc.path, file, "data file offset %i" % pos)
+            self.assertEqual(loc.line, lineno, "data line offset %i" % pos)
+            self.assertEqual(loc.column, col, "data col offset %i" % pos)
+multitest(DataTest)
+
+class LineEnumeratorTest(TestBase):
+    testdata = {
+        'simple': (
+            'Hello, world', [
+                ('Hello, world', 1),
+                ]
+            ),
+        'multi': (
+            'Hello\nhappy  \n\nworld\n', [
+                ('Hello', 1),
+                ('happy  ', 2),
+                ('', 3),
+                ('world', 4),
+                ('', 5),
+                ]
+            ),
+        'continuation': (
+            'Hello, \\\n world\nJellybeans!', [
+                ('Hello, \\\n world', 1),
+                ('Jellybeans!', 3),
+                ]
+            ),
+        'multislash': (
+            'Hello, \\\\\n world', [
+                ('Hello, \\\\', 1),
+                (' world', 2),
+                ]
+            )
+        }
+
+    def runSingle(self, s, lines):
+        gotlines = [(d.s[d.lstart:d.lend], d.loc.line) for d in pymake.parser.enumeratelines(s, 'path')]
+        self.assertEqual(gotlines, lines)
+
+multitest(LineEnumeratorTest)
+
+class IterTest(TestBase):
+    testdata = {
+        'plaindata': (
+            pymake.parser.iterdata,
+            "plaindata # test\n",
+            "plaindata # test\n"
+            ),
+        'makecomment': (
+            pymake.parser.itermakefilechars,
+            "VAR = val # comment",
+            "VAR = val "
+            ),
+        'makeescapedcomment': (
+            pymake.parser.itermakefilechars,
+            "VAR = val \# escaped hash",
+            "VAR = val # escaped hash"
+            ),
+        'makeescapedslash': (
+            pymake.parser.itermakefilechars,
+            "VAR = val\\\\",
+            "VAR = val\\\\",
+            ),
+        'makecontinuation': (
+            pymake.parser.itermakefilechars,
+            "VAR = VAL  \\\n  continuation # comment \\\n  continuation",
+            "VAR = VAL continuation "
+            ),
+        'makecontinuation2': (
+            pymake.parser.itermakefilechars,
+            "VAR = VAL  \\  \\\n continuation",
+            "VAR = VAL  \\ continuation"
+            ),
+        'makeawful': (
+            pymake.parser.itermakefilechars,
+            "VAR = VAL  \\\\# comment\n",
+            "VAR = VAL  \\"
+            ),
+        'command': (
+            pymake.parser.itercommandchars,
+            "echo boo # comment",
+            "echo boo # comment",
+            ),
+        'commandcomment': (
+            pymake.parser.itercommandchars,
+            "echo boo \# comment",
+            "echo boo \# comment",
+            ),
+        'commandcontinue': (
+            pymake.parser.itercommandchars,
+            "echo boo # \\\n\t  command 2",
+            "echo boo # \\\n  command 2"
+            ),
+    }
+
+    def runSingle(self, ifunc, idata, expected):
+        d = pymake.parser.Data.fromstring(idata, 'IterTest data')
+
+        it = pymake.parser._alltokens.finditer(d.s, 0, d.lend)
+        actual = ''.join( [c for c, t, o, oo in ifunc(d, 0, ('dummy-token',), it)] )
+        self.assertEqual(actual, expected)
+
+        if ifunc == pymake.parser.itermakefilechars:
+            print "testing %r" % expected
+            self.assertEqual(pymake.parser.flattenmakesyntax(d, 0), expected)
+
+multitest(IterTest)
+
+
+#         'define': (
+#             pymake.parser.iterdefinechars,
+#             "endef",
+#             ""
+#             ),
+#        'definenesting': (
+#            pymake.parser.iterdefinechars,
+#            """define BAR # comment
+#random text
+#endef not what you think!
+#endef # comment is ok\n""",
+#            """define BAR # comment
+#random text
+#endef not what you think!"""
+#            ),
+#        'defineescaped': (
+#            pymake.parser.iterdefinechars,
+#            """value   \\
+#endef
+#endef\n""",
+#            "value endef"
+#        ),
+
+class MakeSyntaxTest(TestBase):
+    # (string, startat, stopat, stopoffset, expansion
+    testdata = {
+        'text': ('hello world', 0, (), None, ['hello world']),
+        'singlechar': ('hello $W', 0, (), None,
+                       ['hello ',
+                        {'type': 'VariableRef',
+                         '.vname': ['W']}
+                        ]),
+        'stopat': ('hello: world', 0, (':', '='), 6, ['hello']),
+        'funccall': ('h $(flavor FOO)', 0, (), None,
+                     ['h ',
+                      {'type': 'FlavorFunction',
+                       '[0]': ['FOO']}
+                      ]),
+        'escapedollar': ('hello$$world', 0, (), None, ['hello$world']),
+        'varref': ('echo $(VAR)', 0, (), None,
+                   ['echo ',
+                    {'type': 'VariableRef',
+                     '.vname': ['VAR']}
+                    ]),
+        'dynamicvarname': ('echo $($(VARNAME):.c=.o)', 0, (':',), None,
+                           ['echo ',
+                            {'type': 'SubstitutionRef',
+                             '.vname': [{'type': 'VariableRef',
+                                         '.vname': ['VARNAME']}
+                                        ],
+                             '.substfrom': ['.c'],
+                             '.substto': ['.o']}
+                            ]),
+        'substref': ('  $(VAR:VAL) := $(VAL)', 0, (':=', '+=', '=', ':'), 15,
+                     ['  ',
+                      {'type': 'VariableRef',
+                       '.vname': ['VAR:VAL']},
+                      ' ']),
+        'vadsubstref': ('  $(VAR:VAL) = $(VAL)', 15, (), None,
+                        [{'type': 'VariableRef',
+                          '.vname': ['VAL']},
+                         ]),
+        }
+
+    def compareRecursive(self, actual, expected, path):
+        self.assertEqual(len(actual), len(expected),
+                         "compareRecursive: %s %r" % (path, actual))
+        for i in xrange(0, len(actual)):
+            ipath = path + [i]
+
+            a, isfunc = actual[i]
+            e = expected[i]
+            if isinstance(e, str):
+                self.assertEqual(a, e, "compareRecursive: %s" % (ipath,))
+            else:
+                self.assertEqual(type(a), getattr(pymake.functions, e['type']),
+                                 "compareRecursive: %s" % (ipath,))
+                for k, v in e.iteritems():
+                    if k == 'type':
+                        pass
+                    elif k[0] == '[':
+                        item = int(k[1:-1])
+                        proppath = ipath + [item]
+                        self.compareRecursive(a[item], v, proppath)
+                    elif k[0] == '.':
+                        item = k[1:]
+                        proppath = ipath + [item]
+                        self.compareRecursive(getattr(a, item), v, proppath)
+                    else:
+                        raise Exception("Unexpected property at %s: %s" % (ipath, k))
+
+    def runSingle(self, s, startat, stopat, stopoffset, expansion):
+        d = pymake.parser.Data.fromstring(s, pymake.parserdata.Location('testdata', 1, 0))
+
+        a, t, offset = pymake.parser.parsemakesyntax(d, startat, stopat, pymake.parser.itermakefilechars)
+        self.compareRecursive(a, expansion, [])
+        self.assertEqual(offset, stopoffset)
+
+multitest(MakeSyntaxTest)
+
+class VariableTest(TestBase):
+    testdata = """
+    VAR = value
+    VARNAME = TESTVAR
+    $(VARNAME) = testvalue
+    $(VARNAME:VAR=VAL) = moretesting
+    IMM := $(VARNAME) # this is a comment
+    MULTIVAR = val1 \\
+  val2
+    VARNAME = newname
+    """
+    expected = {'VAR': 'value',
+                'VARNAME': 'newname',
+                'TESTVAR': 'testvalue',
+                'TESTVAL': 'moretesting',
+                'IMM': 'TESTVAR ',
+                'MULTIVAR': 'val1 val2',
+                'UNDEF': None}
+
+    def runTest(self):
+        stmts = pymake.parser.parsestring(self.testdata, 'VariableTest')
+
+        m = pymake.data.Makefile()
+        stmts.execute(m)
+        for k, v in self.expected.iteritems():
+            flavor, source, val = m.variables.get(k)
+            if val is None:
+                self.assertEqual(val, v, 'variable named %s' % k)
+            else:
+                self.assertEqual(val.resolvestr(m, m.variables), v, 'variable named %s' % k)
+
+class SimpleRuleTest(TestBase):
+    testdata = """
+    VAR = value
+TSPEC = dummy
+all: TSPEC = myrule
+all:: test test2 $(VAR)
+	echo "Hello, $(TSPEC)"
+
+%.o: %.c
+	$(CC) -o $@ $<
+"""
+
+    def runTest(self):
+        stmts = pymake.parser.parsestring(self.testdata, 'SimpleRuleTest')
+
+        m = pymake.data.Makefile()
+        stmts.execute(m)
+        self.assertEqual(m.defaulttarget, 'all', "Default target")
+
+        self.assertTrue(m.hastarget('all'), "Has 'all' target")
+        target = m.gettarget('all')
+        rules = target.rules
+        self.assertEqual(len(rules), 1, "Number of rules")
+        prereqs = rules[0].prerequisites
+        self.assertEqual(prereqs, ['test', 'test2', 'value'], "Prerequisites")
+        commands = rules[0].commands
+        self.assertEqual(len(commands), 1, "Number of commands")
+        expanded = commands[0].resolvestr(m, target.variables)
+        self.assertEqual(expanded, 'echo "Hello, myrule"')
+
+        irules = m.implicitrules
+        self.assertEqual(len(irules), 1, "Number of implicit rules")
+
+        irule = irules[0]
+        self.assertEqual(len(irule.targetpatterns), 1, "%.o target pattern count")
+        self.assertEqual(len(irule.prerequisites), 1, "%.o prerequisite count")
+        self.assertEqual(irule.targetpatterns[0].match('foo.o'), 'foo', "%.o stem")
+
+if __name__ == '__main__':
+    logging.basicConfig(level=logging.DEBUG)
+    unittest.main()
diff --git a/src/third_party/mozjs-45/build/pymake/tests/path-length.mk b/src/third_party/mozjs-45/build/pymake/tests/path-length.mk
new file mode 100644
index 0000000..10c33b5
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/path-length.mk
@@ -0,0 +1,9 @@
+#T gmake skip
+
+$(shell \
+mkdir foo; \
+touch tfile; \
+)
+
+all: foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../foo/../tfile
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/pathdir/pathtest b/src/third_party/mozjs-45/build/pymake/tests/pathdir/pathtest
new file mode 100755
index 0000000..1703715
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/pathdir/pathtest
@@ -0,0 +1,2 @@
+#!/bin/sh
+echo Called shell script: 2f7cdd0b-7277-48c1-beaf-56cb0dbacb24
diff --git a/src/third_party/mozjs-45/build/pymake/tests/pathdir/pathtest.exe b/src/third_party/mozjs-45/build/pymake/tests/pathdir/pathtest.exe
new file mode 100644
index 0000000..3178db9
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/pathdir/pathtest.exe
Binary files differ
diff --git a/src/third_party/mozjs-45/build/pymake/tests/pathdir/src/Makefile b/src/third_party/mozjs-45/build/pymake/tests/pathdir/src/Makefile
new file mode 100644
index 0000000..6c24bd8
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/pathdir/src/Makefile
@@ -0,0 +1,2 @@
+pathtest.exe: pathtest.cpp
+	cl -EHsc -MT $^
diff --git a/src/third_party/mozjs-45/build/pymake/tests/pathdir/src/pathtest.cpp b/src/third_party/mozjs-45/build/pymake/tests/pathdir/src/pathtest.cpp
new file mode 100644
index 0000000..bef8d8a
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/pathdir/src/pathtest.cpp
@@ -0,0 +1,6 @@
+#include <cstdio>
+
+int main() {
+  std::printf("Called Windows executable: 2f7cdd0b-7277-48c1-beaf-56cb0dbacb24\n");
+  return 0;
+}
diff --git a/src/third_party/mozjs-45/build/pymake/tests/patsubst.mk b/src/third_party/mozjs-45/build/pymake/tests/patsubst.mk
new file mode 100644
index 0000000..0c3efdc
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/patsubst.mk
@@ -0,0 +1,7 @@
+all:
+	test "$(patsubst foo,%.bar,foo)" = "%.bar"
+	test "$(patsubst \%word,replace,word %word other)" = "word replace other"
+	test "$(patsubst %.c,\%%.o,foo.c bar.o baz.cpp)" = "%foo.o bar.o baz.cpp"
+	test "$(patsubst host_%.c,host_%.o,dir/host_foo.c host_bar.c)" = "dir/host_foo.c host_bar.o"
+	test "$(patsubst foo,bar,dir/foo foo baz)" = "dir/foo bar baz"
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/phony.mk b/src/third_party/mozjs-45/build/pymake/tests/phony.mk
new file mode 100644
index 0000000..36db4d1
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/phony.mk
@@ -0,0 +1,10 @@
+$(shell \
+touch dep; \
+sleep 2; \
+touch all; \
+)
+
+all:: dep
+	@echo TEST-PASS
+
+.PHONY: all
diff --git a/src/third_party/mozjs-45/build/pymake/tests/pycmd.py b/src/third_party/mozjs-45/build/pymake/tests/pycmd.py
new file mode 100644
index 0000000..83b9b96
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/pycmd.py
@@ -0,0 +1,38 @@
+import os, sys, subprocess
+
+def writetofile(args):
+  with open(args[0], 'w') as f:
+    f.write(' '.join(args[1:]))
+
+def writeenvtofile(args):
+  with open(args[0], 'w') as f:
+    f.write(os.environ[args[1]])
+
+def writesubprocessenvtofile(args):
+  with open(args[0], 'w') as f:
+    p = subprocess.Popen([sys.executable, "-c",
+                          "import os; print os.environ['%s']" % args[1]],
+                          stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    stdout, stderr = p.communicate()
+    assert p.returncode == 0
+    f.write(stdout)
+
+def convertasplode(arg):
+  try:
+    return int(arg)
+  except:
+    return (None if arg == "None" else arg)
+
+def asplode(args):
+  arg0 = convertasplode(args[0])
+  sys.exit(arg0)
+
+def asplode_return(args):
+  arg0 = convertasplode(args[0])
+  return arg0
+
+def asplode_raise(args):
+  raise Exception(args[0])
+
+def delayloadfn(args):
+    import delayload
diff --git a/src/third_party/mozjs-45/build/pymake/tests/recursive-set.mk b/src/third_party/mozjs-45/build/pymake/tests/recursive-set.mk
new file mode 100644
index 0000000..853f904
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/recursive-set.mk
@@ -0,0 +1,7 @@
+#T returncode: 2
+
+FOO = $(FOO)
+
+all:
+	echo $(FOO)
+	@echo TEST-FAIL
diff --git a/src/third_party/mozjs-45/build/pymake/tests/recursive-set2.mk b/src/third_party/mozjs-45/build/pymake/tests/recursive-set2.mk
new file mode 100644
index 0000000..b68e34f
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/recursive-set2.mk
@@ -0,0 +1,8 @@
+#T returncode: 2
+
+FOO = $(BAR)
+BAR = $(FOO)
+
+all:
+	echo $(FOO)
+	@echo TEST-FAIL
diff --git a/src/third_party/mozjs-45/build/pymake/tests/remake-mtime.mk b/src/third_party/mozjs-45/build/pymake/tests/remake-mtime.mk
new file mode 100644
index 0000000..47c775b
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/remake-mtime.mk
@@ -0,0 +1,14 @@
+# mtime(dep1) < mtime(target) so the target should not be made
+$(shell touch dep1; sleep 1; touch target)
+
+all: target
+	echo TEST-PASS
+
+target: dep1
+	echo TEST-FAIL target should not have been made
+
+dep1: dep2
+	@echo "Remaking dep1 (actually not)"
+
+dep2:
+	@echo "Making dep2 (actually not)"
diff --git a/src/third_party/mozjs-45/build/pymake/tests/rm-fail.mk b/src/third_party/mozjs-45/build/pymake/tests/rm-fail.mk
new file mode 100644
index 0000000..1a9aefb
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/rm-fail.mk
@@ -0,0 +1,7 @@
+#T returncode: 2
+all:
+	mkdir newdir
+	test -d newdir
+	touch newdir/newfile
+	$(RM) newdir
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/rm.mk b/src/third_party/mozjs-45/build/pymake/tests/rm.mk
new file mode 100644
index 0000000..6c7140e
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/rm.mk
@@ -0,0 +1,21 @@
+all:
+# $(RM) defaults to -f
+	$(RM) nosuchfile
+	touch newfile
+	test -f newfile
+	$(RM) newfile
+	test ! -f newfile
+	mkdir newdir
+	test -d newdir
+	touch newdir/newfile
+	mkdir newdir/subdir
+	$(RM) -r newdir/subdir
+	test ! -d newdir/subdir
+	test -d newdir
+	mkdir newdir/subdir1 newdir/subdir2
+	$(RM) -r newdir/subdir1 newdir/subdir2
+	test ! -d newdir/subdir1 -a ! -d newdir/subdir2
+	test -d newdir
+	$(RM) -r newdir
+	test ! -d newdir
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/runtests.py b/src/third_party/mozjs-45/build/pymake/tests/runtests.py
new file mode 100644
index 0000000..ab149ec
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/runtests.py
@@ -0,0 +1,215 @@
+#!/usr/bin/env python
+"""
+Run the test(s) listed on the command line. If a directory is listed, the script will recursively
+walk the directory for files named .mk and run each.
+
+For each test, we run gmake -f test.mk. By default, make must exit with an exit code of 0, and must print 'TEST-PASS'.
+
+Each test is run in an empty directory.
+
+The test file may contain lines at the beginning to alter the default behavior. These are all evaluated as python:
+
+#T commandline: ['extra', 'params', 'here']
+#T returncode: 2
+#T returncode-on: {'win32': 2}
+#T environment: {'VAR': 'VALUE}
+#T grep-for: "text"
+"""
+
+from subprocess import Popen, PIPE, STDOUT
+from optparse import OptionParser
+import os, re, sys, shutil, glob
+
+class ParentDict(dict):
+    def __init__(self, parent, **kwargs):
+        self.d = dict(kwargs)
+        self.parent = parent
+
+    def __setitem__(self, k, v):
+        self.d[k] = v
+
+    def __getitem__(self, k):
+        if k in self.d:
+            return self.d[k]
+
+        return self.parent[k]
+
+thisdir = os.path.dirname(os.path.abspath(__file__))
+
+pymake = [sys.executable, os.path.join(os.path.dirname(thisdir), 'make.py')]
+manifest = os.path.join(thisdir, 'tests.manifest')
+
+o = OptionParser()
+o.add_option('-g', '--gmake',
+             dest="gmake", default="gmake")
+o.add_option('-d', '--tempdir',
+             dest="tempdir", default="_mktests")
+opts, args = o.parse_args()
+
+if len(args) == 0:
+    args = [thisdir]
+
+makefiles = []
+for a in args:
+    if os.path.isfile(a):
+        makefiles.append(a)
+    elif os.path.isdir(a):
+        makefiles.extend(sorted(glob.glob(os.path.join(a, '*.mk'))))
+
+def runTest(makefile, make, logfile, options):
+    """
+    Given a makefile path, test it with a given `make` and return
+    (pass, message).
+    """
+
+    if os.path.exists(opts.tempdir): shutil.rmtree(opts.tempdir)
+    os.mkdir(opts.tempdir, 0755)
+
+    logfd = open(logfile, 'w')
+    p = Popen(make + options['commandline'], stdout=logfd, stderr=STDOUT, env=options['env'])
+    logfd.close()
+    retcode = p.wait()
+
+    if retcode != options['returncode']:
+        return False, "FAIL (returncode=%i)" % retcode
+        
+    logfd = open(logfile)
+    stdout = logfd.read()
+    logfd.close()
+
+    if stdout.find('TEST-FAIL') != -1:
+        print stdout
+        return False, "FAIL (TEST-FAIL printed)"
+
+    if options['grepfor'] and stdout.find(options['grepfor']) == -1:
+        print stdout
+        return False, "FAIL (%s not in output)" % options['grepfor']
+
+    if options['returncode'] == 0 and stdout.find('TEST-PASS') == -1:
+        print stdout
+        return False, 'FAIL (No TEST-PASS printed)'
+
+    if options['returncode'] != 0:
+        return True, 'PASS (retcode=%s)' % retcode
+
+    return True, 'PASS'
+
+print "%-30s%-28s%-28s" % ("Test:", "gmake:", "pymake:")
+
+gmakefails = 0
+pymakefails = 0
+
+tre = re.compile('^#T (gmake |pymake )?([a-z-]+)(?:: (.*))?$')
+
+for makefile in makefiles:
+    # For some reason, MAKEFILE_LIST uses native paths in GNU make on Windows
+    # (even in MSYS!) so we pass both TESTPATH and NATIVE_TESTPATH
+    cline = ['-C', opts.tempdir, '-f', os.path.abspath(makefile), 'TESTPATH=%s' % thisdir.replace('\\','/'), 'NATIVE_TESTPATH=%s' % thisdir]
+    if sys.platform == 'win32':
+        #XXX: hack so we can specialize the separator character on windows.
+        # we really shouldn't need this, but y'know
+        cline += ['__WIN32__=1']
+
+    options = {
+        'returncode': 0,
+        'grepfor': None,
+        'env': dict(os.environ),
+        'commandline': cline,
+        'pass': True,
+        'skip': False,
+        }
+
+    gmakeoptions = ParentDict(options)
+    pymakeoptions = ParentDict(options)
+
+    dmap = {None: options, 'gmake ': gmakeoptions, 'pymake ': pymakeoptions}
+
+    mdata = open(makefile)
+    for line in mdata:
+        line = line.strip()
+        m = tre.search(line)
+        if m is None:
+            break
+
+        make, key, data = m.group(1, 2, 3)
+        d = dmap[make]
+        if data is not None:
+            data = eval(data)
+        if key == 'commandline':
+            assert make is None
+            d['commandline'].extend(data)
+        elif key == 'returncode':
+            d['returncode'] = data
+        elif key == 'returncode-on':
+            if sys.platform in data:
+                d['returncode'] = data[sys.platform]
+        elif key == 'environment':
+            for k, v in data.iteritems():
+                d['env'][k] = v
+        elif key == 'grep-for':
+            d['grepfor'] = data
+        elif key == 'fail':
+            d['pass'] = False
+        elif key == 'skip':
+            d['skip'] = True
+        else:
+            print >>sys.stderr, "%s: Unexpected #T key: %s" % (makefile, key)
+            sys.exit(1)
+
+    mdata.close()
+
+    if gmakeoptions['skip']:
+        gmakepass, gmakemsg = True, ''
+    else:
+        gmakepass, gmakemsg = runTest(makefile, [opts.gmake],
+                                      makefile + '.gmakelog', gmakeoptions)
+
+    if gmakeoptions['pass']:
+        if not gmakepass:
+            gmakefails += 1
+    else:
+        if gmakepass:
+            gmakefails += 1
+            gmakemsg = "UNEXPECTED PASS"
+        else:
+            gmakemsg = "KNOWN FAIL"
+
+    if pymakeoptions['skip']:
+        pymakepass, pymakemsg = True, ''
+    else:
+        pymakepass, pymakemsg = runTest(makefile, pymake,
+                                        makefile + '.pymakelog', pymakeoptions)
+
+    if pymakeoptions['pass']:
+        if not pymakepass:
+            pymakefails += 1
+    else:
+        if pymakepass:
+            pymakefails += 1
+            pymakemsg = "UNEXPECTED PASS"
+        else:
+            pymakemsg = "OK (known fail)"
+
+    print "%-30.30s%-28.28s%-28.28s" % (os.path.basename(makefile),
+                                        gmakemsg, pymakemsg)
+
+print
+print "Summary:"
+print "%-30s%-28s%-28s" % ("", "gmake:", "pymake:")
+
+if gmakefails == 0:
+    gmakemsg = 'PASS'
+else:
+    gmakemsg = 'FAIL (%i failures)' % gmakefails
+
+if pymakefails == 0:
+    pymakemsg = 'PASS'
+else:
+    pymakemsg = 'FAIL (%i failures)' % pymakefails
+
+print "%-30.30s%-28.28s%-28.28s" % ('', gmakemsg, pymakemsg)
+
+shutil.rmtree(opts.tempdir)
+
+if gmakefails or pymakefails:
+    sys.exit(1)
diff --git a/src/third_party/mozjs-45/build/pymake/tests/serial-dep-resolution.mk b/src/third_party/mozjs-45/build/pymake/tests/serial-dep-resolution.mk
new file mode 100644
index 0000000..e65f1ed
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/serial-dep-resolution.mk
@@ -0,0 +1,5 @@
+all: t1 t2
+	@echo TEST-PASS
+
+t1:
+	touch t1 t2
diff --git a/src/third_party/mozjs-45/build/pymake/tests/serial-doublecolon-execution.mk b/src/third_party/mozjs-45/build/pymake/tests/serial-doublecolon-execution.mk
new file mode 100644
index 0000000..1871cb1
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/serial-doublecolon-execution.mk
@@ -0,0 +1,18 @@
+#T commandline: ['-j3']
+
+# Commands of double-colon rules are always executed in order.
+
+all: dc
+	cat status
+	test "$$(cat status)" = "all1:all2:"
+	@echo TEST-PASS
+
+dc:: slowt
+	printf "all1:" >> status
+
+dc::
+	sleep 0.2
+	printf "all2:" >> status
+
+slowt:
+	sleep 1
diff --git a/src/third_party/mozjs-45/build/pymake/tests/serial-rule-execution.mk b/src/third_party/mozjs-45/build/pymake/tests/serial-rule-execution.mk
new file mode 100644
index 0000000..da5b177
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/serial-rule-execution.mk
@@ -0,0 +1,5 @@
+all::
+	touch somefile
+
+all:: somefile
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/serial-rule-execution2.mk b/src/third_party/mozjs-45/build/pymake/tests/serial-rule-execution2.mk
new file mode 100644
index 0000000..252a7df
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/serial-rule-execution2.mk
@@ -0,0 +1,13 @@
+#T returncode: 2
+
+# The dependencies of the command rule of a single-colon target are resolved before the rules without commands.
+
+all: export
+
+export:
+	sleep 1
+	touch somefile
+
+all: somefile
+	test -f somefile
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/serial-toparallel.mk b/src/third_party/mozjs-45/build/pymake/tests/serial-toparallel.mk
new file mode 100644
index 0000000..a980bad
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/serial-toparallel.mk
@@ -0,0 +1,5 @@
+all::
+	$(MAKE) -j2 -f $(TESTPATH)/parallel-simple.mk
+
+all:: results
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/shellfunc.mk b/src/third_party/mozjs-45/build/pymake/tests/shellfunc.mk
new file mode 100644
index 0000000..1e408db
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/shellfunc.mk
@@ -0,0 +1,7 @@
+all: testfile
+	test "$(shell cat $<)" = "Hello world"
+	test "$(shell printf "\n")" = ""
+	@echo TEST-PASS
+
+testfile:
+	printf "Hello\nworld\n" > $@
diff --git a/src/third_party/mozjs-45/build/pymake/tests/simple-makeflags.mk b/src/third_party/mozjs-45/build/pymake/tests/simple-makeflags.mk
new file mode 100644
index 0000000..c7c92ec
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/simple-makeflags.mk
@@ -0,0 +1,10 @@
+# There once was a time when MAKEFLAGS=w without any following spaces would
+# cause us to treat w as a target, not a flag. Silly!
+
+MAKEFLAGS=w
+
+all:
+	$(MAKE) -f $(TESTPATH)/simple-makeflags.mk subt
+	@echo TEST-PASS
+
+subt:
diff --git a/src/third_party/mozjs-45/build/pymake/tests/sort.mk b/src/third_party/mozjs-45/build/pymake/tests/sort.mk
new file mode 100644
index 0000000..e1313ad
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/sort.mk
@@ -0,0 +1,4 @@
+# sort should remove duplicates
+all:
+	@test "$(sort x a y b z c a z b x c y)" = "a b c x y z"
+	@echo "TEST-PASS"
diff --git a/src/third_party/mozjs-45/build/pymake/tests/specified-target.mk b/src/third_party/mozjs-45/build/pymake/tests/specified-target.mk
new file mode 100644
index 0000000..3b23fbf
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/specified-target.mk
@@ -0,0 +1,7 @@
+#T commandline: ['VAR=all', '$(VAR)']
+
+all:
+	@echo TEST-FAIL: unexpected target 'all'
+
+$$(VAR):
+	@echo TEST-PASS: expected target '$$(VAR)'
diff --git a/src/third_party/mozjs-45/build/pymake/tests/static-pattern.mk b/src/third_party/mozjs-45/build/pymake/tests/static-pattern.mk
new file mode 100644
index 0000000..f613b8c
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/static-pattern.mk
@@ -0,0 +1,5 @@
+#T returncode: 2
+
+out/host_foo.o: host_%.o: host_%.c out
+	cp $< $@
+	@echo TEST-FAIL
diff --git a/src/third_party/mozjs-45/build/pymake/tests/static-pattern2.mk b/src/third_party/mozjs-45/build/pymake/tests/static-pattern2.mk
new file mode 100644
index 0000000..08ed834
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/static-pattern2.mk
@@ -0,0 +1,10 @@
+all: foo.out
+	test -f $^
+	@echo TEST-PASS
+
+foo.out: %.out: %.in
+	test "$*" = "foo"
+	cp $^ $@
+
+foo.in:
+	touch $@
diff --git a/src/third_party/mozjs-45/build/pymake/tests/subdir/delayload.py b/src/third_party/mozjs-45/build/pymake/tests/subdir/delayload.py
new file mode 100644
index 0000000..bdd6669
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/subdir/delayload.py
@@ -0,0 +1 @@
+# This module exists to test delay importing of modules at run-time.
diff --git a/src/third_party/mozjs-45/build/pymake/tests/subdir/pymod.py b/src/third_party/mozjs-45/build/pymake/tests/subdir/pymod.py
new file mode 100644
index 0000000..1a47d8a
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/subdir/pymod.py
@@ -0,0 +1,5 @@
+import testmodule
+
+def writetofile(args):
+  with open(args[0], 'w') as f:
+    f.write(' '.join(args[1:]))
diff --git a/src/third_party/mozjs-45/build/pymake/tests/subdir/testmodule.py b/src/third_party/mozjs-45/build/pymake/tests/subdir/testmodule.py
new file mode 100644
index 0000000..05b2f82
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/subdir/testmodule.py
@@ -0,0 +1,3 @@
+# This is an empty module. It is imported by pymod.py to test that if a module
+# is loaded from the PYCOMMANDPATH, it can import other modules from the same
+# directory correctly.
diff --git a/src/third_party/mozjs-45/build/pymake/tests/submake-path.makefile2 b/src/third_party/mozjs-45/build/pymake/tests/submake-path.makefile2
new file mode 100644
index 0000000..1266db7
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/submake-path.makefile2
@@ -0,0 +1,11 @@
+# -*- Mode: Makefile -*-
+
+shellresult := $(shell pathtest)
+ifneq (2f7cdd0b-7277-48c1-beaf-56cb0dbacb24,$(filter $(shellresult),2f7cdd0b-7277-48c1-beaf-56cb0dbacb24))
+$(error pathtest not found in submake shell function)
+endif
+
+all:
+	@pathtest
+	@pathtest | grep -q 2f7cdd0b-7277-48c1-beaf-56cb0dbacb24
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/submake-path.mk b/src/third_party/mozjs-45/build/pymake/tests/submake-path.mk
new file mode 100644
index 0000000..b643227
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/submake-path.mk
@@ -0,0 +1,16 @@
+#T gmake skip
+#T grep-for: "2f7cdd0b-7277-48c1-beaf-56cb0dbacb24"
+
+ifdef __WIN32__
+PS:=;
+else
+PS:=:
+endif
+
+export PATH := $(TESTPATH)/pathdir$(PS)$(PATH)
+
+# This is similar to subprocess-path.mk, except we also check $(shell)
+# invocations since they're affected by exported environment variables too,
+# but only in submakes!
+all:
+	$(MAKE) -f $(TESTPATH)/submake-path.makefile2
diff --git a/src/third_party/mozjs-45/build/pymake/tests/submake.makefile2 b/src/third_party/mozjs-45/build/pymake/tests/submake.makefile2
new file mode 100644
index 0000000..12ce948
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/submake.makefile2
@@ -0,0 +1,24 @@
+# -*- Mode: Makefile -*-
+
+$(info MAKEFLAGS = '$(MAKEFLAGS)')
+$(info MAKE = '$(MAKE)')
+$(info value MAKE = "$(value MAKE)")
+
+shellresult := $(shell echo -n $$EVAR)
+ifneq ($(shellresult),eval)
+$(error EVAR should be eval, is instead $(shellresult))
+endif
+
+all:
+	env
+	test "$(MAKELEVEL)" = "1"
+	echo "value(MAKE)" '$(value MAKE)'
+	echo "value(MAKE_COMMAND)" = '$(value MAKE_COMMAND)'
+	test "$(origin CVAR)" = "command line"
+	test "$(CVAR)" = "c val=spac\ed"
+	test "$(origin EVAR)" = "environment"
+	test "$(EVAR)" = "eval"
+	test "$(OVAL)" = "cline"
+	test "$(OVAL2)" = "cline2"
+	test "$(ALLVAR)" = "allspecific"
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/submake.mk b/src/third_party/mozjs-45/build/pymake/tests/submake.mk
new file mode 100644
index 0000000..41e4713
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/submake.mk
@@ -0,0 +1,16 @@
+#T commandline: ['CVAR=c val=spac\\ed', 'OVAL=cline', 'OVAL2=cline2']
+
+export EVAR = eval
+override OVAL = makefile
+
+# exporting an override variable doesn't mean it's an override variable
+override OVAL2 = makefile2
+export OVAL2
+
+export ALLVAR
+ALLVAR = general
+all: ALLVAR = allspecific
+
+all:
+	test "$(MAKELEVEL)" = "0"
+	$(MAKE) -f $(TESTPATH)/submake.makefile2
diff --git a/src/third_party/mozjs-45/build/pymake/tests/subprocess-path.mk b/src/third_party/mozjs-45/build/pymake/tests/subprocess-path.mk
new file mode 100644
index 0000000..f639214
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/subprocess-path.mk
@@ -0,0 +1,32 @@
+#T gmake skip
+#T grep-for: "2f7cdd0b-7277-48c1-beaf-56cb0dbacb24"
+
+ifdef __WIN32__
+PS:=;
+else
+PS:=:
+endif
+
+export PATH := $(TESTPATH)/pathdir$(PS)$(PATH)
+
+# Test two commands. The first one shouldn't go through the shell and the
+# second one should. The pathdir subdirectory has a Windows executable called
+# pathtest.exe and a shell script called pathtest. We don't care which one is
+# run, just that one of the two is (we use a uuid + grep-for to make sure
+# that happens).
+#
+# FAQ:
+# Q. Why skip GNU Make?
+# A. Because $(TESTPATH) is a Windows-style path, and MSYS make doesn't take
+#    too kindly to Windows paths in the PATH environment variable.
+#
+# Q. Why use an exe and not a batch file?
+# A. The use cases here were all exe files without the extension. Batch file
+#    lookup has broken semantics if the .bat extension isn't passed.
+#
+# Q. Why are the commands silent?
+# A. So that we don't pass the grep-for test by mistake.
+all:
+	@pathtest
+	@pathtest | grep -q 2f7cdd0b-7277-48c1-beaf-56cb0dbacb24
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/tab-intro.mk b/src/third_party/mozjs-45/build/pymake/tests/tab-intro.mk
new file mode 100644
index 0000000..1c25ce7
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/tab-intro.mk
@@ -0,0 +1,16 @@
+# Initial tab characters should be treated well.
+
+	THIS = a value
+
+	ifdef THIS
+	VAR = conditional value
+	endif
+
+all:
+	test "$(THIS)" = "another value"
+	test "$(VAR)" = "conditional value"
+	@echo TEST-PASS
+
+THAT = makefile syntax
+
+	THIS = another value
diff --git a/src/third_party/mozjs-45/build/pymake/tests/target-specific.mk b/src/third_party/mozjs-45/build/pymake/tests/target-specific.mk
new file mode 100644
index 0000000..217ed15
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/target-specific.mk
@@ -0,0 +1,30 @@
+TESTVAR = anonval
+
+all: target.suffix target.suffix2 dummy host_test.py my.test1 my.test2
+	@echo TEST-PASS
+
+target.suffix: TESTVAR = testval
+
+%.suffix:
+	test "$(TESTVAR)" = "testval"
+
+%.suffix2: TESTVAR = testval2
+
+%.suffix2:
+	test "$(TESTVAR)" = "testval2"
+
+%my: TESTVAR = dummyval
+
+dummy:
+	test "$(TESTVAR)" = "dummyval"
+
+%.py: TESTVAR = pyval
+host_%.py: TESTVAR = hostval
+
+host_test.py:
+	test "$(TESTVAR)" = "hostval"
+
+%.test1 %.test2: TESTVAR = %val
+
+my.test1 my.test2:
+	test "$(TESTVAR)" = "%val"
diff --git a/src/third_party/mozjs-45/build/pymake/tests/unexport.mk b/src/third_party/mozjs-45/build/pymake/tests/unexport.mk
new file mode 100644
index 0000000..4244116
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/unexport.mk
@@ -0,0 +1,15 @@
+#T environment: {'ENVVAR': 'envval'}
+
+VAR1 = val1
+VAR2 = val2
+VAR3 = val3
+
+unexport VAR3
+export VAR1 VAR2 VAR3
+unexport VAR2 ENVVAR
+unexport
+
+all:
+	test "$(ENVVAR)" = "envval" # unexport.mk
+	$(MAKE) -f $(TESTPATH)/unexport.submk
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/unexport.submk b/src/third_party/mozjs-45/build/pymake/tests/unexport.submk
new file mode 100644
index 0000000..8db6163
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/unexport.submk
@@ -0,0 +1,15 @@
+# -@- Mode: Makefile -@- 
+
+unexport VAR1
+
+all:
+	env
+	test "$(VAR1)" = "val1"
+	test "$(origin VAR1)" = "environment"
+	test "$(VAR2)" = "" # VAR2
+	test "$(VAR3)" = "val3"
+	test "$(ENVVAR)" = ""
+	$(MAKE) -f $(TESTPATH)/unexport.submk subt
+
+subt:
+	test "$(VAR1)" = ""
diff --git a/src/third_party/mozjs-45/build/pymake/tests/unterminated-dollar.mk b/src/third_party/mozjs-45/build/pymake/tests/unterminated-dollar.mk
new file mode 100644
index 0000000..dee9a20
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/unterminated-dollar.mk
@@ -0,0 +1,6 @@
+VAR = value$
+VAR2 = other
+
+all:
+	test "$(VAR)" = "value"
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/var-change-flavor.mk b/src/third_party/mozjs-45/build/pymake/tests/var-change-flavor.mk
new file mode 100644
index 0000000..0cccf0b
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/var-change-flavor.mk
@@ -0,0 +1,12 @@
+VAR = value1
+VAR := value2
+
+VAR2 := val1
+VAR2 = val2
+
+default:
+	test "$(flavor VAR)" = "simple"
+	test "$(VAR)" = "value2"
+	test "$(flavor VAR2)" = "recursive"
+	test "$(VAR2)" = "val2"
+	@echo "TEST-PASS"
diff --git a/src/third_party/mozjs-45/build/pymake/tests/var-commandline.mk b/src/third_party/mozjs-45/build/pymake/tests/var-commandline.mk
new file mode 100644
index 0000000..e2cdad4
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/var-commandline.mk
@@ -0,0 +1,8 @@
+#T commandline: ['TESTVAR=$(MAKEVAL)', 'TESTVAR2:=$(MAKEVAL)']
+
+MAKEVAL=testvalue
+
+all:
+	test "$(TESTVAR)" = "testvalue"
+	test "$(TESTVAR2)" = ""
+	@echo "TEST-PASS"
\ No newline at end of file
diff --git a/src/third_party/mozjs-45/build/pymake/tests/var-overrides.mk b/src/third_party/mozjs-45/build/pymake/tests/var-overrides.mk
new file mode 100644
index 0000000..bd0765d
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/var-overrides.mk
@@ -0,0 +1,21 @@
+#T commandline: ['CLINEVAR=clineval', 'CLINEVAR2=clineval2']
+
+# this doesn't actually test overrides yet, because they aren't implemented in pymake,
+# but testing origins in general is important
+
+MVAR = mval
+CLINEVAR = deadbeef
+
+override CLINEVAR2 = mval2
+
+all:
+	test "$(origin NOVAR)" = "undefined"
+	test "$(CLINEVAR)" = "clineval"
+	test "$(origin CLINEVAR)" = "command line"
+	test "$(MVAR)" = "mval"
+	test "$(origin MVAR)" = "file"
+	test "$(@)" = "all"
+	test "$(origin @)" = "automatic"
+	test "$(origin CLINEVAR2)" = "override"
+	test "$(CLINEVAR2)" = "mval2"
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/var-ref.mk b/src/third_party/mozjs-45/build/pymake/tests/var-ref.mk
new file mode 100644
index 0000000..3bc1886
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/var-ref.mk
@@ -0,0 +1,19 @@
+VAR = value
+VAR2 == value
+
+VAR5 = $(NULL) $(NULL)
+VARC = value # comment
+
+$(VAR3)
+  $(VAR4)  
+$(VAR5)
+
+VAR6$(VAR5) = val6
+
+all:
+	test "$( VAR)" = ""
+	test "$(VAR2)" = "= value"
+	test "${VAR2}" = "= value"
+	test "$(VAR6 )" = "val6"
+	test "$(VARC)" = "value "
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/var-set.mk b/src/third_party/mozjs-45/build/pymake/tests/var-set.mk
new file mode 100644
index 0000000..1603e7a
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/var-set.mk
@@ -0,0 +1,55 @@
+#T commandline: ['OBASIC=oval']
+
+BASIC = val
+
+TEST = $(TEST)
+
+TEST2 = $(TES
+TEST2 += T)
+
+TES T = val
+
+RECVAR = foo
+RECVAR += var baz 
+
+IMMVAR := bloo
+IMMVAR += $(RECVAR)
+
+BASIC ?= notval
+
+all: BASIC = valall
+all: RECVAR += $(BASIC)
+all: IMMVAR += $(BASIC)
+all: UNSET += more
+all: OBASIC += allmore
+
+CHECKLIT = $(NULL) check
+all: CHECKLIT += appendliteral
+
+RECVAR = blimey
+
+TESTEMPTY = \
+	$(NULL)
+
+all: other
+	test "$(TEST2)" = "val"
+	test '$(value TEST2)' = '$$(TES T)'
+	test "$(RECVAR)" = "blimey valall"
+	test "$(IMMVAR)" = "bloo foo var baz  valall"
+	test "$(UNSET)" = "more"
+	test "$(OBASIC)" = "oval"
+	test "$(CHECKLIT)" = " check appendliteral"
+	test "$(TESTEMPTY)" = ""
+	@echo TEST-PASS
+
+OVAR = oval
+OVAR ?= onotval
+
+other: OVAR ?= ooval
+other: LATERVAR ?= lateroverride
+
+LATERVAR = olater
+
+other:
+	test "$(OVAR)" = "oval"
+	test "$(LATERVAR)" = "lateroverride"
diff --git a/src/third_party/mozjs-45/build/pymake/tests/var-substitutions.mk b/src/third_party/mozjs-45/build/pymake/tests/var-substitutions.mk
new file mode 100644
index 0000000..d5627d7
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/var-substitutions.mk
@@ -0,0 +1,49 @@
+SIMPLEVAR = aabb.cc
+SIMPLEPERCENT = test_value%extra
+
+SIMPLE3SUBSTNAME = SIMPLEVAR:.dd
+$(SIMPLE3SUBSTNAME) = weirdval
+
+PERCENT = dummy
+
+SIMPLESUBST = $(SIMPLEVAR:.cc=.dd)
+SIMPLE2SUBST = $(SIMPLEVAR:.cc)
+SIMPLE3SUBST = $(SIMPLEVAR:.dd)
+SIMPLE4SUBST = $(SIMPLEVAR:.cc=.dd=.ee)
+SIMPLE5SUBST = $(SIMPLEVAR:.cc=%.dd)
+PERCENTSUBST = $(SIMPLEVAR:%.cc=%.ee)
+PERCENT2SUBST = $(SIMPLEVAR:aa%.cc=ff%.f)
+PERCENT3SUBST = $(SIMPLEVAR:aa%.dd=gg%.gg)
+PERCENT4SUBST = $(SIMPLEVAR:aa%.cc=gg)
+PERCENT5SUBST = $(SIMPLEVAR:aa)
+PERCENT6SUBST = $(SIMPLEVAR:%.cc=%.dd=%.ee)
+PERCENT7SUBST = $(SIMPLEVAR:$(PERCENT).cc=%.dd)
+PERCENT8SUBST = $(SIMPLEVAR:%.cc=$(PERCENT).dd)
+PERCENT9SUBST = $(SIMPLEVAR:$(PERCENT).cc=$(PERCENT).dd)
+PERCENT10SUBST = $(SIMPLEVAR:%%.bb.cc=zz.bb.cc)
+PERCENT11SUBST = $(SIMPLEPERCENT:test%value%extra=other%value%extra)
+
+SPACEDVAR = $(NULL)  ex1.c ex2.c $(NULL)
+SPACEDSUBST = $(SPACEDVAR:.c=.o)
+
+all:
+	test "$(SIMPLESUBST)" = "aabb.dd"
+	test "$(SIMPLE2SUBST)" = ""
+	test "$(SIMPLE3SUBST)" = "weirdval"
+	test "$(SIMPLE4SUBST)" = "aabb.dd=.ee"
+	test "$(SIMPLE5SUBST)" = "aabb%.dd"
+	test "$(PERCENTSUBST)" = "aabb.ee"
+	test "$(PERCENT2SUBST)" = "ffbb.f"
+	test "$(PERCENT3SUBST)" = "aabb.cc"
+	test "$(PERCENT4SUBST)" = "gg"
+	test "$(PERCENT5SUBST)" = ""
+	test "$(PERCENT6SUBST)" = "aabb.dd=%.ee"
+	test "$(PERCENT7SUBST)" = "aabb.dd"
+	test "$(PERCENT8SUBST)" = "aabb.dd"
+	test "$(PERCENT9SUBST)" = "aabb.dd"
+	test "$(PERCENT10SUBST)" = "aabb.cc"
+	test "$(PERCENT11SUBST)" = "other_value%extra"
+	test "$(SPACEDSUBST)" = "ex1.o ex2.o"
+	@echo TEST-PASS
+
+PERCENT = %
diff --git a/src/third_party/mozjs-45/build/pymake/tests/vpath-directive-dynamic.mk b/src/third_party/mozjs-45/build/pymake/tests/vpath-directive-dynamic.mk
new file mode 100644
index 0000000..9aa1bf9
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/vpath-directive-dynamic.mk
@@ -0,0 +1,12 @@
+$(shell \
+mkdir subd1; \
+touch subd1/test.in; \
+)
+
+VVAR = %.in subd1
+
+vpath $(VVAR)
+
+all: test.in
+	test "$<" = "subd1/test.in"
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/vpath-directive.mk b/src/third_party/mozjs-45/build/pymake/tests/vpath-directive.mk
new file mode 100644
index 0000000..4c7d4bf
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/vpath-directive.mk
@@ -0,0 +1,31 @@
+# On Windows, MSYS make takes Unix paths but Pymake takes Windows paths
+VPSEP := $(if $(and $(__WIN32__),$(.PYMAKE)),;,:)
+
+$(shell \
+mkdir subd1 subd2 subd3; \
+printf "reallybaddata" >subd1/foo.in; \
+printf "gooddata" >subd2/foo.in; \
+printf "baddata" >subd3/foo.in; \
+touch subd1/foo.in2 subd2/foo.in2 subd3/foo.in2; \
+)
+
+vpath %.in subd
+
+vpath
+vpath %.in subd2$(VPSEP)subd3
+
+vpath %.in2 subd0
+vpath f%.in2 subd1
+vpath %.in2 $(VPSEP)subd2
+
+%.out: %.in
+	test "$<" = "subd2/foo.in"
+	cp $< $@
+
+%.out2: %.in2
+	test "$<" = "subd1/foo.in2"
+	cp $< $@
+
+all: foo.out foo.out2
+	test "$$(cat foo.out)" = "gooddata"
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/pymake/tests/vpath.mk b/src/third_party/mozjs-45/build/pymake/tests/vpath.mk
new file mode 100644
index 0000000..06f5218
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/vpath.mk
@@ -0,0 +1,18 @@
+VPATH = foo bar
+
+$(shell \
+mkdir foo; touch foo/tfile1; \
+mkdir bar; touch bar/tfile2 bar/tfile3 bar/test.objtest; \
+sleep 2; \
+touch bar/test.source; \
+)
+
+all: tfile1 tfile2 tfile3 test.objtest test.source
+	test "$^" = "foo/tfile1 bar/tfile2 tfile3 test.objtest bar/test.source"
+	@echo TEST-PASS
+
+tfile3: test.objtest
+
+%.objtest: %.source
+	test "$<" = bar/test.source
+	test "$@" = test.objtest
diff --git a/src/third_party/mozjs-45/build/pymake/tests/vpath2.mk b/src/third_party/mozjs-45/build/pymake/tests/vpath2.mk
new file mode 100644
index 0000000..be73ffe
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/vpath2.mk
@@ -0,0 +1,18 @@
+VPATH = foo bar
+
+$(shell \
+mkdir bar; touch bar/test.source; \
+sleep 2; \
+mkdir foo; touch foo/tfile1; \
+touch bar/tfile2 bar/tfile3 bar/test.objtest; \
+)
+
+all: tfile1 tfile2 tfile3 test.objtest test.source
+	test "$^" = "foo/tfile1 bar/tfile2 bar/tfile3 bar/test.objtest bar/test.source"
+	@echo TEST-PASS
+
+tfile3: test.objtest
+
+%.objtest: %.source
+	test "$<" = bar/test.source
+	test "$@" = test.objtest
diff --git a/src/third_party/mozjs-45/build/pymake/tests/wildcards.mk b/src/third_party/mozjs-45/build/pymake/tests/wildcards.mk
new file mode 100644
index 0000000..24ff3f1
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/wildcards.mk
@@ -0,0 +1,22 @@
+$(shell \
+mkdir foo; \
+touch a.c b.c c.out foo/d.c; \
+sleep 2; \
+touch c.in; \
+)
+
+VPATH = foo
+
+all: c.out prog
+	cat $<
+	test "$$(cat $<)" = "remadec.out"
+	@echo TEST-PASS
+
+*.out: %.out: %.in
+	test "$@" = c.out
+	test "$<" = c.in
+	printf "remade$@" >$@
+
+prog: *.c
+	test "$^" = "a.c b.c"
+	touch $@
diff --git a/src/third_party/mozjs-45/build/pymake/tests/windows-paths.mk b/src/third_party/mozjs-45/build/pymake/tests/windows-paths.mk
new file mode 100644
index 0000000..5f33a90
--- /dev/null
+++ b/src/third_party/mozjs-45/build/pymake/tests/windows-paths.mk
@@ -0,0 +1,5 @@
+all:
+	touch file.in
+	printf "%s: %s\n\ttrue" '$(CURDIR)/file.out' '$(CURDIR)/file.in' >test.mk
+	$(MAKE) -f test.mk $(CURDIR)/file.out
+	@echo TEST-PASS
diff --git a/src/third_party/mozjs-45/build/qemu-wrap b/src/third_party/mozjs-45/build/qemu-wrap
new file mode 100755
index 0000000..e339389
--- /dev/null
+++ b/src/third_party/mozjs-45/build/qemu-wrap
@@ -0,0 +1,24 @@
+#!/bin/bash
+# this script creates a wrapper shell script for an executable.  The idea is the actual executable cannot be
+# executed natively (it was cross compiled), but we want to run tests natively.  Running this script
+# as part of the compilation process will move the non-native executable to a new location, and replace it
+# with a script that will run it under qemu.
+while [[ -n $1 ]]; do
+    case $1 in
+        --qemu) QEMU="$2"; shift 2;;
+        --libdir) LIBDIR="$2"; shift 2;;
+        --ld) LD="$2"; shift 2;;
+        *) exe="$1"; shift;;
+    esac
+done
+if [[ -z $LIBDIR ]]; then
+    echo "You need to specify a directory for the cross libraries when you configure the shell"
+    echo "You can do this with --with-cross-lib="
+    exit 1
+fi
+LD=${LD:-$LIBDIR/ld-linux.so.3}
+mv $exe $exe.target
+# Just hardcode the path to the executable.  It'll be pretty obvious if it is doing the wrong thing.
+
+echo $'#!/bin/bash\n' $QEMU -E LD_LIBRARY_PATH="${LIBDIR}" "$LD" "$(readlink -f "$exe.target")" '"$@"' >"$exe"
+chmod +x $exe
\ No newline at end of file
diff --git a/src/third_party/mozjs-45/build/release/info.py b/src/third_party/mozjs-45/build/release/info.py
new file mode 100644
index 0000000..9f42edd
--- /dev/null
+++ b/src/third_party/mozjs-45/build/release/info.py
@@ -0,0 +1,218 @@
+from datetime import datetime
+import os
+from os import path
+import re
+import shutil
+import sys
+from urllib2 import urlopen
+
+from release.paths import makeCandidatesDir
+
+import logging
+log = logging.getLogger(__name__)
+
+# If version has two parts with no trailing specifiers like "rc", we
+# consider it a "final" release for which we only create a _RELEASE tag.
+FINAL_RELEASE_REGEX = "^\d+\.\d+$"
+
+
+class ConfigError(Exception):
+    pass
+
+
+def getBuildID(platform, product, version, buildNumber, nightlyDir='nightly',
+               server='stage.mozilla.org'):
+    infoTxt = makeCandidatesDir(product, version, buildNumber, nightlyDir,
+                                protocol='http', server=server) + \
+        '%s_info.txt' % platform
+    try:
+        buildInfo = urlopen(infoTxt).read()
+    except:
+        log.error("Failed to retrieve %s" % infoTxt)
+        raise
+
+    for line in buildInfo.splitlines():
+        key, value = line.rstrip().split('=', 1)
+        if key == 'buildID':
+            return value
+
+
+def findOldBuildIDs(product, version, buildNumber, platforms,
+                    nightlyDir='nightly', server='stage.mozilla.org'):
+    ids = {}
+    if buildNumber <= 1:
+        return ids
+    for n in range(1, buildNumber):
+        for platform in platforms:
+            if platform not in ids:
+                ids[platform] = []
+            try:
+                id = getBuildID(platform, product, version, n, nightlyDir,
+                                server)
+                ids[platform].append(id)
+            except Exception, e:
+                log.error("Hit exception: %s" % e)
+    return ids
+
+
+def getReleaseConfigName(product, branch, version=None, staging=False):
+    # XXX: Horrible hack for bug 842741. Because Thunderbird release
+    # and esr both build out of esr17 repositories we'll bump the wrong
+    # config for release without this.
+    if product == 'thunderbird' and 'esr17' in branch and version and 'esr' not in version:
+        cfg = 'release-thunderbird-comm-release.py'
+    else:
+        cfg = 'release-%s-%s.py' % (product, branch)
+    if staging:
+        cfg = 'staging_%s' % cfg
+    return cfg
+
+
+def readReleaseConfig(configfile, required=[]):
+    return readConfig(configfile, keys=['releaseConfig'], required=required)
+
+
+def readBranchConfig(dir, localconfig, branch, required=[]):
+    shutil.copy(localconfig, path.join(dir, "localconfig.py"))
+    oldcwd = os.getcwd()
+    os.chdir(dir)
+    sys.path.append(".")
+    try:
+        return readConfig("config.py", keys=['BRANCHES', branch],
+                          required=required)
+    finally:
+        os.chdir(oldcwd)
+        sys.path.remove(".")
+
+
+def readConfig(configfile, keys=[], required=[]):
+    c = {}
+    execfile(configfile, c)
+    for k in keys:
+        c = c[k]
+    items = c.keys()
+    err = False
+    for key in required:
+        if key not in items:
+            err = True
+            log.error("Required item `%s' missing from %s" % (key, c))
+    if err:
+        raise ConfigError("Missing at least one item in config, see above")
+    return c
+
+
+def isFinalRelease(version):
+    return bool(re.match(FINAL_RELEASE_REGEX, version))
+
+
+def getBaseTag(product, version):
+    product = product.upper()
+    version = version.replace('.', '_')
+    return '%s_%s' % (product, version)
+
+
+def getTags(baseTag, buildNumber, buildTag=True):
+    t = ['%s_RELEASE' % baseTag]
+    if buildTag:
+        t.append('%s_BUILD%d' % (baseTag, int(buildNumber)))
+    return t
+
+
+def getRuntimeTag(tag):
+    return "%s_RUNTIME" % tag
+
+
+def getReleaseTag(tag):
+    return "%s_RELEASE" % tag
+
+
+def generateRelbranchName(version, prefix='GECKO'):
+    return '%s%s_%s_RELBRANCH' % (
+        prefix, version.replace('.', ''),
+        datetime.now().strftime('%Y%m%d%H'))
+
+
+def getReleaseName(product, version, buildNumber):
+    return '%s-%s-build%s' % (product.title(), version, str(buildNumber))
+
+
+def getRepoMatchingBranch(branch, sourceRepositories):
+    for sr in sourceRepositories.values():
+        if branch in sr['path']:
+            return sr
+    return None
+
+
+def fileInfo(filepath, product):
+    """Extract information about a release file.  Returns a dictionary with the
+    following keys set:
+    'product', 'version', 'locale', 'platform', 'contents', 'format',
+    'pathstyle'
+
+    'contents' is one of 'complete', 'installer'
+    'format' is one of 'mar' or 'exe'
+    'pathstyle' is either 'short' or 'long', and refers to if files are all in
+        one directory, with the locale as part of the filename ('short' paths,
+        firefox 3.0 style filenames), or if the locale names are part of the
+        directory structure, but not the file name itself ('long' paths,
+        firefox 3.5+ style filenames)
+    """
+    try:
+        # Mozilla 1.9.0 style (aka 'short') paths
+        # e.g. firefox-3.0.12.en-US.win32.complete.mar
+        filename = os.path.basename(filepath)
+        m = re.match("^(%s)-([0-9.]+)\.([-a-zA-Z]+)\.(win32)\.(complete|installer)\.(mar|exe)$" % product, filename)
+        if not m:
+            raise ValueError("Could not parse: %s" % filename)
+        return {'product': m.group(1),
+                'version': m.group(2),
+                'locale': m.group(3),
+                'platform': m.group(4),
+                'contents': m.group(5),
+                'format': m.group(6),
+                'pathstyle': 'short',
+                'leading_path': '',
+                }
+    except:
+        # Mozilla 1.9.1 and on style (aka 'long') paths
+        # e.g. update/win32/en-US/firefox-3.5.1.complete.mar
+        #      win32/en-US/Firefox Setup 3.5.1.exe
+        ret = {'pathstyle': 'long'}
+        if filepath.endswith('.mar'):
+            ret['format'] = 'mar'
+            m = re.search("update/(win32|linux-i686|linux-x86_64|mac|mac64)/([-a-zA-Z]+)/(%s)-(\d+\.\d+(?:\.\d+)?(?:\w+(?:\d+)?)?)\.(complete)\.mar" % product, filepath)
+            if not m:
+                raise ValueError("Could not parse: %s" % filepath)
+            ret['platform'] = m.group(1)
+            ret['locale'] = m.group(2)
+            ret['product'] = m.group(3)
+            ret['version'] = m.group(4)
+            ret['contents'] = m.group(5)
+            ret['leading_path'] = ''
+        elif filepath.endswith('.exe'):
+            ret['format'] = 'exe'
+            ret['contents'] = 'installer'
+            # EUballot builds use a different enough style of path than others
+            # that we can't catch them in the same regexp
+            if filepath.find('win32-EUballot') != -1:
+                ret['platform'] = 'win32'
+                m = re.search("(win32-EUballot/)([-a-zA-Z]+)/((?i)%s) Setup (\d+\.\d+(?:\.\d+)?(?:\w+\d+)?(?:\ \w+\ \d+)?)\.exe" % product, filepath)
+                if not m:
+                    raise ValueError("Could not parse: %s" % filepath)
+                ret['leading_path'] = m.group(1)
+                ret['locale'] = m.group(2)
+                ret['product'] = m.group(3).lower()
+                ret['version'] = m.group(4)
+            else:
+                m = re.search("(partner-repacks/[-a-zA-Z0-9_]+/|)(win32|mac|linux-i686)/([-a-zA-Z]+)/((?i)%s) Setup (\d+\.\d+(?:\.\d+)?(?:\w+(?:\d+)?)?(?:\ \w+\ \d+)?)\.exe" % product, filepath)
+                if not m:
+                    raise ValueError("Could not parse: %s" % filepath)
+                ret['leading_path'] = m.group(1)
+                ret['platform'] = m.group(2)
+                ret['locale'] = m.group(3)
+                ret['product'] = m.group(4).lower()
+                ret['version'] = m.group(5)
+        else:
+            raise ValueError("Unknown filetype for %s" % filepath)
+
+        return ret
diff --git a/src/third_party/mozjs-45/build/release/sanity.py b/src/third_party/mozjs-45/build/release/sanity.py
new file mode 100644
index 0000000..cd89eb3
--- /dev/null
+++ b/src/third_party/mozjs-45/build/release/sanity.py
@@ -0,0 +1,124 @@
+import difflib
+import logging
+import re
+import urllib2
+from util.commands import run_cmd, get_output
+from util.hg import get_repo_name, make_hg_url
+from subprocess import CalledProcessError
+
+log = logging.getLogger(__name__)
+
+
+def check_buildbot():
+    """check if buildbot command works"""
+    try:
+        run_cmd(['buildbot', '--version'])
+    except CalledProcessError:
+        log.error("FAIL: buildbot command doesn't work", exc_info=True)
+        raise
+
+
+def find_version(contents, versionNumber):
+    """Given an open readable file-handle look for the occurrence
+       of the version # in the file"""
+    ret = re.search(re.compile(re.escape(versionNumber), re.DOTALL), contents)
+    return ret
+
+
+def locale_diff(locales1, locales2):
+    """ accepts two lists and diffs them both ways, returns any differences
+    found """
+    diff_list = [locale for locale in locales1 if not locale in locales2]
+    diff_list.extend(locale for locale in locales2 if not locale in locales1)
+    return diff_list
+
+
+def get_buildbot_username_param():
+    cmd = ['buildbot', 'sendchange', '--help']
+    output = get_output(cmd)
+    if "-W, --who=" in output:
+        return "--who"
+    else:
+        return "--username"
+
+
+def sendchange(branch, revision, username, master, products):
+    """Send the change to buildbot to kick off the release automation"""
+    if isinstance(products, basestring):
+        products = [products]
+    cmd = [
+        'buildbot',
+        'sendchange',
+        get_buildbot_username_param(),
+        username,
+        '--master',
+        master,
+        '--branch',
+        branch,
+        '-p',
+        'products:%s' % ','.join(products),
+        '-p',
+        'script_repo_revision:%s' % revision,
+        'release_build'
+    ]
+    logging.info("Executing: %s" % cmd)
+    run_cmd(cmd)
+
+
+def verify_mozconfigs(mozconfig_pair, nightly_mozconfig_pair, platform,
+                      mozconfigWhitelist={}):
+    """Compares mozconfig to nightly_mozconfig and compare to an optional
+    whitelist of known differences. mozconfig_pair and nightly_mozconfig_pair
+    are pairs containing the mozconfig's identifier and the list of lines in
+    the mozconfig."""
+
+    # unpack the pairs to get the names, the names are just for
+    # identifying the mozconfigs when logging the error messages
+    mozconfig_name, mozconfig_lines = mozconfig_pair
+    nightly_mozconfig_name, nightly_mozconfig_lines = nightly_mozconfig_pair
+
+    missing_args = mozconfig_lines == [] or nightly_mozconfig_lines == []
+    if missing_args:
+        log.info("Missing mozconfigs to compare for %s" % platform)
+        return False
+
+    success = True
+
+    diffInstance = difflib.Differ()
+    diff_result = diffInstance.compare(mozconfig_lines, nightly_mozconfig_lines)
+    diffList = list(diff_result)
+
+    for line in diffList:
+        clean_line = line[1:].strip()
+        if (line[0] == '-' or line[0] == '+') and len(clean_line) > 1:
+            # skip comment lines
+            if clean_line.startswith('#'):
+                continue
+            # compare to whitelist
+            message = ""
+            if line[0] == '-':
+                if platform in mozconfigWhitelist.get('release', {}):
+                    if clean_line in \
+                            mozconfigWhitelist['release'][platform]:
+                        continue
+            elif line[0] == '+':
+                if platform in mozconfigWhitelist.get('nightly', {}):
+                    if clean_line in \
+                            mozconfigWhitelist['nightly'][platform]:
+                        continue
+                    else:
+                        log.warning("%s not in %s %s!" % (
+                            clean_line, platform,
+                            mozconfigWhitelist['nightly'][platform]))
+            else:
+                log.error("Skipping line %s!" % line)
+                continue
+            message = "found in %s but not in %s: %s"
+            if line[0] == '-':
+                log.error(message % (mozconfig_name,
+                                     nightly_mozconfig_name, clean_line))
+            else:
+                log.error(message % (nightly_mozconfig_name,
+                                     mozconfig_name, clean_line))
+            success = False
+    return success
diff --git a/src/third_party/mozjs-45/build/sanitizers/lsan_suppressions.txt b/src/third_party/mozjs-45/build/sanitizers/lsan_suppressions.txt
new file mode 100644
index 0000000..44b754e
--- /dev/null
+++ b/src/third_party/mozjs-45/build/sanitizers/lsan_suppressions.txt
@@ -0,0 +1,120 @@
+### !!! Please do not add suppressions for new leaks in Gecko code, unless they are intentional !!!
+
+###
+### Some of these leak in every test run.
+###
+
+# LSan runs with a shallow stack depth and no debug symbols, so some small intentional
+# leaks in system libraries show up with this.  You do not want this enabled
+# when running locally with a deep stack, as it can catch too much.
+leak:libc.so
+
+# nsComponentManagerImpl intentionally leaks factory entries, and probably some other stuff.
+leak:nsComponentManagerImpl
+# These two variants are needed when fast unwind is disabled and stack depth is limited.
+leak:mozJSComponentLoader::LoadModule
+leak:nsNativeModuleLoader::LoadModule
+
+# Bug 981220 - Pixman fails to free TLS memory.
+leak:pixman_implementation_lookup_composite
+
+# Bug 987918 - Font shutdown leaks when CLEANUP_MEMORY is not enabled.
+leak:libfontconfig.so
+leak:GI___strdup
+# The symbol is really __GI___strdup, but if you have the leading _, it doesn't suppress it.
+
+# Bug 1078015 - If the process terminates during a PR_Sleep, LSAN  detects a leak
+leak:PR_Sleep
+
+###
+### Bug 979928 - WebRTC leaks. m2, m3.
+###
+
+# WebRTC leaks added for Mochitest 2.
+leak:NR_reg_init
+# nr_reg_local_init should be redundant with NR_reg_init, but with 34 on Aurora
+# we get less stack frames for some reason.
+leak:nr_reg_local_init
+leak:r_log_register
+leak:nr_reg_set
+
+# Bug 1187518 - SCTP leaks in child process while running WebRTC tests.
+leak:recv_function_udp
+
+
+###
+### Many leaks only affect some test suites.  The suite annotations are not checked.
+###
+
+# Bug 987385 - Various plugin leaks. m3
+leak:mozilla::plugins::PPluginInstanceParent::CallNPP_HandleEvent
+leak:mozilla::plugins::PPluginModuleParent::OnCallReceived
+
+# Bug 987925 - Small leak under PK11_ChangePW. m5
+leak:sec_asn1e_allocate_item
+leak:PORT_Strdup_Util
+
+# Bug 1021302 - Leak of fds allocated in nsSocketTransport::BuildSocket(). m1, m5, dt, oth
+leak:nsSocketTransport::BuildSocket
+leak:nsServerSocket::OnSocketReady
+
+# Bug 1021350 - Small leak under event_base_once. m1, m4, bc3
+leak:event_base_once
+
+# Bug 1021854 - nsFileStreamBase::DoOpen() leaking fds. bc1, oth
+leak:nsLocalFile::OpenNSPRFileDesc
+
+# Bug 1022010 - Small leak under _render_glyph_outline. bc1
+leak:_render_glyph_outline
+
+# Bug 1023548 - Small leak under SECITEM_AllocItem_Util. bc1, bc3
+leak:SECITEM_AllocItem_Util
+
+# This is a one-time leak, so it is probably okay to ignore. bc3, oth
+leak:GlobalPrinters::InitializeGlobalPrinters
+leak:nsPSPrinterList::GetPrinterList
+
+# Bug 1028456 - More leaks with _PR_Getfd, in nsLocalFile::CopyToNative and do_create. bc1, bc3
+leak:_PR_Getfd
+
+# Bug 1028483 - The XML parser sometimes leaks an object. bc3
+leak:processInternalEntity
+
+# Bug 1187421 - With e10s, NSS does not always free the error stack. m1.
+leak:nss_ClearErrorStack
+
+# Bug 1122045 - Leaks in MessageLoop::MessageLoop()
+leak:MessageLoop::MessageLoop
+# This may not actually be related to MessageLoop.
+leak:base::WaitableEvent::TimedWait
+leak:MessageLoop::PostTask_Helper
+
+# Bug 1189430 - DNS leaks in mochitest-chrome.
+leak:nsDNSService::AsyncResolveExtended
+leak:_GetAddrInfo_Portable
+
+# Bug 1189568 - Indirect leaks of IMContextWrapper and nsIntRect.
+leak:nsWindow::Create
+leak:nsBaseWidget::StoreWindowClipRegion
+
+
+###
+### Leaks with system libraries in their stacks. These show up across a number of tests.
+### Better symbols and disabling fast stackwalking may help diagnose these.
+###
+
+leak:libcairo.so
+leak:libdl.so
+leak:libdricore.so
+leak:libdricore9.2.1.so
+leak:libGL.so
+leak:libglib-2.0.so
+leak:libp11-kit.so
+leak:libpixman-1.so
+leak:libpulse.so
+leak:libpulsecommon-1.1.so
+leak:libresolv.so
+leak:libstdc++.so
+leak:libXrandr.so
+leak:pthread_setspecific_internal
+leak:swrast_dri.so
diff --git a/src/third_party/mozjs-45/build/sanitizers/tsan_suppressions.txt b/src/third_party/mozjs-45/build/sanitizers/tsan_suppressions.txt
new file mode 100644
index 0000000..3ea562e
--- /dev/null
+++ b/src/third_party/mozjs-45/build/sanitizers/tsan_suppressions.txt
@@ -0,0 +1,21 @@
+# Bug 931149
+race:DoImageDataComplete
+
+# Bug 939786
+race:_pt_root
+
+# Bug 939788
+# Tracked by http://code.google.com/p/thread-sanitizer/issues/detail?id=40
+race:ELMCreationDetector
+
+# Bug 939790
+race:xpcom/components/nsComponentManager.h
+
+# Bug 939807
+race:ComputeUTCTime
+
+# Bug 939805
+race:g_variant_type_info_get
+
+# Bug 844759
+race:js::gc::ArenaLists::allocateFromArenaInline
diff --git a/src/third_party/mozjs-45/build/sccache.mk b/src/third_party/mozjs-45/build/sccache.mk
new file mode 100644
index 0000000..c57befe
--- /dev/null
+++ b/src/third_party/mozjs-45/build/sccache.mk
@@ -0,0 +1,18 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+ifdef OBJDIR
+BASE_DIR = $(OBJDIR)
+else
+# OSX Universal builds only do upload in the first MOZ_BUILD_PROJECTS
+BASE_DIR = $(MOZ_OBJDIR)/$(firstword $(MOZ_BUILD_PROJECTS))
+endif
+
+preflight_all:
+	# Terminate any sccache server that might still be around
+	-python2.7 $(TOPSRCDIR)/sccache/sccache.py > /dev/null 2>&1
+
+postflight_all:
+	# Terminate sccache server. This prints sccache stats.
+	-python2.7 $(TOPSRCDIR)/sccache/sccache.py 2>&1 | gzip > $(BASE_DIR)/dist/sccache.log.gz
diff --git a/src/third_party/mozjs-45/build/stlport/Android.mk b/src/third_party/mozjs-45/build/stlport/Android.mk
new file mode 100644
index 0000000..fb5f972
--- /dev/null
+++ b/src/third_party/mozjs-45/build/stlport/Android.mk
@@ -0,0 +1,133 @@
+LOCAL_PATH := $(call my-dir)
+
+# Normally, we distribute the NDK with prebuilt binaries of STLport
+# in $LOCAL_PATH/libs/<abi>/. However,
+#
+
+STLPORT_FORCE_REBUILD := $(strip $(STLPORT_FORCE_REBUILD))
+ifndef STLPORT_FORCE_REBUILD
+  ifeq (,$(strip $(wildcard $(LOCAL_PATH)/libs/$(TARGET_ARCH_ABI)/libstlport_static$(TARGET_LIB_EXTENSION))))
+    $(call __ndk_info,WARNING: Rebuilding STLport libraries from sources!)
+    $(call __ndk_info,You might want to use $$NDK/build/tools/build-cxx-stl.sh --stl=stlport)
+    $(call __ndk_info,in order to build prebuilt versions to speed up your builds!)
+    STLPORT_FORCE_REBUILD := true
+  endif
+endif
+
+libstlport_path := $(LOCAL_PATH)
+
+libstlport_src_files := \
+        src/dll_main.cpp \
+        src/fstream.cpp \
+        src/strstream.cpp \
+        src/sstream.cpp \
+        src/ios.cpp \
+        src/stdio_streambuf.cpp \
+        src/istream.cpp \
+        src/ostream.cpp \
+        src/iostream.cpp \
+        src/codecvt.cpp \
+        src/collate.cpp \
+        src/ctype.cpp \
+        src/monetary.cpp \
+        src/num_get.cpp \
+        src/num_put.cpp \
+        src/num_get_float.cpp \
+        src/num_put_float.cpp \
+        src/numpunct.cpp \
+        src/time_facets.cpp \
+        src/messages.cpp \
+        src/locale.cpp \
+        src/locale_impl.cpp \
+        src/locale_catalog.cpp \
+        src/facets_byname.cpp \
+        src/complex.cpp \
+        src/complex_io.cpp \
+        src/complex_trig.cpp \
+        src/string.cpp \
+        src/bitset.cpp \
+        src/allocators.cpp \
+        src/c_locale.c \
+        src/cxa.c \
+
+libstlport_cflags := -D_GNU_SOURCE
+libstlport_cppflags := -fuse-cxa-atexit
+libstlport_c_includes := $(libstlport_path)/stlport
+
+#It is much more practical to include the sources of GAbi++ in our builds
+# of STLport. This is similar to what the GNU libstdc++ does (it includes
+# its own copy of libsupc++)
+#
+# This simplifies usage, since you only have to list a single library
+# as a dependency, instead of two, especially when using the standalone
+# toolchain.
+#
+include $(dir $(LOCAL_PATH))/gabi++/sources.mk
+
+libstlport_c_includes += $(libgabi++_c_includes)
+ifneq ($(strip $(filter-out $(NDK_KNOWN_ARCHS),$(TARGET_ARCH))),)
+libgabi++_src_files := src/delete.cc \
+                       src/new.cc
+endif
+
+ifneq ($(STLPORT_FORCE_REBUILD),true)
+
+$(call ndk_log,Using prebuilt STLport libraries)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := stlport_static
+LOCAL_SRC_FILES := libs/$(TARGET_ARCH_ABI)/lib$(LOCAL_MODULE)$(TARGET_LIB_EXTENSION)
+# For armeabi*, choose thumb mode unless LOCAL_ARM_MODE := arm
+ifneq (,$(filter armeabi%,$(TARGET_ARCH_ABI)))
+ifneq (arm,$(LOCAL_ARM_MODE))
+LOCAL_SRC_FILES := libs/$(TARGET_ARCH_ABI)/thumb/lib$(LOCAL_MODULE)$(TARGET_LIB_EXTENSION)
+endif
+endif
+LOCAL_EXPORT_C_INCLUDES := $(libstlport_c_includes)
+LOCAL_CPP_FEATURES := rtti
+include $(PREBUILT_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := stlport_shared
+LOCAL_SRC_FILES := libs/$(TARGET_ARCH_ABI)/lib$(LOCAL_MODULE)$(TARGET_SONAME_EXTENSION)
+# For armeabi*, choose thumb mode unless LOCAL_ARM_MODE := arm
+$(info TARGET_ARCH_ABI=$(TARGET_ARCH_ABI))
+$(info LOCAL_ARM_MODE=$(LOCAL_ARM_MODE))
+ifneq (,$(filter armeabi%,$(TARGET_ARCH_ABI)))
+ifneq (arm,$(LOCAL_ARM_MODE))
+LOCAL_SRC_FILES := libs/$(TARGET_ARCH_ABI)/thumb/lib$(LOCAL_MODULE)$(TARGET_SONAME_EXTENSION)
+endif
+endif
+LOCAL_EXPORT_C_INCLUDES := $(libstlport_c_includes)
+LOCAL_CPP_FEATURES := rtti
+include $(PREBUILT_SHARED_LIBRARY)
+
+else # STLPORT_FORCE_REBUILD == true
+
+$(call ndk_log,Rebuilding STLport libraries from sources)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := stlport_static
+LOCAL_CPP_EXTENSION := .cpp .cc
+LOCAL_SRC_FILES := $(libstlport_src_files)
+LOCAL_SRC_FILES += $(libgabi++_src_files:%=../gabi++/%)
+LOCAL_CFLAGS := $(libstlport_cflags)
+LOCAL_CPPFLAGS := $(libstlport_cppflags)
+LOCAL_C_INCLUDES := $(libstlport_c_includes)
+LOCAL_EXPORT_C_INCLUDES := $(libstlport_c_includes)
+LOCAL_CPP_FEATURES := rtti exceptions
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := stlport_shared
+LOCAL_CPP_EXTENSION := .cpp .cc
+LOCAL_SRC_FILES := $(libstlport_src_files)
+LOCAL_SRC_FILES += $(libgabi++_src_files:%=../gabi++/%)
+LOCAL_CFLAGS := $(libstlport_cflags)
+LOCAL_CPPFLAGS := $(libstlport_cppflags)
+LOCAL_C_INCLUDES := $(libstlport_c_includes)
+LOCAL_EXPORT_C_INCLUDES := $(libstlport_c_includes)
+LOCAL_CPP_FEATURES := rtti exceptions
+include $(BUILD_SHARED_LIBRARY)
+
+endif # STLPORT_FORCE_REBUILD == true
diff --git a/src/third_party/mozjs-45/build/stlport/LICENSE b/src/third_party/mozjs-45/build/stlport/LICENSE
new file mode 100644
index 0000000..6846270
--- /dev/null
+++ b/src/third_party/mozjs-45/build/stlport/LICENSE
@@ -0,0 +1,27 @@
+Boris Fomitchev grants Licensee a non-exclusive, non-transferable, royalty-free license to use STLport and its documentation without fee.
+
+By downloading, using, or copying STLport or any portion thereof,  Licensee agrees to abide by the intellectual property laws and all other applicable laws of the United States of America, and to all of the terms and conditions of this Agreement.
+
+Licensee shall maintain the following copyright and permission  notices on STLport sources and its documentation unchanged :
+
+Copyright 1999,2000 Boris Fomitchev
+
+This material is provided "as is", with absolutely no warranty expressed or implied. Any use is at your own risk.
+Permission to use or copy this software for any purpose is hereby granted without fee, provided the above notices are retained on all copies. Permission to modify the code and to distribute modified code is granted, provided the above notices are retained, and a notice that the code was modified is included with the above copyright notice.
+The Licensee may distribute binaries compiled with STLport (whether original or modified) without any royalties or restrictions.
+
+The Licensee may distribute original or modified STLport sources, provided that:
+
+The conditions indicated in the above permission notice are met;
+The following copyright notices are retained when present, and conditions provided in accompanying permission notices are met :
+Copyright 1994 Hewlett-Packard Company
+
+Copyright 1996,97 Silicon Graphics Computer Systems, Inc.
+
+Copyright 1997 Moscow Center for SPARC Technology.
+
+Permission to use, copy, modify, distribute and sell this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. Hewlett-Packard Company makes no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty.
+
+Permission to use, copy, modify, distribute and sell this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. Silicon Graphics makes no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty.
+
+Permission to use, copy, modify, distribute and sell this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. Moscow Center for SPARC Technology  makes no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty.
diff --git a/src/third_party/mozjs-45/build/stlport/MODULE_LICENSE_BSD_LIKE b/src/third_party/mozjs-45/build/stlport/MODULE_LICENSE_BSD_LIKE
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/third_party/mozjs-45/build/stlport/MODULE_LICENSE_BSD_LIKE
diff --git a/src/third_party/mozjs-45/build/stlport/Makefile.in b/src/third_party/mozjs-45/build/stlport/Makefile.in
new file mode 100644
index 0000000..ca11f30
--- /dev/null
+++ b/src/third_party/mozjs-45/build/stlport/Makefile.in
@@ -0,0 +1,9 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this file,
+# You can obtain one at http://mozilla.org/MPL/2.0/.
+
+MODULES = stlport
+
+include $(topsrcdir)/config/rules.mk
+
+CXXFLAGS += -fuse-cxa-atexit
diff --git a/src/third_party/mozjs-45/build/stlport/README b/src/third_party/mozjs-45/build/stlport/README
new file mode 100644
index 0000000..8f602fe
--- /dev/null
+++ b/src/third_party/mozjs-45/build/stlport/README
@@ -0,0 +1,69 @@
+STLport for Android
+
+WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
+WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
+
+     This feature is currently in beta. In case of issue
+     please contact the android-ndk support forum or
+     file bugs at http://b.android.com
+
+WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
+WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
+
+This directory contains a port of STLport for Android, which provides
+a simple STL implementation. Note that it currently does not support
+C++ exceptions and RTTI. Support for wchar_t and locales is probably buggy.
+
+You can either use it as a static or shared library.
+
+1/ The static library is recommended if you will only produce
+   one shared library for your project. All necessary STLport functions
+   will be added to it. This option should also generate smaller
+   overall binaries.
+
+2/ The shared library, is recommended if you want to produce
+   several shared libraries in your project, because it avoids copying the
+   same STLport functions to each one of them, and having different instances
+   of the same global variables (which can easily conflict or result in
+   undefined behaviour).
+
+To use the *static* library, define APP_STL in your Application.mk as follows:
+
+    APP_STL := stlport_static
+
+To use the *shared* library, use "stlport_shared" instead:
+
+    APP_STL := stlport_shared
+
+Note that, in this case, you will need, in your application, to explicitely
+load the 'stlport_shared' library before any library that depends on it.
+For example:
+
+    static {
+        System.loadLibrary("stlport_shared");
+        System.loadLibrary("foo");
+        System.loadLibrary("bar");
+    }
+
+If both libfoo.so and libbar.so depend on STLport.
+
+You can build the STLport unit test program by doing the following:
+
+  cd $NDK
+  tests/run-tests.sh --test=test-stlport
+
+If you have an Android device connected to your machine, this will
+automatically try to run the generated test command. Note that for now
+a few tests are still failing (mostly related to wchar_t and locales).
+
+They should be fixed hopefully by a later release of this library.
+
+The NDK comes with prebuilt binaries for this library to speed up development.
+You can however rebuild them from sources in your own application build by
+defining STLPORT_FORCE_REBUILD to 'true' in your Application.mk as in:
+
+    STLPORT_FORCE_REBUILD := true
+
+
+VERSION INFORMATION: This module is based on STLport version 5.2.0
+
diff --git a/src/third_party/mozjs-45/build/stlport/README.android b/src/third_party/mozjs-45/build/stlport/README.android
new file mode 100644
index 0000000..a35c955
--- /dev/null
+++ b/src/third_party/mozjs-45/build/stlport/README.android
@@ -0,0 +1,9 @@
+Version: 5.2.1
+
+Changes:
+    * Added _android.h included by _system.h
+    * Do not use linux float functions in num_get_float.cpp as Android does not
+      have them.
+    * _mbstate_t.h cannot define its own mbstate_t as bionic already defines
+      it.
+    * _pair.h needs to define bionic's (sgi's) internal pair header guard.
diff --git a/src/third_party/mozjs-45/build/stlport/README.mozilla b/src/third_party/mozjs-45/build/stlport/README.mozilla
new file mode 100644
index 0000000..15c09bc
--- /dev/null
+++ b/src/third_party/mozjs-45/build/stlport/README.mozilla
@@ -0,0 +1,11 @@
+This copy of STLport was taken from the Android NDK git repository:
+https://android.googlesource.com/platform/ndk.git
+under sources/cxx-stl/stlport/.
+The last changes to that directory come from commit ba4baa4
+
+The overrides/ directory contains Mozilla-specific overrides to the standard
+  C++ headers found in the NDK.
+
+The following patches are applied on top:
+- android-mozilla-config.patch: Adjusts Android-specific configuration
+  to the mozilla codebase use of the STL.
diff --git a/src/third_party/mozjs-45/build/stlport/README.original b/src/third_party/mozjs-45/build/stlport/README.original
new file mode 100644
index 0000000..a759495
--- /dev/null
+++ b/src/third_party/mozjs-45/build/stlport/README.original
@@ -0,0 +1,64 @@
+**********************************************************************
+* 	README file for STLport 5.0                                    *
+*                                                                    *
+**********************************************************************
+
+This directory contains the STLport-5.0 release.
+
+What's inside :
+
+README           - this file
+INSTALL          - installation instructions
+
+bin              - installation directory for STLport unit tests;
+                   it may contain more subdirs, if you use
+                   crosscompilation
+build/lib        - build directory for STLport library (if you use
+                   STLport iostreams and/or locale only)
+build/test/unit  - build directory for regression (unit) tests
+build/test/eh    - build directory for exception handling tests
+stlport          - main STLport include directory
+src              - source for iostreams implementation and other parts
+                   that aren't pure template code
+lib              - installation directory for STLport library (if you
+                   use STLport iostreams and/or locale only);
+                   it may contain more subdirs, if you use
+                   crosscompilation
+test/unit        - unit (regression) tests
+test/eh          - exception handling test using STLport iostreams
+etc              - miscellanous files (ChangeLog, TODO, scripts, etc.) 
+
+GETTING STLPORT
+
+To download the latest version of STLport, please be sure to visit
+https://sourceforge.net/project/showfiles.php?group_id=146814
+
+LEGALESE
+
+This software is being distributed under the following terms:
+
+ *
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Copyright (c) 1996-1999
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Copyright (c) 1997
+ * Moscow Center for SPARC Technology
+ *
+ * Copyright (c) 1999-2003
+ * Boris Fomitchev
+ *
+ * This material is provided "as is", with absolutely no warranty expressed
+ * or implied. Any use is at your own risk.
+ *
+ * Permission to use or copy this software for any purpose is hereby granted 
+ * without fee, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ *
+
+**********************************************************************
diff --git a/src/third_party/mozjs-45/build/stlport/android-mozilla-config.patch b/src/third_party/mozjs-45/build/stlport/android-mozilla-config.patch
new file mode 100644
index 0000000..61a0d7a
--- /dev/null
+++ b/src/third_party/mozjs-45/build/stlport/android-mozilla-config.patch
@@ -0,0 +1,82 @@
+diff --git a/stlport/stl/config/_android.h b/stlport/stl/config/_android.h
+--- a/stlport/stl/config/_android.h
++++ b/stlport/stl/config/_android.h
+@@ -10,18 +10,18 @@
+ #define _PTHREADS
+ 
+ // Don't have native <cplusplus> headers
+ #define _STLP_HAS_NO_NEW_C_HEADERS 1
+ 
+ // Use unix for streams
+ #define _STLP_USE_UNIX_IO 1
+ 
+-// We do have rtti support now through GAbi++
+-#undef _STLP_NO_RTTI
++// We don't want rtti support
++#define _STLP_NO_RTTI 1
+ 
+ // C library is in the global namespace.
+ #define _STLP_VENDOR_GLOBAL_CSTD 1
+ 
+ // Don't have underlying local support.
+ #undef _STLP_REAL_LOCALE_IMPLEMENTED
+ 
+ // No pthread_spinlock_t in Android
+@@ -32,48 +32,42 @@
+ 
+ // Little endian platform.
+ #define _STLP_LITTLE_ENDIAN 1
+ 
+ // No <exception> headers
+ #undef _STLP_NO_EXCEPTION_HEADER
+ 
+ // No throwing exceptions
+-#undef _STLP_NO_EXCEPTIONS
+-
++#define _STLP_NO_EXCEPTIONS 1
++#define _STLP_NO_EXCEPTION_HEADER 1
+ 
+ // No need to define our own namespace
+ #define _STLP_NO_OWN_NAMESPACE 1
+ 
+ // Use __new_alloc instead of __node_alloc, so we don't need static functions.
+ #define _STLP_USE_SIMPLE_NODE_ALLOC 1
+ 
+ // Don't use extern versions of range errors, so we don't need to
+ // compile as a library.
+ #define _STLP_USE_NO_EXTERN_RANGE_ERRORS 1
+ 
+ // The system math library doesn't have long double variants, e.g
+ // sinl, cosl, etc
+ #define _STLP_NO_VENDOR_MATH_L 1
+ 
+-// Define how to include our native headers.
+-#define _STLP_NATIVE_HEADER(header) <usr/include/header>
+-#define _STLP_NATIVE_C_HEADER(header) <../include/header>
+-#define _STLP_NATIVE_CPP_C_HEADER(header) <../../gabi++/include/header>
+-#define _STLP_NATIVE_CPP_RUNTIME_HEADER(header) <../../gabi++/include/header>
+-#define _STLP_NATIVE_OLD_STREAMS_HEADER(header) <usr/include/header>
+-
+ // Include most of the gcc settings.
+ #include <stl/config/_gcc.h>
+ 
+ // Do not use glibc, Android is missing some things.
+ #undef _STLP_USE_GLIBC
+ 
+ // No exceptions.
+-#undef _STLP_NO_UNCAUGHT_EXCEPT_SUPPORT
+-#undef _STLP_NO_UNEXPECTED_EXCEPT_SUPPORT
++#define _STLP_NO_UNCAUGHT_EXCEPT_SUPPORT 1
++#define _STLP_NO_UNEXPECTED_EXCEPT_SUPPORT 1
+ 
+-#ifndef _ANDROID_NDK_BLAZE_
+-// Android does have include_next but it doesn't work well in our build system.
+-#undef _STLP_HAS_INCLUDE_NEXT
+-#endif
++#define _STLP_HAS_INCLUDE_NEXT 1
++
++// Use operator new instead of stlport own node allocator
++#undef _STLP_USE_NEWALLOC
++#define _STLP_USE_NEWALLOC 1
+ 
+ #endif /* __stl_config__android_h */
diff --git a/src/third_party/mozjs-45/build/stlport/moz.build b/src/third_party/mozjs-45/build/stlport/moz.build
new file mode 100644
index 0000000..ef86270
--- /dev/null
+++ b/src/third_party/mozjs-45/build/stlport/moz.build
@@ -0,0 +1,74 @@
+# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+Library('stlport')
+# Keep the same name as the NDK-provided library, while using a shorter
+# name for the Library for convenience in moz.build.
+STATIC_LIBRARY_NAME = 'stlport_static'
+
+FORCE_STATIC_LIB = True
+
+SOURCES += [
+    'src/allocators.cpp',
+    'src/bitset.cpp',
+    'src/codecvt.cpp',
+    'src/collate.cpp',
+    'src/complex.cpp',
+    'src/complex_io.cpp',
+    'src/complex_trig.cpp',
+    'src/ctype.cpp',
+    'src/dll_main.cpp',
+    'src/facets_byname.cpp',
+    'src/fstream.cpp',
+    'src/ios.cpp',
+    'src/iostream.cpp',
+    'src/istream.cpp',
+    'src/locale.cpp',
+    'src/locale_catalog.cpp',
+    'src/locale_impl.cpp',
+    'src/messages.cpp',
+    'src/monetary.cpp',
+    'src/num_get.cpp',
+    'src/num_get_float.cpp',
+    'src/num_put.cpp',
+    'src/num_put_float.cpp',
+    'src/numpunct.cpp',
+    'src/ostream.cpp',
+    'src/sstream.cpp',
+    'src/stdio_streambuf.cpp',
+    'src/string.cpp',
+    'src/strstream.cpp',
+    'src/time_facets.cpp',
+]
+
+SOURCES += [
+    'src/c_locale.c',
+    'src/cxa.c',
+]
+
+DEFINES['_GNU_SOURCE'] = True
+
+LOCAL_INCLUDES += [
+    'stlport',
+]
+
+DISABLE_STL_WRAPPING = True
+NO_VISIBILITY_FLAGS = True
+
+# Suppress warnings in third-party code.
+if CONFIG['GNU_CXX']:
+    CXXFLAGS += [
+        '-Wno-empty-body',
+        '-Wno-type-limits',
+        '-Wno-unused-local-typedefs',
+    ]
+
+# Force to build a static library, instead of a fake library, without
+# installing it in dist/lib.
+NO_EXPAND_LIBS = True
+
+# We allow warnings for third-party code that can be updated from upstream.
+ALLOW_COMPILER_WARNINGS = True
diff --git a/src/third_party/mozjs-45/build/stlport/overrides/new b/src/third_party/mozjs-45/build/stlport/overrides/new
new file mode 100644
index 0000000..34feec8
--- /dev/null
+++ b/src/third_party/mozjs-45/build/stlport/overrides/new
@@ -0,0 +1,65 @@
+/* -*- c++ -*- */
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
+ * This header is taken from $ndk/sources/cxx-stl/system/include/new,
+ * and it fixes a bug in the NDK header where the nothrow versions of
+ * placement new and delete are not specified with 'throw()'. This bug
+ * causes GCC to not null-check the results from these functions.
+ */
+#ifndef __NEW__
+#define __NEW__
+
+#include <cstddef>
+
+extern "C++" {
+
+namespace std {
+    struct nothrow_t {};
+    extern const nothrow_t nothrow;
+}
+
+void* operator new(std::size_t);
+void* operator new[](std::size_t);
+void  operator delete(void*);
+void  operator delete[](void*);
+void* operator new(std::size_t, const std::nothrow_t&) throw();
+void* operator new[](std::size_t, const std::nothrow_t&) throw();
+void  operator delete(void*, const std::nothrow_t&) throw();
+void  operator delete[](void*, const std::nothrow_t&) throw();
+
+inline void* operator new(std::size_t, void* p) { return p; }
+inline void* operator new[](std::size_t, void* p) { return p; }
+
+// these next two are not really required, since exceptions are off
+inline void  operator delete(void*, void*) { }
+inline void  operator delete[](void*, void*) { }
+
+}  // extern C++
+
+#endif // __NEW__
diff --git a/src/third_party/mozjs-45/build/stlport/src/_stdio_file.h b/src/third_party/mozjs-45/build/stlport/src/_stdio_file.h
new file mode 100644
index 0000000..d913fc4
--- /dev/null
+++ b/src/third_party/mozjs-45/build/stlport/src/_stdio_file.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 1999
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Copyright (c) 1999
+ * Boris Fomitchev
+ *
+ * This material is provided "as is", with absolutely no warranty expressed
+ * or implied. Any use is at your own risk.
+ *
+ * Permission to use or copy this software for any purpose is hereby granted
+ * without fee, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ *
+ */
+
+#ifndef _STLP_STDIO_FILE_H
+#define _STLP_STDIO_FILE_H
+
+/* This file provides a low-level interface between the internal
+ * representation of struct FILE, from the C stdio library, and
+ * the C++ I/O library. */
+
+#ifndef _STLP_CSTDIO
+#  include <cstdio>
+#endif
+#ifndef _STLP_CSTDDEF
+#  include <cstddef>
+#endif
+
+#if defined (__MSL__)
+#  include <unix.h>  /* get the definition of fileno */
+#endif
+
+_STLP_BEGIN_NAMESPACE
+
+#if defined (_STLP_WCE)
+
+inline int _FILE_fd(const FILE *__f) {
+  /* Check if FILE is one of the three standard streams
+     We do this check first, because invoking _fileno() on one of them
+     causes a terminal window to be created. This also happens if you do
+     any IO on them, but merely retrieving the filedescriptor shouldn't
+     already do that.
+
+     Obviously this is pretty implementation-specific because it requires
+     that indeed the first three FDs are always the same, but that is not
+     only common but almost guaranteed. */
+  for (int __fd = 0; __fd != 3; ++__fd) {
+    if (__f == _getstdfilex(__fd))
+      return __fd;
+  }
+
+  /* Normal files. */
+  return (int)::_fileno((FILE*)__f); 
+}
+
+# elif defined (_STLP_SCO_OPENSERVER) || defined (__NCR_SVR)
+
+inline int _FILE_fd(const FILE *__f) { return __f->__file; }
+
+# elif defined (__sun) && defined (_LP64)
+
+inline int _FILE_fd(const FILE *__f) { return (int) __f->__pad[2]; }
+
+#elif defined (__hpux) /* && defined(__hppa) && defined(__HP_aCC)) */ || \
+      defined (__MVS__) || \
+      defined (_STLP_USE_UCLIBC) /* should be before _STLP_USE_GLIBC */
+
+inline int _FILE_fd(const FILE *__f) { return fileno(__CONST_CAST(FILE*, __f)); }
+
+#elif defined (_STLP_USE_GLIBC)
+
+inline int _FILE_fd(const FILE *__f) { return __f->_fileno; }
+
+#elif defined (__BORLANDC__)
+
+inline int _FILE_fd(const FILE *__f) { return __f->fd; }
+
+#elif defined (__MWERKS__)
+
+/* using MWERKS-specific defines here to detect other OS targets
+ * dwa: I'm not sure they provide fileno for all OS's, but this should
+ * work for Win32 and WinCE
+
+ * Hmm, at least for Novell NetWare __dest_os == __mac_os true too..
+ * May be both __dest_os and __mac_os defined and empty?   - ptr */
+#  if __dest_os == __mac_os
+inline int _FILE_fd(const FILE *__f) { return ::fileno(__CONST_CAST(FILE*, __f)); }
+#  else
+inline int _FILE_fd(const FILE *__f) { return ::_fileno(__CONST_CAST(FILE*, __f)); }
+#  endif
+
+#elif defined (__QNXNTO__) || defined (__WATCOMC__) || defined (__EMX__)
+
+inline int _FILE_fd(const FILE *__f) { return __f->_handle; }
+
+#elif defined (__Lynx__)
+
+/* the prototypes are taken from LynxOS patch for STLport 4.0 */
+inline int _FILE_fd(const FILE *__f) { return __f->_fd; }
+
+#else  /* The most common access to file descriptor. */
+
+inline int _FILE_fd(const FILE *__f) { return __f->_file; }
+
+#endif
+
+_STLP_END_NAMESPACE
+
+#endif /* _STLP_STDIO_FILE_H */
+
+/* Local Variables:
+ * mode:C++
+ * End: */
diff --git a/src/third_party/mozjs-45/build/stlport/src/acquire_release.h b/src/third_party/mozjs-45/build/stlport/src/acquire_release.h
new file mode 100644
index 0000000..5ea73da
--- /dev/null
+++ b/src/third_party/mozjs-45/build/stlport/src/acquire_release.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 1999
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Copyright (c) 1999
+ * Boris Fomitchev
+ *
+ * This material is provided "as is", with absolutely no warranty expressed
+ * or implied. Any use is at your own risk.
+ *
+ * Permission to use or copy this software for any purpose is hereby granted
+ * without fee, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ *
+ */
+
+#ifndef ACQUIRE_RELEASE_H
+#define ACQUIRE_RELEASE_H
+
+#include "c_locale.h"
+
+_STLP_BEGIN_NAMESPACE
+_STLP_MOVE_TO_PRIV_NAMESPACE
+
+_Locale_ctype* _STLP_CALL __acquire_ctype(const char* &name, char *buf, _Locale_name_hint* hint, int *__err_code);
+_Locale_codecvt* _STLP_CALL __acquire_codecvt(const char* &name, char *buf, _Locale_name_hint* hint, int *__err_code);
+_Locale_numeric* _STLP_CALL __acquire_numeric(const char* &name, char *buf, _Locale_name_hint* hint, int *__err_code);
+_Locale_collate* _STLP_CALL __acquire_collate(const char* &name, char *buf, _Locale_name_hint* hint, int *__err_code);
+_Locale_monetary* _STLP_CALL __acquire_monetary(const char* &name, char *buf, _Locale_name_hint* hint, int *__err_code);
+_Locale_time* _STLP_CALL __acquire_time(const char* &name, char *buf, _Locale_name_hint*, int *__err_code);
+_Locale_messages* _STLP_CALL __acquire_messages(const char* &name, char *buf, _Locale_name_hint* hint, int *__err_code);
+
+void _STLP_CALL __release_ctype(_Locale_ctype* cat);
+void _STLP_CALL __release_codecvt(_Locale_codecvt* cat);
+void _STLP_CALL __release_numeric(_Locale_numeric* cat);
+void _STLP_CALL __release_collate(_Locale_collate* cat);
+void _STLP_CALL __release_monetary(_Locale_monetary* cat);
+void _STLP_CALL __release_time(_Locale_time* __time);
+void _STLP_CALL __release_messages(_Locale_messages* cat);
+
+_STLP_MOVE_TO_STD_NAMESPACE
+_STLP_END_NAMESPACE
+
+#endif /* ACQUIRE_RELEASE_H */
diff --git a/src/third_party/mozjs-45/build/stlport/src/aligned_buffer.h b/src/third_party/mozjs-45/build/stlport/src/aligned_buffer.h
new file mode 100644
index 0000000..6ff6ca6
--- /dev/null
+++ b/src/third_party/mozjs-45/build/stlport/src/aligned_buffer.h
@@ -0,0 +1,21 @@
+#ifndef ALIGNED_BUFFER_H
+#define ALIGNED_BUFFER_H
+
+_STLP_BEGIN_NAMESPACE
+// this is for fake initialization
+template<class T>
+union _Stl_aligned_buffer {
+  char buf[sizeof(T)];
+  struct { double a; double b; } padding;
+
+  T* operator&() {
+    return __REINTERPRET_CAST(T*, this);
+  }
+
+  T const* operator&() const {
+    return __REINTERPRET_CAST(T const*, this);
+  }
+};
+_STLP_END_NAMESPACE
+
+#endif
diff --git a/src/third_party/mozjs-45/build/stlport/src/allocators.cpp b/src/third_party/mozjs-45/build/stlport/src/allocators.cpp
new file mode 100644
index 0000000..8bbcca8
--- /dev/null
+++ b/src/third_party/mozjs-45/build/stlport/src/allocators.cpp
@@ -0,0 +1,1121 @@
+/*
+ *
+ * Copyright (c) 1996,1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Copyright (c) 1997
+ * Moscow Center for SPARC Technology
+ *
+ * Copyright (c) 1999
+ * Boris Fomitchev
+ *
+ * This material is provided "as is", with absolutely no warranty expressed
+ * or implied. Any use is at your own risk.
+ *
+ * Permission to use or copy this software for any purpose is hereby granted
+ * without fee, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ *
+ */
+
+#include "stlport_prefix.h"
+
+#include <memory>
+
+#if defined (__GNUC__) && (defined (__CYGWIN__) || defined (__MINGW32__))
+#  include <malloc.h>
+#endif
+
+#if defined (_STLP_PTHREADS) && !defined (_STLP_NO_THREADS)
+#  include <pthread_alloc>
+#  include <cerrno>
+#endif
+
+#include <stl/_threads.h>
+
+#include "lock_free_slist.h"
+
+#if defined (__WATCOMC__)
+#  pragma warning 13 9
+#  pragma warning 367 9
+#  pragma warning 368 9
+#endif
+
+#if defined (_STLP_SGI_THREADS)
+  // We test whether threads are in use before locking.
+  // Perhaps this should be moved into stl_threads.h, but that
+  // probably makes it harder to avoid the procedure call when
+  // it isn't needed.
+extern "C" {
+  extern int __us_rsthread_malloc;
+}
+#endif
+
+// Specialised debug form of new operator which does not provide "false"
+// memory leaks when run with debug CRT libraries.
+#if defined (_STLP_MSVC) && (_STLP_MSVC >= 1020 && defined (_STLP_DEBUG_ALLOC)) && !defined (_STLP_WCE)
+#  include <crtdbg.h>
+inline char* __stlp_new_chunk(size_t __bytes) {
+  void *__chunk = _STLP_CHECK_NULL_ALLOC(::operator new(__bytes, __FILE__, __LINE__));
+  return __STATIC_CAST(char*, __chunk);
+}
+inline void __stlp_delete_chunck(void* __p) { ::operator delete(__p, __FILE__, __LINE__); }
+#else
+#  ifdef _STLP_NODE_ALLOC_USE_MALLOC
+#    include <cstdlib>
+inline char* __stlp_new_chunk(size_t __bytes) {
+  // do not use _STLP_CHECK_NULL_ALLOC, this macro is dedicated to new operator.
+  void *__chunk = _STLP_VENDOR_CSTD::malloc(__bytes);
+  if (__chunk == 0) {
+    _STLP_THROW_BAD_ALLOC;
+  }
+  return __STATIC_CAST(char*, __chunk);
+}
+inline void __stlp_delete_chunck(void* __p) { _STLP_VENDOR_CSTD::free(__p); }
+#  else
+inline char* __stlp_new_chunk(size_t __bytes)
+{ return __STATIC_CAST(char*, _STLP_STD::__stl_new(__bytes)); }
+inline void __stlp_delete_chunck(void* __p) { _STLP_STD::__stl_delete(__p); }
+#  endif
+#endif
+
+/* This is an additional atomic operations to the ones already defined in
+ * stl/_threads.h, platform should try to support it to improve performance.
+ * __add_atomic_t _STLP_ATOMIC_ADD(volatile __add_atomic_t* __target, __add_atomic_t __val) :
+ * does *__target = *__target + __val and returns the old *__target value */
+typedef long __add_atomic_t;
+typedef unsigned long __uadd_atomic_t;
+
+#if defined (__GNUC__) && defined (__i386__)
+inline long _STLP_atomic_add_gcc_x86(long volatile* p, long addend) {
+  long result;
+  __asm__ __volatile__
+    ("lock; xaddl %1, %0;"
+    :"=m" (*p), "=r" (result)
+    :"m"  (*p), "1"  (addend)
+    :"cc");
+ return result + addend;
+}
+#  define _STLP_ATOMIC_ADD(__dst, __val)  _STLP_atomic_add_gcc_x86(__dst, __val)
+#elif defined (_STLP_WIN32THREADS)
+// The Win32 API function InterlockedExchangeAdd is not available on Windows 95.
+#  if !defined (_STLP_WIN95_LIKE)
+#    if defined (_STLP_NEW_PLATFORM_SDK)
+#      define _STLP_ATOMIC_ADD(__dst, __val) InterlockedExchangeAdd(__dst, __val)
+#    else
+#      define _STLP_ATOMIC_ADD(__dst, __val) InterlockedExchangeAdd(__CONST_CAST(__add_atomic_t*, __dst), __val)
+#    endif
+#  endif
+#endif
+
+#if defined (__OS400__)
+// dums 02/05/2007: is it really necessary ?
+enum { _ALIGN = 16, _ALIGN_SHIFT = 4 };
+#else
+enum { _ALIGN = 2 * sizeof(void*), _ALIGN_SHIFT = 2 + sizeof(void*) / 4 };
+#endif
+
+#define _S_FREELIST_INDEX(__bytes) ((__bytes - size_t(1)) >> (int)_ALIGN_SHIFT)
+
+_STLP_BEGIN_NAMESPACE
+
+// malloc_alloc out-of-memory handling
+static __oom_handler_type __oom_handler = __STATIC_CAST(__oom_handler_type, 0);
+
+#ifdef _STLP_THREADS
+_STLP_mutex __oom_handler_lock;
+#endif
+
+void* _STLP_CALL __malloc_alloc::allocate(size_t __n)
+{
+  void *__result = malloc(__n);
+  if ( 0 == __result ) {
+    __oom_handler_type __my_malloc_handler;
+
+    for (;;) {
+      {
+#ifdef _STLP_THREADS
+        _STLP_auto_lock _l( __oom_handler_lock );
+#endif
+        __my_malloc_handler = __oom_handler;
+      }
+      if ( 0 == __my_malloc_handler) {
+        _STLP_THROW_BAD_ALLOC;
+      }
+      (*__my_malloc_handler)();
+      __result = malloc(__n);
+      if ( __result )
+        return __result;
+    }
+  }
+  return __result;
+}
+
+__oom_handler_type _STLP_CALL __malloc_alloc::set_malloc_handler(__oom_handler_type __f)
+{
+#ifdef _STLP_THREADS
+  _STLP_auto_lock _l( __oom_handler_lock );
+#endif
+  __oom_handler_type __old = __oom_handler;
+  __oom_handler = __f;
+  return __old;
+}
+
+// *******************************************************
+// Default node allocator.
+// With a reasonable compiler, this should be roughly as fast as the
+// original STL class-specific allocators, but with less fragmentation.
+//
+// Important implementation properties:
+// 1. If the client request an object of size > _MAX_BYTES, the resulting
+//    object will be obtained directly from malloc.
+// 2. In all other cases, we allocate an object of size exactly
+//    _S_round_up(requested_size).  Thus the client has enough size
+//    information that we can return the object to the proper free list
+//    without permanently losing part of the object.
+//
+
+#define _STLP_NFREELISTS 16
+
+#if defined (_STLP_LEAKS_PEDANTIC) && defined (_STLP_USE_DYNAMIC_LIB)
+/*
+ * We can only do cleanup of the node allocator memory pool if we are
+ * sure that the STLport library is used as a shared one as it guaranties
+ * the unicity of the node allocator instance. Without that guaranty node
+ * allocator instances might exchange memory blocks making the implementation
+ * of a cleaning process much more complicated.
+ */
+#  define _STLP_DO_CLEAN_NODE_ALLOC
+#endif
+
+/* When STLport is used without multi threaded safety we use the node allocator
+ * implementation with locks as locks becomes no-op. The lock free implementation
+ * always use system specific atomic operations which are slower than 'normal'
+ * ones.
+ */
+#if defined (_STLP_THREADS) && \
+    defined (_STLP_HAS_ATOMIC_FREELIST) && defined (_STLP_ATOMIC_ADD)
+/*
+ * We have an implementation of the atomic freelist (_STLP_atomic_freelist)
+ * for this architecture and compiler.  That means we can use the non-blocking
+ * implementation of the node-allocation engine.*/
+#  define _STLP_USE_LOCK_FREE_IMPLEMENTATION
+#endif
+
+#if !defined (_STLP_USE_LOCK_FREE_IMPLEMENTATION)
+#  if defined (_STLP_THREADS)
+
+class _Node_Alloc_Lock {
+  static _STLP_STATIC_MUTEX& _S_Mutex() {
+    static _STLP_STATIC_MUTEX mutex _STLP_MUTEX_INITIALIZER;
+    return mutex;
+  }
+public:
+  _Node_Alloc_Lock() {
+#    if defined (_STLP_SGI_THREADS)
+    if (__us_rsthread_malloc)
+#    endif
+      _S_Mutex()._M_acquire_lock();
+  }
+
+  ~_Node_Alloc_Lock() {
+#    if defined (_STLP_SGI_THREADS)
+    if (__us_rsthread_malloc)
+#    endif
+      _S_Mutex()._M_release_lock();
+  }
+};
+
+#  else
+
+class _Node_Alloc_Lock {
+public:
+  _Node_Alloc_Lock() { }
+  ~_Node_Alloc_Lock() { }
+};
+
+#  endif
+
+struct _Node_alloc_obj {
+  _Node_alloc_obj * _M_next;
+};
+#endif
+
+class __node_alloc_impl {
+  static inline size_t _STLP_CALL _S_round_up(size_t __bytes)
+  { return (((__bytes) + (size_t)_ALIGN-1) & ~((size_t)_ALIGN - 1)); }
+
+#if defined (_STLP_USE_LOCK_FREE_IMPLEMENTATION)
+  typedef _STLP_atomic_freelist::item   _Obj;
+  typedef _STLP_atomic_freelist         _Freelist;
+  typedef _STLP_atomic_freelist         _ChunkList;
+
+  // Header of blocks of memory that have been allocated as part of
+  // a larger chunk but have not yet been chopped up into nodes.
+  struct _FreeBlockHeader : public _STLP_atomic_freelist::item {
+    char* _M_end;     // pointer to end of free memory
+  };
+#else
+  typedef _Node_alloc_obj       _Obj;
+  typedef _Obj* _STLP_VOLATILE  _Freelist;
+  typedef _Obj*                 _ChunkList;
+#endif
+
+private:
+  // Returns an object of size __n, and optionally adds to size __n free list.
+  static _Obj* _S_refill(size_t __n);
+  // Allocates a chunk for nobjs of size __p_size.  nobjs may be reduced
+  // if it is inconvenient to allocate the requested number.
+  static char* _S_chunk_alloc(size_t __p_size, int& __nobjs);
+  // Chunk allocation state.
+  static _Freelist _S_free_list[_STLP_NFREELISTS];
+  // Amount of total allocated memory
+#if defined (_STLP_USE_LOCK_FREE_IMPLEMENTATION)
+  static _STLP_VOLATILE __add_atomic_t _S_heap_size;
+#else
+  static size_t _S_heap_size;
+#endif
+
+#if defined (_STLP_USE_LOCK_FREE_IMPLEMENTATION)
+  // List of blocks of free memory
+  static _STLP_atomic_freelist  _S_free_mem_blocks;
+#else
+  // Start of the current free memory buffer
+  static char* _S_start_free;
+  // End of the current free memory buffer
+  static char* _S_end_free;
+#endif
+
+#if defined (_STLP_DO_CLEAN_NODE_ALLOC)
+public:
+  // Methods to report alloc/dealloc calls to the counter system.
+#  if defined (_STLP_USE_LOCK_FREE_IMPLEMENTATION)
+  typedef _STLP_VOLATILE __stl_atomic_t _AllocCounter;
+#  else
+  typedef __stl_atomic_t _AllocCounter;
+#  endif
+  static _AllocCounter& _STLP_CALL _S_alloc_counter();
+  static void _S_alloc_call();
+  static void _S_dealloc_call();
+
+private:
+  // Free all the allocated chuncks of memory
+  static void _S_chunk_dealloc();
+  // Beginning of the linked list of allocated chunks of memory
+  static _ChunkList _S_chunks;
+#endif /* _STLP_DO_CLEAN_NODE_ALLOC */
+
+public:
+  /* __n must be > 0      */
+  static void* _M_allocate(size_t& __n);
+  /* __p may not be 0 */
+  static void _M_deallocate(void *__p, size_t __n);
+};
+
+#if !defined (_STLP_USE_LOCK_FREE_IMPLEMENTATION)
+void* __node_alloc_impl::_M_allocate(size_t& __n) {
+  __n = _S_round_up(__n);
+  _Obj * _STLP_VOLATILE * __my_free_list = _S_free_list + _S_FREELIST_INDEX(__n);
+  _Obj *__r;
+
+  // Acquire the lock here with a constructor call.
+  // This ensures that it is released in exit or during stack
+  // unwinding.
+  _Node_Alloc_Lock __lock_instance;
+
+  if ( (__r  = *__my_free_list) != 0 ) {
+    *__my_free_list = __r->_M_next;
+  } else {
+    __r = _S_refill(__n);
+  }
+#  if defined (_STLP_DO_CLEAN_NODE_ALLOC)
+  _S_alloc_call();
+#  endif
+  // lock is released here
+  return __r;
+}
+
+void __node_alloc_impl::_M_deallocate(void *__p, size_t __n) {
+  _Obj * _STLP_VOLATILE * __my_free_list = _S_free_list + _S_FREELIST_INDEX(__n);
+  _Obj * __pobj = __STATIC_CAST(_Obj*, __p);
+
+  // acquire lock
+  _Node_Alloc_Lock __lock_instance;
+  __pobj->_M_next = *__my_free_list;
+  *__my_free_list = __pobj;
+
+#  if defined (_STLP_DO_CLEAN_NODE_ALLOC)
+  _S_dealloc_call();
+#  endif
+  // lock is released here
+}
+
+#  if defined (_STLP_DO_CLEAN_NODE_ALLOC)
+#    define _STLP_OFFSET sizeof(_Obj)
+#  else
+#    define _STLP_OFFSET 0
+#  endif
+
+/* We allocate memory in large chunks in order to avoid fragmenting     */
+/* the malloc heap too much.                                            */
+/* We assume that size is properly aligned.                             */
+/* We hold the allocation lock.                                         */
+char* __node_alloc_impl::_S_chunk_alloc(size_t _p_size, int& __nobjs) {
+  char* __result;
+  size_t __total_bytes = _p_size * __nobjs;
+  size_t __bytes_left = _S_end_free - _S_start_free;
+
+  if (__bytes_left > 0) {
+    if (__bytes_left >= __total_bytes) {
+      __result = _S_start_free;
+      _S_start_free += __total_bytes;
+      return __result;
+    }
+
+    if (__bytes_left >= _p_size) {
+      __nobjs = (int)(__bytes_left / _p_size);
+      __total_bytes = _p_size * __nobjs;
+      __result = _S_start_free;
+      _S_start_free += __total_bytes;
+      return __result;
+    }
+
+    // Try to make use of the left-over piece.
+    _Obj* _STLP_VOLATILE* __my_free_list = _S_free_list + _S_FREELIST_INDEX(__bytes_left);
+    __REINTERPRET_CAST(_Obj*, _S_start_free)->_M_next = *__my_free_list;
+    *__my_free_list = __REINTERPRET_CAST(_Obj*, _S_start_free);
+    _S_start_free = _S_end_free = 0;
+  }
+
+  size_t __bytes_to_get = 2 * __total_bytes + _S_round_up(_S_heap_size) + _STLP_OFFSET;
+
+  _STLP_TRY {
+    _S_start_free = __stlp_new_chunk(__bytes_to_get);
+  }
+#if defined (_STLP_USE_EXCEPTIONS)
+  catch (const _STLP_STD::bad_alloc&) {
+    _Obj* _STLP_VOLATILE* __my_free_list;
+    _Obj* __p;
+    // Try to do with what we have.  That can't hurt.
+    // We do not try smaller requests, since that tends
+    // to result in disaster on multi-process machines.
+    for (size_t __i = _p_size; __i <= (size_t)_MAX_BYTES; __i += (size_t)_ALIGN) {
+      __my_free_list = _S_free_list + _S_FREELIST_INDEX(__i);
+      __p = *__my_free_list;
+      if (0 != __p) {
+        *__my_free_list = __p -> _M_next;
+        _S_start_free = __REINTERPRET_CAST(char*, __p);
+        _S_end_free = _S_start_free + __i;
+        return _S_chunk_alloc(_p_size, __nobjs);
+        // Any leftover piece will eventually make it to the
+        // right free list.
+      }
+    }
+    __bytes_to_get = __total_bytes + _STLP_OFFSET;
+    _S_start_free = __stlp_new_chunk(__bytes_to_get);
+  }
+#endif
+
+  _S_heap_size += __bytes_to_get >> 4;
+#  if defined (_STLP_DO_CLEAN_NODE_ALLOC)
+  __REINTERPRET_CAST(_Obj*, _S_start_free)->_M_next = _S_chunks;
+  _S_chunks = __REINTERPRET_CAST(_Obj*, _S_start_free);
+#  endif
+  _S_end_free = _S_start_free + __bytes_to_get;
+  _S_start_free += _STLP_OFFSET;
+  return _S_chunk_alloc(_p_size, __nobjs);
+}
+
+/* Returns an object of size __n, and optionally adds to size __n free list.*/
+/* We assume that __n is properly aligned.                                  */
+/* We hold the allocation lock.                                             */
+_Node_alloc_obj* __node_alloc_impl::_S_refill(size_t __n) {
+  int __nobjs = 20;
+  char* __chunk = _S_chunk_alloc(__n, __nobjs);
+
+  if (1 == __nobjs) return __REINTERPRET_CAST(_Obj*, __chunk);
+
+  _Obj* _STLP_VOLATILE* __my_free_list = _S_free_list + _S_FREELIST_INDEX(__n);
+  _Obj* __result;
+  _Obj* __current_obj;
+  _Obj* __next_obj;
+
+  /* Build free list in chunk */
+  __result = __REINTERPRET_CAST(_Obj*, __chunk);
+  *__my_free_list = __next_obj = __REINTERPRET_CAST(_Obj*, __chunk + __n);
+  for (--__nobjs; --__nobjs; ) {
+    __current_obj = __next_obj;
+    __next_obj = __REINTERPRET_CAST(_Obj*, __REINTERPRET_CAST(char*, __next_obj) + __n);
+    __current_obj->_M_next = __next_obj;
+  }
+  __next_obj->_M_next = 0;
+  return __result;
+}
+
+#  if defined (_STLP_DO_CLEAN_NODE_ALLOC)
+void __node_alloc_impl::_S_alloc_call()
+{ ++_S_alloc_counter(); }
+
+void __node_alloc_impl::_S_dealloc_call() {
+  __stl_atomic_t &counter = _S_alloc_counter();
+  if (--counter == 0)
+  { _S_chunk_dealloc(); }
+}
+
+/* We deallocate all the memory chunks      */
+void __node_alloc_impl::_S_chunk_dealloc() {
+  _Obj *__pcur = _S_chunks, *__pnext;
+  while (__pcur != 0) {
+    __pnext = __pcur->_M_next;
+    __stlp_delete_chunck(__pcur);
+    __pcur = __pnext;
+  }
+  _S_chunks = 0;
+  _S_start_free = _S_end_free = 0;
+  _S_heap_size = 0;
+  memset(__REINTERPRET_CAST(char*, __CONST_CAST(_Obj**, &_S_free_list[0])), 0, _STLP_NFREELISTS * sizeof(_Obj*));
+}
+#  endif
+
+#else
+
+void* __node_alloc_impl::_M_allocate(size_t& __n) {
+  __n = _S_round_up(__n);
+  _Obj* __r = _S_free_list[_S_FREELIST_INDEX(__n)].pop();
+  if (__r  == 0)
+  { __r = _S_refill(__n); }
+
+#  if defined (_STLP_DO_CLEAN_NODE_ALLOC)
+  _S_alloc_call();
+#  endif
+  return __r;
+}
+
+void __node_alloc_impl::_M_deallocate(void *__p, size_t __n) {
+  _S_free_list[_S_FREELIST_INDEX(__n)].push(__STATIC_CAST(_Obj*, __p));
+
+#  if defined (_STLP_DO_CLEAN_NODE_ALLOC)
+  _S_dealloc_call();
+#  endif
+}
+
+/* Returns an object of size __n, and optionally adds additional ones to    */
+/* freelist of objects of size __n.                                         */
+/* We assume that __n is properly aligned.                                  */
+__node_alloc_impl::_Obj* __node_alloc_impl::_S_refill(size_t __n) {
+  int __nobjs = 20;
+  char* __chunk = _S_chunk_alloc(__n, __nobjs);
+
+  if (__nobjs <= 1)
+    return __REINTERPRET_CAST(_Obj*, __chunk);
+
+  // Push all new nodes (minus first one) onto freelist
+  _Obj* __result   = __REINTERPRET_CAST(_Obj*, __chunk);
+  _Obj* __cur_item = __result;
+  _Freelist* __my_freelist = _S_free_list + _S_FREELIST_INDEX(__n);
+  for (--__nobjs; __nobjs != 0; --__nobjs) {
+    __cur_item  = __REINTERPRET_CAST(_Obj*, __REINTERPRET_CAST(char*, __cur_item) + __n);
+    __my_freelist->push(__cur_item);
+  }
+  return __result;
+}
+
+#  if defined (_STLP_DO_CLEAN_NODE_ALLOC)
+#    define _STLP_OFFSET _ALIGN
+#  else
+#    define _STLP_OFFSET 0
+#  endif
+
+/* We allocate memory in large chunks in order to avoid fragmenting     */
+/* the malloc heap too much.                                            */
+/* We assume that size is properly aligned.                             */
+char* __node_alloc_impl::_S_chunk_alloc(size_t _p_size, int& __nobjs) {
+#  if defined (_STLP_DO_CLEAN_NODE_ALLOC)
+  //We are going to add a small memory block to keep all the allocated blocks
+  //address, we need to do so respecting the memory alignment. The following
+  //static assert checks that the reserved block is big enough to store a pointer.
+  _STLP_STATIC_ASSERT(sizeof(_Obj) <= _ALIGN)
+#  endif
+  char*  __result       = 0;
+  __add_atomic_t __total_bytes  = __STATIC_CAST(__add_atomic_t, _p_size) * __nobjs;
+
+  _FreeBlockHeader* __block = __STATIC_CAST(_FreeBlockHeader*, _S_free_mem_blocks.pop());
+  if (__block != 0) {
+    // We checked a block out and can now mess with it with impugnity.
+    // We'll put the remainder back into the list if we're done with it below.
+    char*  __buf_start  = __REINTERPRET_CAST(char*, __block);
+    __add_atomic_t __bytes_left = __block->_M_end - __buf_start;
+
+    if ((__bytes_left < __total_bytes) && (__bytes_left >= __STATIC_CAST(__add_atomic_t, _p_size))) {
+      // There's enough left for at least one object, but not as much as we wanted
+      __result      = __buf_start;
+      __nobjs       = (int)(__bytes_left/_p_size);
+      __total_bytes = __STATIC_CAST(__add_atomic_t, _p_size) * __nobjs;
+      __bytes_left -= __total_bytes;
+      __buf_start  += __total_bytes;
+    }
+    else if (__bytes_left >= __total_bytes) {
+      // The block has enough left to satisfy all that was asked for
+      __result      = __buf_start;
+      __bytes_left -= __total_bytes;
+      __buf_start  += __total_bytes;
+    }
+
+    if (__bytes_left != 0) {
+      // There is still some memory left over in block after we satisfied our request.
+      if ((__result != 0) && (__bytes_left >= (__add_atomic_t)sizeof(_FreeBlockHeader))) {
+        // We were able to allocate at least one object and there is still enough
+        // left to put remainder back into list.
+        _FreeBlockHeader* __newblock = __REINTERPRET_CAST(_FreeBlockHeader*, __buf_start);
+        __newblock->_M_end  = __block->_M_end;
+        _S_free_mem_blocks.push(__newblock);
+      }
+      else {
+        // We were not able to allocate enough for at least one object.
+        // Shove into freelist of nearest (rounded-down!) size.
+        size_t __rounded_down = _S_round_up(__bytes_left + 1) - (size_t)_ALIGN;
+        if (__rounded_down > 0)
+          _S_free_list[_S_FREELIST_INDEX(__rounded_down)].push((_Obj*)__buf_start);
+      }
+    }
+    if (__result != 0)
+      return __result;
+  }
+
+  // We couldn't satisfy it from the list of free blocks, get new memory.
+  __add_atomic_t __bytes_to_get = 2 * __total_bytes +
+                                  __STATIC_CAST(__add_atomic_t,
+                                                _S_round_up(__STATIC_CAST(__uadd_atomic_t, _STLP_ATOMIC_ADD(&_S_heap_size, 0)))) +
+                                  _STLP_OFFSET;
+  _STLP_TRY {
+    __result = __stlp_new_chunk(__bytes_to_get);
+  }
+#if defined (_STLP_USE_EXCEPTIONS)
+  catch (const bad_alloc&) {
+    // Allocation failed; try to canibalize from freelist of a larger object size.
+    for (size_t __i = _p_size; __i <= (size_t)_MAX_BYTES; __i += (size_t)_ALIGN) {
+      _Obj* __p  = _S_free_list[_S_FREELIST_INDEX(__i)].pop();
+      if (0 != __p) {
+        if (__i < sizeof(_FreeBlockHeader)) {
+          // Not enough to put into list of free blocks, divvy it up here.
+          // Use as much as possible for this request and shove remainder into freelist.
+          __nobjs = (int)(__i/_p_size);
+          __total_bytes = __nobjs * __STATIC_CAST(__add_atomic_t, _p_size);
+          size_t __bytes_left = __i - __total_bytes;
+          size_t __rounded_down = _S_round_up(__bytes_left+1) - (size_t)_ALIGN;
+          if (__rounded_down > 0) {
+            _S_free_list[_S_FREELIST_INDEX(__rounded_down)].push(__REINTERPRET_CAST(_Obj*, __REINTERPRET_CAST(char*, __p) + __total_bytes));
+          }
+          return __REINTERPRET_CAST(char*, __p);
+        }
+        else {
+          // Add node to list of available blocks and recursively allocate from it.
+          _FreeBlockHeader* __newblock = (_FreeBlockHeader*)__p;
+          __newblock->_M_end  = __REINTERPRET_CAST(char*, __p) + __i;
+          _S_free_mem_blocks.push(__newblock);
+          return _S_chunk_alloc(_p_size, __nobjs);
+        }
+      }
+    }
+
+    // We were not able to find something in a freelist, try to allocate a smaller amount.
+    __bytes_to_get  = __total_bytes + _STLP_OFFSET;
+    __result = __stlp_new_chunk(__bytes_to_get);
+
+    // This should either throw an exception or remedy the situation.
+    // Thus we assume it succeeded.
+  }
+#endif
+  // Alignment check
+  _STLP_VERBOSE_ASSERT(((__REINTERPRET_CAST(size_t, __result) & __STATIC_CAST(size_t, _ALIGN - 1)) == 0),
+                       _StlMsg_DBA_DELETED_TWICE)
+  _STLP_ATOMIC_ADD(&_S_heap_size, __bytes_to_get >> 4);
+
+#  if defined (_STLP_DO_CLEAN_NODE_ALLOC)
+  // We have to track the allocated memory chunks for release on exit.
+  _S_chunks.push(__REINTERPRET_CAST(_Obj*, __result));
+  __result       += _ALIGN;
+  __bytes_to_get -= _ALIGN;
+#  endif
+
+  if (__bytes_to_get > __total_bytes) {
+    // Push excess memory allocated in this chunk into list of free memory blocks
+    _FreeBlockHeader* __freeblock = __REINTERPRET_CAST(_FreeBlockHeader*, __result + __total_bytes);
+    __freeblock->_M_end  = __result + __bytes_to_get;
+    _S_free_mem_blocks.push(__freeblock);
+  }
+  return __result;
+}
+
+#  if defined (_STLP_DO_CLEAN_NODE_ALLOC)
+void __node_alloc_impl::_S_alloc_call()
+{ _STLP_ATOMIC_INCREMENT(&_S_alloc_counter()); }
+
+void __node_alloc_impl::_S_dealloc_call() {
+  _STLP_VOLATILE __stl_atomic_t *pcounter = &_S_alloc_counter();
+  if (_STLP_ATOMIC_DECREMENT(pcounter) == 0)
+    _S_chunk_dealloc();
+}
+
+/* We deallocate all the memory chunks      */
+void __node_alloc_impl::_S_chunk_dealloc() {
+  // Note: The _Node_alloc_helper class ensures that this function
+  // will only be called when the (shared) library is unloaded or the
+  // process is shutdown.  It's thus not possible that another thread
+  // is currently trying to allocate a node (we're not thread-safe here).
+  //
+
+  // Clear the free blocks and all freelistst.  This makes sure that if
+  // for some reason more memory is allocated again during shutdown
+  // (it'd also be really nasty to leave references to deallocated memory).
+  _S_free_mem_blocks.clear();
+  _S_heap_size      = 0;
+
+  for (size_t __i = 0; __i < _STLP_NFREELISTS; ++__i) {
+    _S_free_list[__i].clear();
+  }
+
+  // Detach list of chunks and free them all
+  _Obj* __chunk = _S_chunks.clear();
+  while (__chunk != 0) {
+    _Obj* __next = __chunk->_M_next;
+    __stlp_delete_chunck(__chunk);
+    __chunk  = __next;
+  }
+}
+#  endif
+
+#endif
+
+#if defined (_STLP_DO_CLEAN_NODE_ALLOC)
+struct __node_alloc_cleaner {
+  ~__node_alloc_cleaner()
+  { __node_alloc_impl::_S_dealloc_call(); }
+};
+
+#  if defined (_STLP_USE_LOCK_FREE_IMPLEMENTATION)
+_STLP_VOLATILE __stl_atomic_t& _STLP_CALL
+#  else
+__stl_atomic_t& _STLP_CALL
+#  endif
+__node_alloc_impl::_S_alloc_counter() {
+  static _AllocCounter _S_counter = 1;
+  static __node_alloc_cleaner _S_node_alloc_cleaner;
+  return _S_counter;
+}
+#endif
+
+#if !defined (_STLP_USE_LOCK_FREE_IMPLEMENTATION)
+_Node_alloc_obj * _STLP_VOLATILE
+__node_alloc_impl::_S_free_list[_STLP_NFREELISTS]
+= {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+// The 16 zeros are necessary to make version 4.1 of the SunPro
+// compiler happy.  Otherwise it appears to allocate too little
+// space for the array.
+#else
+_STLP_atomic_freelist __node_alloc_impl::_S_free_list[_STLP_NFREELISTS];
+_STLP_atomic_freelist __node_alloc_impl::_S_free_mem_blocks;
+#endif
+
+#if !defined (_STLP_USE_LOCK_FREE_IMPLEMENTATION)
+char *__node_alloc_impl::_S_start_free = 0;
+char *__node_alloc_impl::_S_end_free = 0;
+#endif
+
+#if defined (_STLP_USE_LOCK_FREE_IMPLEMENTATION)
+_STLP_VOLATILE __add_atomic_t
+#else
+size_t
+#endif
+__node_alloc_impl::_S_heap_size = 0;
+
+#if defined (_STLP_DO_CLEAN_NODE_ALLOC)
+#  if defined (_STLP_USE_LOCK_FREE_IMPLEMENTATION)
+_STLP_atomic_freelist __node_alloc_impl::_S_chunks;
+#  else
+_Node_alloc_obj* __node_alloc_impl::_S_chunks  = 0;
+#  endif
+#endif
+
+void * _STLP_CALL __node_alloc::_M_allocate(size_t& __n)
+{ return __node_alloc_impl::_M_allocate(__n); }
+
+void _STLP_CALL __node_alloc::_M_deallocate(void *__p, size_t __n)
+{ __node_alloc_impl::_M_deallocate(__p, __n); }
+
+#if defined (_STLP_PTHREADS) && !defined (_STLP_NO_THREADS)
+
+#  define _STLP_DATA_ALIGNMENT 8
+
+_STLP_MOVE_TO_PRIV_NAMESPACE
+
+// *******************************************************
+// __perthread_alloc implementation
+union _Pthread_alloc_obj {
+  union _Pthread_alloc_obj * __free_list_link;
+  char __client_data[_STLP_DATA_ALIGNMENT];    /* The client sees this.    */
+};
+
+// Pthread allocators don't appear to the client to have meaningful
+// instances.  We do in fact need to associate some state with each
+// thread.  That state is represented by _Pthread_alloc_per_thread_state.
+
+struct _Pthread_alloc_per_thread_state {
+  typedef _Pthread_alloc_obj __obj;
+  enum { _S_NFREELISTS = _MAX_BYTES / _STLP_DATA_ALIGNMENT };
+
+  // Free list link for list of available per thread structures.
+  // When one of these becomes available for reuse due to thread
+  // termination, any objects in its free list remain associated
+  // with it.  The whole structure may then be used by a newly
+  // created thread.
+  _Pthread_alloc_per_thread_state() : __next(0)
+  { memset((void *)__CONST_CAST(_Pthread_alloc_obj**, __free_list), 0, (size_t)_S_NFREELISTS * sizeof(__obj *)); }
+  // Returns an object of size __n, and possibly adds to size n free list.
+  void *_M_refill(size_t __n);
+
+  _Pthread_alloc_obj* volatile __free_list[_S_NFREELISTS];
+  _Pthread_alloc_per_thread_state *__next;
+  // this data member is only to be used by per_thread_allocator, which returns memory to the originating thread.
+  _STLP_mutex _M_lock;
+};
+
+// Pthread-specific allocator.
+class _Pthread_alloc_impl {
+public: // but only for internal use:
+  typedef _Pthread_alloc_per_thread_state __state_type;
+  typedef char value_type;
+
+  // Allocates a chunk for nobjs of size size.  nobjs may be reduced
+  // if it is inconvenient to allocate the requested number.
+  static char *_S_chunk_alloc(size_t __size, size_t &__nobjs, __state_type*);
+
+  enum {_S_ALIGN = _STLP_DATA_ALIGNMENT};
+
+  static size_t _S_round_up(size_t __bytes)
+  { return (((__bytes) + (int)_S_ALIGN - 1) & ~((int)_S_ALIGN - 1)); }
+  static size_t _S_freelist_index(size_t __bytes)
+  { return (((__bytes) + (int)_S_ALIGN - 1) / (int)_S_ALIGN - 1); }
+
+private:
+  // Chunk allocation state. And other shared state.
+  // Protected by _S_chunk_allocator_lock.
+  static _STLP_STATIC_MUTEX _S_chunk_allocator_lock;
+  static char *_S_start_free;
+  static char *_S_end_free;
+  static size_t _S_heap_size;
+  static __state_type *_S_free_per_thread_states;
+  static pthread_key_t _S_key;
+  static bool _S_key_initialized;
+  // Pthread key under which per thread state is stored.
+  // Allocator instances that are currently unclaimed by any thread.
+  static void _S_destructor(void *instance);
+  // Function to be called on thread exit to reclaim per thread
+  // state.
+  static __state_type *_S_new_per_thread_state();
+public:
+  // Return a recycled or new per thread state.
+  static __state_type *_S_get_per_thread_state();
+private:
+        // ensure that the current thread has an associated
+        // per thread state.
+  class _M_lock;
+  friend class _M_lock;
+  class _M_lock {
+  public:
+    _M_lock () { _S_chunk_allocator_lock._M_acquire_lock(); }
+    ~_M_lock () { _S_chunk_allocator_lock._M_release_lock(); }
+  };
+
+public:
+
+  /* n must be > 0      */
+  static void * allocate(size_t& __n);
+
+  /* p may not be 0 */
+  static void deallocate(void *__p, size_t __n);
+
+  // boris : versions for per_thread_allocator
+  /* n must be > 0      */
+  static void * allocate(size_t& __n, __state_type* __a);
+
+  /* p may not be 0 */
+  static void deallocate(void *__p, size_t __n, __state_type* __a);
+
+  static void * reallocate(void *__p, size_t __old_sz, size_t& __new_sz);
+};
+
+/* Returns an object of size n, and optionally adds to size n free list.*/
+/* We assume that n is properly aligned.                                */
+/* We hold the allocation lock.                                         */
+void *_Pthread_alloc_per_thread_state::_M_refill(size_t __n) {
+  typedef _Pthread_alloc_obj __obj;
+  size_t __nobjs = 128;
+  char * __chunk = _Pthread_alloc_impl::_S_chunk_alloc(__n, __nobjs, this);
+  __obj * volatile * __my_free_list;
+  __obj * __result;
+  __obj * __current_obj, * __next_obj;
+  size_t __i;
+
+  if (1 == __nobjs)  {
+    return __chunk;
+  }
+
+  __my_free_list = __free_list + _Pthread_alloc_impl::_S_freelist_index(__n);
+
+  /* Build free list in chunk */
+  __result = (__obj *)__chunk;
+  *__my_free_list = __next_obj = (__obj *)(__chunk + __n);
+  for (__i = 1; ; ++__i) {
+    __current_obj = __next_obj;
+    __next_obj = (__obj *)((char *)__next_obj + __n);
+    if (__nobjs - 1 == __i) {
+      __current_obj -> __free_list_link = 0;
+      break;
+    } else {
+      __current_obj -> __free_list_link = __next_obj;
+    }
+  }
+  return __result;
+}
+
+void _Pthread_alloc_impl::_S_destructor(void *__instance) {
+  _M_lock __lock_instance;  // Need to acquire lock here.
+  _Pthread_alloc_per_thread_state* __s = (_Pthread_alloc_per_thread_state*)__instance;
+  __s -> __next = _S_free_per_thread_states;
+  _S_free_per_thread_states = __s;
+}
+
+_Pthread_alloc_per_thread_state* _Pthread_alloc_impl::_S_new_per_thread_state() {
+  /* lock already held here.  */
+  if (0 != _S_free_per_thread_states) {
+    _Pthread_alloc_per_thread_state *__result = _S_free_per_thread_states;
+    _S_free_per_thread_states = _S_free_per_thread_states -> __next;
+    return __result;
+  }
+  else {
+    return new _Pthread_alloc_per_thread_state;
+  }
+}
+
+_Pthread_alloc_per_thread_state* _Pthread_alloc_impl::_S_get_per_thread_state() {
+  int __ret_code;
+  __state_type* __result;
+
+  if (_S_key_initialized && (__result = (__state_type*) pthread_getspecific(_S_key)))
+    return __result;
+
+  /*REFERENCED*/
+  _M_lock __lock_instance;  // Need to acquire lock here.
+  if (!_S_key_initialized) {
+    if (pthread_key_create(&_S_key, _S_destructor)) {
+      _STLP_THROW_BAD_ALLOC;  // failed
+    }
+    _S_key_initialized = true;
+  }
+
+  __result = _S_new_per_thread_state();
+  __ret_code = pthread_setspecific(_S_key, __result);
+  if (__ret_code) {
+    if (__ret_code == ENOMEM) {
+      _STLP_THROW_BAD_ALLOC;
+    } else {
+  // EINVAL
+      _STLP_ABORT();
+    }
+  }
+  return __result;
+}
+
+/* We allocate memory in large chunks in order to avoid fragmenting     */
+/* the malloc heap too much.                                            */
+/* We assume that size is properly aligned.                             */
+char *_Pthread_alloc_impl::_S_chunk_alloc(size_t __p_size, size_t &__nobjs, _Pthread_alloc_per_thread_state *__a) {
+  typedef _Pthread_alloc_obj __obj;
+  {
+    char * __result;
+    size_t __total_bytes;
+    size_t __bytes_left;
+    /*REFERENCED*/
+    _M_lock __lock_instance;         // Acquire lock for this routine
+
+    __total_bytes = __p_size * __nobjs;
+    __bytes_left = _S_end_free - _S_start_free;
+    if (__bytes_left >= __total_bytes) {
+      __result = _S_start_free;
+      _S_start_free += __total_bytes;
+      return __result;
+    } else if (__bytes_left >= __p_size) {
+      __nobjs = __bytes_left/__p_size;
+      __total_bytes = __p_size * __nobjs;
+      __result = _S_start_free;
+      _S_start_free += __total_bytes;
+      return __result;
+    } else {
+      size_t __bytes_to_get = 2 * __total_bytes + _S_round_up(_S_heap_size);
+      // Try to make use of the left-over piece.
+      if (__bytes_left > 0) {
+        __obj * volatile * __my_free_list = __a->__free_list + _S_freelist_index(__bytes_left);
+        ((__obj *)_S_start_free) -> __free_list_link = *__my_free_list;
+        *__my_free_list = (__obj *)_S_start_free;
+      }
+#  ifdef _SGI_SOURCE
+      // Try to get memory that's aligned on something like a
+      // cache line boundary, so as to avoid parceling out
+      // parts of the same line to different threads and thus
+      // possibly different processors.
+      {
+        const int __cache_line_size = 128;  // probable upper bound
+        __bytes_to_get &= ~(__cache_line_size-1);
+        _S_start_free = (char *)memalign(__cache_line_size, __bytes_to_get);
+        if (0 == _S_start_free) {
+          _S_start_free = (char *)__malloc_alloc::allocate(__bytes_to_get);
+        }
+      }
+#  else  /* !SGI_SOURCE */
+      _S_start_free = (char *)__malloc_alloc::allocate(__bytes_to_get);
+#  endif
+      _S_heap_size += __bytes_to_get >> 4;
+      _S_end_free = _S_start_free + __bytes_to_get;
+    }
+  }
+  // lock is released here
+  return _S_chunk_alloc(__p_size, __nobjs, __a);
+}
+
+
+/* n must be > 0      */
+void *_Pthread_alloc_impl::allocate(size_t& __n) {
+  typedef _Pthread_alloc_obj __obj;
+  __obj * volatile * __my_free_list;
+  __obj * __result;
+  __state_type* __a;
+
+  if (__n > _MAX_BYTES) {
+    return __malloc_alloc::allocate(__n);
+  }
+
+  __n = _S_round_up(__n);
+  __a = _S_get_per_thread_state();
+
+  __my_free_list = __a->__free_list + _S_freelist_index(__n);
+  __result = *__my_free_list;
+  if (__result == 0) {
+    void *__r = __a->_M_refill(__n);
+    return __r;
+  }
+  *__my_free_list = __result->__free_list_link;
+  return __result;
+};
+
+/* p may not be 0 */
+void _Pthread_alloc_impl::deallocate(void *__p, size_t __n) {
+  typedef _Pthread_alloc_obj __obj;
+  __obj *__q = (__obj *)__p;
+  __obj * volatile * __my_free_list;
+  __state_type* __a;
+
+  if (__n > _MAX_BYTES) {
+      __malloc_alloc::deallocate(__p, __n);
+      return;
+  }
+
+  __a = _S_get_per_thread_state();
+
+  __my_free_list = __a->__free_list + _S_freelist_index(__n);
+  __q -> __free_list_link = *__my_free_list;
+  *__my_free_list = __q;
+}
+
+// boris : versions for per_thread_allocator
+/* n must be > 0      */
+void *_Pthread_alloc_impl::allocate(size_t& __n, __state_type* __a) {
+  typedef _Pthread_alloc_obj __obj;
+  __obj * volatile * __my_free_list;
+  __obj * __result;
+
+  if (__n > _MAX_BYTES) {
+    return __malloc_alloc::allocate(__n);
+  }
+  __n = _S_round_up(__n);
+
+  // boris : here, we have to lock per thread state, as we may be getting memory from
+  // different thread pool.
+  _STLP_auto_lock __lock(__a->_M_lock);
+
+  __my_free_list = __a->__free_list + _S_freelist_index(__n);
+  __result = *__my_free_list;
+  if (__result == 0) {
+    void *__r = __a->_M_refill(__n);
+    return __r;
+  }
+  *__my_free_list = __result->__free_list_link;
+  return __result;
+};
+
+/* p may not be 0 */
+void _Pthread_alloc_impl::deallocate(void *__p, size_t __n, __state_type* __a) {
+  typedef _Pthread_alloc_obj __obj;
+  __obj *__q = (__obj *)__p;
+  __obj * volatile * __my_free_list;
+
+  if (__n > _MAX_BYTES) {
+    __malloc_alloc::deallocate(__p, __n);
+    return;
+  }
+
+  // boris : here, we have to lock per thread state, as we may be returning memory from
+  // different thread.
+  _STLP_auto_lock __lock(__a->_M_lock);
+
+  __my_free_list = __a->__free_list + _S_freelist_index(__n);
+  __q -> __free_list_link = *__my_free_list;
+  *__my_free_list = __q;
+}
+
+void *_Pthread_alloc_impl::reallocate(void *__p, size_t __old_sz, size_t& __new_sz) {
+  void * __result;
+  size_t __copy_sz;
+
+  if (__old_sz > _MAX_BYTES && __new_sz > _MAX_BYTES) {
+    return realloc(__p, __new_sz);
+  }
+
+  if (_S_round_up(__old_sz) == _S_round_up(__new_sz)) return __p;
+  __result = allocate(__new_sz);
+  __copy_sz = __new_sz > __old_sz? __old_sz : __new_sz;
+  memcpy(__result, __p, __copy_sz);
+  deallocate(__p, __old_sz);
+  return __result;
+}
+
+_Pthread_alloc_per_thread_state* _Pthread_alloc_impl::_S_free_per_thread_states = 0;
+pthread_key_t _Pthread_alloc_impl::_S_key = 0;
+_STLP_STATIC_MUTEX _Pthread_alloc_impl::_S_chunk_allocator_lock _STLP_MUTEX_INITIALIZER;
+bool _Pthread_alloc_impl::_S_key_initialized = false;
+char *_Pthread_alloc_impl::_S_start_free = 0;
+char *_Pthread_alloc_impl::_S_end_free = 0;
+size_t _Pthread_alloc_impl::_S_heap_size = 0;
+
+void * _STLP_CALL _Pthread_alloc::allocate(size_t& __n)
+{ return _Pthread_alloc_impl::allocate(__n); }
+void _STLP_CALL _Pthread_alloc::deallocate(void *__p, size_t __n)
+{ _Pthread_alloc_impl::deallocate(__p, __n); }
+void * _STLP_CALL _Pthread_alloc::allocate(size_t& __n, __state_type* __a)
+{ return _Pthread_alloc_impl::allocate(__n, __a); }
+void _STLP_CALL _Pthread_alloc::deallocate(void *__p, size_t __n, __state_type* __a)
+{ _Pthread_alloc_impl::deallocate(__p, __n, __a); }
+void * _STLP_CALL _Pthread_alloc::reallocate(void *__p, size_t __old_sz, size_t& __new_sz)
+{ return _Pthread_alloc_impl::reallocate(__p, __old_sz, __new_sz); }
+_Pthread_alloc_per_thread_state* _STLP_CALL _Pthread_alloc::_S_get_per_thread_state()
+{ return _Pthread_alloc_impl::_S_get_per_thread_state(); }
+
+_STLP_MOVE_TO_STD_NAMESPACE
+
+#endif
+
+_STLP_END_NAMESPACE
+
+#undef _S_FREELIST_INDEX
diff --git a/src/third_party/mozjs-45/build/stlport/src/bitset.cpp b/src/third_party/mozjs-45/build/stlport/src/bitset.cpp
new file mode 100644
index 0000000..90f1799
--- /dev/null
+++ b/src/third_party/mozjs-45/build/stlport/src/bitset.cpp
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 1998
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Copyright (c) 1999
+ * Boris Fomitchev
+ *
+ * This material is provided "as is", with absolutely no warranty expressed
+ * or implied. Any use is at your own risk.
+ *
+ * Permission to use or copy this software for any purpose is hereby granted
+ * without fee, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ *
+ */
+
+#include "stlport_prefix.h"
+
+#include <bitset>
+
+_STLP_BEGIN_NAMESPACE
+
+_STLP_MOVE_TO_PRIV_NAMESPACE
+
+// ------------------------------------------------------------
+// Lookup tables for find and count operations.
+
+size_t _Bs_G::_S_count(const unsigned char *__first,
+                       const unsigned char *__last)
+{
+  static const unsigned char _bit_count[256] = {
+  0, /*   0 */ 1, /*   1 */ 1, /*   2 */ 2, /*   3 */ 1, /*   4 */
+  2, /*   5 */ 2, /*   6 */ 3, /*   7 */ 1, /*   8 */ 2, /*   9 */
+  2, /*  10 */ 3, /*  11 */ 2, /*  12 */ 3, /*  13 */ 3, /*  14 */
+  4, /*  15 */ 1, /*  16 */ 2, /*  17 */ 2, /*  18 */ 3, /*  19 */
+  2, /*  20 */ 3, /*  21 */ 3, /*  22 */ 4, /*  23 */ 2, /*  24 */
+  3, /*  25 */ 3, /*  26 */ 4, /*  27 */ 3, /*  28 */ 4, /*  29 */
+  4, /*  30 */ 5, /*  31 */ 1, /*  32 */ 2, /*  33 */ 2, /*  34 */
+  3, /*  35 */ 2, /*  36 */ 3, /*  37 */ 3, /*  38 */ 4, /*  39 */
+  2, /*  40 */ 3, /*  41 */ 3, /*  42 */ 4, /*  43 */ 3, /*  44 */
+  4, /*  45 */ 4, /*  46 */ 5, /*  47 */ 2, /*  48 */ 3, /*  49 */
+  3, /*  50 */ 4, /*  51 */ 3, /*  52 */ 4, /*  53 */ 4, /*  54 */
+  5, /*  55 */ 3, /*  56 */ 4, /*  57 */ 4, /*  58 */ 5, /*  59 */
+  4, /*  60 */ 5, /*  61 */ 5, /*  62 */ 6, /*  63 */ 1, /*  64 */
+  2, /*  65 */ 2, /*  66 */ 3, /*  67 */ 2, /*  68 */ 3, /*  69 */
+  3, /*  70 */ 4, /*  71 */ 2, /*  72 */ 3, /*  73 */ 3, /*  74 */
+  4, /*  75 */ 3, /*  76 */ 4, /*  77 */ 4, /*  78 */ 5, /*  79 */
+  2, /*  80 */ 3, /*  81 */ 3, /*  82 */ 4, /*  83 */ 3, /*  84 */
+  4, /*  85 */ 4, /*  86 */ 5, /*  87 */ 3, /*  88 */ 4, /*  89 */
+  4, /*  90 */ 5, /*  91 */ 4, /*  92 */ 5, /*  93 */ 5, /*  94 */
+  6, /*  95 */ 2, /*  96 */ 3, /*  97 */ 3, /*  98 */ 4, /*  99 */
+  3, /* 100 */ 4, /* 101 */ 4, /* 102 */ 5, /* 103 */ 3, /* 104 */
+  4, /* 105 */ 4, /* 106 */ 5, /* 107 */ 4, /* 108 */ 5, /* 109 */
+  5, /* 110 */ 6, /* 111 */ 3, /* 112 */ 4, /* 113 */ 4, /* 114 */
+  5, /* 115 */ 4, /* 116 */ 5, /* 117 */ 5, /* 118 */ 6, /* 119 */
+  4, /* 120 */ 5, /* 121 */ 5, /* 122 */ 6, /* 123 */ 5, /* 124 */
+  6, /* 125 */ 6, /* 126 */ 7, /* 127 */ 1, /* 128 */ 2, /* 129 */
+  2, /* 130 */ 3, /* 131 */ 2, /* 132 */ 3, /* 133 */ 3, /* 134 */
+  4, /* 135 */ 2, /* 136 */ 3, /* 137 */ 3, /* 138 */ 4, /* 139 */
+  3, /* 140 */ 4, /* 141 */ 4, /* 142 */ 5, /* 143 */ 2, /* 144 */
+  3, /* 145 */ 3, /* 146 */ 4, /* 147 */ 3, /* 148 */ 4, /* 149 */
+  4, /* 150 */ 5, /* 151 */ 3, /* 152 */ 4, /* 153 */ 4, /* 154 */
+  5, /* 155 */ 4, /* 156 */ 5, /* 157 */ 5, /* 158 */ 6, /* 159 */
+  2, /* 160 */ 3, /* 161 */ 3, /* 162 */ 4, /* 163 */ 3, /* 164 */
+  4, /* 165 */ 4, /* 166 */ 5, /* 167 */ 3, /* 168 */ 4, /* 169 */
+  4, /* 170 */ 5, /* 171 */ 4, /* 172 */ 5, /* 173 */ 5, /* 174 */
+  6, /* 175 */ 3, /* 176 */ 4, /* 177 */ 4, /* 178 */ 5, /* 179 */
+  4, /* 180 */ 5, /* 181 */ 5, /* 182 */ 6, /* 183 */ 4, /* 184 */
+  5, /* 185 */ 5, /* 186 */ 6, /* 187 */ 5, /* 188 */ 6, /* 189 */
+  6, /* 190 */ 7, /* 191 */ 2, /* 192 */ 3, /* 193 */ 3, /* 194 */
+  4, /* 195 */ 3, /* 196 */ 4, /* 197 */ 4, /* 198 */ 5, /* 199 */
+  3, /* 200 */ 4, /* 201 */ 4, /* 202 */ 5, /* 203 */ 4, /* 204 */
+  5, /* 205 */ 5, /* 206 */ 6, /* 207 */ 3, /* 208 */ 4, /* 209 */
+  4, /* 210 */ 5, /* 211 */ 4, /* 212 */ 5, /* 213 */ 5, /* 214 */
+  6, /* 215 */ 4, /* 216 */ 5, /* 217 */ 5, /* 218 */ 6, /* 219 */
+  5, /* 220 */ 6, /* 221 */ 6, /* 222 */ 7, /* 223 */ 3, /* 224 */
+  4, /* 225 */ 4, /* 226 */ 5, /* 227 */ 4, /* 228 */ 5, /* 229 */
+  5, /* 230 */ 6, /* 231 */ 4, /* 232 */ 5, /* 233 */ 5, /* 234 */
+  6, /* 235 */ 5, /* 236 */ 6, /* 237 */ 6, /* 238 */ 7, /* 239 */
+  4, /* 240 */ 5, /* 241 */ 5, /* 242 */ 6, /* 243 */ 5, /* 244 */
+  6, /* 245 */ 6, /* 246 */ 7, /* 247 */ 5, /* 248 */ 6, /* 249 */
+  6, /* 250 */ 7, /* 251 */ 6, /* 252 */ 7, /* 253 */ 7, /* 254 */
+  8  /* 255 */
+  };
+
+  size_t __result(0);
+  while ( __first < __last ) {
+    __result += _bit_count[*(__first++)];
+  }
+  return __result;
+}
+
+unsigned char _Bs_G::_S_first_one(unsigned char __byte)
+{
+  static const unsigned char _first_one[256] = {
+  0, /*   0 */ 0, /*   1 */ 1, /*   2 */ 0, /*   3 */ 2, /*   4 */
+  0, /*   5 */ 1, /*   6 */ 0, /*   7 */ 3, /*   8 */ 0, /*   9 */
+  1, /*  10 */ 0, /*  11 */ 2, /*  12 */ 0, /*  13 */ 1, /*  14 */
+  0, /*  15 */ 4, /*  16 */ 0, /*  17 */ 1, /*  18 */ 0, /*  19 */
+  2, /*  20 */ 0, /*  21 */ 1, /*  22 */ 0, /*  23 */ 3, /*  24 */
+  0, /*  25 */ 1, /*  26 */ 0, /*  27 */ 2, /*  28 */ 0, /*  29 */
+  1, /*  30 */ 0, /*  31 */ 5, /*  32 */ 0, /*  33 */ 1, /*  34 */
+  0, /*  35 */ 2, /*  36 */ 0, /*  37 */ 1, /*  38 */ 0, /*  39 */
+  3, /*  40 */ 0, /*  41 */ 1, /*  42 */ 0, /*  43 */ 2, /*  44 */
+  0, /*  45 */ 1, /*  46 */ 0, /*  47 */ 4, /*  48 */ 0, /*  49 */
+  1, /*  50 */ 0, /*  51 */ 2, /*  52 */ 0, /*  53 */ 1, /*  54 */
+  0, /*  55 */ 3, /*  56 */ 0, /*  57 */ 1, /*  58 */ 0, /*  59 */
+  2, /*  60 */ 0, /*  61 */ 1, /*  62 */ 0, /*  63 */ 6, /*  64 */
+  0, /*  65 */ 1, /*  66 */ 0, /*  67 */ 2, /*  68 */ 0, /*  69 */
+  1, /*  70 */ 0, /*  71 */ 3, /*  72 */ 0, /*  73 */ 1, /*  74 */
+  0, /*  75 */ 2, /*  76 */ 0, /*  77 */ 1, /*  78 */ 0, /*  79 */
+  4, /*  80 */ 0, /*  81 */ 1, /*  82 */ 0, /*  83 */ 2, /*  84 */
+  0, /*  85 */ 1, /*  86 */ 0, /*  87 */ 3, /*  88 */ 0, /*  89 */
+  1, /*  90 */ 0, /*  91 */ 2, /*  92 */ 0, /*  93 */ 1, /*  94 */
+  0, /*  95 */ 5, /*  96 */ 0, /*  97 */ 1, /*  98 */ 0, /*  99 */
+  2, /* 100 */ 0, /* 101 */ 1, /* 102 */ 0, /* 103 */ 3, /* 104 */
+  0, /* 105 */ 1, /* 106 */ 0, /* 107 */ 2, /* 108 */ 0, /* 109 */
+  1, /* 110 */ 0, /* 111 */ 4, /* 112 */ 0, /* 113 */ 1, /* 114 */
+  0, /* 115 */ 2, /* 116 */ 0, /* 117 */ 1, /* 118 */ 0, /* 119 */
+  3, /* 120 */ 0, /* 121 */ 1, /* 122 */ 0, /* 123 */ 2, /* 124 */
+  0, /* 125 */ 1, /* 126 */ 0, /* 127 */ 7, /* 128 */ 0, /* 129 */
+  1, /* 130 */ 0, /* 131 */ 2, /* 132 */ 0, /* 133 */ 1, /* 134 */
+  0, /* 135 */ 3, /* 136 */ 0, /* 137 */ 1, /* 138 */ 0, /* 139 */
+  2, /* 140 */ 0, /* 141 */ 1, /* 142 */ 0, /* 143 */ 4, /* 144 */
+  0, /* 145 */ 1, /* 146 */ 0, /* 147 */ 2, /* 148 */ 0, /* 149 */
+  1, /* 150 */ 0, /* 151 */ 3, /* 152 */ 0, /* 153 */ 1, /* 154 */
+  0, /* 155 */ 2, /* 156 */ 0, /* 157 */ 1, /* 158 */ 0, /* 159 */
+  5, /* 160 */ 0, /* 161 */ 1, /* 162 */ 0, /* 163 */ 2, /* 164 */
+  0, /* 165 */ 1, /* 166 */ 0, /* 167 */ 3, /* 168 */ 0, /* 169 */
+  1, /* 170 */ 0, /* 171 */ 2, /* 172 */ 0, /* 173 */ 1, /* 174 */
+  0, /* 175 */ 4, /* 176 */ 0, /* 177 */ 1, /* 178 */ 0, /* 179 */
+  2, /* 180 */ 0, /* 181 */ 1, /* 182 */ 0, /* 183 */ 3, /* 184 */
+  0, /* 185 */ 1, /* 186 */ 0, /* 187 */ 2, /* 188 */ 0, /* 189 */
+  1, /* 190 */ 0, /* 191 */ 6, /* 192 */ 0, /* 193 */ 1, /* 194 */
+  0, /* 195 */ 2, /* 196 */ 0, /* 197 */ 1, /* 198 */ 0, /* 199 */
+  3, /* 200 */ 0, /* 201 */ 1, /* 202 */ 0, /* 203 */ 2, /* 204 */
+  0, /* 205 */ 1, /* 206 */ 0, /* 207 */ 4, /* 208 */ 0, /* 209 */
+  1, /* 210 */ 0, /* 211 */ 2, /* 212 */ 0, /* 213 */ 1, /* 214 */
+  0, /* 215 */ 3, /* 216 */ 0, /* 217 */ 1, /* 218 */ 0, /* 219 */
+  2, /* 220 */ 0, /* 221 */ 1, /* 222 */ 0, /* 223 */ 5, /* 224 */
+  0, /* 225 */ 1, /* 226 */ 0, /* 227 */ 2, /* 228 */ 0, /* 229 */
+  1, /* 230 */ 0, /* 231 */ 3, /* 232 */ 0, /* 233 */ 1, /* 234 */
+  0, /* 235 */ 2, /* 236 */ 0, /* 237 */ 1, /* 238 */ 0, /* 239 */
+  4, /* 240 */ 0, /* 241 */ 1, /* 242 */ 0, /* 243 */ 2, /* 244 */
+  0, /* 245 */ 1, /* 246 */ 0, /* 247 */ 3, /* 248 */ 0, /* 249 */
+  1, /* 250 */ 0, /* 251 */ 2, /* 252 */ 0, /* 253 */ 1, /* 254 */
+  0, /* 255 */
+  };
+  return _first_one[__byte];
+}
+
+_STLP_MOVE_TO_STD_NAMESPACE
+
+_STLP_END_NAMESPACE
diff --git a/src/third_party/mozjs-45/build/stlport/src/c_locale.c b/src/third_party/mozjs-45/build/stlport/src/c_locale.c
new file mode 100644
index 0000000..376e22e
--- /dev/null
+++ b/src/third_party/mozjs-45/build/stlport/src/c_locale.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 1999
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Copyright (c) 1999
+ * Boris Fomitchev
+ *
+ * This material is provided "as is", with absolutely no warranty expressed
+ * or implied. Any use is at your own risk.
+ *
+ * Permission to use or copy this software for any purpose is hereby granted
+ * without fee, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ *
+ */
+
+#include "stlport_prefix.h"
+
+#include "c_locale.h"
+
+#if defined (_STLP_WIN32) && !defined (_STLP_WCE)
+#  include "c_locale_win32/c_locale_win32.c"
+#elif defined (_STLP_USE_GLIBC2_LOCALIZATION)
+#  include "c_locale_glibc/c_locale_glibc2.c" /* glibc 2.2 and newer */
+#else
+#  include "c_locale_dummy/c_locale_dummy.c"
+#endif
diff --git a/src/third_party/mozjs-45/build/stlport/src/c_locale.h b/src/third_party/mozjs-45/build/stlport/src/c_locale.h
new file mode 100644
index 0000000..36d9961
--- /dev/null
+++ b/src/third_party/mozjs-45/build/stlport/src/c_locale.h
@@ -0,0 +1,450 @@
+/*
+ * Copyright (c) 1999
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Copyright (c) 1999
+ * Boris Fomitchev
+ *
+ * This material is provided "as is", with absolutely no warranty expressed
+ * or implied. Any use is at your own risk.
+ *
+ * Permission to use or copy this software for any purpose is hereby granted
+ * without fee, provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ *
+ */
+
+/*
+ * It is impossible to write the C++ locale library in terms of locales
+ * as defined in the C standard.  Instead, we write the C++ locale and I/O
+ * library in terms of a low level C-like interface.  This file defines
+ * that interface.
+ *
+ * The low-level locale interface can't be written portably; there
+ * must be a version of it for each platform that the C++ library
+ * is ported to.  On many systems this interface may be a thin wrapper
+ * for existing functionality.
+ */
+
+#ifndef _STLP_C_LOCALE_IMPL_H
+#define _STLP_C_LOCALE_IMPL_H
+
+#include "stlport_prefix.h"
+
+#include <wchar.h> /* for mbstate_t */
+#include <stl/c_locale.h>
+
+struct _Locale_name_hint;
+
+#if defined (_GNU_SOURCE) && defined (__GLIBC__) && \
+    ((__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2))
+#  define _STLP_USE_GLIBC2_LOCALIZATION
+#  include <nl_types.h>
+typedef nl_catd nl_catd_type;
+#else
+typedef int nl_catd_type;
+#endif
+
+/*
+ * A number: the maximum length of a simple locale name.
+ * (i.e. a name like like en_US, as opposed to a name like
+ * en_US/de_AT/de_AT/es_MX/en_US/en_US) */
+#define _Locale_MAX_SIMPLE_NAME 256
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Typedefs:
+ */
+typedef unsigned short int _Locale_mask_t;
+
+/* Function called during STLport library load phase. Might contain any
+ * code necessary to the platform localization layer.
+ */
+void _Locale_init(void);
+
+/* Function called during STLport library unload. Might contain any
+ * code necessary to the platform localization layer.
+ */
+void _Locale_final(void);
+
+/* Create a category of the locale with the given name.
+ *
+ * The char* argument is a simple (not a composite) locale name, which may
+ * neither be an empty string nor a null pointer.
+ *
+ * These functions return NULL to indicate failure. Failure reason should be reported
+ * using the __err_code pointer.
+ */
+struct _Locale_ctype* _Locale_ctype_create(const char *, struct _Locale_name_hint*, int * /* __err_code */);
+struct _Locale_codecvt* _Locale_codecvt_create(const char *, struct _Locale_name_hint*, int * /* __err_code */);
+struct _Locale_numeric* _Locale_numeric_create(const char *, struct _Locale_name_hint*, int * /* __err_code */);
+struct _Locale_time* _Locale_time_create(const char *, struct _Locale_name_hint*, int * /* __err_code */);
+struct _Locale_collate* _Locale_collate_create(const char *, struct _Locale_name_hint*, int * /* __err_code */);
+struct _Locale_monetary* _Locale_monetary_create(const char *, struct _Locale_name_hint*, int * /* __err_code */);
+struct _Locale_messages* _Locale_messages_create(const char *, struct _Locale_name_hint*, int * /* __err_code */);
+
+/* Give error reason on failure of one of the _Locale_*_create functions. Available
+ * reasons are:
+ * 0: No specific error reason has been reported.
+ * 1: No platform support for the given facet.
+ * 2: Unknown locale name
+ * 3: No platform API for localization support.
+ * 4: No more memory
+ */
+#define _STLP_LOC_UNDEFINED 0
+#define _STLP_LOC_UNSUPPORTED_FACET_CATEGORY 1
+#define _STLP_LOC_UNKNOWN_NAME 2
+#define _STLP_LOC_NO_PLATFORM_SUPPORT 3
+#define _STLP_LOC_NO_MEMORY 4
+
+/* Release a category of a locale
+ *
+ * These functions are used to release a category acquired with the
+ * according _Locale_*_create() functions.
+ */
+void _Locale_ctype_destroy(struct _Locale_ctype *);
+void _Locale_codecvt_destroy(struct _Locale_codecvt *);
+void _Locale_numeric_destroy(struct _Locale_numeric *);
+void _Locale_time_destroy(struct _Locale_time *);
+void _Locale_collate_destroy(struct _Locale_collate *);
+void _Locale_monetary_destroy(struct _Locale_monetary *);
+void _Locale_messages_destroy(struct _Locale_messages *);
+
+/*
+ * Returns the name of the user's default locale in each
+ * cat