aboutsummaryrefslogtreecommitdiff
path: root/lang/spidermonkey185
diff options
context:
space:
mode:
authorAntoine Brodin <antoine@FreeBSD.org>2021-01-01 10:11:34 +0000
committerAntoine Brodin <antoine@FreeBSD.org>2021-01-01 10:11:34 +0000
commit26b4c8f71f91d22e081b27814782686edde0c90a (patch)
tree1c321c39372c25d8634e75b5c8e08edc676b296d /lang/spidermonkey185
parent548f16bd1a2915f08878b716eed92ff3267e6de2 (diff)
downloadports-26b4c8f71f91d22e081b27814782686edde0c90a.tar.gz
ports-26b4c8f71f91d22e081b27814782686edde0c90a.zip
Revert r559792 to unbreak INDEX and bulk -a
It seems a lot of reverse dependencies were missed With hat: portmgr
Notes
Notes: svn path=/head/; revision=559822
Diffstat (limited to 'lang/spidermonkey185')
-rw-r--r--lang/spidermonkey185/Makefile127
-rw-r--r--lang/spidermonkey185/distinfo2
-rw-r--r--lang/spidermonkey185/files/patch-assembler_jit_ExecutableAllocator.h14
-rw-r--r--lang/spidermonkey185/files/patch-assembler_wtf_Platform.h18
-rw-r--r--lang/spidermonkey185/files/patch-bug7712811839
-rw-r--r--lang/spidermonkey185/files/patch-c++11247
-rw-r--r--lang/spidermonkey185/files/patch-configure.in36
-rw-r--r--lang/spidermonkey185/files/patch-jsscript.h48
-rw-r--r--lang/spidermonkey185/files/patch-jsstr.cpp36
-rw-r--r--lang/spidermonkey185/files/patch-nanojit_CodeAlloc.cpp10
-rw-r--r--lang/spidermonkey185/files/patch-nanojit_njcpudetect.h11
-rw-r--r--lang/spidermonkey185/pkg-descr3
-rw-r--r--lang/spidermonkey185/pkg-plist106
13 files changed, 2497 insertions, 0 deletions
diff --git a/lang/spidermonkey185/Makefile b/lang/spidermonkey185/Makefile
new file mode 100644
index 000000000000..263096f3e96d
--- /dev/null
+++ b/lang/spidermonkey185/Makefile
@@ -0,0 +1,127 @@
+# Created by: Kubilay Kocak <koobs@FreeBSD.org>
+# $FreeBSD$
+
+PORTNAME= spidermonkey185
+PORTVERSION= 1.8.5
+PORTREVISION= 5
+CATEGORIES= lang
+MASTER_SITES= MOZILLA/js
+DISTNAME= js185-1.0.0
+
+MAINTAINER= koobs@FreeBSD.org
+COMMENT= Standalone JavaScript (1.8.5) interpreter from Mozilla
+
+BUILD_DEPENDS= zip:archivers/zip \
+ autoconf-2.13:devel/autoconf213
+LIB_DEPENDS= libnspr4.so:devel/nspr
+
+USES= gmake pathfix perl5 pkgconfig python:2.7,build
+GNU_CONFIGURE= yes
+USE_LDCONFIG= yes
+USE_PERL5= build
+
+WRKSRC= ${WRKDIR}/js-${PORTVERSION}/js/src
+
+BROKEN_aarch64= Does not compile: error: cacheFlush support is missing on this platform
+BROKEN_mips64= Does not compile: error: const union jsval_layout has no member named word
+BROKEN_sparc64= Does not build: fails to link
+
+NOT_FOR_ARCHS= powerpc powerpc64
+NOT_FOR_ARCHS_REASON= PowerPC is not supported
+
+CONFIGURE_ARGS= --with-pthreads \
+ --with-system-nspr
+
+# This comes from bsd.gecko.mk, fixes linking issues on 9.0 and higher.
+post-configure:
+ ${ECHO_CMD} "fenv.h" >> ${WRKSRC}/config/system-headers
+ ${ECHO_CMD} "pthread_np.h" >> ${WRKSRC}/config/system-headers
+
+OPTIONS_DEFINE= DEBUG GCZEAL JEMALLOC METHODJIT OPTIMIZE READLINE \
+ THREADSAFE TRACEJIT UTF8 \
+
+OPTIONS_DEFAULT= METHODJIT OPTIMIZE READLINE THREADSAFE TRACEJIT
+
+GCZEAL_DESC= Enable Zealous garbage collecting
+JEMALLOC_DESC= Use jemalloc as memory allocator
+METHODJIT_DESC= Enable method JIT support
+OPTIMIZE_DESC= Enable compiler optimizations
+READLINE_DESC= Link js shell to system readline library
+THREADSAFE_DESC= Enable multiple thread support
+TRACEJIT_DESC= Enable tracing JIT support
+UTF8_DESC= Treat strings as UTF8 instead of ISO-8859-1
+
+DEBUG_CONFIGURE_ENABLE= debug
+DEBUG_CONFIGURE_ON= --enable-debug-sumbols
+GCZEAL_CONFIGURE_ENABLE= gczeal
+JEMALLOC_CONFIGURE_ENABLE= jemalloc
+METHODJIT_CONFIGURE_ENABLE= methodjit
+OPTIMIZE_CONFIGURE_ENABLE= optimize
+READLINE_CONFIGURE_ENABLE= readline
+READLINE_USES= readline
+THREADSAFE_CONFIGURE_ENABLE= threadsafe
+TRACEJIT_CONFIGURE_ENABLE= tracejit
+UTF8_CFLAGS= -DJS_C_STRINGS_ARE_UTF8
+
+.include <bsd.port.options.mk>
+
+.if ${ARCH} == amd64
+CONFIGURE_TARGET= x86_64-portbld-freebsd${OSREL}
+.endif
+
+.if ${ARCH} == "amd64"
+PLIST_SUB+= AMD64=""
+.else
+PLIST_SUB+= AMD64="@comment "
+.endif
+
+.if ${ARCH} == "i386"
+PLIST_SUB+= I386=""
+.else
+PLIST_SUB+= I386="@comment "
+.endif
+
+.if ${ARCH} == "arm"
+PLIST_SUB+= ARM=""
+.else
+PLIST_SUB+= ARM="@comment "
+.endif
+
+.if ${ARCH} == "mips"
+PLIST_SUB+= MIPS=""
+.else
+PLIST_SUB+= MIPS="@comment "
+.endif
+
+.if ${ARCH} == "powerpc" || ${ARCH} == "powerpc64"
+PLIST_SUB+= PPC=""
+.else
+PLIST_SUB+= PPC="@comment "
+.endif
+
+.if ${ARCH} == "sparc64"
+PLIST_SUB+= SPARC=""
+.else
+PLIST_SUB+= SPARC="@comment "
+.endif
+
+pre-configure:
+ (cd ${WRKSRC} && ${LOCALBASE}/bin/autoconf-2.13)
+
+do-test:
+ @${ECHO_MSG} -n "===> Running jstests.py: "
+ @cd ${WRKSRC} && ${SETENV} TZ=PST8PDT ${PYTHON_CMD} tests/jstests.py \
+ --no-progress --worker-count=${MAKE_JOBS_NUMBER} ./js
+.if ${PORT_OPTIONS:MMETHODJIT} || ${PORT_OPTIONS:MTRACEJIT}
+ @${ECHO_MSG} -n "===> Running jit_test.py: "
+ @cd ${WRKSRC} && ${SETENV} TZ=PST8PDT ${PYTHON_CMD} jit-test/jit_test.py \
+ --no-progress --jitflags=,m,j,mj,mjp,am,amj,amjp,amd ./js
+.endif
+
+post-install:
+ ${LN} -sf libmozjs185.so.1.0.0 ${STAGEDIR}${PREFIX}/lib/libmozjs185.so
+ ${LN} -sf libmozjs185.so.1.0.0 ${STAGEDIR}${PREFIX}/lib/libmozjs185.so.1
+ ${LN} -sf libmozjs185.so.1.0.0 ${STAGEDIR}${PREFIX}/lib/libmozjs185.so.1.0
+ @${STRIP_CMD} ${STAGEDIR}${PREFIX}/lib/libmozjs185.so.1.0.0
+
+.include <bsd.port.mk>
diff --git a/lang/spidermonkey185/distinfo b/lang/spidermonkey185/distinfo
new file mode 100644
index 000000000000..ac820e9f43a3
--- /dev/null
+++ b/lang/spidermonkey185/distinfo
@@ -0,0 +1,2 @@
+SHA256 (js185-1.0.0.tar.gz) = 5d12f7e1f5b4a99436685d97b9b7b75f094d33580227aa998c406bbae6f2a687
+SIZE (js185-1.0.0.tar.gz) = 6164605
diff --git a/lang/spidermonkey185/files/patch-assembler_jit_ExecutableAllocator.h b/lang/spidermonkey185/files/patch-assembler_jit_ExecutableAllocator.h
new file mode 100644
index 000000000000..94770e435051
--- /dev/null
+++ b/lang/spidermonkey185/files/patch-assembler_jit_ExecutableAllocator.h
@@ -0,0 +1,14 @@
+--- assembler/jit/ExecutableAllocator.h.orig 2016-09-07 UTC
++++ assembler/jit/ExecutableAllocator.h
+@@ -391,6 +391,11 @@ public:
+ {
+ CacheRangeFlush(code, size, CACHE_SYNC_ALL);
+ }
++#elif WTF_CPU_ARM_TRADITIONAL && WTF_PLATFORM_FREEBSD
++ static void cacheFlush(void* code, size_t size)
++ {
++ __clear_cache(code, reinterpret_cast<char*>(code) + size);
++ }
+ #else
+ #error "The cacheFlush support is missing on this platform."
+ #endif
diff --git a/lang/spidermonkey185/files/patch-assembler_wtf_Platform.h b/lang/spidermonkey185/files/patch-assembler_wtf_Platform.h
new file mode 100644
index 000000000000..9556c0f7e638
--- /dev/null
+++ b/lang/spidermonkey185/files/patch-assembler_wtf_Platform.h
@@ -0,0 +1,18 @@
+--- ./assembler/wtf/Platform.h.orig 2016-09-07 UTC
++++ ./assembler/wtf/Platform.h
+@@ -213,6 +213,7 @@
+ #elif defined(__ARM_ARCH_6__) \
+ || defined(__ARM_ARCH_6J__) \
+ || defined(__ARM_ARCH_6K__) \
++ || defined(__ARM_ARCH_6KZ__) \
+ || defined(__ARM_ARCH_6Z__) \
+ || defined(__ARM_ARCH_6ZK__) \
+ || defined(__ARM_ARCH_6T2__) \
+@@ -243,6 +244,7 @@
+
+ #elif defined(__ARM_ARCH_6J__) \
+ || defined(__ARM_ARCH_6K__) \
++ || defined(__ARM_ARCH_6KZ__) \
+ || defined(__ARM_ARCH_6Z__) \
+ || defined(__ARM_ARCH_6ZK__) \
+ || defined(__ARM_ARCH_6M__)
diff --git a/lang/spidermonkey185/files/patch-bug771281 b/lang/spidermonkey185/files/patch-bug771281
new file mode 100644
index 000000000000..1b59e5dfeafb
--- /dev/null
+++ b/lang/spidermonkey185/files/patch-bug771281
@@ -0,0 +1,1839 @@
+diff -ruN src/shell/Makefile.in src.new/shell/Makefile.in
+--- shell/Makefile.in 2011-04-01 06:08:36.000000000 +1100
++++ shell/Makefile.in 2013-03-23 22:01:26.876752286 +1100
+@@ -47,7 +47,6 @@
+ PROGRAM = js$(BIN_SUFFIX)
+ CPPSRCS = \
+ js.cpp \
+- jsworkers.cpp \
+ $(NULL)
+
+ DEFINES += -DEXPORT_JS_API
+diff -ruN src/shell/js.cpp src.new/shell/js.cpp
+--- shell/js.cpp 2011-04-01 06:08:36.000000000 +1100
++++ shell/js.cpp 2013-03-23 22:02:46.436700725 +1100
+@@ -91,8 +91,6 @@
+ #endif /* JSDEBUGGER_C_UI */
+ #endif /* JSDEBUGGER */
+
+-#include "jsworkers.h"
+-
+ #include "jsinterpinlines.h"
+ #include "jsobjinlines.h"
+ #include "jsscriptinlines.h"
+@@ -194,10 +192,6 @@
+ JSBool gQuitting = JS_FALSE;
+ FILE *gErrFile = NULL;
+ FILE *gOutFile = NULL;
+-#ifdef JS_THREADSAFE
+-JSObject *gWorkers = NULL;
+-js::workers::ThreadPool *gWorkerThreadPool = NULL;
+-#endif
+
+ static JSBool reportWarnings = JS_TRUE;
+ static JSBool compileOnly = JS_FALSE;
+@@ -1315,10 +1309,6 @@
+ JS_ConvertArguments(cx, argc, JS_ARGV(cx, vp), "/ i", &gExitCode);
+
+ gQuitting = JS_TRUE;
+-#ifdef JS_THREADSAFE
+- if (gWorkerThreadPool)
+- js::workers::terminateAll(JS_GetRuntime(cx), gWorkerThreadPool);
+-#endif
+ return JS_FALSE;
+ }
+
+@@ -4150,10 +4140,6 @@
+ gCanceled = true;
+ if (gExitCode == 0)
+ gExitCode = EXITCODE_TIMEOUT;
+-#ifdef JS_THREADSAFE
+- if (gWorkerThreadPool)
+- js::workers::terminateAll(rt, gWorkerThreadPool);
+-#endif
+ JS_TriggerAllOperationCallbacks(rt);
+
+ static const char msg[] = "Script runs for too long, terminating.\n";
+@@ -5681,29 +5667,8 @@
+ #endif /* JSDEBUGGER_C_UI */
+ #endif /* JSDEBUGGER */
+
+-#ifdef JS_THREADSAFE
+- class ShellWorkerHooks : public js::workers::WorkerHooks {
+- public:
+- JSObject *newGlobalObject(JSContext *cx) {
+- return NewGlobalObject(cx, NEW_COMPARTMENT);
+- }
+- };
+- ShellWorkerHooks hooks;
+- if (!JS_AddNamedObjectRoot(cx, &gWorkers, "Workers") ||
+- (gWorkerThreadPool = js::workers::init(cx, &hooks, glob, &gWorkers)) == NULL) {
+- return 1;
+- }
+-#endif
+-
+ int result = ProcessArgs(cx, glob, argv, argc);
+
+-#ifdef JS_THREADSAFE
+- js::workers::finish(cx, gWorkerThreadPool);
+- JS_RemoveObjectRoot(cx, &gWorkers);
+- if (result == 0)
+- result = gExitCode;
+-#endif
+-
+ #ifdef JSDEBUGGER
+ if (jsdc) {
+ #ifdef JSDEBUGGER_C_UI
+diff -ruN src/shell/jsworkers.cpp src.new/shell/jsworkers.cpp
+--- shell/jsworkers.cpp 2011-04-01 06:08:36.000000000 +1100
++++ shell/jsworkers.cpp 1970-01-01 10:00:00.000000000 +1000
+@@ -1,1280 +0,0 @@
+-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+- * vim: set ts=8 sw=4 et tw=99:
+- *
+- * ***** BEGIN LICENSE BLOCK *****
+- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+- *
+- * The contents of this file are subject to the Mozilla Public License Version
+- * 1.1 (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.mozilla.org/MPL/
+- *
+- * Software distributed under the License is distributed on an "AS IS" basis,
+- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+- * for the specific language governing rights and limitations under the
+- * License.
+- *
+- * The Original Code is JavaScript shell workers.
+- *
+- * The Initial Developer of the Original Code is
+- * Mozilla Corporation.
+- * Portions created by the Initial Developer are Copyright (C) 2010
+- * the Initial Developer. All Rights Reserved.
+- *
+- * Contributor(s):
+- * Jason Orendorff <jorendorff@mozilla.com>
+- *
+- * Alternatively, the contents of this file may be used under the terms of
+- * either of the GNU General Public License Version 2 or later (the "GPL"),
+- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+- * in which case the provisions of the GPL or the LGPL are applicable instead
+- * of those above. If you wish to allow use of your version of this file only
+- * under the terms of either the GPL or the LGPL, and not to allow others to
+- * use your version of this file under the terms of the MPL, indicate your
+- * decision by deleting the provisions above and replace them with the notice
+- * and other provisions required by the GPL or the LGPL. If you do not delete
+- * the provisions above, a recipient may use your version of this file under
+- * the terms of any one of the MPL, the GPL or the LGPL.
+- *
+- * ***** END LICENSE BLOCK ***** */
+-
+-#ifdef JS_THREADSAFE
+-
+-#include <algorithm>
+-#include <string.h>
+-#include "prthread.h"
+-#include "prlock.h"
+-#include "prcvar.h"
+-#include "jsapi.h"
+-#include "jscntxt.h"
+-#include "jshashtable.h"
+-#include "jsstdint.h"
+-#include "jslock.h"
+-#include "jsvector.h"
+-#include "jsworkers.h"
+-
+-extern size_t gMaxStackSize;
+-
+-/*
+- * JavaScript shell workers.
+- *
+- * == Object lifetime rules ==
+- *
+- * - The ThreadPool lasts from init() to finish().
+- *
+- * - The ThreadPool owns the MainQueue and the WorkerQueue. Those live from
+- * the time the first Worker is created until finish().
+- *
+- * - Each JS Worker object has the same lifetime as the corresponding C++
+- * Worker object. A Worker is live if (a) the Worker JSObject is still
+- * live; (b) the Worker has an incoming event pending or running; (c) it
+- * has sent an outgoing event to its parent that is still pending; or (d)
+- * it has any live child Workers.
+- *
+- * - finish() continues to wait for events until all threads are idle.
+- *
+- * Event objects, however, are basically C++-only. The JS Event objects are
+- * just plain old JSObjects. They don't keep anything alive.
+- *
+- * == Locking scheme ==
+- *
+- * When mixing mutexes and the JSAPI request model, there are two choices:
+- *
+- * - Always nest the mutexes in requests. Since threads in requests are not
+- * supposed to block, this means the mutexes must be only briefly held.
+- *
+- * - Never nest the mutexes in requests. Since this allows threads to race
+- * with the GC, trace() methods must go through the mutexes just like
+- * everyone else.
+- *
+- * This code uses the latter approach for all locks.
+- *
+- * In one case, a thread holding a Worker's mutex can acquire the mutex of one
+- * of its child Workers. See Worker::terminateSelf. (This can't deadlock because
+- * the parent-child relationship is a partial order.)
+- */
+-
+-namespace js {
+-namespace workers {
+-
+-template <class T, class AllocPolicy>
+-class Queue {
+- private:
+- typedef Vector<T, 4, AllocPolicy> Vec;
+- Vec v1;
+- Vec v2;
+- Vec *front;
+- Vec *back;
+-
+- // Queue is not copyable.
+- Queue(const Queue &);
+- Queue & operator=(const Queue &);
+-
+- public:
+- Queue() : front(&v1), back(&v2) {}
+- bool push(T t) { return back->append(t); }
+- bool empty() { return front->empty() && back->empty(); }
+-
+- T pop() {
+- if (front->empty()) {
+- std::reverse(back->begin(), back->end());
+- Vec *tmp = front;
+- front = back;
+- back = tmp;
+- }
+- T item = front->back();
+- front->popBack();
+- return item;
+- }
+-
+- void clear() {
+- v1.clear();
+- v2.clear();
+- }
+-
+- void trace(JSTracer *trc) {
+- for (T *p = v1.begin(); p != v1.end(); p++)
+- (*p)->trace(trc);
+- for (T *p = v2.begin(); p != v2.end(); p++)
+- (*p)->trace(trc);
+- }
+-};
+-
+-class Event;
+-class ThreadPool;
+-class Worker;
+-
+-class WorkerParent {
+- protected:
+- typedef HashSet<Worker *, DefaultHasher<Worker *>, SystemAllocPolicy> ChildSet;
+- ChildSet children;
+-
+- bool initWorkerParent() { return children.init(8); }
+-
+- public:
+- virtual JSLock *getLock() = 0;
+- virtual ThreadPool *getThreadPool() = 0;
+- virtual bool post(Event *item) = 0; // false on OOM or queue closed
+- virtual void trace(JSTracer *trc) = 0;
+-
+- bool addChild(Worker *w) {
+- AutoLock hold(getLock());
+- return children.put(w) != NULL;
+- }
+-
+- // This must be called only from GC or when all threads are shut down. It
+- // does not bother with locking.
+- void removeChild(Worker *w) {
+- ChildSet::Ptr p = children.lookup(w);
+- JS_ASSERT(p);
+- children.remove(p);
+- }
+-
+- void disposeChildren();
+-};
+-
+-template <class T>
+-class ThreadSafeQueue
+-{
+- protected:
+- Queue<T, SystemAllocPolicy> queue;
+- JSLock *lock;
+- PRCondVar *condvar;
+- bool closed;
+-
+- private:
+- Vector<T, 8, SystemAllocPolicy> busy;
+-
+- protected:
+- ThreadSafeQueue() : lock(NULL), condvar(NULL), closed(false) {}
+-
+- ~ThreadSafeQueue() {
+- if (condvar)
+- JS_DESTROY_CONDVAR(condvar);
+- if (lock)
+- JS_DESTROY_LOCK(lock);
+- }
+-
+- // Called by take() with the lock held.
+- virtual bool shouldStop() { return closed; }
+-
+- public:
+- bool initThreadSafeQueue() {
+- JS_ASSERT(!lock);
+- JS_ASSERT(!condvar);
+- return (lock = JS_NEW_LOCK()) && (condvar = JS_NEW_CONDVAR(lock));
+- }
+-
+- bool post(T t) {
+- AutoLock hold(lock);
+- if (closed)
+- return false;
+- if (queue.empty())
+- JS_NOTIFY_ALL_CONDVAR(condvar);
+- return queue.push(t);
+- }
+-
+- void close() {
+- AutoLock hold(lock);
+- closed = true;
+- queue.clear();
+- JS_NOTIFY_ALL_CONDVAR(condvar);
+- }
+-
+- // The caller must hold the lock.
+- bool take(T *t) {
+- while (queue.empty()) {
+- if (shouldStop())
+- return false;
+- JS_WAIT_CONDVAR(condvar, JS_NO_TIMEOUT);
+- }
+- *t = queue.pop();
+- busy.append(*t);
+- return true;
+- }
+-
+- // The caller must hold the lock.
+- void drop(T item) {
+- for (T *p = busy.begin(); p != busy.end(); p++) {
+- if (*p == item) {
+- *p = busy.back();
+- busy.popBack();
+- return;
+- }
+- }
+- JS_NOT_REACHED("removeBusy");
+- }
+-
+- bool lockedIsIdle() { return busy.empty() && queue.empty(); }
+-
+- bool isIdle() {
+- AutoLock hold(lock);
+- return lockedIsIdle();
+- }
+-
+- void wake() {
+- AutoLock hold(lock);
+- JS_NOTIFY_ALL_CONDVAR(condvar);
+- }
+-
+- void trace(JSTracer *trc) {
+- AutoLock hold(lock);
+- for (T *p = busy.begin(); p != busy.end(); p++)
+- (*p)->trace(trc);
+- queue.trace(trc);
+- }
+-};
+-
+-class MainQueue;
+-
+-class Event
+-{
+- protected:
+- virtual ~Event() { JS_ASSERT(!data); }
+-
+- WorkerParent *recipient;
+- Worker *child;
+- uint64 *data;
+- size_t nbytes;
+-
+- public:
+- enum Result { fail = JS_FALSE, ok = JS_TRUE, forwardToParent };
+-
+- virtual void destroy(JSContext *cx) {
+- JS_free(cx, data);
+-#ifdef DEBUG
+- data = NULL;
+-#endif
+- delete this;
+- }
+-
+- void setChildAndRecipient(Worker *aChild, WorkerParent *aRecipient) {
+- child = aChild;
+- recipient = aRecipient;
+- }
+-
+- bool deserializeData(JSContext *cx, jsval *vp) {
+- return !!JS_ReadStructuredClone(cx, data, nbytes, JS_STRUCTURED_CLONE_VERSION, vp,
+- NULL, NULL);
+- }
+-
+- virtual Result process(JSContext *cx) = 0;
+-
+- inline void trace(JSTracer *trc);
+-
+- template <class EventType>
+- static EventType *createEvent(JSContext *cx, WorkerParent *recipient, Worker *child,
+- jsval v)
+- {
+- uint64 *data;
+- size_t nbytes;
+- if (!JS_WriteStructuredClone(cx, v, &data, &nbytes, NULL, NULL))
+- return NULL;
+-
+- EventType *event = new EventType;
+- if (!event) {
+- JS_ReportOutOfMemory(cx);
+- return NULL;
+- }
+- event->recipient = recipient;
+- event->child = child;
+- event->data = data;
+- event->nbytes = nbytes;
+- return event;
+- }
+-
+- Result dispatch(JSContext *cx, JSObject *thisobj, const char *dataPropName,
+- const char *methodName, Result noHandler)
+- {
+- if (!data)
+- return fail;
+-
+- JSBool found;
+- if (!JS_HasProperty(cx, thisobj, methodName, &found))
+- return fail;
+- if (!found)
+- return noHandler;
+-
+- // Create event object.
+- jsval v;
+- if (!deserializeData(cx, &v))
+- return fail;
+- JSObject *obj = JS_NewObject(cx, NULL, NULL, NULL);
+- if (!obj || !JS_DefineProperty(cx, obj, dataPropName, v, NULL, NULL, 0))
+- return fail;
+-
+- // Call event handler.
+- jsval argv[1] = { OBJECT_TO_JSVAL(obj) };
+- jsval rval = JSVAL_VOID;
+- return Result(JS_CallFunctionName(cx, thisobj, methodName, 1, argv, &rval));
+- }
+-};
+-
+-typedef ThreadSafeQueue<Event *> EventQueue;
+-
+-class MainQueue : public EventQueue, public WorkerParent
+-{
+- private:
+- ThreadPool *threadPool;
+-
+- public:
+- explicit MainQueue(ThreadPool *tp) : threadPool(tp) {}
+-
+- ~MainQueue() {
+- JS_ASSERT(queue.empty());
+- }
+-
+- bool init() { return initThreadSafeQueue() && initWorkerParent(); }
+-
+- void destroy(JSContext *cx) {
+- while (!queue.empty())
+- queue.pop()->destroy(cx);
+- delete this;
+- }
+-
+- virtual JSLock *getLock() { return lock; }
+- virtual ThreadPool *getThreadPool() { return threadPool; }
+-
+- protected:
+- virtual bool shouldStop();
+-
+- public:
+- virtual bool post(Event *event) { return EventQueue::post(event); }
+-
+- virtual void trace(JSTracer *trc);
+-
+- void traceChildren(JSTracer *trc) { EventQueue::trace(trc); }
+-
+- JSBool mainThreadWork(JSContext *cx, bool continueOnError) {
+- JSAutoSuspendRequest suspend(cx);
+- AutoLock hold(lock);
+-
+- Event *event;
+- while (take(&event)) {
+- JS_RELEASE_LOCK(lock);
+- Event::Result result;
+- {
+- JSAutoRequest req(cx);
+- result = event->process(cx);
+- if (result == Event::forwardToParent) {
+- // FIXME - pointlessly truncates the string to 8 bits
+- jsval data;
+- JSAutoByteString bytes;
+- if (event->deserializeData(cx, &data) &&
+- JSVAL_IS_STRING(data) &&
+- bytes.encode(cx, JSVAL_TO_STRING(data))) {
+- JS_ReportError(cx, "%s", bytes.ptr());
+- } else {
+- JS_ReportOutOfMemory(cx);
+- }
+- result = Event::fail;
+- }
+- if (result == Event::fail && continueOnError) {
+- if (JS_IsExceptionPending(cx) && !JS_ReportPendingException(cx))
+- JS_ClearPendingException(cx);
+- result = Event::ok;
+- }
+- }
+- JS_ACQUIRE_LOCK(lock);
+- drop(event);
+- event->destroy(cx);
+- if (result != Event::ok)
+- return false;
+- }
+- return true;
+- }
+-};
+-
+-/*
+- * A queue of workers.
+- *
+- * We keep a queue of workers with pending events, rather than a queue of
+- * events, so that two threads won't try to run a Worker at the same time.
+- */
+-class WorkerQueue : public ThreadSafeQueue<Worker *>
+-{
+- private:
+- MainQueue *main;
+-
+- public:
+- explicit WorkerQueue(MainQueue *main) : main(main) {}
+-
+- void work();
+-};
+-
+-/* The top-level object that owns everything else. */
+-class ThreadPool
+-{
+- private:
+- enum { threadCount = 6 };
+-
+- JSObject *obj;
+- WorkerHooks *hooks;
+- MainQueue *mq;
+- WorkerQueue *wq;
+- PRThread *threads[threadCount];
+- int32_t terminating;
+-
+- static JSClass jsClass;
+-
+- static void start(void* arg) {
+- ((WorkerQueue *) arg)->work();
+- }
+-
+- explicit ThreadPool(WorkerHooks *hooks) : hooks(hooks), mq(NULL), wq(NULL), terminating(0) {
+- for (int i = 0; i < threadCount; i++)
+- threads[i] = NULL;
+- }
+-
+- public:
+- ~ThreadPool() {
+- JS_ASSERT(!mq);
+- JS_ASSERT(!wq);
+- JS_ASSERT(!threads[0]);
+- }
+-
+- static ThreadPool *create(JSContext *cx, WorkerHooks *hooks) {
+- ThreadPool *tp = new ThreadPool(hooks);
+- if (!tp) {
+- JS_ReportOutOfMemory(cx);
+- return NULL;
+- }
+-
+- JSObject *obj = JS_NewObject(cx, &jsClass, NULL, NULL);
+- if (!obj || !JS_SetPrivate(cx, obj, tp)) {
+- delete tp;
+- return NULL;
+- }
+- tp->obj = obj;
+- return tp;
+- }
+-
+- JSObject *asObject() { return obj; }
+- WorkerHooks *getHooks() { return hooks; }
+- WorkerQueue *getWorkerQueue() { return wq; }
+- MainQueue *getMainQueue() { return mq; }
+- bool isTerminating() { return terminating != 0; }
+-
+- /*
+- * Main thread only. Requires request (to prevent GC, which could see the
+- * object in an inconsistent state).
+- */
+- bool start(JSContext *cx) {
+- JS_ASSERT(!mq && !wq);
+- mq = new MainQueue(this);
+- if (!mq || !mq->init()) {
+- mq->destroy(cx);
+- mq = NULL;
+- return false;
+- }
+- wq = new WorkerQueue(mq);
+- if (!wq || !wq->initThreadSafeQueue()) {
+- delete wq;
+- wq = NULL;
+- mq->destroy(cx);
+- mq = NULL;
+- return false;
+- }
+- JSAutoSuspendRequest suspend(cx);
+- bool ok = true;
+- for (int i = 0; i < threadCount; i++) {
+- threads[i] = PR_CreateThread(PR_USER_THREAD, start, wq, PR_PRIORITY_NORMAL,
+- PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
+- if (!threads[i]) {
+- shutdown(cx);
+- ok = false;
+- break;
+- }
+- }
+- return ok;
+- }
+-
+- void terminateAll(JSRuntime *rt) {
+- // See comment about JS_ATOMIC_SET in the implementation of
+- // JS_TriggerOperationCallback.
+- JS_ATOMIC_SET(&terminating, 1);
+- JS_TriggerAllOperationCallbacks(rt);
+- }
+-
+- /* This context is used only to free memory. */
+- void shutdown(JSContext *cx) {
+- wq->close();
+- for (int i = 0; i < threadCount; i++) {
+- if (threads[i]) {
+- PR_JoinThread(threads[i]);
+- threads[i] = NULL;
+- }
+- }
+-
+- delete wq;
+- wq = NULL;
+-
+- mq->disposeChildren();
+- mq->destroy(cx);
+- mq = NULL;
+- terminating = 0;
+- }
+-
+- private:
+- static void jsTraceThreadPool(JSTracer *trc, JSObject *obj) {
+- ThreadPool *tp = unwrap(trc->context, obj);
+- if (tp->mq) {
+- tp->mq->traceChildren(trc);
+- tp->wq->trace(trc);
+- }
+- }
+-
+-
+- static void jsFinalize(JSContext *cx, JSObject *obj) {
+- if (ThreadPool *tp = unwrap(cx, obj))
+- delete tp;
+- }
+-
+- public:
+- static ThreadPool *unwrap(JSContext *cx, JSObject *obj) {
+- JS_ASSERT(JS_GET_CLASS(cx, obj) == &jsClass);
+- return (ThreadPool *) JS_GetPrivate(cx, obj);
+- }
+-};
+-
+-/*
+- * A Worker is always in one of 4 states, except when it is being initialized
+- * or destroyed, or its lock is held:
+- * - idle (!terminated && current == NULL && events.empty())
+- * - enqueued (!terminated && current == NULL && !events.empty())
+- * - busy (!terminated && current != NULL)
+- * - terminated (terminated && current == NULL && events.empty())
+- *
+- * Separately, there is a terminateFlag that other threads can set
+- * asynchronously to tell the Worker to terminate.
+- */
+-class Worker : public WorkerParent
+-{
+- private:
+- ThreadPool *threadPool;
+- WorkerParent *parent;
+- JSObject *object; // Worker object exposed to parent
+- JSContext *context;
+- JSLock *lock;
+- Queue<Event *, SystemAllocPolicy> events; // owning pointers to pending events
+- Event *current;
+- bool terminated;
+- int32_t terminateFlag;
+-
+- static JSClass jsWorkerClass;
+-
+- Worker()
+- : threadPool(NULL), parent(NULL), object(NULL),
+- context(NULL), lock(NULL), current(NULL), terminated(false), terminateFlag(0) {}
+-
+- bool init(JSContext *parentcx, WorkerParent *parent, JSObject *obj) {
+- JS_ASSERT(!threadPool && !this->parent && !object && !lock);
+-
+- if (!initWorkerParent() || !parent->addChild(this))
+- return false;
+- threadPool = parent->getThreadPool();
+- this->parent = parent;
+- this->object = obj;
+- lock = JS_NEW_LOCK();
+- return lock &&
+- createContext(parentcx, parent) &&
+- JS_SetPrivate(parentcx, obj, this);
+- }
+-
+- bool createContext(JSContext *parentcx, WorkerParent *parent) {
+- JSRuntime *rt = JS_GetRuntime(parentcx);
+- context = JS_NewContext(rt, 8192);
+- if (!context)
+- return false;
+-
+- // The Worker has a strong reference to the global; see jsTraceWorker.
+- // JSOPTION_UNROOTED_GLOBAL ensures that when the worker becomes
+- // unreachable, it and its global object can be collected. Otherwise
+- // the cx->globalObject root would keep them both alive forever.
+- JS_SetOptions(context, JS_GetOptions(parentcx) | JSOPTION_UNROOTED_GLOBAL |
+- JSOPTION_DONT_REPORT_UNCAUGHT);
+- JS_SetVersion(context, JS_GetVersion(parentcx));
+- JS_SetContextPrivate(context, this);
+- JS_SetOperationCallback(context, jsOperationCallback);
+- JS_BeginRequest(context);
+-
+- JSObject *global = threadPool->getHooks()->newGlobalObject(context);
+- JSObject *post, *proto, *ctor;
+- if (!global)
+- goto bad;
+- JS_SetGlobalObject(context, global);
+-
+- // Because the Worker is completely isolated from the rest of the
+- // runtime, and because any pending events on a Worker keep the Worker
+- // alive, this postMessage function cannot be called after the Worker
+- // is collected. Therefore it's safe to stash a pointer (a weak
+- // reference) to the C++ Worker object in the reserved slot.
+- post = JS_GetFunctionObject(JS_DefineFunction(context, global, "postMessage",
+- (JSNative) jsPostMessageToParent, 1, 0));
+- if (!post || !JS_SetReservedSlot(context, post, 0, PRIVATE_TO_JSVAL(this)))
+- goto bad;
+-
+- proto = JS_InitClass(context, global, NULL, &jsWorkerClass, jsConstruct, 1,
+- NULL, jsMethods, NULL, NULL);
+- if (!proto)
+- goto bad;
+-
+- ctor = JS_GetConstructor(context, proto);
+- if (!ctor || !JS_SetReservedSlot(context, ctor, 0, PRIVATE_TO_JSVAL(this)))
+- goto bad;
+-
+- JS_EndRequest(context);
+- JS_ClearContextThread(context);
+- return true;
+-
+- bad:
+- JS_EndRequest(context);
+- JS_DestroyContext(context);
+- context = NULL;
+- return false;
+- }
+-
+- static void jsTraceWorker(JSTracer *trc, JSObject *obj) {
+- JS_ASSERT(JS_GET_CLASS(trc->context, obj) == &jsWorkerClass);
+- if (Worker *w = (Worker *) JS_GetPrivate(trc->context, obj)) {
+- w->parent->trace(trc);
+- w->events.trace(trc);
+- if (w->current)
+- w->current->trace(trc);
+- JS_CALL_OBJECT_TRACER(trc, JS_GetGlobalObject(w->context), "Worker global");
+- }
+- }
+-
+- static void jsFinalize(JSContext *cx, JSObject *obj) {
+- JS_ASSERT(JS_GET_CLASS(cx, obj) == &jsWorkerClass);
+- if (Worker *w = (Worker *) JS_GetPrivate(cx, obj))
+- delete w;
+- }
+-
+- static JSBool jsOperationCallback(JSContext *cx) {
+- Worker *w = (Worker *) JS_GetContextPrivate(cx);
+- JSAutoSuspendRequest suspend(cx); // avoid nesting w->lock in a request
+- return !w->checkTermination();
+- }
+-
+- static JSBool jsResolveGlobal(JSContext *cx, JSObject *obj, jsid id, uintN flags,
+- JSObject **objp)
+- {
+- JSBool resolved;
+-
+- if (!JS_ResolveStandardClass(cx, obj, id, &resolved))
+- return false;
+- if (resolved)
+- *objp = obj;
+-
+- return true;
+- }
+-
+- static JSBool jsPostMessageToParent(JSContext *cx, uintN argc, jsval *vp);
+- static JSBool jsPostMessageToChild(JSContext *cx, uintN argc, jsval *vp);
+- static JSBool jsTerminate(JSContext *cx, uintN argc, jsval *vp);
+-
+- bool checkTermination() {
+- AutoLock hold(lock);
+- return lockedCheckTermination();
+- }
+-
+- bool lockedCheckTermination() {
+- if (terminateFlag || threadPool->isTerminating()) {
+- terminateSelf();
+- terminateFlag = 0;
+- }
+- return terminated;
+- }
+-
+- // Caller must hold the lock.
+- void terminateSelf() {
+- terminated = true;
+- while (!events.empty())
+- events.pop()->destroy(context);
+-
+- // Tell the children to shut down too. An arbitrarily silly amount of
+- // processing could happen before the whole tree is terminated; but
+- // this way we don't have to worry about blowing the C stack.
+- for (ChildSet::Enum e(children); !e.empty(); e.popFront())
+- e.front()->setTerminateFlag(); // note: nesting locks here
+- }
+-
+- public:
+- ~Worker() {
+- if (parent)
+- parent->removeChild(this);
+- dispose();
+- }
+-
+- void dispose() {
+- JS_ASSERT(!current);
+- while (!events.empty())
+- events.pop()->destroy(context);
+- if (lock) {
+- JS_DESTROY_LOCK(lock);
+- lock = NULL;
+- }
+- if (context) {
+- JS_SetContextThread(context);
+- JS_DestroyContextNoGC(context);
+- context = NULL;
+- }
+- object = NULL;
+-
+- // Do not call parent->removeChild(). This is called either from
+- // ~Worker, which calls it for us; or from parent->disposeChildren or
+- // Worker::create, which require that it not be called.
+- parent = NULL;
+- disposeChildren();
+- }
+-
+- static Worker *create(JSContext *parentcx, WorkerParent *parent,
+- JSString *scriptName, JSObject *obj);
+-
+- JSObject *asObject() { return object; }
+-
+- JSObject *getGlobal() { return JS_GetGlobalObject(context); }
+-
+- WorkerParent *getParent() { return parent; }
+-
+- virtual JSLock *getLock() { return lock; }
+-
+- virtual ThreadPool *getThreadPool() { return threadPool; }
+-
+- bool post(Event *event) {
+- AutoLock hold(lock);
+- if (terminated)
+- return false;
+- if (!current && events.empty() && !threadPool->getWorkerQueue()->post(this))
+- return false;
+- return events.push(event);
+- }
+-
+- void setTerminateFlag() {
+- AutoLock hold(lock);
+- terminateFlag = true;
+- if (current)
+- JS_TriggerOperationCallback(context);
+- }
+-
+- void processOneEvent();
+-
+- /* Trace method to be called from C++. */
+- void trace(JSTracer *trc) {
+- // Just mark the JSObject. If we haven't already been marked,
+- // jsTraceWorker will be called, at which point we'll trace referents.
+- JS_CALL_OBJECT_TRACER(trc, object, "queued Worker");
+- }
+-
+- static bool getWorkerParentFromConstructor(JSContext *cx, JSObject *ctor, WorkerParent **p) {
+- jsval v;
+- if (!JS_GetReservedSlot(cx, ctor, 0, &v))
+- return false;
+- if (JSVAL_IS_VOID(v)) {
+- // This means ctor is the root Worker constructor (created in
+- // Worker::initWorkers as opposed to Worker::createContext, which sets up
+- // Worker sandboxes) and nothing is initialized yet.
+- if (!JS_GetReservedSlot(cx, ctor, 1, &v))
+- return false;
+- ThreadPool *threadPool = (ThreadPool *) JSVAL_TO_PRIVATE(v);
+- if (!threadPool->start(cx))
+- return false;
+- WorkerParent *parent = threadPool->getMainQueue();
+- if (!JS_SetReservedSlot(cx, ctor, 0, PRIVATE_TO_JSVAL(parent))) {
+- threadPool->shutdown(cx);
+- return false;
+- }
+- *p = parent;
+- return true;
+- }
+- *p = (WorkerParent *) JSVAL_TO_PRIVATE(v);
+- return true;
+- }
+-
+- static JSBool jsConstruct(JSContext *cx, uintN argc, jsval *vp) {
+- WorkerParent *parent;
+- if (!getWorkerParentFromConstructor(cx, JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)), &parent))
+- return false;
+-
+-
+- JSString *scriptName = JS_ValueToString(cx, argc ? JS_ARGV(cx, vp)[0] : JSVAL_VOID);
+- if (!scriptName)
+- return false;
+-
+- JSObject *obj = JS_NewObject(cx, &jsWorkerClass, NULL, NULL);
+- if (!obj || !create(cx, parent, scriptName, obj))
+- return false;
+- JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(obj));
+- return true;
+- }
+-
+- static JSFunctionSpec jsMethods[3];
+- static JSFunctionSpec jsStaticMethod[2];
+-
+- static ThreadPool *initWorkers(JSContext *cx, WorkerHooks *hooks, JSObject *global,
+- JSObject **objp) {
+- // Create the ThreadPool object and its JSObject wrapper.
+- ThreadPool *threadPool = ThreadPool::create(cx, hooks);
+- if (!threadPool)
+- return NULL;
+-
+- // Root the ThreadPool JSObject early.
+- *objp = threadPool->asObject();
+-
+- // Create the Worker constructor.
+- JSObject *proto = JS_InitClass(cx, global, NULL, &jsWorkerClass,
+- jsConstruct, 1,
+- NULL, jsMethods, NULL, NULL);
+- if (!proto)
+- return NULL;
+-
+- // Stash a pointer to the ThreadPool in constructor reserved slot 1.
+- // It will be used later when lazily creating the MainQueue.
+- JSObject *ctor = JS_GetConstructor(cx, proto);
+- if (!JS_SetReservedSlot(cx, ctor, 1, PRIVATE_TO_JSVAL(threadPool)))
+- return NULL;
+-
+- return threadPool;
+- }
+-};
+-
+-class InitEvent : public Event
+-{
+- public:
+- static InitEvent *create(JSContext *cx, Worker *worker, JSString *scriptName) {
+- return createEvent<InitEvent>(cx, worker, worker, STRING_TO_JSVAL(scriptName));
+- }
+-
+- Result process(JSContext *cx) {
+- jsval s;
+- if (!deserializeData(cx, &s))
+- return fail;
+- JS_ASSERT(JSVAL_IS_STRING(s));
+- JSAutoByteString filename(cx, JSVAL_TO_STRING(s));
+- if (!filename)
+- return fail;
+-
+- JSObject *scriptObj = JS_CompileFile(cx, child->getGlobal(), filename.ptr());
+- if (!scriptObj)
+- return fail;
+-
+- AutoValueRooter rval(cx);
+- JSBool ok = JS_ExecuteScript(cx, child->getGlobal(), scriptObj, Jsvalify(rval.addr()));
+- return Result(ok);
+- }
+-};
+-
+-class DownMessageEvent : public Event
+-{
+- public:
+- static DownMessageEvent *create(JSContext *cx, Worker *child, jsval data) {
+- return createEvent<DownMessageEvent>(cx, child, child, data);
+- }
+-
+- Result process(JSContext *cx) {
+- return dispatch(cx, child->getGlobal(), "data", "onmessage", ok);
+- }
+-};
+-
+-class UpMessageEvent : public Event
+-{
+- public:
+- static UpMessageEvent *create(JSContext *cx, Worker *child, jsval data) {
+- return createEvent<UpMessageEvent>(cx, child->getParent(), child, data);
+- }
+-
+- Result process(JSContext *cx) {
+- return dispatch(cx, child->asObject(), "data", "onmessage", ok);
+- }
+-};
+-
+-class ErrorEvent : public Event
+-{
+- public:
+- static ErrorEvent *create(JSContext *cx, Worker *child) {
+- JSString *data = NULL;
+- jsval exc;
+- if (JS_GetPendingException(cx, &exc)) {
+- AutoValueRooter tvr(cx, Valueify(exc));
+- JS_ClearPendingException(cx);
+-
+- // Determine what error message to put in the error event.
+- // If exc.message is a string, use that; otherwise use String(exc).
+- // (This is a little different from what web workers do.)
+- if (JSVAL_IS_OBJECT(exc)) {
+- jsval msg;
+- if (!JS_GetProperty(cx, JSVAL_TO_OBJECT(exc), "message", &msg))
+- JS_ClearPendingException(cx);
+- else if (JSVAL_IS_STRING(msg))
+- data = JSVAL_TO_STRING(msg);
+- }
+- if (!data) {
+- data = JS_ValueToString(cx, exc);
+- if (!data)
+- return NULL;
+- }
+- }
+- return createEvent<ErrorEvent>(cx, child->getParent(), child,
+- data ? STRING_TO_JSVAL(data) : JSVAL_VOID);
+- }
+-
+- Result process(JSContext *cx) {
+- return dispatch(cx, child->asObject(), "message", "onerror", forwardToParent);
+- }
+-};
+-
+-} /* namespace workers */
+-} /* namespace js */
+-
+-using namespace js::workers;
+-
+-void
+-WorkerParent::disposeChildren()
+-{
+- for (ChildSet::Enum e(children); !e.empty(); e.popFront()) {
+- e.front()->dispose();
+- e.removeFront();
+- }
+-}
+-
+-bool
+-MainQueue::shouldStop()
+-{
+- // Note: This deliberately nests WorkerQueue::lock in MainQueue::lock.
+- // Releasing MainQueue::lock would risk a race -- isIdle() could return
+- // false, but the workers could become idle before we reacquire
+- // MainQueue::lock and go to sleep, and we would wait on the condvar
+- // forever.
+- return closed || threadPool->getWorkerQueue()->isIdle();
+-}
+-
+-void
+-MainQueue::trace(JSTracer *trc)
+-{
+- JS_CALL_OBJECT_TRACER(trc, threadPool->asObject(), "MainQueue");
+-}
+-
+-void
+-WorkerQueue::work() {
+- AutoLock hold(lock);
+-
+- Worker *w;
+- while (take(&w)) { // can block outside the mutex
+- JS_RELEASE_LOCK(lock);
+- w->processOneEvent(); // enters request on w->context
+- JS_ACQUIRE_LOCK(lock);
+- drop(w);
+-
+- if (lockedIsIdle()) {
+- JS_RELEASE_LOCK(lock);
+- main->wake();
+- JS_ACQUIRE_LOCK(lock);
+- }
+- }
+-}
+-
+-const bool mswin =
+-#ifdef XP_WIN
+- true
+-#else
+- false
+-#endif
+- ;
+-
+-template <class Ch> bool
+-IsAbsolute(const Ch *filename)
+-{
+- return filename[0] == '/' ||
+- (mswin && (filename[0] == '\\' || (filename[0] != '\0' && filename[1] == ':')));
+-}
+-
+-// Note: base is a filename, not a directory name.
+-static JSString *
+-ResolveRelativePath(JSContext *cx, const char *base, JSString *filename)
+-{
+- size_t fileLen = JS_GetStringLength(filename);
+- const jschar *fileChars = JS_GetStringCharsZ(cx, filename);
+- if (!fileChars)
+- return NULL;
+-
+- if (IsAbsolute(fileChars))
+- return filename;
+-
+- // Strip off the filename part of base.
+- size_t dirLen = -1;
+- for (size_t i = 0; base[i]; i++) {
+- if (base[i] == '/' || (mswin && base[i] == '\\'))
+- dirLen = i;
+- }
+-
+- // If base is relative and contains no directories, use filename unchanged.
+- if (!IsAbsolute(base) && dirLen == (size_t) -1)
+- return filename;
+-
+- // Otherwise return base[:dirLen + 1] + filename.
+- js::Vector<jschar, 0, js::ContextAllocPolicy> result(cx);
+- size_t nchars;
+- if (!JS_DecodeBytes(cx, base, dirLen + 1, NULL, &nchars))
+- return NULL;
+- if (!result.reserve(dirLen + 1 + fileLen)) {
+- JS_ReportOutOfMemory(cx);
+- return NULL;
+- }
+- JS_ALWAYS_TRUE(result.resize(dirLen + 1));
+- if (!JS_DecodeBytes(cx, base, dirLen + 1, result.begin(), &nchars))
+- return NULL;
+- JS_ALWAYS_TRUE(result.append(fileChars, fileLen));
+- return JS_NewUCStringCopyN(cx, result.begin(), result.length());
+-}
+-
+-Worker *
+-Worker::create(JSContext *parentcx, WorkerParent *parent, JSString *scriptName, JSObject *obj)
+-{
+- Worker *w = new Worker();
+- if (!w || !w->init(parentcx, parent, obj)) {
+- delete w;
+- return NULL;
+- }
+-
+- JSStackFrame *frame = JS_GetScriptedCaller(parentcx, NULL);
+- const char *base = JS_GetScriptFilename(parentcx, JS_GetFrameScript(parentcx, frame));
+- JSString *scriptPath = ResolveRelativePath(parentcx, base, scriptName);
+- if (!scriptPath)
+- return NULL;
+-
+- // Post an InitEvent to run the initialization script.
+- Event *event = InitEvent::create(parentcx, w, scriptPath);
+- if (!event)
+- return NULL;
+- if (!w->events.push(event) || !w->threadPool->getWorkerQueue()->post(w)) {
+- event->destroy(parentcx);
+- JS_ReportOutOfMemory(parentcx);
+- w->dispose();
+- return NULL;
+- }
+- return w;
+-}
+-
+-void
+-Worker::processOneEvent()
+-{
+- Event *event;
+- {
+- AutoLock hold1(lock);
+- if (lockedCheckTermination() || events.empty())
+- return;
+-
+- event = current = events.pop();
+- }
+-
+- JS_SetContextThread(context);
+- JS_SetNativeStackQuota(context, gMaxStackSize);
+-
+- Event::Result result;
+- {
+- JSAutoRequest req(context);
+- result = event->process(context);
+- }
+-
+- // Note: we have to leave the above request before calling parent->post or
+- // checkTermination, both of which acquire locks.
+- if (result == Event::forwardToParent) {
+- event->setChildAndRecipient(this, parent);
+- if (parent->post(event)) {
+- event = NULL; // to prevent it from being deleted below
+- } else {
+- JS_ReportOutOfMemory(context);
+- result = Event::fail;
+- }
+- }
+- if (result == Event::fail && !checkTermination()) {
+- JSAutoRequest req(context);
+- Event *err = ErrorEvent::create(context, this);
+- if (err && !parent->post(err)) {
+- JS_ReportOutOfMemory(context);
+- err->destroy(context);
+- err = NULL;
+- }
+- if (!err) {
+- // FIXME - out of memory, probably should panic
+- }
+- }
+-
+- if (event)
+- event->destroy(context);
+- JS_ClearContextThread(context);
+-
+- {
+- AutoLock hold2(lock);
+- current = NULL;
+- if (!lockedCheckTermination() && !events.empty()) {
+- // Re-enqueue this worker. OOM here effectively kills the worker.
+- if (!threadPool->getWorkerQueue()->post(this))
+- JS_ReportOutOfMemory(context);
+- }
+- }
+-}
+-
+-JSBool
+-Worker::jsPostMessageToParent(JSContext *cx, uintN argc, jsval *vp)
+-{
+- jsval workerval;
+- if (!JS_GetReservedSlot(cx, JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)), 0, &workerval))
+- return false;
+- Worker *w = (Worker *) JSVAL_TO_PRIVATE(workerval);
+-
+- {
+- JSAutoSuspendRequest suspend(cx); // avoid nesting w->lock in a request
+- if (w->checkTermination())
+- return false;
+- }
+-
+- jsval data = argc > 0 ? JS_ARGV(cx, vp)[0] : JSVAL_VOID;
+- Event *event = UpMessageEvent::create(cx, w, data);
+- if (!event)
+- return false;
+- if (!w->parent->post(event)) {
+- event->destroy(cx);
+- JS_ReportOutOfMemory(cx);
+- return false;
+- }
+- JS_SET_RVAL(cx, vp, JSVAL_VOID);
+- return true;
+-}
+-
+-JSBool
+-Worker::jsPostMessageToChild(JSContext *cx, uintN argc, jsval *vp)
+-{
+- JSObject *workerobj = JS_THIS_OBJECT(cx, vp);
+- if (!workerobj)
+- return false;
+- Worker *w = (Worker *) JS_GetInstancePrivate(cx, workerobj, &jsWorkerClass, JS_ARGV(cx, vp));
+- if (!w) {
+- if (!JS_IsExceptionPending(cx))
+- JS_ReportError(cx, "Worker was shut down");
+- return false;
+- }
+-
+- jsval data = argc > 0 ? JS_ARGV(cx, vp)[0] : JSVAL_VOID;
+- Event *event = DownMessageEvent::create(cx, w, data);
+- if (!event)
+- return false;
+- if (!w->post(event)) {
+- JS_ReportOutOfMemory(cx);
+- return false;
+- }
+- JS_SET_RVAL(cx, vp, JSVAL_VOID);
+- return true;
+-}
+-
+-JSBool
+-Worker::jsTerminate(JSContext *cx, uintN argc, jsval *vp)
+-{
+- JS_SET_RVAL(cx, vp, JSVAL_VOID);
+-
+- JSObject *workerobj = JS_THIS_OBJECT(cx, vp);
+- if (!workerobj)
+- return false;
+- Worker *w = (Worker *) JS_GetInstancePrivate(cx, workerobj, &jsWorkerClass, JS_ARGV(cx, vp));
+- if (!w)
+- return !JS_IsExceptionPending(cx); // ok to terminate twice
+-
+- JSAutoSuspendRequest suspend(cx);
+- w->setTerminateFlag();
+- return true;
+-}
+-
+-void
+-Event::trace(JSTracer *trc)
+-{
+- if (recipient)
+- recipient->trace(trc);
+- if (child)
+- JS_CALL_OBJECT_TRACER(trc, child->asObject(), "worker");
+-}
+-
+-JSClass ThreadPool::jsClass = {
+- "ThreadPool", JSCLASS_HAS_PRIVATE | JSCLASS_MARK_IS_TRACE,
+- JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
+- JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, jsFinalize,
+- NULL, NULL, NULL, NULL,
+- NULL, NULL, JS_CLASS_TRACE(jsTraceThreadPool), NULL
+-};
+-
+-JSClass Worker::jsWorkerClass = {
+- "Worker", JSCLASS_HAS_PRIVATE | JSCLASS_MARK_IS_TRACE,
+- JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
+- JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, jsFinalize,
+- NULL, NULL, NULL, NULL,
+- NULL, NULL, JS_CLASS_TRACE(jsTraceWorker), NULL
+-};
+-
+-JSFunctionSpec Worker::jsMethods[3] = {
+- JS_FN("postMessage", Worker::jsPostMessageToChild, 1, 0),
+- JS_FN("terminate", Worker::jsTerminate, 0, 0),
+- JS_FS_END
+-};
+-
+-ThreadPool *
+-js::workers::init(JSContext *cx, WorkerHooks *hooks, JSObject *global, JSObject **rootp)
+-{
+- return Worker::initWorkers(cx, hooks, global, rootp);
+-}
+-
+-void
+-js::workers::terminateAll(JSRuntime *rt, ThreadPool *tp)
+-{
+- tp->terminateAll(rt);
+-}
+-
+-void
+-js::workers::finish(JSContext *cx, ThreadPool *tp)
+-{
+- if (MainQueue *mq = tp->getMainQueue()) {
+- JS_ALWAYS_TRUE(mq->mainThreadWork(cx, true));
+- tp->shutdown(cx);
+- }
+-}
+-
+-#endif /* JS_THREADSAFE */
+diff -ruN src/shell/jsworkers.h src.new/shell/jsworkers.h
+--- shell/jsworkers.h 2011-04-01 06:08:36.000000000 +1100
++++ shell/jsworkers.h 1970-01-01 10:00:00.000000000 +1000
+@@ -1,93 +0,0 @@
+-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+- * vim: set ts=8 sw=4 et tw=99:
+- *
+- * ***** BEGIN LICENSE BLOCK *****
+- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+- *
+- * The contents of this file are subject to the Mozilla Public License Version
+- * 1.1 (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.mozilla.org/MPL/
+- *
+- * Software distributed under the License is distributed on an "AS IS" basis,
+- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+- * for the specific language governing rights and limitations under the
+- * License.
+- *
+- * The Original Code is JavaScript shell workers.
+- *
+- * The Initial Developer of the Original Code is
+- * Mozilla Corporation.
+- * Portions created by the Initial Developer are Copyright (C) 2010
+- * the Initial Developer. All Rights Reserved.
+- *
+- * Contributor(s):
+- * Jason Orendorff <jorendorff@mozilla.com>
+- *
+- * Alternatively, the contents of this file may be used under the terms of
+- * either of the GNU General Public License Version 2 or later (the "GPL"),
+- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+- * in which case the provisions of the GPL or the LGPL are applicable instead
+- * of those above. If you wish to allow use of your version of this file only
+- * under the terms of either the GPL or the LGPL, and not to allow others to
+- * use your version of this file under the terms of the MPL, indicate your
+- * decision by deleting the provisions above and replace them with the notice
+- * and other provisions required by the GPL or the LGPL. If you do not delete
+- * the provisions above, a recipient may use your version of this file under
+- * the terms of any one of the MPL, the GPL or the LGPL.
+- *
+- * ***** END LICENSE BLOCK ***** */
+-
+-#ifndef jsworkers_h___
+-#define jsworkers_h___
+-
+-#ifdef JS_THREADSAFE
+-
+-#include "jsapi.h"
+-
+-/*
+- * Workers for the JS shell.
+- *
+- * Note: The real implementation of DOM Workers is in dom/src/threads.
+- */
+-namespace js {
+- namespace workers {
+- class ThreadPool;
+-
+- class WorkerHooks {
+- public:
+- virtual JSObject *newGlobalObject(JSContext *cx) = 0;
+- virtual ~WorkerHooks() {}
+- };
+-
+- /*
+- * Initialize workers. This defines the Worker constructor on global.
+- * Requires request. rootp must point to a GC root.
+- *
+- * On success, *rootp receives a pointer to an object, and init returns
+- * a non-null value. The caller must keep the object rooted and must
+- * pass it to js::workers::finish later.
+- */
+- ThreadPool *init(JSContext *cx, WorkerHooks *hooks, JSObject *global, JSObject **rootp);
+-
+- /* Asynchronously signal for all workers to terminate.
+- *
+- * Call this before calling finish() to shut down without waiting for
+- * all messages to be proceesed.
+- */
+- void terminateAll(JSRuntime *rt, ThreadPool *tp);
+-
+- /*
+- * Finish running any workers, shut down the thread pool, and free all
+- * resources associated with workers. The application must call this
+- * before shutting down the runtime, and not during GC.
+- *
+- * Requires request.
+- */
+- void finish(JSContext *cx, ThreadPool *tp);
+- }
+-}
+-
+-#endif /* JS_THREADSAFE */
+-
+-#endif /* jsworkers_h___ */
+diff -ruN src/tests/browser.js src.new/tests/browser.js
+--- tests/browser.js 2011-04-01 06:08:36.000000000 +1100
++++ tests/browser.js 2013-03-23 22:03:56.716635673 +1100
+@@ -767,17 +767,6 @@
+ document.write(s);
+ }
+
+-var JSTest = {
+- waitForExplicitFinish: function () {
+- gDelayTestDriverEnd = true;
+- },
+-
+- testFinished: function () {
+- gDelayTestDriverEnd = false;
+- jsTestDriverEnd();
+- }
+-};
+-
+ function jsTestDriverEnd()
+ {
+ // gDelayTestDriverEnd is used to
+diff -ruN src/tests/js1_8_5/extensions/jstests.list src.new/tests/js1_8_5/extensions/jstests.list
+--- tests/js1_8_5/extensions/jstests.list 2011-04-01 06:08:36.000000000 +1100
++++ tests/js1_8_5/extensions/jstests.list 2013-03-23 22:29:16.973264001 +1100
+@@ -1,13 +1,6 @@
+ url-prefix ../../jsreftest.html?test=js1_8_5/extensions/
+ script typedarray.js
+ script typedarray-prototype.js
+-skip-if(!xulRuntime.shell) script worker-error.js # these tests sometimes hang in browser, bug 559954, bug 562333
+-skip-if(!xulRuntime.shell) script worker-error-propagation.js
+-skip-if(!xulRuntime.shell) script worker-fib.js
+-skip-if(!xulRuntime.shell) script worker-init.js
+-skip-if(!xulRuntime.shell) script worker-simple.js
+-skip-if(!xulRuntime.shell) script worker-terminate.js
+-skip-if(!xulRuntime.shell) script worker-timeout.js
+ script scripted-proxies.js
+ script array-length-protochange.js
+ script parseInt-octal.js
+diff -ruN src/tests/js1_8_5/extensions/worker-error-child.js src.new/tests/js1_8_5/extensions/worker-error-child.js
+--- tests/js1_8_5/extensions/worker-error-child.js 2011-04-01 06:08:36.000000000 +1100
++++ tests/js1_8_5/extensions/worker-error-child.js 1970-01-01 10:00:00.000000000 +1000
+@@ -1,9 +0,0 @@
+-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+-/*
+- * Any copyright is dedicated to the Public Domain.
+- * http://creativecommons.org/licenses/publicdomain/
+- * Contributor: Jason Orendorff <jorendorff@mozilla.com>
+- */
+-function onmessage(event) {
+- throw new Error("fail");
+-}
+diff -ruN src/tests/js1_8_5/extensions/worker-error-propagation-child.js src.new/tests/js1_8_5/extensions/worker-error-propagation-child.js
+--- tests/js1_8_5/extensions/worker-error-propagation-child.js 2011-04-01 06:08:36.000000000 +1100
++++ tests/js1_8_5/extensions/worker-error-propagation-child.js 1970-01-01 10:00:00.000000000 +1000
+@@ -1,16 +0,0 @@
+-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+-/*
+- * Any copyright is dedicated to the Public Domain.
+- * http://creativecommons.org/licenses/publicdomain/
+- * Contributor: Jason Orendorff <jorendorff@mozilla.com>
+- */
+-
+-function onmessage(event) {
+- var n = +event.data;
+- if (n == 0)
+- throw new Error("boom");
+- var w = new Worker(workerDir + "worker-error-propagation-child.js");
+- w.onmessage = function (event) { postMessage(event.data); };
+- // No w.onerror here. We are testing error propagation when it is absent.
+- w.postMessage(n - 1 + "");
+-}
+diff -ruN src/tests/js1_8_5/extensions/worker-error-propagation.js src.new/tests/js1_8_5/extensions/worker-error-propagation.js
+--- tests/js1_8_5/extensions/worker-error-propagation.js 2011-04-01 06:08:36.000000000 +1100
++++ tests/js1_8_5/extensions/worker-error-propagation.js 1970-01-01 10:00:00.000000000 +1000
+@@ -1,20 +0,0 @@
+-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+-/*
+- * Any copyright is dedicated to the Public Domain.
+- * http://creativecommons.org/licenses/publicdomain/
+- * Contributor: Jason Orendorff <jorendorff@mozilla.com>
+- */
+-
+-if (typeof Worker != 'undefined') {
+- JSTest.waitForExplicitFinish();
+- var w = Worker(workerDir + "worker-error-propagation-child.js");
+- var errors = 0;
+- w.onmessage = function () { throw new Error("no reply expected"); };
+- w.onerror = function (event) {
+- reportCompare("string", typeof event.message, "typeof event.message");
+- JSTest.testFinished();
+- };
+- w.postMessage("5");
+-} else {
+- reportCompare(0, 0, " PASSED! Test skipped. Shell workers required.");
+-}
+diff -ruN src/tests/js1_8_5/extensions/worker-error.js src.new/tests/js1_8_5/extensions/worker-error.js
+--- tests/js1_8_5/extensions/worker-error.js 2011-04-01 06:08:36.000000000 +1100
++++ tests/js1_8_5/extensions/worker-error.js 1970-01-01 10:00:00.000000000 +1000
+@@ -1,21 +0,0 @@
+-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+-/*
+- * Any copyright is dedicated to the Public Domain.
+- * http://creativecommons.org/licenses/publicdomain/
+- * Contributor: Jason Orendorff <jorendorff@mozilla.com>
+- */
+-
+-if (typeof Worker != 'undefined') {
+- JSTest.waitForExplicitFinish();
+-
+- // The script throws new Error("fail") on first message.
+- var w = Worker(workerDir + "worker-error-child.js");
+- var a = [];
+- w.onerror = function (event) {
+- reportCompare("fail", event.message, "worker-error");
+- JSTest.testFinished();
+- };
+- w.postMessage("hello");
+-} else {
+- reportCompare(0, 0, "Test skipped. Shell workers required.");
+-}
+diff -ruN src/tests/js1_8_5/extensions/worker-fib-child.js src.new/tests/js1_8_5/extensions/worker-fib-child.js
+--- tests/js1_8_5/extensions/worker-fib-child.js 2011-04-01 06:08:36.000000000 +1100
++++ tests/js1_8_5/extensions/worker-fib-child.js 1970-01-01 10:00:00.000000000 +1000
+@@ -1,27 +0,0 @@
+-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+-/*
+- * Any copyright is dedicated to the Public Domain.
+- * http://creativecommons.org/licenses/publicdomain/
+- * Contributor: Jason Orendorff <jorendorff@mozilla.com>
+- */
+-
+-function onmessage(event) {
+- var a = event.data.split(/\t/);
+- var n = Number(a[0]);
+- var workerDir = a[1];
+-
+- if (n <= 1) {
+- postMessage("" + n);
+- } else {
+- var w1 = new Worker(workerDir + "worker-fib-child.js"),
+- w2 = new Worker(workerDir + "worker-fib-child.js");
+- var a = [];
+- w1.onmessage = w2.onmessage = function(event) {
+- a.push(+event.data);
+- if (a.length == 2)
+- postMessage(a[0] + a[1] + "");
+- };
+- w1.postMessage(n - 1 + "\t" + workerDir);
+- w2.postMessage(n - 2 + "\t" + workerDir);
+- }
+-}
+diff -ruN src/tests/js1_8_5/extensions/worker-fib.js src.new/tests/js1_8_5/extensions/worker-fib.js
+--- tests/js1_8_5/extensions/worker-fib.js 2011-04-01 06:08:36.000000000 +1100
++++ tests/js1_8_5/extensions/worker-fib.js 1970-01-01 10:00:00.000000000 +1000
+@@ -1,18 +0,0 @@
+-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+-/*
+- * Any copyright is dedicated to the Public Domain.
+- * http://creativecommons.org/licenses/publicdomain/
+- * Contributor: Jason Orendorff <jorendorff@mozilla.com>
+- */
+-
+-if (typeof Worker != 'undefined') {
+- JSTest.waitForExplicitFinish();
+- var w = Worker(workerDir + "worker-fib-child.js");
+- w.onmessage = function (event) {
+- reportCompare("55", event.data, "worker-fib");
+- JSTest.testFinished();
+- };
+- w.postMessage("10\t" + workerDir); // 0 1 1 2 3 5 8 13 21 34 55
+-} else {
+- reportCompare(0, 0, "Test skipped. Shell workers required.");
+-}
+diff -ruN src/tests/js1_8_5/extensions/worker-init-child.js src.new/tests/js1_8_5/extensions/worker-init-child.js
+--- tests/js1_8_5/extensions/worker-init-child.js 2011-04-01 06:08:36.000000000 +1100
++++ tests/js1_8_5/extensions/worker-init-child.js 1970-01-01 10:00:00.000000000 +1000
+@@ -1,8 +0,0 @@
+-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+-/*
+- * Any copyright is dedicated to the Public Domain.
+- * http://creativecommons.org/licenses/publicdomain/
+- * Contributor: Jason Orendorff <jorendorff@mozilla.com>
+- */
+-postMessage('do your worst');
+-for (;;) ;
+diff -ruN src/tests/js1_8_5/extensions/worker-init.js src.new/tests/js1_8_5/extensions/worker-init.js
+--- tests/js1_8_5/extensions/worker-init.js 2011-04-01 06:08:36.000000000 +1100
++++ tests/js1_8_5/extensions/worker-init.js 1970-01-01 10:00:00.000000000 +1000
+@@ -1,19 +0,0 @@
+-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+-/*
+- * Any copyright is dedicated to the Public Domain.
+- * http://creativecommons.org/licenses/publicdomain/
+- * Contributor: Jason Orendorff <jorendorff@mozilla.com>
+- */
+-
+-if (typeof Worker != 'undefined') {
+- JSTest.waitForExplicitFinish();
+- // Messages sent during initialization are a corner case, but in any case
+- // they should be delivered (no waiting until initialization is complete).
+- var w = new Worker(workerDir + "worker-init-child.js"); // posts a message, then loops forever
+- w.onmessage = function (event) {
+- reportCompare(0, 0, "worker-init");
+- JSTest.testFinished();
+- };
+-} else {
+- reportCompare(0, 0, "Test skipped. Shell workers required.");
+-}
+diff -ruN src/tests/js1_8_5/extensions/worker-simple-child.js src.new/tests/js1_8_5/extensions/worker-simple-child.js
+--- tests/js1_8_5/extensions/worker-simple-child.js 2011-04-01 06:08:36.000000000 +1100
++++ tests/js1_8_5/extensions/worker-simple-child.js 1970-01-01 10:00:00.000000000 +1000
+@@ -1,8 +0,0 @@
+-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+-/*
+- * Any copyright is dedicated to the Public Domain.
+- * http://creativecommons.org/licenses/publicdomain/
+- * Contributor: Jason Orendorff <jorendorff@mozilla.com>
+- */
+-
+-onmessage = function (event) { postMessage(event.data); };
+diff -ruN src/tests/js1_8_5/extensions/worker-simple.js src.new/tests/js1_8_5/extensions/worker-simple.js
+--- tests/js1_8_5/extensions/worker-simple.js 2011-04-01 06:08:36.000000000 +1100
++++ tests/js1_8_5/extensions/worker-simple.js 1970-01-01 10:00:00.000000000 +1000
+@@ -1,20 +0,0 @@
+-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+-/*
+- * Any copyright is dedicated to the Public Domain.
+- * http://creativecommons.org/licenses/publicdomain/
+- * Contributor: Jason Orendorff <jorendorff@mozilla.com>
+- */
+-
+-if (typeof Worker != 'undefined') {
+- JSTest.waitForExplicitFinish();
+- var w = new Worker(workerDir + "worker-simple-child.js");
+- var a = [];
+- w.onmessage = function (event) {
+- a.push(event.data);
+- reportCompare(0, 0, "worker-simple");
+- JSTest.testFinished();
+- };
+- w.postMessage("hello");
+-} else {
+- reportCompare(0, 0, "Test skipped. Shell workers required.");
+-}
+diff -ruN src/tests/js1_8_5/extensions/worker-terminate-child.js src.new/tests/js1_8_5/extensions/worker-terminate-child.js
+--- tests/js1_8_5/extensions/worker-terminate-child.js 2011-04-01 06:08:36.000000000 +1100
++++ tests/js1_8_5/extensions/worker-terminate-child.js 1970-01-01 10:00:00.000000000 +1000
+@@ -1,13 +0,0 @@
+-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+-/*
+- * Any copyright is dedicated to the Public Domain.
+- * http://creativecommons.org/licenses/publicdomain/
+- * Contributor: Jason Orendorff <jorendorff@mozilla.com>
+- */
+-
+-onmessage = function (event) {
+- var workerDir = event.message;
+- var child = new Worker(workerDir + 'worker-terminate-iloop.js'); // loops forever
+- child.terminate();
+- postMessage("killed");
+-};
+diff -ruN src/tests/js1_8_5/extensions/worker-terminate-iloop.js src.new/tests/js1_8_5/extensions/worker-terminate-iloop.js
+--- tests/js1_8_5/extensions/worker-terminate-iloop.js 2011-04-01 06:08:36.000000000 +1100
++++ tests/js1_8_5/extensions/worker-terminate-iloop.js 1970-01-01 10:00:00.000000000 +1000
+@@ -1,9 +0,0 @@
+-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+-/*
+- * Any copyright is dedicated to the Public Domain.
+- * http://creativecommons.org/licenses/publicdomain/
+- * Contributor: Jason Orendorff <jorendorff@mozilla.com>
+- */
+-
+-for (;;)
+- ;
+diff -ruN src/tests/js1_8_5/extensions/worker-terminate.js src.new/tests/js1_8_5/extensions/worker-terminate.js
+--- tests/js1_8_5/extensions/worker-terminate.js 2011-04-01 06:08:36.000000000 +1100
++++ tests/js1_8_5/extensions/worker-terminate.js 1970-01-01 10:00:00.000000000 +1000
+@@ -1,37 +0,0 @@
+-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+-/*
+- * Any copyright is dedicated to the Public Domain.
+- * http://creativecommons.org/licenses/publicdomain/
+- * Contributor: Jason Orendorff <jorendorff@mozilla.com>
+- */
+-
+-if (typeof Worker != 'undefined') {
+- JSTest.waitForExplicitFinish();
+-
+- // This tests that a parent worker can terminate a child. We run the test
+- // several times serially. If terminate() doesn't work, the runaway Workers
+- // will soon outnumber the number of threads in the thread pool, and we
+- // will deadlock.
+- var i = 0;
+-
+- function next() {
+- if (++i == 10) {
+- reportCompare(0, 0, "worker-terminate");
+- JSTest.testFinished();
+- return;
+- }
+-
+- var w = new Worker(workerDir + "worker-terminate-child.js");
+- w.onmessage = function (event) {
+- reportCompare("killed", event.data, "killed runaway worker #" + i);
+- next();
+- };
+- w.onerror = function (event) {
+- reportCompare(0, 1, "Got error: " + event.message);
+- };
+- w.postMessage(workerDir);
+- }
+- next();
+-} else {
+- reportCompare(0, 0, "Test skipped. Shell workers required.");
+-}
+diff -ruN src/tests/js1_8_5/extensions/worker-timeout-child.js src.new/tests/js1_8_5/extensions/worker-timeout-child.js
+--- tests/js1_8_5/extensions/worker-timeout-child.js 2011-04-01 06:08:36.000000000 +1100
++++ tests/js1_8_5/extensions/worker-timeout-child.js 1970-01-01 10:00:00.000000000 +1000
+@@ -1,9 +0,0 @@
+-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+-/*
+- * Any copyright is dedicated to the Public Domain.
+- * http://creativecommons.org/licenses/publicdomain/
+- * Contributor: Jason Orendorff
+- */
+-
+-for (;;)
+- ;
+diff -ruN src/tests/js1_8_5/extensions/worker-timeout.js src.new/tests/js1_8_5/extensions/worker-timeout.js
+--- tests/js1_8_5/extensions/worker-timeout.js 2011-04-01 06:08:36.000000000 +1100
++++ tests/js1_8_5/extensions/worker-timeout.js 1970-01-01 10:00:00.000000000 +1000
+@@ -1,18 +0,0 @@
+-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+-/*
+- * Any copyright is dedicated to the Public Domain.
+- * http://creativecommons.org/licenses/publicdomain/
+- * Contributor: Jason Orendorff
+- */
+-
+-if (typeof timeout == 'function' && typeof Worker != 'undefined') {
+- // We don't actually ever call JSTest.testFinished(); instead we
+- // time out and exit the shell with exit code 6.
+- JSTest.waitForExplicitFinish();
+- expectExitCode(6);
+- timeout(1.0);
+- for (var i = 0; i < 5; i++)
+- new Worker(workerDir + "worker-timeout-child.js"); // just loops forever
+-} else {
+- reportCompare(0, 0, "Test skipped. Shell workers and timeout required.");
+-}
+diff -ruN src/tests/shell.js src.new/tests/shell.js
+--- tests/shell.js 2011-04-01 06:08:36.000000000 +1100
++++ tests/shell.js 2013-03-23 22:07:41.387249919 +1100
+@@ -833,18 +833,6 @@
+ }
+ }
+
+-var JSTest = {
+- waitForExplicitFinish: function () {
+- gDelayTestDriverEnd = true;
+- },
+-
+- testFinished: function () {
+- gDelayTestDriverEnd = false;
+- jsTestDriverEnd();
+- quit();
+- }
+-};
+-
+ function jsTestDriverEnd()
+ {
+ // gDelayTestDriverEnd is used to
diff --git a/lang/spidermonkey185/files/patch-c++11 b/lang/spidermonkey185/files/patch-c++11
new file mode 100644
index 000000000000..95a68426f5de
--- /dev/null
+++ b/lang/spidermonkey185/files/patch-c++11
@@ -0,0 +1,247 @@
+jsapi.cpp:3988:16: error: cannot initialize return object of type 'JSIdArray *' with an rvalue of type 'bool'
+ return false;
+ ^~~~~
+jsarray.cpp:497:1: error: non-constant-expression cannot be narrowed from type 'intptr_t' (aka 'long') to 'uintptr_t' (aka 'unsigned long') in initializer list [-Wc++11-narrowing]
+JS_DEFINE_CALLINFO_3(extern, BOOL, js_EnsureDenseArrayCapacity, CONTEXT, OBJECT, INT32,
+^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+./jsbuiltins.h:350:5: note: expanded from macro 'JS_DEFINE_CALLINFO_3'
+ _JS_DEFINE_CALLINFO(linkage, op, \
+ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+./jsbuiltins.h:294:11: note: expanded from macro '_JS_DEFINE_CALLINFO'
+ { (intptr_t) &name, argtypes, nanojit::ABI_FASTCALL, isPure, storeAccSet _JS_CI_NAME(name) }; \
+ ^~~~~~~~~~~~~~~~
+jsfun.cpp:2054:16: error: cannot initialize return object of type 'JSString *' with an rvalue of type 'bool'
+ return false;
+ ^~~~~
+jsfun.cpp:2660:20: error: cannot initialize return object of type 'const js::Shape *' with an rvalue of type 'bool'
+ return false;
+ ^~~~~
+jsiter.cpp:428:20: error: cannot initialize return object of type 'JSObject *' with an rvalue of type 'bool'
+ return false;
+ ^~~~~
+jsparse.cpp:3355:20: error: cannot initialize return object of type 'JSParseNode *' with an rvalue of type 'bool'
+ return false;
+ ^~~~~
+jsstr.cpp:1737:24: error: cannot initialize return object of type 'const RegExpPair *' with an rvalue of type 'bool'
+ return false;
+ ^~~~~
+jsstr.cpp:3403:16: error: cannot initialize return object of type 'JSObject *' with an rvalue of type 'JSIntn' (aka 'int')
+ return JS_FALSE;
+ ^~~~~~~~
+./jstypes.h:395:18: note: expanded from macro 'JS_FALSE'
+#define JS_FALSE (JSIntn)0
+ ^~~~~~~~~
+jstypedarray.cpp:1337:20: error: cannot initialize return object of type 'JSObject *' with an rvalue of type 'bool'
+ return false;
+ ^~~~~
+jstypedarray.cpp:1671:16: error: cannot initialize return object of type 'JSObject *' with an rvalue of type 'bool'
+ return false;
+ ^~~~~
+jsxml.cpp:285:16: error: cannot initialize return object of type 'JSObject *' with an rvalue of type 'JSIntn' (aka 'int')
+ return JS_FALSE;
+ ^~~~~~~~
+jsxml.cpp:434:20: error: cannot initialize return object of type 'JSString *' with an rvalue of type 'JSIntn' (aka 'int')
+ return JS_FALSE;
+ ^~~~~~~~
+./jstypes.h:395:18: note: expanded from macro 'JS_FALSE'
+#define JS_FALSE (JSIntn)0
+ ^~~~~~~~~
+./methodjit/InvokeHelpers.cpp:731:16: error: cannot initialize return object of type 'void *' with an rvalue of type 'bool'
+ return false;
+ ^~~~~
+./nanojit/NativeX64.cpp:1902:59: error: constant expression evaluates to 9223372036854775808 which cannot be narrowed to type 'int64_t' (aka 'long') [-Wc++11-narrowing]
+ static const AVMPLUS_ALIGN16(int64_t) negateMask[] = {0x8000000000000000LL,0};
+ ^~~~~~~~~~~~~~~~~~~~
+./nanojit/NativeX64.cpp:1902:59: note: insert an explicit cast to silence this issue
+ static const AVMPLUS_ALIGN16(int64_t) negateMask[] = {0x8000000000000000LL,0};
+ ^~~~~~~~~~~~~~~~~~~~
+ static_cast<int64_t>( )
+./nanojit/RegAlloc.h:189:24: error: non-constant-expression cannot be narrowed from type 'int' to 'nanojit::Register' (aka 'unsigned int') in initializer list [-Wc++11-narrowing]
+ Register r = { (sizeof(RegisterMask) == 4) ? lsbSet32(mask) : lsbSet64(mask) };
+ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+./nanojit/RegAlloc.h:189:24: note: insert an explicit cast to silence this issue
+ Register r = { (sizeof(RegisterMask) == 4) ? lsbSet32(mask) : lsbSet64(mask) };
+ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ static_cast<Register>( )
+./nanojit/RegAlloc.h:197:24: error: non-constant-expression cannot be narrowed from type 'int' to 'nanojit::Register' (aka 'unsigned int') in initializer list [-Wc++11-narrowing]
+ Register r = { (sizeof(RegisterMask) == 4) ? msbSet32(mask) : msbSet64(mask) };
+ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+./nanojit/RegAlloc.h:197:24: note: insert an explicit cast to silence this issue
+ Register r = { (sizeof(RegisterMask) == 4) ? msbSet32(mask) : msbSet64(mask) };
+ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ static_cast<Register>( )
+
+--- jsapi.cpp.orig 2011-03-31 19:08:36 UTC
++++ jsapi.cpp
+@@ -3985,7 +3985,7 @@ JS_Enumerate(JSContext *cx, JSObject *obj)
+ AutoIdVector props(cx);
+ JSIdArray *ida;
+ if (!GetPropertyNames(cx, obj, JSITER_OWNONLY, &props) || !VectorToIdArray(cx, props, &ida))
+- return false;
++ return NULL;
+ for (size_t n = 0; n < size_t(ida->length); ++n)
+ JS_ASSERT(js_CheckForStringIndex(ida->vector[n]) == ida->vector[n]);
+ return ida;
+--- jsbuiltins.h.orig 2011-03-31 19:08:36 UTC
++++ jsbuiltins.h
+@@ -284,14 +284,14 @@ struct ClosureVarInfo;
+ #define _JS_DEFINE_CALLINFO(linkage, name, crtype, cargtypes, argtypes, isPure, storeAccSet) \
+ _JS_TN_LINKAGE(linkage, crtype) name cargtypes; \
+ _JS_CI_LINKAGE(linkage) const nanojit::CallInfo _JS_CALLINFO(name) = \
+- { (intptr_t) &name, argtypes, nanojit::ABI_CDECL, isPure, storeAccSet _JS_CI_NAME(name) };\
++ { (uintptr_t) &name, argtypes, nanojit::ABI_CDECL, isPure, storeAccSet _JS_CI_NAME(name) };\
+ JS_STATIC_ASSERT_IF(isPure, (storeAccSet) == nanojit::ACCSET_NONE);
+
+ #else
+ #define _JS_DEFINE_CALLINFO(linkage, name, crtype, cargtypes, argtypes, isPure, storeAccSet) \
+ _JS_TN_LINKAGE(linkage, crtype) FASTCALL name cargtypes; \
+ _JS_CI_LINKAGE(linkage) const nanojit::CallInfo _JS_CALLINFO(name) = \
+- { (intptr_t) &name, argtypes, nanojit::ABI_FASTCALL, isPure, storeAccSet _JS_CI_NAME(name) }; \
++ { (uintptr_t) &name, argtypes, nanojit::ABI_FASTCALL, isPure, storeAccSet _JS_CI_NAME(name) }; \
+ JS_STATIC_ASSERT_IF(isPure, (storeAccSet) == nanojit::ACCSET_NONE);
+ #endif
+
+--- jsfun.cpp.orig 2011-03-31 19:08:36 UTC
++++ jsfun.cpp
+@@ -2051,7 +2051,7 @@ fun_toStringHelper(JSContext *cx, JSObject *obj, uintN
+
+ JSString *str = JS_DecompileFunction(cx, fun, indent);
+ if (!str)
+- return false;
++ return NULL;
+
+ if (!indent)
+ cx->compartment->toSourceCache.put(fun, str);
+@@ -2657,7 +2657,7 @@ LookupInterpretedFunctionPrototype(JSContext *cx, JSOb
+ const Shape *shape = funobj->nativeLookup(id);
+ if (!shape) {
+ if (!ResolveInterpretedFunctionPrototype(cx, funobj))
+- return false;
++ return NULL;
+ shape = funobj->nativeLookup(id);
+ }
+ JS_ASSERT(!shape->configurable());
+--- jsiter.cpp.orig 2011-03-31 19:08:36 UTC
++++ jsiter.cpp
+@@ -425,7 +425,7 @@ NewIteratorObject(JSContext *cx, uintN flags)
+ */
+ JSObject *obj = js_NewGCObject(cx, FINALIZE_OBJECT0);
+ if (!obj)
+- return false;
++ return NULL;
+ obj->init(cx, &js_IteratorClass, NULL, NULL, NULL, false);
+ obj->setMap(cx->compartment->emptyEnumeratorShape);
+ return obj;
+--- jsparse.cpp.orig 2011-03-31 19:08:36 UTC
++++ jsparse.cpp
+@@ -3352,7 +3352,7 @@ Parser::functionDef(JSAtom *funAtom, FunctionType type
+ if (!outertc->inFunction() && bodyLevel && funAtom && !lambda && outertc->compiling()) {
+ JS_ASSERT(pn->pn_cookie.isFree());
+ if (!DefineGlobal(pn, outertc->asCodeGenerator(), funAtom))
+- return false;
++ return NULL;
+ }
+
+ pn->pn_blockid = outertc->blockid();
+--- jsstr.cpp.orig 2011-03-31 19:08:36 UTC
++++ jsstr.cpp
+@@ -1734,7 +1734,7 @@ class RegExpGuard
+ if (flat) {
+ patstr = flattenPattern(cx, fm.patstr);
+ if (!patstr)
+- return false;
++ return NULL;
+ } else {
+ patstr = fm.patstr;
+ }
+@@ -3400,7 +3400,7 @@ js_InitStringClass(JSContext *cx, JSObject *obj)
+ UndefinedValue(), NULL, NULL,
+ JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0,
+ NULL)) {
+- return JS_FALSE;
++ return NULL;
+ }
+
+ return proto;
+--- jstypedarray.cpp.orig 2011-03-31 19:08:36 UTC
++++ jstypedarray.cpp
+@@ -1334,7 +1334,7 @@ class TypedArrayTemplate
+ if (size != 0 && count >= INT32_MAX / size) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_NEED_DIET, "size and count");
+- return false;
++ return NULL;
+ }
+
+ int32 bytelen = size * count;
+@@ -1668,7 +1668,7 @@ TypedArrayConstruct(JSContext *cx, jsint atype, uintN
+
+ default:
+ JS_NOT_REACHED("shouldn't have gotten here");
+- return false;
++ return NULL;
+ }
+ }
+
+--- jsxml.cpp.orig 2011-03-31 19:08:36 UTC
++++ jsxml.cpp
+@@ -282,7 +282,7 @@ NewXMLNamespace(JSContext *cx, JSLinearString *prefix,
+
+ obj = NewBuiltinClassInstanceXML(cx, &js_NamespaceClass);
+ if (!obj)
+- return JS_FALSE;
++ return NULL;
+ JS_ASSERT(JSVAL_IS_VOID(obj->getNamePrefixVal()));
+ JS_ASSERT(JSVAL_IS_VOID(obj->getNameURIVal()));
+ JS_ASSERT(JSVAL_IS_VOID(obj->getNamespaceDeclared()));
+@@ -431,7 +431,7 @@ ConvertQNameToString(JSContext *cx, JSObject *obj)
+ size_t length = str->length();
+ jschar *chars = (jschar *) cx->malloc((length + 2) * sizeof(jschar));
+ if (!chars)
+- return JS_FALSE;
++ return NULL;
+ *chars = '@';
+ const jschar *strChars = str->getChars(cx);
+ if (!strChars) {
+--- methodjit/InvokeHelpers.cpp.orig 2011-03-31 19:08:36 UTC
++++ methodjit/InvokeHelpers.cpp
+@@ -728,7 +728,7 @@ AtSafePoint(JSContext *cx)
+ {
+ JSStackFrame *fp = cx->fp();
+ if (fp->hasImacropc())
+- return false;
++ return NULL;
+
+ JSScript *script = fp->script();
+ return script->maybeNativeCodeForPC(fp->isConstructing(), cx->regs->pc);
+--- nanojit/NativeX64.cpp.orig 2011-03-31 19:08:36 UTC
++++ nanojit/NativeX64.cpp
+@@ -1899,7 +1899,7 @@ namespace nanojit
+ }
+ }
+
+- static const AVMPLUS_ALIGN16(int64_t) negateMask[] = {0x8000000000000000LL,0};
++ static const AVMPLUS_ALIGN16(int64_t) negateMask[] = {(int64_t)0x8000000000000000LL,0};
+
+ void Assembler::asm_fneg(LIns *ins) {
+ Register rr, ra;
+--- nanojit/RegAlloc.h.orig 2011-03-31 19:08:36 UTC
++++ nanojit/RegAlloc.h
+@@ -186,7 +186,7 @@ namespace nanojit
+ inline Register lsReg(RegisterMask mask) {
+ // This is faster than it looks; we rely on the C++ optimizer
+ // to strip the dead branch and inline just one alternative.
+- Register r = { (sizeof(RegisterMask) == 4) ? lsbSet32(mask) : lsbSet64(mask) };
++ Register r = { (sizeof(RegisterMask) == 4) ? (Register)lsbSet32(mask) : (Register)lsbSet64(mask) };
+ return r;
+ }
+
+@@ -194,7 +194,7 @@ namespace nanojit
+ inline Register msReg(RegisterMask mask) {
+ // This is faster than it looks; we rely on the C++ optimizer
+ // to strip the dead branch and inline just one alternative.
+- Register r = { (sizeof(RegisterMask) == 4) ? msbSet32(mask) : msbSet64(mask) };
++ Register r = { (sizeof(RegisterMask) == 4) ? (Register)msbSet32(mask) : (Register)msbSet64(mask) };
+ return r;
+ }
+
diff --git a/lang/spidermonkey185/files/patch-configure.in b/lang/spidermonkey185/files/patch-configure.in
new file mode 100644
index 000000000000..c8910057a423
--- /dev/null
+++ b/lang/spidermonkey185/files/patch-configure.in
@@ -0,0 +1,36 @@
+--- ./configure.in.orig 2011-04-01 06:08:36.000000000 +1100
++++ ./configure.in 2013-05-26 00:19:28.032315432 +1000
+@@ -3378,7 +3378,8 @@
+ rm -f conftest.{c,S}
+ ])
+ if test "$ac_cv_have_visibility_builtin_bug" = "no" -a \
+- "$ac_cv_have_visibility_class_bug" = "no"; then
++ "$ac_cv_have_visibility_class_bug" = "no" -a \
++ "$OS_ARCH" != "FreeBSD" ; then
+ VISIBILITY_FLAGS='-I$(DIST)/system_wrappers_js -include $(topsrcdir)/config/gcc_hidden.h'
+ WRAP_SYSTEM_INCLUDES=1
+ STL_FLAGS='-I$(DIST)/stl_wrappers'
+@@ -4656,6 +4657,9 @@ MOZ_ARG_HEADER(Individual module options
+
+ dnl Setup default CPU arch for arm target
+ case "$target_cpu" in
++ armv6*)
++ MOZ_ARM_ARCH=armv6
++ ;;
+ arm*)
+ MOZ_ARM_ARCH=armv7
+ ;;
+@@ -4716,6 +4720,13 @@ elif test "$MOZ_ARM_ARCH" = "armv7"; the
+ esac
+ else
+ case "$target_cpu" in
++ armv6*)
++ if test "$GNU_CC"; then
++ CFLAGS="$CFLAGS"
++ CXXFLAGS="$CXXFLAGS"
++ ASFLAGS="$ASFLAGS"
++ fi
++ ;;
+ arm*)
+ if test "$GNU_CC"; then
+ CFLAGS="$CFLAGS -march=armv5te -mthumb-interwork -msoft-float"
diff --git a/lang/spidermonkey185/files/patch-jsscript.h b/lang/spidermonkey185/files/patch-jsscript.h
new file mode 100644
index 000000000000..a642b31a8642
--- /dev/null
+++ b/lang/spidermonkey185/files/patch-jsscript.h
@@ -0,0 +1,48 @@
+# HG changeset patch
+# User Ehsan Akhgari <ehsan@mozilla.com>
+# Date 1308340787 14400
+# Node ID c0e8643e8e60d1c98bff30c78e034f991f75c191
+# Parent 284ebc48b2cb8e35dc04482ede700e717d8d214f
+Bug 662962 - Silence the clang warnings issued because of alignment requirements increase when compiling jsscript.h; r=Waldo
+
+--- ./jsscript.h.orig 2011-04-01 06:08:36.000000000 +1100
++++ ./jsscript.h 2013-05-26 00:23:16.202260566 +1000
+@@ -496,32 +496,32 @@
+
+ JSObjectArray *objects() {
+ JS_ASSERT(isValidOffset(objectsOffset));
+- return (JSObjectArray *)((uint8 *) (this + 1) + objectsOffset);
++ return reinterpret_cast<JSObjectArray *>(uintptr_t(this + 1) + objectsOffset);
+ }
+
+ JSUpvarArray *upvars() {
+ JS_ASSERT(isValidOffset(upvarsOffset));
+- return (JSUpvarArray *) ((uint8 *) (this + 1) + upvarsOffset);
++ return reinterpret_cast<JSUpvarArray *>(uintptr_t(this + 1) + upvarsOffset);
+ }
+
+ JSObjectArray *regexps() {
+ JS_ASSERT(isValidOffset(regexpsOffset));
+- return (JSObjectArray *) ((uint8 *) (this + 1) + regexpsOffset);
++ return reinterpret_cast<JSObjectArray *>(uintptr_t(this + 1) + regexpsOffset);
+ }
+
+ JSTryNoteArray *trynotes() {
+ JS_ASSERT(isValidOffset(trynotesOffset));
+- return (JSTryNoteArray *) ((uint8 *) (this + 1) + trynotesOffset);
++ return reinterpret_cast<JSTryNoteArray *>(uintptr_t(this + 1) + trynotesOffset);
+ }
+
+ js::GlobalSlotArray *globals() {
+ JS_ASSERT(isValidOffset(globalsOffset));
+- return (js::GlobalSlotArray *) ((uint8 *) (this + 1) + globalsOffset);
++ return reinterpret_cast<js::GlobalSlotArray *>(uintptr_t(this + 1) + globalsOffset);
+ }
+
+ JSConstArray *consts() {
+ JS_ASSERT(isValidOffset(constOffset));
+- return (JSConstArray *) ((uint8 *) (this + 1) + constOffset);
++ return reinterpret_cast<JSConstArray *>(uintptr_t(this + 1) + constOffset);
+ }
+
+ JSAtom *getAtom(size_t index) {
diff --git a/lang/spidermonkey185/files/patch-jsstr.cpp b/lang/spidermonkey185/files/patch-jsstr.cpp
new file mode 100644
index 000000000000..13ab1ee9f3d4
--- /dev/null
+++ b/lang/spidermonkey185/files/patch-jsstr.cpp
@@ -0,0 +1,36 @@
+# HG changeset patch
+# User Ehsan Akhgari <ehsan@mozilla.com>
+# Date 1308517488 14400
+# Node ID 284ebc48b2cb8e35dc04482ede700e717d8d214f
+# Parent cecc5adfc44068fb6f11b9baa78cb5fddc100b27
+Bug 662961 - Silence the clang warnings issued because of alignment requirements increase when compiling jsstr.cpp; r=Waldo
+
+--- ./jsstr.cpp.orig 2013-05-26 00:44:33.383765764 +1000
++++ ./jsstr.cpp 2013-05-26 00:46:35.842211859 +1000
+@@ -3147,7 +3147,7 @@
+ */
+ #define R(c) { \
+ BUILD_LENGTH_AND_FLAGS(1, JSString::FLAT | JSString::ATOMIZED), \
+- { (jschar *)(((char *)(unitStringTable + (c))) + \
++ { (jschar *)(uintptr_t(unitStringTable + (c)) + \
+ offsetof(JSString, inlineStorage)) }, \
+ { {(c), 0x00} } }
+
+@@ -3207,7 +3207,7 @@
+ */
+ #define R(c) { \
+ BUILD_LENGTH_AND_FLAGS(2, JSString::FLAT | JSString::ATOMIZED), \
+- { (jschar *)(((char *)(length2StringTable + (c))) + \
++ { (jschar *)(uintptr_t(length2StringTable + (c)) + \
+ offsetof(JSString, inlineStorage)) }, \
+ { {FROM_SMALL_CHAR((c) >> 6), FROM_SMALL_CHAR((c) & 0x3F), 0x00} } }
+
+@@ -3240,7 +3240,7 @@
+ */
+ #define R(c) { \
+ BUILD_LENGTH_AND_FLAGS(3, JSString::FLAT | JSString::ATOMIZED), \
+- { (jschar *)(((char *)(hundredStringTable + ((c) - 100))) + \
++ { (jschar *)(uintptr_t(hundredStringTable + ((c) - 100)) + \
+ offsetof(JSString, inlineStorage)) }, \
+ { {((c) / 100) + '0', ((c) / 10 % 10) + '0', ((c) % 10) + '0', 0x00} } }
+
diff --git a/lang/spidermonkey185/files/patch-nanojit_CodeAlloc.cpp b/lang/spidermonkey185/files/patch-nanojit_CodeAlloc.cpp
new file mode 100644
index 000000000000..52c65c0e9624
--- /dev/null
+++ b/lang/spidermonkey185/files/patch-nanojit_CodeAlloc.cpp
@@ -0,0 +1,10 @@
+--- nanojit/CodeAlloc.cpp.orig 2016-09-07 UTC
++++ nanojit/CodeAlloc.cpp
+@@ -261,7 +261,6 @@ namespace nanojit
+ #endif
+
+ #if defined(AVMPLUS_UNIX) && defined(NANOJIT_ARM)
+-#include <asm/unistd.h>
+ extern "C" void __clear_cache(char *BEG, char *END);
+ #endif
+
diff --git a/lang/spidermonkey185/files/patch-nanojit_njcpudetect.h b/lang/spidermonkey185/files/patch-nanojit_njcpudetect.h
new file mode 100644
index 000000000000..4a26a07ab688
--- /dev/null
+++ b/lang/spidermonkey185/files/patch-nanojit_njcpudetect.h
@@ -0,0 +1,11 @@
+--- nanojit/njcpudetect.h.orig 2016-09-07 UTC
++++ nanojit/njcpudetect.h
+@@ -77,6 +77,8 @@
+ #elif defined(__ARM_ARCH_6__) || \
+ defined(__ARM_ARCH_6J__) || \
+ defined(__ARM_ARCH_6T2__) || \
++ defined(__ARM_ARCH_6K__) || \
++ defined(__ARM_ARCH_6KZ__) || \
+ defined(__ARM_ARCH_6Z__) || \
+ defined(__ARM_ARCH_6ZK__) || \
+ defined(__ARM_ARCH_6M__) || \
diff --git a/lang/spidermonkey185/pkg-descr b/lang/spidermonkey185/pkg-descr
new file mode 100644
index 000000000000..db4318240eed
--- /dev/null
+++ b/lang/spidermonkey185/pkg-descr
@@ -0,0 +1,3 @@
+Spidermonkey is the JavaScript interpreter from the Mozilla project.
+
+WWW: http://www.mozilla.org/js/spidermonkey/
diff --git a/lang/spidermonkey185/pkg-plist b/lang/spidermonkey185/pkg-plist
new file mode 100644
index 000000000000..f7735572dd26
--- /dev/null
+++ b/lang/spidermonkey185/pkg-plist
@@ -0,0 +1,106 @@
+bin/js-config
+include/js/Allocator.h
+include/js/Assembler.h
+include/js/CodeAlloc.h
+include/js/Containers.h
+include/js/Fragmento.h
+include/js/LIR.h
+include/js/LIRopcode.tbl
+include/js/Native.h
+include/js/NativeCommon.h
+%%ARM%%/include/js/NativeARM.h
+%%MIPS%%/include/js/NativeMIPS.h
+%%PPC%%/include/js/NativePPC.h
+%%SPARC%%/include/js/NativeSparc.h
+%%AMD64%%include/js/NativeX64.h
+%%I386%%include/js/Nativei386.h
+include/js/RegAlloc.h
+include/js/VMPI.h
+include/js/Writer.h
+include/js/avmplus.h
+include/js/js-config.h
+include/js/js.msg
+include/js/jsanalyze.h
+include/js/jsapi.h
+include/js/jsarena.h
+include/js/jsarray.h
+include/js/jsatom.h
+include/js/jsautocfg.h
+include/js/jsautokw.h
+include/js/jsbit.h
+include/js/jsbool.h
+include/js/jsbuiltins.h
+include/js/jscell.h
+include/js/jsclist.h
+include/js/jsclone.h
+include/js/jscntxt.h
+include/js/jscompartment.h
+include/js/jscompat.h
+include/js/jsdate.h
+include/js/jsdbgapi.h
+include/js/jsdhash.h
+include/js/jsdtoa.h
+include/js/jsemit.h
+include/js/jsfriendapi.h
+include/js/jsfun.h
+include/js/jsgc.h
+include/js/jsgcchunk.h
+include/js/jsgcstats.h
+include/js/jshash.h
+include/js/jshashtable.h
+include/js/jshotloop.h
+include/js/jsinterp.h
+include/js/jsinttypes.h
+include/js/jsiter.h
+include/js/jslock.h
+include/js/jslong.h
+include/js/jsmath.h
+include/js/jsobj.h
+include/js/jsobjinlines.h
+include/js/json.h
+include/js/jsopcode.h
+include/js/jsopcode.tbl
+include/js/jsopcodeinlines.h
+include/js/jsotypes.h
+include/js/jsparse.h
+include/js/jsperf.h
+include/js/jsprf.h
+include/js/jsprobes.h
+include/js/jspropertycache.h
+include/js/jspropertycacheinlines.h
+include/js/jspropertytree.h
+include/js/jsproto.tbl
+include/js/jsproxy.h
+include/js/jsprvtd.h
+include/js/jspubtd.h
+include/js/jsreflect.h
+include/js/jsregexp.h
+include/js/jsscan.h
+include/js/jsscope.h
+include/js/jsscript.h
+include/js/jsscriptinlines.h
+include/js/jsstaticcheck.h
+include/js/jsstdint.h
+include/js/jsstr.h
+include/js/jstl.h
+include/js/jstracer.h
+include/js/jstypedarray.h
+include/js/jstypes.h
+include/js/jsutil.h
+include/js/jsval.h
+include/js/jsvalue.h
+include/js/jsvector.h
+include/js/jsversion.h
+include/js/jswrapper.h
+include/js/jsxdrapi.h
+include/js/jsxml.h
+include/js/nanojit.h
+include/js/njconfig.h
+include/js/njcpudetect.h
+include/js/prmjtime.h
+lib/libmozjs185.so
+lib/libmozjs185-1.0.a
+lib/libmozjs185.so.1.0.0
+lib/libmozjs185.so.1.0
+lib/libmozjs185.so.1
+libdata/pkgconfig/mozjs185.pc