This file is part of MXE. See LICENSE.md for licensing information.

Contains ad hoc patches for cross building.

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Tony Theodore <tonyt@logyst.com>
Date: Sat, 18 Nov 2017 20:43:52 +1100
Subject: [PATCH 1/2] fixes

This patch has been taken from: https://bitbucket.org/msys2/coin/commits/69e9990b05cee506f5fa16c6edad02a7808bc610/raw/

It was modified to work with Coin 3.1.3.
(The order of the template arguments of SbHash was switched.)

diff --git a/include/Inventor/C/glue/spidermonkey.h b/include/Inventor/C/glue/spidermonkey.h
index 1111111..2222222 100644
--- a/include/Inventor/C/glue/spidermonkey.h
+++ b/include/Inventor/C/glue/spidermonkey.h
@@ -47,7 +47,7 @@ extern "C" {
    Structs and defines.
 */
 typedef int JSBool;
-typedef long jsword;
+typedef intmax_t jsword;
 typedef jsword jsval;
 typedef jsword jsid;
 typedef int intN;
diff --git a/include/Inventor/C/glue/spidermonkey.h.orig b/include/Inventor/C/glue/spidermonkey.h.orig
new file mode 100644
index 1111111..2222222
--- /dev/null
+++ b/include/Inventor/C/glue/spidermonkey.h.orig
@@ -0,0 +1,470 @@
+#ifndef COIN_GLUE_SPIDERMONKEY_H
+#define COIN_GLUE_SPIDERMONKEY_H
+
+/**************************************************************************\
+ *
+ *  This file is part of the Coin 3D visualization library.
+ *  Copyright (C) by Kongsberg Oil & Gas Technologies.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  ("GPL") version 2 as published by the Free Software Foundation.
+ *  See the file LICENSE.GPL at the root directory of this source
+ *  distribution for additional information about the GNU GPL.
+ *
+ *  For using Coin with software that can not be combined with the GNU
+ *  GPL, and for taking advantage of the additional benefits of our
+ *  support services, please contact Kongsberg Oil & Gas Technologies
+ *  about acquiring a Coin Professional Edition License.
+ *
+ *  See http://www.coin3d.org/ for more information.
+ *
+ *  Kongsberg Oil & Gas Technologies, Bygdoy Alle 5, 0257 Oslo, NORWAY.
+ *  http://www.sim.no/  sales@sim.no  coin-support@coin3d.org
+ *
+\**************************************************************************/
+
+#include <Inventor/C/basic.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#if 0 /* to get proper auto-indentation in emacs */
+}
+#endif /* emacs indentation */
+
+
+/*
+  This is used to detect whether the 'jsapi.h' was included by the
+  user or not. The JSVERSION_IS_ECMA is defined in the 'jspubtd.h'
+  file in the SpiderMonkey header directory. 
+*/
+#ifndef JSVERSION_IS_ECMA
+
+
+/*
+   Structs and defines.
+*/
+typedef int JSBool;
+typedef long jsword;
+typedef jsword jsval;
+typedef jsword jsid;
+typedef int intN;
+typedef unsigned int uintN;
+typedef uint16_t jschar;
+
+typedef int32_t jsrefcount;
+typedef uint8_t jsbytecode;
+typedef uint32_t JSHashNumber;
+typedef uint32_t jsatomid;
+
+typedef enum JSType {
+  JSTYPE_VOID,
+  JSTYPE_OBJECT,
+  JSTYPE_FUNCTION,
+  JSTYPE_STRING,
+  JSTYPE_NUMBER,
+  JSTYPE_BOOLEAN,
+  JSTYPE_LIMIT
+} JSType;
+
+typedef enum JSAccessMode {
+  JSACC_PROTO = 0,
+  JSACC_PARENT = 1,
+  JSACC_IMPORT = 2,
+  JSACC_WATCH = 3,
+  JSACC_READ = 4,
+  JSACC_WRITE = 8,
+  JSACC_LIMIT
+} JSAccessMode;
+
+typedef enum JSGCStatus {
+  JSGC_BEGIN,
+  JSGC_END,
+  JSGC_MARK_END,
+  JSGC_FINALIZE_END
+} JSGCStatus;
+
+struct JSIdArray {
+    int32_t length;
+    jsid vector[1];
+};
+
+typedef void JSRuntime;
+typedef void JSContext;
+typedef void JSObject;
+typedef void JSObjectOps;
+typedef void JSXDRState;
+typedef void JSString;
+typedef struct JSClass JSClass;
+typedef struct JSPropertySpec JSPropertySpec;
+typedef int JSVersion;
+typedef void JSFunction;
+typedef struct JSFunctionSpec JSFunctionSpec;
+typedef struct JSErrorReport JSErrorReport;
+typedef void JSScript;
+
+#define JS_DLL_CALLBACK /* FIXME: set up this define properly. 20050601 mortene. */
+
+typedef JSBool (* JS_DLL_CALLBACK JSPropertyOp)(JSContext *, JSObject *, jsval, jsval *);
+typedef JSBool (* JS_DLL_CALLBACK JSEnumerateOp)(JSContext *, JSObject *);
+typedef JSBool (* JS_DLL_CALLBACK JSResolveOp)(JSContext *, JSObject *, jsval);
+typedef JSBool (* JS_DLL_CALLBACK JSConvertOp)(JSContext *, JSObject *, JSType, jsval *);
+typedef void (* JS_DLL_CALLBACK JSFinalizeOp)(JSContext *, JSObject *);
+typedef JSObjectOps * (* JS_DLL_CALLBACK JSGetObjectOps)(JSContext *, JSClass *);
+typedef JSBool (* JS_DLL_CALLBACK JSCheckAccessOp)(JSContext *, JSObject *, jsval, JSAccessMode, jsval *);
+typedef JSBool (* JS_DLL_CALLBACK JSNative)(JSContext *, JSObject *, uintN, jsval *, jsval *);
+typedef JSBool (* JS_DLL_CALLBACK JSXDRObjectOp)(JSXDRState *, JSObject **);
+typedef JSBool (* JS_DLL_CALLBACK JSHasInstanceOp)(JSContext *, JSObject *, jsval, JSBool *);
+typedef uint32_t (* JS_DLL_CALLBACK JSMarkOp)(JSContext *, JSObject *, void *);
+
+struct JSClass {
+  const char * name;
+  uint32_t flags;
+  JSPropertyOp addProperty;
+  JSPropertyOp delProperty;
+  JSPropertyOp getProperty;
+  JSPropertyOp setProperty;
+  JSEnumerateOp enumerate;
+  JSResolveOp resolve;
+  JSConvertOp convert;
+  JSFinalizeOp finalize;
+  JSGetObjectOps getObjectOps;
+  JSCheckAccessOp checkAccess;
+  JSNative call;
+  JSNative construct;
+  JSXDRObjectOp xdrObject;
+  JSHasInstanceOp hasInstance;
+  JSMarkOp mark;
+  jsword spare;
+};
+
+struct JSPropertySpec {
+  const char * name;
+  int8_t tinyid;
+  uint8_t flags;
+  JSPropertyOp getter;
+  JSPropertyOp setter;
+};
+
+struct JSFunctionSpec {
+  const char *name;
+  JSNative call;
+  uint8_t nargs;
+  uint8_t flags;
+  uint16_t extra;
+};
+
+struct JSErrorReport {
+  const char * filename;
+  uintN lineno;
+  const char * linebuf;
+  const char * tokenptr;
+  const jschar * uclinebuf;
+  const jschar * uctokenptr;
+  uintN flags;
+  uintN errorNumber;
+  const jschar * ucmessage;
+  const jschar ** messageArgs;
+};
+
+
+/* Defines and macros. ************************************************** */
+
+#define JSVAL_OBJECT 0x0
+#define JSVAL_INT 0x1
+#define JSVAL_DOUBLE 0x2
+#define JSVAL_STRING 0x4
+#define JSVAL_BOOLEAN 0x6
+
+#define JS_BIT(n)       ((uint32_t)1 << (n))
+#define JS_BITMASK(n)   (JS_BIT(n) - 1)
+
+#define JSVAL_TAGBITS 3
+#define JSVAL_TAGMASK           JS_BITMASK(JSVAL_TAGBITS)
+#define JSVAL_TAG(v)            ((v) & JSVAL_TAGMASK)
+#define JSVAL_SETTAG(v,t) ((v) | (t))
+#define JSVAL_CLRTAG(v)         ((v) & ~(jsval)JSVAL_TAGMASK)
+
+#define JSVAL_IS_PRIMITIVE(v)   (!JSVAL_IS_OBJECT(v) || JSVAL_IS_NULL(v))
+#define JSVAL_IS_OBJECT(v)      (JSVAL_TAG(v) == JSVAL_OBJECT)
+#define JSVAL_IS_NUMBER(v)      (JSVAL_IS_INT(v) || JSVAL_IS_DOUBLE(v))
+#define JSVAL_IS_INT(v)         (((v) & JSVAL_INT) && (v) != JSVAL_VOID)
+#define JSVAL_IS_DOUBLE(v)      (JSVAL_TAG(v) == JSVAL_DOUBLE)
+#define JSVAL_IS_STRING(v)      (JSVAL_TAG(v) == JSVAL_STRING)
+#define JSVAL_IS_BOOLEAN(v)     (JSVAL_TAG(v) == JSVAL_BOOLEAN)
+#define JSVAL_IS_NULL(v)        ((v) == JSVAL_NULL)
+#define JSVAL_IS_VOID(v)        ((v) == JSVAL_VOID)
+
+#define BOOLEAN_TO_JSVAL(b) JSVAL_SETTAG((jsval)(b) << JSVAL_TAGBITS, JSVAL_BOOLEAN)
+#define JSVAL_TO_BOOLEAN(v) ((JSBool)((v) >> JSVAL_TAGBITS))
+
+#define JSVAL_INT_BITS          31
+#define JSVAL_INT_POW2(n)       ((jsval)1 << (n))
+#define JSVAL_INT_MIN           ((jsval)1 - JSVAL_INT_POW2(30))
+#define JSVAL_INT_MAX           (JSVAL_INT_POW2(30) - 1)
+#define INT_FITS_IN_JSVAL(i)    ((uint32_t)((i)+JSVAL_INT_MAX) <= 2*JSVAL_INT_MAX)
+#define JSVAL_TO_INT(v)         ((int32_t)(v) >> 1)
+#define INT_TO_JSVAL(i)         (((jsval)(i) << 1) | JSVAL_INT)
+
+#define JSVAL_TO_GCTHING(v)     ((void *)JSVAL_CLRTAG(v))
+#define JSVAL_TO_OBJECT(v)      ((JSObject *)JSVAL_TO_GCTHING(v))
+#define JSVAL_TO_DOUBLE(v)      ((double *)JSVAL_TO_GCTHING(v))
+#define JSVAL_TO_STRING(v)      ((JSString *)JSVAL_TO_GCTHING(v))
+#define OBJECT_TO_JSVAL(obj)    ((jsval)(obj))
+#define DOUBLE_TO_JSVAL(dp)     JSVAL_SETTAG((jsval)(dp), JSVAL_DOUBLE)
+#define STRING_TO_JSVAL(str)    JSVAL_SETTAG((jsval)(str), JSVAL_STRING)
+#define JSVAL_TO_PRIVATE(v)     ((void *)((v) & ~JSVAL_INT))
+#define PRIVATE_TO_JSVAL(p)     ((jsval)(p) | JSVAL_INT)
+
+#define JSPROP_ENUMERATE 0x01
+#define JSPROP_READONLY 0x02
+#define JSPROP_PERMANENT 0x04
+#define JSPROP_EXPORTED 0x08
+#define JSPROP_GETTER 0x10
+#define JSPROP_SETTER 0x20
+#define JSPROP_SHARED 0x40
+#define JSPROP_INDEX 0x80
+
+#define JS_FALSE (int)0
+#define JS_TRUE (int)1
+
+#define JSVAL_VOID   INT_TO_JSVAL(0 - JSVAL_INT_POW2(30))
+#define JSVAL_NULL   OBJECT_TO_JSVAL(0)
+#define JSVAL_ZERO   INT_TO_JSVAL(0)
+#define JSVAL_ONE    INT_TO_JSVAL(1)
+#define JSVAL_FALSE  BOOLEAN_TO_JSVAL(JS_FALSE)
+#define JSVAL_TRUE   BOOLEAN_TO_JSVAL(JS_TRUE)
+
+#define JSCLASS_HAS_PRIVATE             (1<<0)
+#define JSCLASS_NEW_ENUMERATE           (1<<1)
+#define JSCLASS_NEW_RESOLVE             (1<<2)
+#define JSCLASS_PRIVATE_IS_NSISUPPORTS  (1<<3)
+#define JSCLASS_SHARE_ALL_PROPERTIES    (1<<4)
+#define JSCLASS_NEW_RESOLVE_GETS_START  (1<<5)
+
+#define JSFUN_BOUND_METHOD 0x40
+
+#define JSOPTION_STRICT                 JS_BIT(0)
+#define JSOPTION_WERROR                 JS_BIT(1)
+#define JSOPTION_VAROBJFIX              JS_BIT(2)
+#define JSOPTION_PRIVATE_IS_NSISUPPORTS JS_BIT(3)
+#define JSOPTION_COMPILE_N_GO           JS_BIT(4)
+
+
+/* Function typedefs. *************************************************** */
+
+typedef void (* JS_DLL_CALLBACK JSErrorReporter)(JSContext *, const char *, JSErrorReport *);
+typedef JSBool (* JS_DLL_CALLBACK JSGCCallback)(JSContext *, JSGCStatus);
+
+#endif /* !JSVERSION_IS_ECMA */
+
+typedef JSBool (* JS_EvaluateScript_t)(JSContext *, JSObject *, const char *, uintN, const char *, uintN, jsval *);
+typedef JSString * (* JS_ValueToString_t)(JSContext *, jsval);
+typedef char * (* JS_GetStringBytes_t)(JSString *);
+typedef JSBool (* JS_SetProperty_t)(JSContext *, JSObject *, const char *, jsval *);
+typedef JSBool (* JS_GetProperty_t)(JSContext *, JSObject *, const char *, jsval *);
+typedef JSBool (* JS_CallFunctionName_t)(JSContext *, JSObject *, const char *, uintN, jsval *, jsval *);
+typedef JSBool (* JS_CallFunctionValue_t)(JSContext *, JSObject *, jsval, uintN, jsval *, jsval *);
+typedef JSObject * (* JS_ConstructObjectWithArguments_t)(JSContext *, JSClass *, JSObject *, JSObject *, uintN, jsval *);
+typedef JSRuntime * (* JS_NewRuntime_t)(uint32_t);
+typedef void (* JS_DestroyRuntime_t)(JSRuntime *);
+typedef JSContext * (* JS_NewContext_t)(JSRuntime *, size_t);
+typedef void (* JS_DestroyContext_t)(JSContext *);
+typedef void (* JS_ShutDown_t)(void);
+typedef JSObject * (* JS_NewObject_t)(JSContext *, JSClass *, JSObject *, JSObject *);
+typedef JSBool (* JS_InitStandardClasses_t)(JSContext *, JSObject *);
+typedef JSErrorReporter (* JS_SetErrorReporter_t)(JSContext *, JSErrorReporter);
+typedef JSBool (* JS_PropertyStub_t)(JSContext *, JSObject *, jsval, jsval *);
+typedef JSBool (* JS_EnumerateStub_t)(JSContext *, JSObject *);
+typedef JSBool (* JS_ResolveStub_t)(JSContext *, JSObject *, jsval);
+typedef JSBool (* JS_ConvertStub_t)(JSContext *, JSObject *, JSType, jsval *);
+typedef void (* JS_FinalizeStub_t)(JSContext *, JSObject *);
+typedef const char * (* JS_GetImplementationVersion_t)(void);
+typedef void * (* JS_GetPrivate_t)(JSContext *, JSObject *);
+typedef JSBool (* JS_SetPrivate_t)(JSContext *, JSObject *, void *);
+typedef JSFunction * (* JS_NewFunction_t)(JSContext *, JSNative, uintN, uintN flags, JSObject *, const char *);
+typedef JSObject * (* JS_GetFunctionObject_t)(JSFunction *);
+typedef JSObject * (* JS_DefineObject_t)(JSContext *, JSObject *, const char *, JSClass *, JSObject *, uintN);
+typedef JSBool (* JS_DefineProperties_t)(JSContext *, JSObject *, JSPropertySpec *);
+typedef JSObject * (* JS_GetParent_t)(JSContext *, JSObject *);
+typedef JSBool (* JS_SetParent_t)(JSContext *, JSObject *, JSObject *);
+typedef JSBool (* JS_DefineFunctions_t)(JSContext *, JSObject *, JSFunctionSpec *);
+typedef JSString * (* JS_NewStringCopyZ_t)(JSContext *, const char *);
+typedef JSType (* JS_TypeOfValue_t)(JSContext *, jsval);
+typedef const char * (* JS_GetTypeName_t)(JSContext *, JSType);
+typedef JSBool (* JS_InstanceOf_t)(JSContext *, JSObject *, JSClass *, jsval *);
+typedef JSObject * (* JS_InitClass_t)(JSContext *, JSObject *, JSObject *, JSClass *,
+                                      JSNative, uintN, JSPropertySpec *, JSFunctionSpec *,
+                                      JSPropertySpec *, JSFunctionSpec *);
+typedef JSBool (* JS_NewDoubleValue_t)(JSContext *, double, jsval *);
+typedef void * (* JS_GetContextPrivate_t)(JSContext *);
+typedef void (* JS_SetContextPrivate_t)(JSContext *, void *);
+typedef JSBool (* JS_ValueToBoolean_t)(JSContext *, jsval, JSBool *);
+typedef JSBool (* JS_ValueToNumber_t)(JSContext *, jsval, double *);
+typedef JSObject * (* JS_NewArrayObject_t)(JSContext *, int32_t, jsval *);
+typedef JSBool (* JS_GetArrayLength_t)(JSContext *, JSObject *, uint32_t *);
+typedef JSBool (* JS_SetArrayLength_t)(JSContext *, JSObject *, uint32_t);
+typedef JSBool (* JS_HasArrayLength_t)(JSContext *, JSObject *, uint32_t *);
+typedef JSBool (* JS_GetElement_t)(JSContext *, JSObject *, int32_t, jsval *);
+typedef JSBool (* JS_SetElement_t)(JSContext *, JSObject *, int32_t, jsval *);
+typedef JSBool (* JS_AddRoot_t)(JSContext *, void *);
+typedef JSBool (* JS_RemoveRoot_t)(JSContext *, void *);
+typedef size_t (* JS_GetStringLength_t)(JSString *);
+typedef JSBool (* JS_LookupProperty_t)(JSContext *, JSObject *, const char *, jsval *);
+typedef JSBool (* JS_DefineProperty_t)(JSContext *, JSObject *, const char *, jsval, JSPropertyOp, JSPropertyOp, uintN);
+typedef JSScript * (* JS_CompileFile_t)(JSContext *, JSObject *, const char *);
+typedef JSBool (* JS_ValueToObject_t)(JSContext *, jsval, JSObject **);
+typedef JSBool (* JS_ExecuteScript_t)(JSContext *, JSObject *, JSScript *, jsval *);
+typedef JSBool (* JS_IsExceptionPending_t)(JSContext *);
+typedef JSBool (* JS_GetPendingException_t)(JSContext *, jsval *);
+typedef void (* JS_SetPendingException_t)(JSContext *, jsval);
+typedef void (* JS_ClearPendingException_t)(JSContext *);
+typedef double * (* JS_NewDouble_t)(JSContext *, double);
+typedef JSBool (* JS_CallFunction_t)(JSContext *, JSObject *, JSFunction *, uintN, jsval *, jsval *);
+typedef JSFunction * (* JS_ValueToFunction_t)(JSContext *, jsval);
+typedef void (* JS_ReportError_t)(JSContext *, const char *, ...);
+typedef JSBool (* JS_IsArrayObject_t)(JSContext *, JSObject *);
+typedef JSBool (* JS_ObjectIsFunction_t)(JSContext *, JSObject *);
+typedef JSBool (* JS_ValueToECMAInt32_t)(JSContext *, jsval, int32_t *);
+typedef JSFunction * (* JS_DefineFunction_t)(JSContext *, JSObject *, const char *, JSNative, uintN, uintN);
+typedef JSObject * (* JS_GetGlobalObject_t)(JSContext *);
+typedef JSGCCallback (* JS_SetGCCallback_t)(JSContext *, JSGCCallback);
+typedef void (* JS_GC_t)(JSContext *);
+typedef void (* JS_MaybeGC_t)(JSContext *);
+typedef JSBool (* JS_IsRunning_t)(JSContext *);
+typedef JSBool (* JS_DeleteProperty_t)(JSContext *, JSObject *, const char *);
+typedef JSScript * (* JS_CompileScript_t)(JSContext *, JSObject *,
+                                          const char *, size_t,
+                                          const char *, uintN);
+typedef jsval (* JS_GetNaNValue_t)(JSContext *);
+typedef jsval (* JS_GetNegativeInfinityValue_t)(JSContext *);
+typedef jsval (* JS_GetPositiveInfinityValue_t)(JSContext *);
+typedef jsval (* JS_GetEmptyStringValue_t)(JSContext *);
+typedef JSBool (* JS_SetPropertyAttributes_t)(JSContext *, JSObject *, const char *, uintN, JSBool *);
+typedef JSBool (* JS_GetPropertyAttributes_t)(JSContext *, JSObject *, const char *, uintN *, JSBool *);
+typedef JSClass * (* JS_GetClass_t)(JSObject *);
+typedef JSObject * (* JS_GetPrototype_t)(JSContext *, JSObject *);
+typedef JSObject * (* JS_SetPrototype_t)(JSContext *, JSObject *, JSObject *);
+typedef intN (* JS_CompareStrings_t)(JSString *, JSString *);
+typedef uint32_t (* JS_GetOptions_t)(JSContext *);
+typedef uint32_t (* JS_SetOptions_t)(JSContext *, uint32_t);
+typedef uint32_t (* JS_ToggleOptions_t)(JSContext *, uint32_t);
+typedef struct JSIdArray * (* JS_Enumerate_t)(JSContext *, JSObject *);
+typedef JSBool (* JS_IdToValue_t)(JSContext *, jsid, jsval *);
+typedef const char * (* JS_GetFunctionName_t)(JSFunction *);
+typedef JSObject * (* JS_GetConstructor_t)(JSContext *, JSObject *);
+typedef void (* JS_DestroyIdArray_t)(JSContext *, struct JSIdArray *);
+
+
+/* Access interface. **************************************************** */
+
+typedef struct {
+  int available;
+
+  JS_CallFunctionName_t JS_CallFunctionName;
+  JS_CallFunctionValue_t JS_CallFunctionValue;
+  JS_ConstructObjectWithArguments_t JS_ConstructObjectWithArguments;
+  JS_ConvertStub_t JS_ConvertStub;
+  JS_DestroyContext_t JS_DestroyContext;
+  JS_DestroyRuntime_t JS_DestroyRuntime;
+  JS_EnumerateStub_t JS_EnumerateStub;
+  JS_EvaluateScript_t JS_EvaluateScript;
+  JS_FinalizeStub_t JS_FinalizeStub;
+  JS_GetClass_t JS_GetClass;
+  JS_GetImplementationVersion_t JS_GetImplementationVersion;
+  JS_GetProperty_t JS_GetProperty;
+  JS_GetStringBytes_t JS_GetStringBytes;
+  JS_InitStandardClasses_t JS_InitStandardClasses;
+  JS_NewContext_t JS_NewContext;
+  JS_NewObject_t JS_NewObject;
+  JS_NewRuntime_t JS_NewRuntime;
+  JS_PropertyStub_t JS_PropertyStub;
+  JS_ResolveStub_t JS_ResolveStub;
+  JS_SetErrorReporter_t JS_SetErrorReporter;
+  JS_SetProperty_t JS_SetProperty;
+  JS_ShutDown_t JS_ShutDown;
+  JS_ValueToString_t JS_ValueToString;
+  JS_DefineObject_t JS_DefineObject;
+  JS_DefineProperties_t JS_DefineProperties;
+  JS_GetPrivate_t JS_GetPrivate;
+  JS_SetPrivate_t JS_SetPrivate;
+  JS_NewFunction_t JS_NewFunction;
+  JS_GetFunctionObject_t JS_GetFunctionObject;
+  JS_GetParent_t JS_GetParent;
+  JS_SetParent_t JS_SetParent;
+  JS_DefineFunctions_t JS_DefineFunctions;
+  JS_NewStringCopyZ_t JS_NewStringCopyZ;
+  JS_TypeOfValue_t JS_TypeOfValue;
+  JS_GetTypeName_t JS_GetTypeName;
+  JS_InstanceOf_t JS_InstanceOf;
+  JS_InitClass_t JS_InitClass;
+  JS_NewDoubleValue_t JS_NewDoubleValue;
+  JS_GetContextPrivate_t JS_GetContextPrivate;
+  JS_SetContextPrivate_t JS_SetContextPrivate;
+  JS_ValueToBoolean_t JS_ValueToBoolean;
+  JS_ValueToNumber_t JS_ValueToNumber;
+  JS_NewArrayObject_t JS_NewArrayObject;
+  JS_GetArrayLength_t JS_GetArrayLength;
+  JS_SetArrayLength_t JS_SetArrayLength;
+  JS_HasArrayLength_t JS_HasArrayLength;
+  JS_GetElement_t JS_GetElement;
+  JS_SetElement_t JS_SetElement;
+  JS_AddRoot_t JS_AddRoot;
+  JS_RemoveRoot_t JS_RemoveRoot;
+  JS_GetStringLength_t JS_GetStringLength;
+  JS_LookupProperty_t JS_LookupProperty;
+  JS_DefineProperty_t JS_DefineProperty;
+  JS_CompileFile_t JS_CompileFile;
+  JS_ValueToObject_t JS_ValueToObject;
+  JS_ExecuteScript_t JS_ExecuteScript;
+  JS_IsExceptionPending_t JS_IsExceptionPending;
+  JS_GetPendingException_t JS_GetPendingException;
+  JS_SetPendingException_t JS_SetPendingException;
+  JS_ClearPendingException_t JS_ClearPendingException;
+  JS_NewDouble_t JS_NewDouble;
+  JS_CallFunction_t JS_CallFunction;
+  JS_ValueToFunction_t JS_ValueToFunction;
+  JS_ReportError_t JS_ReportError;
+  JS_IsArrayObject_t JS_IsArrayObject;
+  JS_ObjectIsFunction_t JS_ObjectIsFunction;
+  // Note: We use this function instead of JS_ValueToInt32() since the 
+  // latter is buggy in versions of SpiderMonkey older than 2005-09-29, 
+  // see Mozilla bug #284032.
+  JS_ValueToECMAInt32_t JS_ValueToECMAInt32;
+  JS_DefineFunction_t JS_DefineFunction;
+  JS_GetGlobalObject_t JS_GetGlobalObject;
+  JS_SetGCCallback_t JS_SetGCCallback;
+  JS_GC_t JS_GC;
+  JS_MaybeGC_t JS_MaybeGC;
+  JS_IsRunning_t JS_IsRunning;
+  JS_DeleteProperty_t JS_DeleteProperty;
+  JS_CompileScript_t JS_CompileScript;
+  JS_GetNaNValue_t JS_GetNaNValue;
+  JS_GetNegativeInfinityValue_t JS_GetNegativeInfinityValue;
+  JS_GetPositiveInfinityValue_t JS_GetPositiveInfinityValue;
+  JS_GetEmptyStringValue_t JS_GetEmptyStringValue;
+  JS_SetPropertyAttributes_t JS_SetPropertyAttributes;
+  JS_GetPropertyAttributes_t JS_GetPropertyAttributes;
+  JS_GetPrototype_t JS_GetPrototype;
+  JS_SetPrototype_t JS_SetPrototype;
+  JS_CompareStrings_t JS_CompareStrings;
+  JS_GetOptions_t JS_GetOptions;
+  JS_SetOptions_t JS_SetOptions;
+  JS_ToggleOptions_t JS_ToggleOptions;
+  JS_Enumerate_t JS_Enumerate;
+  JS_IdToValue_t JS_IdToValue;
+  JS_GetFunctionName_t JS_GetFunctionName;
+  JS_GetConstructor_t JS_GetConstructor;
+  JS_DestroyIdArray_t JS_DestroyIdArray;
+
+} SpiderMonkey_t;
+
+COIN_DLL_API const SpiderMonkey_t * spidermonkey(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* !COIN_GLUE_SPIDERMONKEY_H */
diff --git a/src/foreignfiles/SoSTLFileKit.cpp b/src/foreignfiles/SoSTLFileKit.cpp
index 1111111..2222222 100644
--- a/src/foreignfiles/SoSTLFileKit.cpp
+++ b/src/foreignfiles/SoSTLFileKit.cpp
@@ -594,14 +594,14 @@ SoSTLFileKit::addFacet(const SbVec3f & v1, const SbVec3f & v2, const SbVec3f & v
     SO_GET_ANY_PART(this, "facets", SoIndexedFaceSet);
 
   // find existing indexes if any
-  long v1idx = PRIVATE(this)->points->findPoint(v1), v1new = (v1idx == -1);
-  long v2idx = PRIVATE(this)->points->findPoint(v2), v2new = (v2idx == -1);
-  long v3idx = PRIVATE(this)->points->findPoint(v3), v3new = (v3idx == -1);
-  if (!v1new) { v1idx = (long) PRIVATE(this)->points->getUserData(v1idx); }
-  if (!v2new) { v2idx = (long) PRIVATE(this)->points->getUserData(v2idx); }
-  if (!v3new) { v3idx = (long) PRIVATE(this)->points->getUserData(v3idx); }
-  long nidx = PRIVATE(this)->normals->findPoint(n);
-  if (nidx != -1) { nidx = (long) PRIVATE(this)->normals->getUserData(nidx); }
+  intmax_t v1idx = PRIVATE(this)->points->findPoint(v1), v1new = (v1idx == -1);
+  intmax_t v2idx = PRIVATE(this)->points->findPoint(v2), v2new = (v2idx == -1);
+  intmax_t v3idx = PRIVATE(this)->points->findPoint(v3), v3new = (v3idx == -1);
+  if (!v1new) { v1idx = (intmax_t) PRIVATE(this)->points->getUserData(v1idx); }
+  if (!v2new) { v2idx = (intmax_t) PRIVATE(this)->points->getUserData(v2idx); }
+  if (!v3new) { v3idx = (intmax_t) PRIVATE(this)->points->getUserData(v3idx); }
+  intmax_t nidx = PRIVATE(this)->normals->findPoint(n);
+  if (nidx != -1) { nidx = (intmax_t) PRIVATE(this)->normals->getUserData(nidx); }
 
   // toss out invalid facets - facets where two or more points are in
   // the same location.  what are these - are they lines and points or
diff --git a/src/foreignfiles/SoSTLFileKit.cpp.orig b/src/foreignfiles/SoSTLFileKit.cpp.orig
new file mode 100644
index 1111111..2222222
--- /dev/null
+++ b/src/foreignfiles/SoSTLFileKit.cpp.orig
@@ -0,0 +1,799 @@
+/**************************************************************************\
+ *
+ *  This file is part of the Coin 3D visualization library.
+ *  Copyright (C) by Kongsberg Oil & Gas Technologies.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  ("GPL") version 2 as published by the Free Software Foundation.
+ *  See the file LICENSE.GPL at the root directory of this source
+ *  distribution for additional information about the GNU GPL.
+ *
+ *  For using Coin with software that can not be combined with the GNU
+ *  GPL, and for taking advantage of the additional benefits of our
+ *  support services, please contact Kongsberg Oil & Gas Technologies
+ *  about acquiring a Coin Professional Edition License.
+ *
+ *  See http://www.coin3d.org/ for more information.
+ *
+ *  Kongsberg Oil & Gas Technologies, Bygdoy Alle 5, 0257 Oslo, NORWAY.
+ *  http://www.sim.no/  sales@sim.no  coin-support@coin3d.org
+ *
+\**************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#ifdef HAVE_NODEKITS
+
+#include <ForeignFiles/SoSTLFileKit.h>
+
+#include <Inventor/SbBasic.h>
+#include <Inventor/lists/SbList.h>
+#include <Inventor/errors/SoDebugError.h>
+#include <Inventor/actions/SoCallbackAction.h>
+#include <Inventor/actions/SoReorganizeAction.h>
+#include <Inventor/nodes/SoSeparator.h>
+#include <Inventor/nodes/SoShapeHints.h>
+#include <Inventor/nodes/SoTexture2.h>
+#include <Inventor/nodes/SoNormal.h>
+#include <Inventor/nodes/SoNormalBinding.h>
+#include <Inventor/nodes/SoMaterial.h>
+#include <Inventor/nodes/SoMaterialBinding.h>
+#include <Inventor/nodes/SoCoordinate3.h>
+#include <Inventor/nodes/SoIndexedFaceSet.h>
+#include <Inventor/nodes/SoInfo.h>
+#include <Inventor/SbBSPTree.h>
+#include <Inventor/SoPrimitiveVertex.h>
+
+#include "steel.h"
+#include "nodekits/SoSubKitP.h"
+
+
+#if 0
+  SoCallback         "callbackList"         SoBaseKit
+  SoSeparator        "topSeparator"         SoForeignFileKit
+  SoShapeHints         "shapehints"           SoSTLFileKit
+  SoTexture2           "texture"              SoSTLFileKit
+  SoNormalBinding      "normalbinding"        SoSTLFileKit
+  SoNormal             "normals"              SoSTLFileKit
+  SoMaterialBinding    "materialbinding"      SoSTLFileKit
+  SoMaterial           "material"             SoSTLFileKit
+  SoCoordinate3        "coordinates"          SoSTLFileKit
+  SoIndexedFaceSet     "facets"               SoSTLFileKit
+#endif // 0
+
+class SoSTLFileKitP {
+public:
+  SoSTLFileKitP(SoSTLFileKit * pub)
+  : api(pub) {
+    this->data = new SbList<uint16_t>;
+    this->points = new SbBSPTree;
+    this->normals = new SbBSPTree;
+  }
+  ~SoSTLFileKitP(void) {
+    delete this->data;
+    delete this->points;
+    delete this->normals;
+  }
+
+public:
+  SoSTLFileKit * const api;
+
+  SbList<uint16_t> * data;
+  SbBSPTree * points;
+  SbBSPTree * normals;
+
+  int numfacets;
+  int numvertices;
+  int numnormals;
+  int numsharedvertices;
+  int numsharednormals;
+  int numredundantfacets;
+}; // SoSTLFileKitP
+
+// *************************************************************************
+
+/*!
+  \class SoSTLFileKit SoSTLFileKit.h ForeignFiles/SoSTLFileKit.h
+  \brief SoSTLFileKit is a class for using STL files with Coin.
+
+  Class for using STL files with Coin.  You can use it to read and
+  write STL files, and convert back and forth between Open Inventor
+  scene graphs and SoSTLFileKits.
+
+  STL files are 3D models intended for 3D printers, and is a format
+  supported by a wide variety of computer-aided design programs.  STL
+  models are, because of their intended purpose, always
+  representations of solid objects.  STL is short for
+  Stereolithography, the process used for 3D printing.
+
+  Ordinary STL models do not contain color information.  There are,
+  however, two extensions to the binary file format for specifying
+  color.  Currently neither extension is supported.  This is caused by
+  lack of sample models using the extensions and will be added as soon
+  as such models are found.  We have the specs on the extensions, and
+  it should be pretty straight-forwards to implement, but we want to
+  get it right at once since we have write support (we don't want to
+  inadvertently create a third color extension ;).
+
+  When writing STL files, certain STL model criterias are not enforced
+  by SoSTLFileKit.  These are:
+
+  - STL models should represent complete solids - it is the user's
+    responsibility to give models of solid data to readScene(), and
+    not readScene()'s responsibility to check the incoming data.
+
+  - STL models should have all triangles in counterclockwise order.
+    This is not enforced either.
+
+  - STL models should reside in the positive octant of the coordinate
+    space.  This is also the user's responsibility to ensure, although
+    adding functionality for translating the model should be easy, so
+    it might get implemented.
+
+  Since the color extensions are not supported yet, color information
+  is not collected either when converting Open Inventor scene graphs to
+  SoSTLFileKits.
+
+  \relates foreignfileformats
+  \COIN_CLASS_EXTENSION
+  \since Coin 3.0
+*/
+
+#define PRIVATE(obj) ((obj)->pimpl)
+
+SO_KIT_SOURCE(SoSTLFileKit)
+
+/*!
+  Initializes class and registers file identification functions.
+*/
+
+void
+SoSTLFileKit::initClass(void)
+{
+  SO_KIT_INIT_CLASS(SoSTLFileKit, SoForeignFileKit, SoForeignFileKit);
+
+  SoType type = SoSTLFileKit::getClassTypeId();
+  SoForeignFileKit::registerFileExtension(type, "stl", SoSTLFileKit::identify);
+}
+
+/*!
+  Returns wether or not \a filename is identified as an STL file.
+*/
+
+SbBool
+SoSTLFileKit::identify(const char * filename)
+{
+  assert(filename);
+  stl_reader * reader = stl_reader_create(filename);
+  if ( !reader ) {
+    return FALSE;
+  }
+  stl_reader_destroy(reader);
+  return TRUE;
+}
+
+/*!
+  Constructor.
+*/
+
+SoSTLFileKit::SoSTLFileKit(void)
+{
+  PRIVATE(this) = new SoSTLFileKitP(this);
+
+  SO_KIT_INTERNAL_CONSTRUCTOR(SoSTLFileKit);
+
+  SO_KIT_ADD_FIELD(info, (""));
+  SO_KIT_ADD_FIELD(binary, (FALSE));
+  SO_KIT_ADD_FIELD(colorization, (SoSTLFileKit::GREY));
+
+  SO_KIT_DEFINE_ENUM_VALUE(Colorization, GREY);
+  SO_KIT_DEFINE_ENUM_VALUE(Colorization, MATERIALISE);
+  SO_KIT_DEFINE_ENUM_VALUE(Colorization, TNO_VISICAM);
+
+  SO_KIT_SET_SF_ENUM_TYPE(colorization, Colorization);
+
+  SO_KIT_ADD_CATALOG_ENTRY(facets, SoIndexedFaceSet,
+                           FALSE, topSeparator, \x0, FALSE);
+  SO_KIT_ADD_CATALOG_ENTRY(coordinates, SoCoordinate3,
+                           FALSE, topSeparator, facets, FALSE);
+  SO_KIT_ADD_CATALOG_ENTRY(material, SoMaterial,
+                           FALSE, topSeparator, coordinates, FALSE);
+  SO_KIT_ADD_CATALOG_ENTRY(materialbinding, SoMaterialBinding,
+                           FALSE, topSeparator, material, FALSE);
+  SO_KIT_ADD_CATALOG_ENTRY(normals, SoNormal,
+                           FALSE, topSeparator, materialbinding, FALSE);
+  SO_KIT_ADD_CATALOG_ENTRY(normalbinding, SoNormalBinding,
+                           FALSE, topSeparator, normals, FALSE);
+  SO_KIT_ADD_CATALOG_ENTRY(texture, SoTexture2,
+                           FALSE, topSeparator, normalbinding, FALSE);
+  SO_KIT_ADD_CATALOG_ENTRY(shapehints, SoShapeHints,
+                           FALSE, topSeparator, texture, FALSE);
+
+  SO_KIT_INIT_INSTANCE();
+}
+
+/*!
+  Destructor.
+*/
+
+SoSTLFileKit::~SoSTLFileKit(void)
+{
+  delete PRIVATE(this);
+  PRIVATE(this) = NULL;
+}
+
+// doc in inherited class
+SbBool
+SoSTLFileKit::canReadFile(const char * filename) const
+{
+  if ( !filename ) return TRUE; // we can read STL files, in general
+  return SoSTLFileKit::identify(filename);
+}
+
+/*!
+  Reads in an STL file.  Both ascii and binary files are supported.
+  For binary files, the color extensions are not implemented yet.
+
+  Returns FALSE if \a filename could not be opened or parsed
+  correctly.
+
+  \sa canReadFile, canWriteScene, writeScene
+*/
+
+SbBool
+SoSTLFileKit::readFile(const char * filename)
+{
+  assert(filename);
+
+  this->reset();
+
+  stl_reader * reader = stl_reader_create(filename);
+  if ( !reader ) {
+    SoDebugError::postInfo("SoSTLFileKit::readFile",
+                           "unable to create STL reader for '%s'.",
+                           filename);
+    return FALSE;
+  }
+
+  SbBool binary = (stl_reader_flags(reader) & STL_BINARY) ? TRUE : FALSE;
+
+  SoShapeHints * hints =
+    SO_GET_ANY_PART(this, "shapehints", SoShapeHints);
+  hints->vertexOrdering.setValue(SoShapeHints::UNKNOWN_ORDERING);
+  // what it should have been
+  // hints->vertexOrdering.setValue(SoShapeHints::COUNTERCLOCKWISE);
+  hints->shapeType.setValue(SoShapeHints::SOLID);
+  hints->faceType.setValue(SoShapeHints::UNKNOWN_FACE_TYPE);
+
+  SoNormalBinding * normalbinding =
+    SO_GET_ANY_PART(this, "normalbinding", SoNormalBinding);
+  normalbinding->value = SoNormalBinding::PER_FACE_INDEXED;
+
+  stl_facet * facet = stl_facet_create();
+  SbBool loop = TRUE, success = TRUE;
+  while ( loop ) {
+    const int peekval = stl_reader_peek(reader);
+    if ( peekval == STL_BEGIN ) {
+    } else if ( peekval == STL_INIT_INFO ) {
+      // FIXME: set info
+    } else if ( peekval == STL_EXIT_INFO ) {
+    } else if ( peekval == STL_END ) {
+      loop = FALSE;
+    } else if ( peekval == STL_FACET ) {
+      stl_real x, y, z;
+      stl_reader_fill_facet(reader, facet);
+      stl_facet_get_normal(facet, &x, &y, &z);
+      SbVec3f normal((float) x, (float) y, (float) z);
+      stl_facet_get_vertex1(facet, &x, &y, &z);
+      SbVec3f vertex1((float) x, (float) y, (float) z);
+      stl_facet_get_vertex2(facet, &x, &y, &z);
+      SbVec3f vertex2((float) x, (float) y, (float) z);
+      stl_facet_get_vertex3(facet, &x, &y, &z);
+      SbVec3f vertex3((float) x, (float) y, (float) z);
+      if ( normal.length() == 0.0f ) { // auto-calculate
+        SbVec3f v1(vertex2-vertex1);
+        SbVec3f v2(vertex3-vertex1);
+        normal = v1.cross(v2);
+        float len = normal.length();
+        if ( len > 0 ) normal /= len;
+      }
+      unsigned int data = stl_facet_get_padding(facet);
+
+      SbBool added = this->addFacet(vertex1, vertex2, vertex3, normal);
+
+#if defined(COIN_EXTRA_DEBUG) || 1
+      if ( added && binary ) {
+        // binary contains padding, which might be colorization
+        // colorization is not implemented yet, so therefore some debug
+        // output comes here so colorized models can be detected.
+        PRIVATE(this)->data->append((uint16_t) data);
+        if ( data != 0 ) {
+          fprintf(stderr, "facet %5d - data: %04x\n", PRIVATE(this)->numfacets - 1, data);
+        }
+      }
+#endif // COIN_EXTRA_DEBUG
+    } else if ( peekval == STL_ERROR ) {
+      SoDebugError::post("SoSTLFileKit::readFile",
+                         "error '%s' after %d facets, line %d.",
+                         stl_reader_get_error(reader),
+                         PRIVATE(this)->numfacets,
+                         stl_reader_get_line_number(reader));
+      loop = FALSE;
+      success = FALSE;
+      if (strcmp(stl_reader_get_error(reader), "premature end of file") == 0) {
+        // this one we will accept though - models with missing
+        // end-indicator have been found...
+        success = TRUE;
+      }
+    }
+  }
+
+  // done - no need for the BSP trees to contain data any more
+  PRIVATE(this)->points->clear();
+  PRIVATE(this)->normals->clear();
+
+  stl_facet_destroy(facet);
+  stl_reader_destroy(reader);
+
+  if ( !success ) {
+    this->reset();
+  } else {
+    this->organizeModel();
+  }
+  return success;
+}
+
+// doc in inherited class
+SbBool
+SoSTLFileKit::canReadScene(void) const
+{
+  return TRUE;
+}
+
+/*!
+  Converts a scene graph into an SoSTLFileKit.  Useful for creating
+  STL files.
+
+  \sa canReadScene, canWriteFile, writeFile
+*/
+
+SbBool
+SoSTLFileKit::readScene(SoNode * scene)
+{
+  this->reset();
+
+  scene->ref();
+  SoCallbackAction cba;
+  cba.addTriangleCallback(SoType::fromName("SoNode"), add_facet_cb, this);
+  cba.apply(scene);
+  scene->unrefNoDelete();
+
+  // no need for the BSP trees to contain data any more
+  PRIVATE(this)->points->clear();
+  PRIVATE(this)->normals->clear();
+
+  this->organizeModel();
+
+  return TRUE;
+}
+
+// doc in inherited class
+SbBool
+SoSTLFileKit::canWriteScene(const char * format) const
+{
+  if ( !format ) return TRUE;
+  // FIXME: implement format checking (VRML1, VRML97)
+  return TRUE;
+}
+
+/*!
+  Converts the STL model into a native scene graph.
+
+  \sa canWriteScene
+*/
+
+SbBool
+SoSTLFileKit::writeScene(SoNode *& root, const char * format)
+{
+  static const char default_format[] = "#VRML 1.0"; // syntax for this?
+  if ( !format ) format = default_format;
+
+  SbBool success = true;
+
+  // FIXME: implement format check to specify scene graph setup
+  enum Format {
+    UNKNOWN,
+    VRML1,
+    VRML97
+  };
+
+  Format build = VRML1;
+
+  if ( build == VRML1 ) {
+    // create VRML1 scene
+    SoSeparator * sceneroot = new SoSeparator;
+    sceneroot->ref();
+
+    SoInfo * info = new SoInfo;
+    info->string = "STL model data, created by Coin " COIN_VERSION ".";
+    sceneroot->addChild(info);
+    
+    SoShapeHints * shapehints_orig =
+      SO_GET_ANY_PART(this, "shapehints", SoShapeHints);
+    SoShapeHints * shapehints_copy = new SoShapeHints;
+    shapehints_copy->copyContents(shapehints_orig, FALSE);
+    sceneroot->addChild(shapehints_copy);
+
+    SoTexture2 * texture_orig = SO_GET_ANY_PART(this, "texture", SoTexture2);
+    SoTexture2 * texture_copy = new SoTexture2;
+    texture_copy->copyContents(texture_orig, FALSE);
+    sceneroot->addChild(texture_copy);
+
+    SoNormalBinding * normalbinding_orig =
+      SO_GET_ANY_PART(this, "normalbinding", SoNormalBinding);
+    SoNormalBinding * normalbinding_copy = new SoNormalBinding;
+    normalbinding_copy->copyContents(normalbinding_orig, FALSE);
+    sceneroot->addChild(normalbinding_copy);
+
+    SoNormal * normals_orig = SO_GET_ANY_PART(this, "normals", SoNormal);
+    SoNormal * normals_copy = new SoNormal;
+    normals_copy->copyContents(normals_orig, FALSE);
+    sceneroot->addChild(normals_copy);
+
+    SoMaterialBinding * materialbinding_orig =
+      SO_GET_ANY_PART(this, "materialbinding", SoMaterialBinding);
+    SoMaterialBinding * materialbinding_copy = new SoMaterialBinding;
+    materialbinding_copy->copyContents(materialbinding_orig, FALSE);
+    sceneroot->addChild(materialbinding_copy);
+
+    SoMaterial * material_orig = SO_GET_ANY_PART(this, "material", SoMaterial);
+    SoMaterial * material_copy = new SoMaterial;
+    material_copy->copyContents(material_orig, FALSE);
+    sceneroot->addChild(material_copy);
+
+    SoCoordinate3 * coordinates_orig =
+      SO_GET_ANY_PART(this, "coordinates", SoCoordinate3);
+    SoCoordinate3 * coordinates_copy = new SoCoordinate3;
+    coordinates_copy->copyContents(coordinates_orig, FALSE);
+    sceneroot->addChild(coordinates_copy);
+
+    SoIndexedFaceSet * facets_orig =
+      SO_GET_ANY_PART(this, "facets", SoIndexedFaceSet);
+    SoIndexedFaceSet * facets_copy = new SoIndexedFaceSet;
+    facets_copy->copyContents(facets_orig, FALSE);
+    sceneroot->addChild(facets_copy);
+
+    // optimize/reorganize mesh
+    SoReorganizeAction ra;
+    ra.apply(sceneroot);
+
+    // FIXME: remove redundant scene graph nodes after scene reorganization
+
+    sceneroot->unrefNoDelete();
+    root = sceneroot;
+  } else {
+    SoDebugError::postWarning("SoSTLFileKit::writeScene",
+                              "unsupported format - could not create scene.");
+    success = FALSE;
+  }
+
+  return success;
+}
+
+// doc in inherited class
+SbBool
+SoSTLFileKit::canWriteFile(const char * filename) const
+{
+  return inherited::canWriteFile(filename);
+}
+
+/*!
+  Writes the STL model to an STL file.
+
+  \sa binary, info, canWriteFile, canReadScene
+*/
+
+SbBool
+SoSTLFileKit::writeFile(const char * filename)
+{
+  unsigned int flags = 0;
+  if ( this->binary.getValue() ) {
+    flags |= STL_BINARY;
+    // set up flags for colorization if wanted
+  }
+
+  stl_writer * writer = stl_writer_create(filename, flags);
+  if ( !writer ) {
+    return FALSE;
+  }
+
+  stl_facet * facet = stl_facet_create();
+  assert(facet);
+  stl_writer_set_facet(writer, facet);
+
+  SbString infostring = this->info.getValue();
+  if ( infostring.getLength() > 0 ) {
+    if ( stl_writer_set_info(writer, infostring.getString()) != STL_OK ) {
+      SoDebugError::post("SoSTLFileKit::writeFile",
+                         "error: '%s'",
+                         stl_writer_get_error(writer));
+      return FALSE;
+    }
+  }
+
+  this->ref();
+  SoCallbackAction cba;
+  cba.addTriangleCallback(SoNode::getClassTypeId(), put_facet_cb, writer);
+  cba.apply(this);
+  this->unrefNoDelete();
+
+  stl_writer_destroy(writer);
+
+  return TRUE;
+}
+
+// *************************************************************************
+
+/*!
+  Resets the STL model so it contains nothing.
+*/
+
+void
+SoSTLFileKit::reset(void)
+{
+  PRIVATE(this)->numvertices = 0;
+  PRIVATE(this)->numfacets = 0;
+  PRIVATE(this)->numnormals = 0;
+  PRIVATE(this)->numsharedvertices = 0;
+  PRIVATE(this)->numsharednormals = 0;
+  PRIVATE(this)->numredundantfacets = 0;
+
+  PRIVATE(this)->data->truncate(0);
+  PRIVATE(this)->points->clear();
+  PRIVATE(this)->normals->clear();
+    
+  this->setAnyPart("shapehints", new SoShapeHints);
+  this->setAnyPart("texture", new SoTexture2);
+  this->setAnyPart("normalbinding", new SoNormalBinding);
+  this->setAnyPart("normals", new SoNormal);
+  this->setAnyPart("materialbinding", new SoMaterialBinding);
+  this->setAnyPart("material", new SoMaterial);
+  this->setAnyPart("coordinates", new SoCoordinate3);
+  this->setAnyPart("facets", new SoIndexedFaceSet);
+
+  SoNormalBinding * normalbinding =
+    SO_GET_ANY_PART(this, "normalbinding", SoNormalBinding);
+  normalbinding->value = SoNormalBinding::PER_FACE_INDEXED;
+
+  SoShapeHints * shapehints =
+    SO_GET_ANY_PART(this, "shapehints", SoShapeHints);
+  shapehints->vertexOrdering = SoShapeHints::UNKNOWN_ORDERING;
+  // proper model is
+  //   shapehints->vertexOrdering = SoShapeHints::COUNTERCLOCKWISE;
+  // but many models are not proper
+  shapehints->shapeType = SoShapeHints::SOLID;
+}
+
+/*!
+  Adds one triangle to the STL model.
+
+  \sa reset, organizeModel
+*/
+
+SbBool
+SoSTLFileKit::addFacet(const SbVec3f & v1, const SbVec3f & v2, const SbVec3f & v3, const SbVec3f & n)
+{
+  SoNormal * normals =
+    SO_GET_ANY_PART(this, "normals", SoNormal);
+  SoCoordinate3 * coordinates =
+    SO_GET_ANY_PART(this, "coordinates", SoCoordinate3);
+  SoIndexedFaceSet * facets =
+    SO_GET_ANY_PART(this, "facets", SoIndexedFaceSet);
+
+  // find existing indexes if any
+  long v1idx = PRIVATE(this)->points->findPoint(v1), v1new = (v1idx == -1);
+  long v2idx = PRIVATE(this)->points->findPoint(v2), v2new = (v2idx == -1);
+  long v3idx = PRIVATE(this)->points->findPoint(v3), v3new = (v3idx == -1);
+  if (!v1new) { v1idx = (long) PRIVATE(this)->points->getUserData(v1idx); }
+  if (!v2new) { v2idx = (long) PRIVATE(this)->points->getUserData(v2idx); }
+  if (!v3new) { v3idx = (long) PRIVATE(this)->points->getUserData(v3idx); }
+  long nidx = PRIVATE(this)->normals->findPoint(n);
+  if (nidx != -1) { nidx = (long) PRIVATE(this)->normals->getUserData(nidx); }
+
+  // toss out invalid facets - facets where two or more points are in
+  // the same location.  what are these - are they lines and points or
+  // something?  selection?  borders?  creases?
+  if ((!v1new && !v2new && (v1idx == v2idx)) ||
+      (!v1new && !v3new && (v1idx == v3idx)) ||
+      (!v2new && !v3new && (v2idx == v3idx)) ||
+      (v1new && v2new && (v1 == v2)) ||
+      (v1new && v3new && (v1 == v3)) ||
+      (v2new && v3new && (v2 == v3))) {
+    // the above test is optimized for using vertex indexes if
+    // possible and avoid vec3f-comparisons when index-comparisons
+    // should have sufficed.
+    PRIVATE(this)->numredundantfacets += 1;
+    return FALSE;
+  }
+
+#if 0 // disabled (O(n^2))
+  // toss out redundant facets, if any...
+  if (!v1new && !v2new && !v3new) {
+    int count = facets->coordIndex.getNum();
+    const int32_t * points = facets->coordIndex.getValues(0);
+    int i;
+    for (i = 0; i < count; i++) {
+      if (points[i] == v1idx) {
+        int beg = i - (i % 4);
+        if ( ((points[beg] == v1idx) && (points[beg+1] == v2idx) &&
+              (points[beg+2] == v3idx)) ||
+             ((points[beg] == v2idx) && (points[beg+1] == v3idx) &&
+              (points[beg+2] == v1idx)) ||
+             ((points[beg] == v3idx) && (points[beg+1] == v1idx) &&
+              (points[beg+2] == v2idx)) ) {
+          // same vertices, same vertex ordering (we drop comparing normal)
+          PRIVATE(this)->numredundantfacets += 1;
+          return FALSE;
+        }
+      }
+    }
+  }
+#endif
+
+  // add facet (triangle) to faceset
+  if (v1new) {
+    v1idx = PRIVATE(this)->numvertices;
+    coordinates->point.set1Value(v1idx, v1);
+    PRIVATE(this)->points->addPoint(v1, (void *) v1idx);
+    PRIVATE(this)->numvertices++;
+  } else {
+    PRIVATE(this)->numsharedvertices++;
+  }
+  facets->coordIndex.set1Value(PRIVATE(this)->numfacets*4, v1idx);
+  
+  if (v2new) {
+    v2idx = PRIVATE(this)->numvertices;
+    coordinates->point.set1Value(v2idx, v2);
+    PRIVATE(this)->points->addPoint(v2, (void *) v2idx);
+    PRIVATE(this)->numvertices++;
+  } else {
+    PRIVATE(this)->numsharedvertices++;
+  }
+  facets->coordIndex.set1Value(PRIVATE(this)->numfacets*4+1, v2idx);
+
+  if (v3new) {
+    v3idx = PRIVATE(this)->numvertices;
+    coordinates->point.set1Value(v3idx, v3);
+    PRIVATE(this)->points->addPoint(v3, (void *) v3idx);
+    PRIVATE(this)->numvertices++;
+  } else {
+    PRIVATE(this)->numsharedvertices++;
+  }
+  facets->coordIndex.set1Value(PRIVATE(this)->numfacets*4+2, v3idx);
+  facets->coordIndex.set1Value(PRIVATE(this)->numfacets*4+3, -1);
+
+  if (nidx == -1) {
+    nidx = PRIVATE(this)->numnormals;
+    normals->vector.set1Value(nidx, n);
+    PRIVATE(this)->normals->addPoint(n, (void *) nidx);
+    PRIVATE(this)->numnormals++;
+  } else {
+    PRIVATE(this)->numsharednormals++;
+  }
+  facets->normalIndex.set1Value(PRIVATE(this)->numfacets, nidx);
+
+  PRIVATE(this)->numfacets++;
+  return TRUE;
+}
+
+/*!
+  Should be called after the STL model is completely set up in the
+  SoSTLFileKit through import from a file or from a scene graph.  The
+  model will then be optimized for fast rendering.
+
+  \sa addFacet, reset
+*/
+
+void
+SoSTLFileKit::organizeModel(void)
+{
+#if defined(COIN_EXTRA_DEBUG)
+  SoDebugError::postInfo("SoSTLFileKit::organizeModel",
+                         "model data imported successfully. "
+                         "%d unique vertices, %d reuses. "
+                         "%d unique normals, %d reuses. "
+                         "%d facets, %d redundant facets.",
+                         PRIVATE(this)->numvertices,
+                         PRIVATE(this)->numsharedvertices,
+                         PRIVATE(this)->numnormals,
+                         PRIVATE(this)->numsharednormals,
+                         PRIVATE(this)->numfacets,
+                         PRIVATE(this)->numredundantfacets);
+#endif // COIN_EXTRA_DEBUG
+
+  SoIndexedFaceSet * facets =
+    SO_GET_ANY_PART(this, "facets", SoIndexedFaceSet);
+
+  assert(facets->coordIndex.getNum() == PRIVATE(this)->numfacets*4);
+  assert(facets->normalIndex.getNum() == (PRIVATE(this)->numfacets));
+
+  if ( PRIVATE(this)->numfacets > 300 ) {
+    // FIXME: at some number of facets, reorganization for faster
+    // rendering should really be performed.
+  }
+}
+
+/*!
+  Helper callback for readScene(), calling addFacet() for each
+  triangle in the provided scene graph.
+
+  \sa readScene
+*/
+
+void
+SoSTLFileKit::add_facet_cb(void * closure,
+                           SoCallbackAction * action,
+                           const SoPrimitiveVertex * v1,
+                           const SoPrimitiveVertex * v2,
+                           const SoPrimitiveVertex * v3)
+{
+  assert(closure); assert(v1); assert(v2); assert(v3);
+  SoSTLFileKit * filekit = (SoSTLFileKit *) closure;
+
+  SbVec3f vertex1(v1->getPoint());
+  SbVec3f vertex2(v2->getPoint());
+  SbVec3f vertex3(v3->getPoint());
+
+  SbVec3f vec1(vertex2-vertex1);
+  SbVec3f vec2(vertex3-vertex1);
+  SbVec3f normal(vec1.cross(vec2));
+  float len = normal.length();
+  if ( len > 0.0f && len != 1.0f ) normal /= len;
+  assert(len != 0.0f);
+
+  filekit->addFacet(vertex1, vertex2, vertex3, normal);
+}
+
+/*!
+  Helper callback for writeFile(), writing each triangle in the STL
+  model to the STL file.
+
+  \sa writeFile
+*/
+
+void
+SoSTLFileKit::put_facet_cb(void * closure,
+                           SoCallbackAction * action,
+                           const SoPrimitiveVertex * v1,
+                           const SoPrimitiveVertex * v2,
+                           const SoPrimitiveVertex * v3)
+{
+  assert(closure); assert(v1); assert(v2); assert(v3);
+  stl_writer * writer = (stl_writer *) closure;
+
+  SbVec3f vertex1(v1->getPoint());
+  SbVec3f vertex2(v2->getPoint());
+  SbVec3f vertex3(v3->getPoint());
+
+  SbVec3f vec1(vertex2-vertex1);
+  SbVec3f vec2(vertex3-vertex1);
+  SbVec3f normal(vec1.cross(vec2));
+  float len = normal.length();
+  if ( len > 0 ) normal /= len;
+
+  stl_facet * facet = stl_writer_get_facet(writer);
+  assert(facet);
+  stl_facet_set_vertex1(facet, vertex1[0], vertex1[1], vertex1[2]);
+  stl_facet_set_vertex2(facet, vertex2[0], vertex2[1], vertex2[2]);
+  stl_facet_set_vertex3(facet, vertex3[0], vertex3[1], vertex3[2]);
+  stl_facet_set_normal(facet, normal[0], normal[1], normal[2]);
+  stl_facet_set_padding(facet, 0);
+
+  stl_writer_put_facet(writer, facet);
+}
+
+#undef PRIVATE
+#endif // HAVE_NODEKITS
diff --git a/src/threads/thread.cpp b/src/threads/thread.cpp
index 1111111..2222222 100644
--- a/src/threads/thread.cpp
+++ b/src/threads/thread.cpp
@@ -120,7 +120,7 @@ cc_thread_join(cc_thread * thread,
 void
 cc_sleep(float seconds)
 {
-#ifndef _WIN32
+#if !defined(_WIN32) || defined(__MINGW32__)
   /* FIXME: 20011107, thammer: create a configure macro to detect
    * which sleep function is available */
   sleep(floor(seconds));
@@ -154,7 +154,7 @@ cc_thread_id(void)
       assert(0 && "unexpected failure");
     }
   }
-  return (unsigned long) val;
+  return static_cast<unsigned long>(reinterpret_cast<intptr_t>(val));
 }
 
 static void 
diff --git a/src/threads/thread.cpp.orig b/src/threads/thread.cpp.orig
new file mode 100644
index 1111111..2222222
--- /dev/null
+++ b/src/threads/thread.cpp.orig
@@ -0,0 +1,347 @@
+/**************************************************************************\
+ *
+ *  This file is part of the Coin 3D visualization library.
+ *  Copyright (C) by Kongsberg Oil & Gas Technologies.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  ("GPL") version 2 as published by the Free Software Foundation.
+ *  See the file LICENSE.GPL at the root directory of this source
+ *  distribution for additional information about the GNU GPL.
+ *
+ *  For using Coin with software that can not be combined with the GNU
+ *  GPL, and for taking advantage of the additional benefits of our
+ *  support services, please contact Kongsberg Oil & Gas Technologies
+ *  about acquiring a Coin Professional Edition License.
+ *
+ *  See http://www.coin3d.org/ for more information.
+ *
+ *  Kongsberg Oil & Gas Technologies, Bygdoy Alle 5, 0257 Oslo, NORWAY.
+ *  http://www.sim.no/  sales@sim.no  coin-support@coin3d.org
+ *
+\**************************************************************************/
+
+#include <Inventor/C/threads/thread.h>
+
+#include <stdlib.h>
+#include <assert.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#include <Inventor/C/errors/debugerror.h>
+
+#include "threads/threadp.h"
+#include "threads/mutexp.h"
+#include "threads/recmutexp.h"
+#include "threads/syncp.h"
+#include "tidbitsp.h"
+
+
+/* ********************************************************************** */
+
+/*
+ FIXME:
+ - copy struct malloc/free/init/clean setup scheme from cc_string
+ - use static table of cc_thread structures?
+ - use cc_storage to reference self-structure for cc_thread_get_self()?
+*/
+
+/* ********************************************************************** */
+
+#ifdef USE_PTHREAD
+#include "threads/thread_pthread.icc"
+#endif /* USE_PTHREAD */
+
+#ifdef USE_W32THREAD
+#include "threads/thread_win32.icc"
+#endif /* USE_W32THREAD */
+
+/*
+*/
+
+cc_thread *
+cc_thread_construct(cc_thread_f * func, void * closure)
+{
+  cc_thread * thread;
+  int ok;
+
+  thread = (cc_thread*) malloc(sizeof(cc_thread));
+  assert(thread != NULL);
+  thread->func = func;
+  thread->closure = closure;
+
+  ok = internal_init(thread);
+  if (ok) return thread;
+  assert(0 && "unable to create thread");
+  free(thread);
+  return NULL;
+}
+
+/* ********************************************************************** */
+
+/*
+*/
+
+void
+cc_thread_destruct(cc_thread * thread)
+{
+  int ok;
+  assert(thread != NULL);
+  ok = internal_clean(thread);
+  assert(ok == CC_OK);
+  free(thread);
+}
+
+/* ********************************************************************** */
+
+/*
+*/
+
+int
+cc_thread_join(cc_thread * thread,
+               void ** retvalptr)
+{
+  int ok;
+  assert(thread != NULL);
+
+  ok = internal_join(thread, retvalptr);
+  assert(ok == CC_OK);
+  return ok;
+}
+
+/* ********************************************************************** */
+
+void
+cc_sleep(float seconds)
+{
+#ifndef _WIN32
+  /* FIXME: 20011107, thammer: create a configure macro to detect
+   * which sleep function is available */
+  sleep(floor(seconds));
+#else
+  Sleep((int)(seconds*1000.0));
+#endif
+};
+
+#ifdef USE_PTHREAD
+unsigned long 
+cc_thread_id(void)
+{
+  return (unsigned long) pthread_self();
+}
+#endif /* USE_PTHREAD */
+
+#ifdef USE_W32THREAD
+
+static DWORD win32_threadid_idx;
+
+unsigned long 
+cc_thread_id(void)
+{
+  static unsigned long currentidx = 1;
+  LPVOID val = TlsGetValue(win32_threadid_idx);
+  if (val == 0) { /* not set yet */
+    cc_mutex_global_lock();
+    val = (LPVOID) currentidx++;
+    cc_mutex_global_unlock();
+    if (!TlsSetValue(win32_threadid_idx, (LPVOID)val)) {
+      assert(0 && "unexpected failure");
+    }
+  }
+  return (unsigned long) val;
+}
+
+static void 
+win32_threadid_idx_cleanup(void)
+{
+  TlsFree(win32_threadid_idx);
+}
+
+#endif /* USE_WIN32THREAD */
+
+
+void
+cc_thread_init(void)
+{
+  cc_mutex_init();
+  cc_sync_init();
+#ifdef USE_W32THREAD
+  /* needed to quickly generate a thread-id for each thread */
+  win32_threadid_idx = TlsAlloc();
+  assert(win32_threadid_idx != TLS_OUT_OF_INDEXES); 
+  /* clean-up priority for the thread sub-system in Coin is set so it
+     is done very late at exit */
+  /* FIXME: not sure if this really needs the "- 2", but I added it
+     to keep the same order wrt the other thread-related clean-up
+     functions, since before I changed hard-coded numbers for
+     enumerated values for coin_atexit() invocations. 20060301 mortene. */
+  coin_atexit(win32_threadid_idx_cleanup, CC_ATEXIT_THREADING_SUBSYSTEM_VERYLOWPRIORITY);
+#endif /* USE_WIN32THREAD */ 
+  cc_recmutex_init();
+}
+
+/* ********************************************************************** */
+
+/* maybe use static table of thread structures, reference counted, to be
+   able to implement something like this, if needed */
+/* cc_thread * cc_thread_get_self(void); */
+
+/* ********************************************************************** */
+
+/*
+ * We don't really want to expose internal id types, which would mean we
+ * must include threads-implementation-specific headers in the header files.
+ * It's therefore better to implement the missing/needed functionality for
+ * the cc_thread type, so id peeking won't be necessary.
+ */
+
+/* <id> cc_thread_get_id(cc_thread * thread); */
+/* <id> cc_thread_get_current_id(void); */
+
+/* ********************************************************************** */
+
+/*!
+  \page multithreading_support Multithreading Support in Coin
+
+  The support in Coin for using multiple threads in application
+  programs and the Coin library itself, consists of two main features:
+
+  <ul>
+
+  <li>
+  Coin provides platform-independent thread-handling abstraction
+  classes. These are classes that the application programmer can
+  freely use in her application code to start new threads, control
+  their execution, work with mutexes and do other tasks related to
+  handling multiple threads.
+
+  The classes in question are SbThread, SbMutex, SbStorage, SbBarrier,
+  SbCondVar, SbFifo, SbThreadAutoLock, SbRWMutex, and
+  SbTypedStorage. See their respective documentation for the detailed
+  information.
+
+  The classes fully hides the system-specific implementation, which is
+  either done on top of native Win32 (if on Microsoft Windows), or
+  over POSIX threads (on UNIX and UNIX-like systems).
+  </li>
+
+  <li>
+  The other aspect of our multi-threading support is that Coin can be
+  specially configured so that rendering traversals of the scene graph
+  are done in a thread-safe manner. This means e.g. that it is
+  possible to have Coin render the scene in parallel on multiple CPUs
+  for multiple rendering pipes, to better take advantage of such
+  high-end systems (like CAVE environments, for instance).
+
+  Thread-safe render traversals are \e off by default, because there
+  is a small overhead involved which would make rendering (very)
+  slightly slower on single-threaded invocations.
+
+  To get a Coin library built with thread-safe rendering, one must
+  actively re-configure Coin and build a special, local version. For
+  configure-based builds (UNIX and UNIX-like systems, or with Cygwin
+  on Microsoft Windows) this is done with the option
+  "--enable-threadsafe" to Autoconf configure. For how to change the
+  configuration and re-build with Visual Studio, get in touch with us
+  at "coin-support@coin3d.org".
+  </li>
+
+  </ul>
+
+  There are some restrictions and other issues which it is important
+  to be aware of:
+  
+  <ul>
+
+  <li> We do not yet provide any support for binding the
+  multi-threaded rendering support into the SoQt / SoWin / etc GUI
+  bindings, and neither do we provide bindings against any specific
+  library that handles multi-pipe rendering. This means the
+  application programmer will have to possess some expertise, and put
+  in some effort, to be able to utilize multi-pipe rendering with
+  Coin. </li>
+
+  <li> Rendering traversals is currently the only operation which we
+  publicly support to be thread-safe. There are other aspects of Coin
+  that we know are thread-safe, like most other action traversals
+  beside just rendering, but we make no guarantees in this
+  regard. </li>
+
+  <li> Be careful about using a separate thread for changing Coin
+  structures versus what is used for the application's GUI event
+  thread.
+
+  We are aware of at least issues with Qt (and thereby SoQt), where
+  you should not modify the scene graph in any way in a thread
+  separate from the main Qt thread. This because it will trigger
+  operations where Qt is not thread-safe. </li>
+
+  </ul>
+
+  \since Coin 2.0
+*/
+
+/* ********************************************************************** */
+
+/*!
+  \class SbThread Inventor/threads/SbThread.h
+  \brief A class for managing threads.
+  \ingroup threads
+
+  This class provides a portable framework around the tasks of
+  instantiating, starting, stopping and joining threads.
+
+  It wraps the underlying native thread-handling toolkit in a
+  transparent manner, to make multiplatform threads programming
+  straightforward for the application programmer.
+*/
+
+/*!
+  \fn static SbThread * SbThread::create(void *(*func)(void *), void * closure)
+
+  This function creates a new thread, or returns NULL on failure.
+*/
+
+/*!
+  \fn static void SbThread::destroy(SbThread * thread)
+
+  This function destroys a thread.
+*/
+
+/*!
+  \fn static int SbThread::join(SbThread * thread, void ** retval)
+
+  This function waits on the death of the given thread, returning the thread's
+  return value at the location pointed to by \c retval.
+*/
+
+/*!
+  \fn int SbThread::join(void ** retval)
+
+  This function waits on the death of the given thread, returning the thread's
+  return value at the location pointed to by \c retval.
+*/
+
+/*!
+  \fn SbThread::SbThread(cc_thread * thread)
+
+  Protected constructor handling the internal thread ADT.
+
+  \sa SbThread::create
+*/
+
+/*!
+  \fn SbThread::~SbThread(void)
+
+  Destructor.
+
+  \sa SbThread::destroy
+*/
+
+/* ********************************************************************** */
diff --git a/src/threads/thread_win32.icc b/src/threads/thread_win32.icc
index 1111111..2222222 100644
--- a/src/threads/thread_win32.icc
+++ b/src/threads/thread_win32.icc
@@ -29,7 +29,7 @@ static DWORD WINAPI
 cc_w32thread_thread_proc(LPVOID lpParameter)
 {
   cc_thread *thread = (cc_thread *)lpParameter;
-  return (DWORD) thread->func(thread->closure);
+  return static_cast<DWORD>(reinterpret_cast<intptr_t>(thread->func(thread->closure)));
 }
 
 static int
diff --git a/src/threads/thread_win32.icc.orig b/src/threads/thread_win32.icc.orig
new file mode 100644
index 1111111..2222222
--- /dev/null
+++ b/src/threads/thread_win32.icc.orig
@@ -0,0 +1,110 @@
+/**************************************************************************\
+ *
+ *  This file is part of the Coin 3D visualization library.
+ *  Copyright (C) by Kongsberg Oil & Gas Technologies.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  ("GPL") version 2 as published by the Free Software Foundation.
+ *  See the file LICENSE.GPL at the root directory of this source
+ *  distribution for additional information about the GNU GPL.
+ *
+ *  For using Coin with software that can not be combined with the GNU
+ *  GPL, and for taking advantage of the additional benefits of our
+ *  support services, please contact Kongsberg Oil & Gas Technologies
+ *  about acquiring a Coin Professional Edition License.
+ *
+ *  See http://www.coin3d.org/ for more information.
+ *
+ *  Kongsberg Oil & Gas Technologies, Bygdoy Alle 5, 0257 Oslo, NORWAY.
+ *  http://www.sim.no/  sales@sim.no  coin-support@coin3d.org
+ *
+\**************************************************************************/
+
+/* this file should only be included from thread.c */
+
+#include "glue/win32api.h"
+
+static DWORD WINAPI
+cc_w32thread_thread_proc(LPVOID lpParameter)
+{
+  cc_thread *thread = (cc_thread *)lpParameter;
+  return (DWORD) thread->func(thread->closure);
+}
+
+static int
+internal_init(cc_thread * thread)
+{
+  DWORD threadid_unused;
+
+  thread->w32thread.threadhandle = CreateThread(NULL, 0,
+    cc_w32thread_thread_proc, (LPVOID) thread, 0, &threadid_unused);
+
+  /* threadid_unused - see PlatformSDK doc. for CreateThread */
+
+  /* FIXME: thammer 20011108, check PlatformSDK doc for
+   * _beginthreadex, _endthreadex, and note about using these with
+   * LIBCMT.LIB "A thread that uses functions from the C run-time
+   * libraries should use the beginthread and endthread C run-time
+   * functions for thread management rather than CreateThread and
+   * ExitThread. Failure to do so results in small memory leaks when
+   * ExitThread is called. " */
+
+  if (thread->w32thread.threadhandle == NULL) {
+    if (COIN_DEBUG) {
+      cc_win32_print_error("internal_init", "CreateThread()", GetLastError());
+    }
+    return CC_ERROR;
+  }
+  return CC_OK;
+}
+
+static int
+internal_clean(cc_thread * thread_struct)
+{
+  /* FIXME: Is there really nothing to do here? pederb, 2001-12-10 */
+  return CC_OK;
+}
+
+static int
+internal_join(cc_thread * thread,
+               void ** retvalptr)
+{
+  DWORD status;
+  BOOL bstatus;
+  DWORD exitcode;
+
+  status = WaitForSingleObject(thread->w32thread.threadhandle, INFINITE);
+  if (status == WAIT_FAILED) {
+    if (COIN_DEBUG) {
+      cc_win32_print_error("internal_join", "WaitForSingleObject()",
+                           GetLastError());
+    }
+    return CC_ERROR;
+  }
+  else if (status != WAIT_OBJECT_0) {
+    if (COIN_DEBUG) {
+      cc_debugerror_post("internal_join",
+                         "WaitForSingleObject() - unknown return value: %d\n",
+                         status);
+    }
+    return CC_ERROR;
+  }
+  bstatus = GetExitCodeThread(thread->w32thread.threadhandle, &exitcode);
+  if (bstatus == FALSE) {
+    if (COIN_DEBUG) {
+      cc_win32_print_error("internal_join", "GetExitCodeThread()",
+                           GetLastError());
+    }
+  }
+  else if (retvalptr) {
+    *retvalptr = (void *)exitcode;
+  }
+  /* termination could be forced with TerminateThread() - but this
+   * will result in memory leaks - or bigger problems - see Platform
+   * SDK doc. */
+  CloseHandle(thread->w32thread.threadhandle);
+  thread->w32thread.threadhandle = NULL;
+
+  return bstatus ? CC_OK : CC_ERROR;
+}
diff --git a/src/vrml97/JS_VRMLClasses.cpp b/src/vrml97/JS_VRMLClasses.cpp
index 1111111..2222222 100644
--- a/src/vrml97/JS_VRMLClasses.cpp
+++ b/src/vrml97/JS_VRMLClasses.cpp
@@ -100,8 +100,11 @@ struct CoinVrmlJs {
 struct CoinVrmlJs_SensorInfo {
   SbList <JSObject *> objects;
 };
+#if defined(_WIN64)
+SbHash <void *, unsigned long long> * CoinVrmlJs_sensorinfohash = NULL;
+#else
 SbHash <void *, unsigned long> * CoinVrmlJs_sensorinfohash = NULL;
-
+#endif
 
 const char * CoinVrmlJs_SFColorAliases[] = {"r", "g", "b"};
 const char * CoinVrmlJs_SFRotationAliases[] = {"x", "y", "z", "angle"};
@@ -664,7 +667,11 @@ static void SFNode_deleteCB(void * data, SoSensor * sensor)
 {
   SoNode * node = ((SoNodeSensor *) sensor)->getAttachedNode();
   void * tmp;
+#if defined(_WIN64)
+  if(!CoinVrmlJs_sensorinfohash->get((unsigned long long) node, tmp)) {
+#else
   if(!CoinVrmlJs_sensorinfohash->get((unsigned long) node, tmp)) {
+#endif
     assert(FALSE && "Trying to delete an unregistered SoNodeSensor. Internal error.");
     return;
   }
@@ -680,7 +687,11 @@ static void SFNode_deleteCB(void * data, SoSensor * sensor)
 
   // Store the sensor-pointer so that it can be properly deleted later
   nodesensorstobedeleted->append((SoNodeSensor *) sensor);
+#if defined(_WIN64)
+  CoinVrmlJs_sensorinfohash->remove((unsigned long long) node);
+#else
   CoinVrmlJs_sensorinfohash->remove((unsigned long) node);
+#endif
   delete si;
 }
 
@@ -1418,13 +1429,21 @@ static void attachSensorToNode(SoNode * node, JSObject * obj)
 {
   // Has the hash-table been initialized?
   if (!CoinVrmlJs_sensorinfohash) {
+#if defined(_WIN64)
+    CoinVrmlJs_sensorinfohash = new SbHash <void *, unsigned long long>;
+#else
     CoinVrmlJs_sensorinfohash = new SbHash <void *, unsigned long>;
+#endif
     coin_atexit(deleteSensorInfoHash, CC_ATEXIT_NORMAL);
   }
 
   // Is a sensor already attached to this SoNode?
   void * tmp;
+#if defined(_WIN64)
+  if (CoinVrmlJs_sensorinfohash->get((unsigned long long) node, tmp)) {
+#else
   if (CoinVrmlJs_sensorinfohash->get((unsigned long) node, tmp)) {
+#endif
     CoinVrmlJs_SensorInfo * si = (CoinVrmlJs_SensorInfo *) tmp;
     si->objects.append(obj);
   }
@@ -1434,7 +1453,11 @@ static void attachSensorToNode(SoNode * node, JSObject * obj)
     ns->attach(node);
     CoinVrmlJs_SensorInfo * si = new CoinVrmlJs_SensorInfo;
     si->objects.append(obj);
+#if defined(_WIN64)
+    CoinVrmlJs_sensorinfohash->put((unsigned long long) node, si);
+#else
     CoinVrmlJs_sensorinfohash->put((unsigned long) node, si);
+#endif
   }
 }
 
diff --git a/src/vrml97/JS_VRMLClasses.cpp.orig b/src/vrml97/JS_VRMLClasses.cpp.orig
new file mode 100644
index 1111111..2222222
--- /dev/null
+++ b/src/vrml97/JS_VRMLClasses.cpp.orig
@@ -0,0 +1,2099 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#ifdef HAVE_VRML97
+
+/**************************************************************************\
+ *
+ *  This file is part of the Coin 3D visualization library.
+ *  Copyright (C) by Kongsberg Oil & Gas Technologies.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  ("GPL") version 2 as published by the Free Software Foundation.
+ *  See the file LICENSE.GPL at the root directory of this source
+ *  distribution for additional information about the GNU GPL.
+ *
+ *  For using Coin with software that can not be combined with the GNU
+ *  GPL, and for taking advantage of the additional benefits of our
+ *  support services, please contact Kongsberg Oil & Gas Technologies
+ *  about acquiring a Coin Professional Edition License.
+ *
+ *  See http://www.coin3d.org/ for more information.
+ *
+ *  Kongsberg Oil & Gas Technologies, Bygdoy Alle 5, 0257 Oslo, NORWAY.
+ *  http://www.sim.no/  sales@sim.no  coin-support@coin3d.org
+ *
+\**************************************************************************/
+
+#include "JS_VRMLClasses.h"
+
+#include <Inventor/actions/SoWriteAction.h>
+#include <Inventor/misc/SoJavaScriptEngine.h>
+#include <Inventor/C/glue/spidermonkey.h>
+#include <Inventor/fields/SoSFBool.h>
+#include <Inventor/fields/SoSFInt32.h>
+#include <Inventor/fields/SoSFEnum.h>
+#include <Inventor/fields/SoSFFloat.h>
+#include <Inventor/fields/SoSFString.h>
+#include <Inventor/fields/SoSFTime.h>
+#include <Inventor/fields/SoSFColor.h>
+#include <Inventor/fields/SoSFNode.h>
+#include <Inventor/fields/SoSFImage.h>
+#include <Inventor/fields/SoSFVec2f.h>
+#include <Inventor/fields/SoSFVec3f.h>
+#include <Inventor/fields/SoSFVec3d.h>
+#include <Inventor/fields/SoSFRotation.h>
+#include <Inventor/fields/SoMFInt32.h>
+#include <Inventor/fields/SoMFFloat.h>
+#include <Inventor/fields/SoMFString.h>
+#include <Inventor/fields/SoMFTime.h>
+#include <Inventor/fields/SoMFColor.h>
+#include <Inventor/fields/SoMFNode.h>
+#include <Inventor/fields/SoMFVec2f.h>
+#include <Inventor/fields/SoMFVec3f.h>
+#include <Inventor/fields/SoMFVec3d.h>
+#include <Inventor/fields/SoMFRotation.h>
+#include <Inventor/nodes/SoGroup.h>
+#include <Inventor/nodes/SoSeparator.h>
+#include <Inventor/SoDB.h>
+#include <Inventor/SoInput.h>
+#include <Inventor/SoOutput.h> 
+#include <Inventor/VRMLnodes/SoVRMLGroup.h>
+#include <Inventor/errors/SoDebugError.h>
+#include <Inventor/sensors/SoNodeSensor.h>
+
+#include "misc/SbHash.h"
+
+// FIXME: toString() missing for all classes
+
+// "namespace" for all vrml classes
+struct CoinVrmlJs {
+  struct ClassDescriptor {
+    JSClass cls;
+    JSFunctionSpec * functions;
+
+  };
+
+  static ClassDescriptor SFColor;
+  static ClassDescriptor SFNode;
+  static ClassDescriptor SFRotation;
+  static ClassDescriptor SFVec2f;
+  static ClassDescriptor SFVec3f;
+  static ClassDescriptor SFVec3d;
+
+  static ClassDescriptor MFColor;
+  static ClassDescriptor MFFloat;
+  static ClassDescriptor MFInt32;
+  static ClassDescriptor MFNode;
+  static ClassDescriptor MFRotation;
+  static ClassDescriptor MFString;
+  static ClassDescriptor MFTime;
+  static ClassDescriptor MFVec2f;
+  static ClassDescriptor MFVec3f;
+  static ClassDescriptor MFVec3d;
+};
+
+// Struct and SbHash for keeping track of SoNodeSensors for recycling
+// purposes.
+struct CoinVrmlJs_SensorInfo {
+  SbList <JSObject *> objects;
+};
+SbHash <void *, unsigned long> * CoinVrmlJs_sensorinfohash = NULL;
+
+
+const char * CoinVrmlJs_SFColorAliases[] = {"r", "g", "b"};
+const char * CoinVrmlJs_SFRotationAliases[] = {"x", "y", "z", "angle"};
+float CoinVrmlJs_SFdefaultValues[] = {0.0, 0.0, 0.0, 0.0};
+double CoinVrmlJs_SFdefaultValuesDouble[] = {0.0, 0.0, 0.0, 0.0};
+float CoinVrmlJs_SFRotationDefaultValues[] = {0.0, 1.0, 0.0, 0.0};
+
+// Macros for instance checking
+#define JSVAL_IS_SFVEC2F(cx, jsval) (JSVAL_IS_OBJECT(jsval) && spidermonkey()->JS_InstanceOf(cx, JSVAL_TO_OBJECT(jsval), &CoinVrmlJs::SFVec2f.cls, NULL))
+#define JSVAL_IS_SFVEC3F(cx, jsval) (JSVAL_IS_OBJECT(jsval) && spidermonkey()->JS_InstanceOf(cx, JSVAL_TO_OBJECT(jsval), &CoinVrmlJs::SFVec3f.cls, NULL))
+#define JSVAL_IS_SFVEC3D(cx, jsval) (JSVAL_IS_OBJECT(jsval) && spidermonkey()->JS_InstanceOf(cx, JSVAL_TO_OBJECT(jsval), &CoinVrmlJs::SFVec3d.cls, NULL))
+#define JSVAL_IS_SFCOLOR(cx, jsval) (JSVAL_IS_OBJECT(jsval) && spidermonkey()->JS_InstanceOf(cx, JSVAL_TO_OBJECT(jsval), &CoinVrmlJs::SFColor.cls, NULL))
+#define JSVAL_IS_SFROTATION(cx, jsval) (JSVAL_IS_OBJECT(jsval) && spidermonkey()->JS_InstanceOf(cx, JSVAL_TO_OBJECT(jsval), &CoinVrmlJs::SFRotation.cls, NULL))
+
+// Handlers
+#define SFColorHandler CoinVrmlJsSFHandler<SbColor, 3, CoinVrmlJs_SFColorAliases, float, CoinVrmlJs_SFdefaultValues>
+#define SFRotationHandler CoinVrmlJsSFHandler<SbVec4f, 4, CoinVrmlJs_SFRotationAliases, float, CoinVrmlJs_SFRotationDefaultValues>
+#define SFVec2fHandler CoinVrmlJsSFHandler<SbVec2f, 2, CoinVrmlJs_SFRotationAliases, float, CoinVrmlJs_SFdefaultValues>
+#define SFVec3fHandler CoinVrmlJsSFHandler<SbVec3f, 3, CoinVrmlJs_SFRotationAliases, float, CoinVrmlJs_SFdefaultValues>
+#define SFVec3dHandler CoinVrmlJsSFHandler<SbVec3d, 3, CoinVrmlJs_SFRotationAliases, double, CoinVrmlJs_SFdefaultValuesDouble>
+
+#define MFColorHandler CoinVrmlJsMFHandler<SoMFColor, SoSFColor, &CoinVrmlJs::MFColor>
+#define MFFloatHandler CoinVrmlJsMFHandler<SoMFFloat, SoSFFloat, &CoinVrmlJs::MFFloat>
+#define MFInt32Handler CoinVrmlJsMFHandler<SoMFInt32, SoSFInt32, &CoinVrmlJs::MFInt32>
+#define MFNodeHandler CoinVrmlJsMFHandler<SoMFNode, SoSFNode, &CoinVrmlJs::MFNode>
+#define MFRotationHandler CoinVrmlJsMFHandler<SoMFRotation, SoSFRotation, &CoinVrmlJs::MFRotation>
+#define MFStringHandler CoinVrmlJsMFHandler<SoMFString, SoSFString, &CoinVrmlJs::MFString>
+#define MFTimeHandler CoinVrmlJsMFHandler<SoMFTime, SoSFTime, &CoinVrmlJs::MFTime>
+#define MFVec2fHandler CoinVrmlJsMFHandler<SoMFVec2f, SoSFVec2f, &CoinVrmlJs::MFVec2f>
+#define MFVec3fHandler CoinVrmlJsMFHandler<SoMFVec3f, SoSFVec3f, &CoinVrmlJs::MFVec3f>
+#define MFVec3dHandler CoinVrmlJsMFHandler<SoMFVec3d, SoSFVec3d, &CoinVrmlJs::MFVec3d>
+
+static JSFunctionSpec MFFunctions[] = {
+//  {"toString", MF_toString, 0, 0, 0},
+  {NULL, NULL, 0, 0, 0}
+};
+
+static JSBool SFRotationConstructor(JSContext * cx, JSObject * obj,
+                                    uintN argc, jsval * argv, jsval * rval);
+
+// Factory methods for converting to javascript objects
+static JSObject * SFColorFactory(JSContext * cx, const SbColor & self);
+static JSObject * SFNodeFactory(JSContext * cx, SoNode * container);
+static JSObject * SFRotationFactory(JSContext * cx, const SbRotation & self);
+static JSObject * SFVec2fFactory(JSContext * cx, const SbVec2f & self);
+static JSObject * SFVec3fFactory(JSContext * cx, const SbVec3f & self);
+static JSObject * SFVec3dFactory(JSContext * cx, const SbVec3d & self);
+
+static SbList <JSObject *> * garbagecollectedobjects = NULL;
+static SbList <SoNodeSensor *> * nodesensorstobedeleted = NULL;
+
+// getIndex returns -1 if id is not an alias or in range 0-max
+static JSBool getIndex(JSContext * cx, jsval id, const char * aliases[], int max)
+{
+  int index;
+
+  if (JSVAL_IS_INT(id)) {
+    index = JSVAL_TO_INT(id);
+    if (index < 0 || index >= max) {
+      spidermonkey()->JS_ReportError(cx, "index must be between 0 and %d", max);
+      return -1;
+    }
+    return index;
+  }
+  else {
+    JSString * jsstr = spidermonkey()->JS_ValueToString(cx, id);
+    const char * str = spidermonkey()->JS_GetStringBytes(jsstr);
+
+    for (index=0; index<max; ++index) {
+      if (strcmp(str, aliases[index]) == 0) {
+        return index;
+      }
+    }
+    return -1;
+  }
+}
+
+// *************************************************************************
+// handlers
+bool jsval2int(JSContext *cx, const jsval v, int32_t &value) 
+{
+  if (JSVAL_IS_NULL(v)) return false;
+  int32_t tempval;
+  if (!spidermonkey()->JS_ValueToECMAInt32(cx, v, &tempval)) {
+    return false;
+  }
+  value = tempval;
+  return true;
+}
+
+bool jsval2double(JSContext *cx, const jsval v, double &value) 
+{
+  if (JSVAL_IS_NULL(v)) return false;
+  double tempval;
+  if (!spidermonkey()->JS_ValueToNumber(cx, v, &tempval)) {
+    return false;
+  }
+  value = tempval;
+  return true;
+}
+
+
+// FIXME: number of aliases must not be lower than max. This may lead to
+// unsafe programming. 20050721 erikgors.
+template <class Base, int max, const char * aliases[], class basetype, basetype defaultValues[]>
+struct CoinVrmlJsSFHandler {
+  static JSBool get(JSContext * cx, JSObject * obj, jsval id, jsval * rval)
+  {
+    int index = getIndex(cx, id, aliases, max);
+    if (index == -1) {
+      return JS_TRUE;
+    }
+
+    Base * data = (Base *)spidermonkey()->JS_GetPrivate(cx, obj);
+    assert(data != NULL);
+    basetype var = (*data)[index];
+    SbBool ok = spidermonkey()->JS_NewDoubleValue(cx, (double)var, rval);
+    assert(ok && "JS_NewDoubleValue failed");
+    return JS_TRUE;
+  }
+
+  static JSBool set(JSContext * cx, JSObject * obj, jsval id, jsval * val)
+  {
+    int index = getIndex(cx, id, aliases, max);
+    if (index == -1) {
+      return JS_FALSE;
+    }
+
+    Base * data = (Base *)spidermonkey()->JS_GetPrivate(cx, obj);
+    assert(data != NULL);
+
+    // FIXME: number may be NaN, PositiveInfinity and NegativeInfinity.
+    // Should be checked for every time we run JS_ValueToNumber.
+    // ie: "blipp" will become NaN. 20050720 erikgors.
+    double number;
+    spidermonkey()->JS_ValueToNumber(cx, *val, &number);
+    (*data)[index] = (basetype)number;
+    return JS_TRUE;
+  }
+
+  static JSBool constructor(JSContext * cx, JSObject * obj,
+                            uintN argc, jsval * argv, jsval * rval)
+  {
+    basetype vals[max];
+
+    // convert all arguments to numbers or use defaultValues if missing
+    uint32_t i;
+    for (i=0; i<max; ++i) {
+      vals[i] = defaultValues[i];
+      if (i<argc) {
+        double val;
+        if (spidermonkey()->JS_ValueToNumber(cx, argv[i], &val)) {
+          vals[i] = (basetype)val;
+        }
+        else {
+          spidermonkey()->JS_ReportError(cx, "WARNING: failed converting argument %d "
+                                             "to a double", i + 1);
+        }
+      }
+    }
+
+    Base * data = new Base(vals);
+    spidermonkey()->JS_SetPrivate(cx, obj, data);
+    *rval = OBJECT_TO_JSVAL(obj);
+    return JS_TRUE;
+  }
+  static void destructor(JSContext * cx, JSObject * obj)
+  {
+    Base * data = (Base *)spidermonkey()->JS_GetPrivate(cx, obj);
+    // FIXME: We cannot assume this since the class object itself is an
+    // instance of this JSClass. kintel 20050804.
+    //    assert(data != NULL);
+    delete data;
+  }
+};
+
+template <class MFFieldClass, class SFFieldClass, CoinVrmlJs::ClassDescriptor * desc>
+struct CoinVrmlJsMFHandler {
+  static JSBool constructor(JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval)
+  {
+    jsval * val = new jsval;
+    JSObject * array = spidermonkey()->JS_NewArrayObject(cx, 0, NULL);
+    *val = OBJECT_TO_JSVAL(array);
+    SbBool ok = spidermonkey()->JS_AddRoot(cx, val);
+    assert(ok && "JS_AddRoot failed");
+    spidermonkey()->JS_SetPrivate(cx, obj, val);
+
+    SFFieldClass * field = (SFFieldClass *)SFFieldClass::createInstance();
+    uintN i;
+
+    for (i=0; i<argc; ++i) {
+      if (SoJavaScriptEngine::getEngine(cx)->jsval2field(argv[i], field)) {
+        SbBool ok = spidermonkey()->JS_SetElement(cx, array, i, &argv[i]);
+        assert(ok && "JS_SetElement failed");
+      }
+      else {
+        // FIXME: should we insert a default value? 20050727 erikgors.
+        spidermonkey()->JS_ReportError(cx, "argv %d is of wrong type", i);
+      }
+    }
+    delete field;
+    return JS_TRUE;
+  }
+
+  static void destructor(JSContext * cx, JSObject * obj)
+  {
+    jsval * val = (jsval *)spidermonkey()->JS_GetPrivate(cx, obj);
+    if (val != NULL) {
+      SbBool ok = spidermonkey()->JS_RemoveRoot(cx, val);
+      assert(ok && "JS_RemoveRoot failed");
+      delete val;
+    }
+  }
+
+  static JSObject * init(JSContext * cx, JSObject * obj)
+  {
+    return spidermonkey()->JS_InitClass(cx, obj, NULL, &desc->cls,
+                                        constructor, 0,
+                                        NULL, MFFunctions, NULL, NULL);
+  }
+
+  static void resize(JSContext * cx, JSObject * array, uint32_t newLength)
+  {
+    uint32_t length;
+    SbBool ok = spidermonkey()->JS_GetArrayLength(cx, array, &length);
+    assert(ok && "JS_GetArrayLength failed");
+
+    if (length > newLength) {
+      spidermonkey()->JS_SetArrayLength(cx, array, newLength);
+    }
+    else {
+      SoType type = MFFieldClass::getClassTypeId();
+
+      // expand and fill with new objects
+      for (; length<newLength; ++length) {
+        jsval val;
+
+        if (type == SoMFInt32::getClassTypeId() ||
+            type == SoMFFloat::getClassTypeId()) {
+          val = INT_TO_JSVAL(0);
+        }
+        else if (type == SoMFString::getClassTypeId()) {
+          JSString * str = spidermonkey()->JS_NewStringCopyZ(cx, "");
+          val = STRING_TO_JSVAL(str);
+        }
+        else if (type == SoMFNode::getClassTypeId()) {
+          // All elements not explicitly initialized are set to NULL
+          val = JSVAL_VOID;
+        }
+        else if (type == SoMFColor::getClassTypeId()) {
+          JSObject * newObj =
+            spidermonkey()->JS_NewObject(cx, &CoinVrmlJs::SFColor.cls, NULL, NULL);
+          assert(newObj != NULL);
+          SFColorHandler::constructor(cx, newObj, 0, NULL, &val);
+          val = OBJECT_TO_JSVAL(newObj);
+        }
+        else if (type == SoMFRotation::getClassTypeId()) {
+          JSObject * newObj =
+            spidermonkey()->JS_NewObject(cx, &CoinVrmlJs::SFRotation.cls, NULL, NULL);
+          assert(newObj != NULL);
+          SFRotationConstructor(cx, newObj, 0, NULL, &val);
+          val = OBJECT_TO_JSVAL(newObj);
+        }
+        else if (type == SoMFVec2f::getClassTypeId()) {
+          JSObject * newObj =
+            spidermonkey()->JS_NewObject(cx, &CoinVrmlJs::SFVec2f.cls, NULL, NULL);
+          assert(newObj != NULL);
+          SFVec2fHandler::constructor(cx, newObj, 0, NULL, &val);
+          val = OBJECT_TO_JSVAL(newObj);
+        }
+        else if (type == SoMFVec3f::getClassTypeId()) {
+          JSObject * newObj =
+            spidermonkey()->JS_NewObject(cx, &CoinVrmlJs::SFVec3f.cls, NULL, NULL);
+          assert(newObj != NULL);
+          SFVec3fHandler::constructor(cx, newObj, 0, NULL, &val);
+          val = OBJECT_TO_JSVAL(newObj);
+        }
+        else if (type == SoMFVec3d::getClassTypeId()) {
+          JSObject * newObj =
+            spidermonkey()->JS_NewObject(cx, &CoinVrmlJs::SFVec3d.cls, NULL, NULL);
+          assert(newObj != NULL);
+          SFVec3dHandler::constructor(cx, newObj, 0, NULL, &val);
+          val = OBJECT_TO_JSVAL(newObj);
+        }
+        else {
+          assert(0 && "this should not happen");
+        }
+        SbBool ok = spidermonkey()->JS_SetElement(cx, array, length, &val);
+        assert(ok && "JS_SetElement failed");
+      }
+    }
+  }
+
+  static JSBool get(JSContext * cx, JSObject * obj, jsval id, jsval * rval)
+  {
+
+    jsval * array = (jsval *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+    if (JSVAL_IS_INT(id)) {
+      assert(array != NULL);
+      int index = JSVAL_TO_INT(id);
+      return spidermonkey()->JS_GetElement(cx, JSVAL_TO_OBJECT(*array), index, rval);
+    }
+    else if (JSVAL_IS_STRING(id)) {
+      const char * str = spidermonkey()->JS_GetStringBytes(JSVAL_TO_STRING(id));
+      if (SbName("length") == str) {
+        assert(array != NULL);
+        uint32_t length;
+        SbBool ok = spidermonkey()->JS_GetArrayLength(cx, JSVAL_TO_OBJECT(*array), &length);
+        assert(ok && "JS_GetArrayLength failed");
+        *rval = INT_TO_JSVAL(length);
+        return JS_TRUE;
+      }
+    }
+
+    return JS_TRUE;
+  }
+
+  static JSBool set(JSContext * cx, JSObject * obj, jsval id, jsval * val)
+  {
+    jsval * array = (jsval *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+    if (JSVAL_IS_INT(id)) {
+      int index = JSVAL_TO_INT(id);
+
+      // check for bounds
+      if (index < 0) {
+        return JS_FALSE;
+      }
+
+      // resize if necessary
+      uint32_t length;
+      SbBool ok = spidermonkey()->JS_GetArrayLength(cx, JSVAL_TO_OBJECT(*array), &length);
+      assert(ok && "JS_GetArrayLength failed");
+      if (index >= (int)length) {
+        resize(cx, JSVAL_TO_OBJECT(*array), index+1);
+      }
+
+      SFFieldClass * field = (SFFieldClass *)SFFieldClass::createInstance();
+      // Check if val is not of wrong type
+      if (SoJavaScriptEngine::getEngine(cx)->jsval2field(*val, field)) {
+        // assign it
+        SbBool ok = spidermonkey()->JS_SetElement(cx, JSVAL_TO_OBJECT(*array), index, val);
+        assert(ok && "JS_SetElement failed");
+        return JS_TRUE;
+      }
+      delete field;
+    }
+    else if (JSVAL_IS_STRING(id)) {
+      const char * str = spidermonkey()->JS_GetStringBytes(JSVAL_TO_STRING(id));
+      if (SbName("length") == str) {
+        double number;
+        spidermonkey()->JS_ValueToNumber(cx, *val, &number);
+        if (number < 0) {
+          spidermonkey()->JS_ReportError(cx, "RangeError: invalid array length");
+        }
+        else {
+          resize(cx, JSVAL_TO_OBJECT(*array), (uint32_t)number);
+        }
+        return JS_TRUE;
+      }
+    }
+
+    return JS_FALSE;
+  }
+
+
+  static SbBool jsval2field(JSContext * cx, const jsval v, SoField * f)
+  {
+    if (JSVAL_IS_OBJECT(v) &&
+        spidermonkey()->JS_InstanceOf(cx, JSVAL_TO_OBJECT(v), &desc->cls, NULL)) {
+      JSObject * obj = JSVAL_TO_OBJECT(v);
+      jsval * array = (jsval *)spidermonkey()->JS_GetPrivate(cx, obj);
+      assert(array != NULL);
+
+      jsval element;
+      uint32_t i;
+      uint32_t num;
+      JSBool ok = spidermonkey()->JS_GetArrayLength(cx, JSVAL_TO_OBJECT(*array), &num);
+
+      SFFieldClass * field = (SFFieldClass *)SFFieldClass::createInstance();
+
+      for (i=0; i<num; ++i) {
+        ok = spidermonkey()->JS_GetElement(cx, obj, i, &element);
+        assert(ok);
+
+        ok = SoJavaScriptEngine::getEngine(cx)->jsval2field(element, field);
+        assert(ok && "jsval2field failed");
+        ((MFFieldClass *)f)->set1Value(i, field->getValue());
+      }
+      delete field;
+      return TRUE;
+    }
+    return FALSE;
+  }
+
+  static void field2jsval(JSContext * cx, const SoField * f, jsval * v)
+  {
+    JSObject * obj = spidermonkey()->JS_NewObject(cx, &desc->cls, NULL, NULL);
+    spidermonkey()->JS_DefineFunctions(cx, obj, desc->functions);
+
+    int num = ((SoMField *)f)->getNum();
+    jsval * vals = new jsval[num];
+
+    MFFieldClass & mf = *(MFFieldClass *)f;
+
+    SFFieldClass * field = (SFFieldClass *)SFFieldClass::createInstance();
+    for (int i=0; i<num; ++i) {
+      field->setValue(mf[i]);
+      SbBool ok = SoJavaScriptEngine::getEngine(cx)->field2jsval(field, &vals[i]);
+      assert(ok && "field2jsval failed");
+    }
+
+    jsval rval;
+    constructor(cx, obj, num, vals, &rval);
+    *v = OBJECT_TO_JSVAL(obj);
+    delete field;
+    delete [] vals;
+  }
+};
+
+// *************************************************************************
+// constructors
+
+static JSBool SFRotationConstructor(JSContext * cx, JSObject * obj,
+                                    uintN argc, jsval * argv, jsval * rval)
+{
+  if (argc == 2) {
+    if (JSVAL_IS_SFVEC3F(cx, argv[0])) {
+      SbVec3f & vec =
+        *(SbVec3f *)spidermonkey()->JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[0]));
+
+      SbVec4f * data = new SbVec4f();
+      spidermonkey()->JS_SetPrivate(cx, obj, data);
+      *rval = OBJECT_TO_JSVAL(obj);
+      // new SFRotation(SFVec3f fromVector, SFVec3f toVector)
+      if (JSVAL_IS_SFVEC3F(cx, argv[1])) {
+        SbVec3f & vec2 =
+          *(SbVec3f *)spidermonkey()->JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[1]));
+
+        SbRotation rot(vec, vec2);
+        SbVec3f axis;
+        float rad;
+        rot.getValue(axis, rad);
+
+        data->setValue(axis[0], axis[1], axis[2], rad);
+        return JS_TRUE;
+      }
+      // new SFRotation(SFVec3f axis, numeric angle)
+      else {
+        SbVec4f * data = new SbVec4f();
+        spidermonkey()->JS_SetPrivate(cx, obj, data);
+        *rval = OBJECT_TO_JSVAL(obj);
+
+        double number = 0.0;
+        spidermonkey()->JS_ValueToNumber(cx, argv[1], &number);
+
+        data->setValue(vec[0], vec[1], vec[2], (float)number);
+        return JS_TRUE;
+      }
+    }
+  }
+  // new SFRotation(numeric x, numeric y, numeric z, numeric angle)
+  // Missing values default to 0.0, except y, which defaults to 1.0.
+  //
+  // SbRotation will default to 0.0, 0.0, 1.0, when angle is 0.0
+  // So we use SbVec4f to hold values for SFRotation, since we need to support
+  // patterns like this:
+  // var colors = new MFColor();
+  // colors.length = 10;
+  // colors[0].x = 1
+  // colors[0].y = 0
+  // colors[0].z = 0
+  // colors[0].angle = 1.8
+  //
+  // This will not work when SbRotation holds the values. 20050714 erikgors.
+
+  return SFRotationHandler::constructor(cx, obj, argc, argv, rval);
+}
+
+// *************************************************************************
+// functions
+
+static JSBool SFNode_ref(JSContext * cx, JSObject * obj, uintN argc,
+                         jsval * argv, jsval * rval)
+{
+  // Check if the JS object has already been garbage collected. This
+  // must be done to prevent a Java script from crashing the
+  // application.
+  if (garbagecollectedobjects->find(obj) != -1) {
+    if (SoJavaScriptEngine::debug())
+      SoDebugError::postInfo("SFNode_ref", "WARNING! Trying to ref a deleted node.");
+    return JSVAL_FALSE;
+  }
+
+  SoNode & node = *(SoNode *)spidermonkey()->JS_GetPrivate(cx, obj);
+  node.ref();
+  return JSVAL_TRUE;
+}
+
+static JSBool SFNode_unref(JSContext * cx, JSObject * obj, uintN argc,
+                           jsval * argv, jsval * rval)
+{
+  // Check if the JS object has already been garbage collected. This
+  // must be done to prevent a Java script from crashing the
+  // application.
+  if (garbagecollectedobjects->find(obj) != -1) {
+    if (SoJavaScriptEngine::debug())
+      SoDebugError::postInfo("SFNode_unref", "WARNING! Trying to unref an already deleted node.");
+    return JSVAL_FALSE;
+  }
+
+  SoNode & node = *(SoNode *)spidermonkey()->JS_GetPrivate(cx, obj);
+  node.unref();
+  return JSVAL_TRUE;
+}
+
+static void *
+buffer_realloc(void * bufptr, size_t size)
+{
+  char *buffer = (char *)realloc(bufptr, size);
+  return buffer;
+}
+
+static JSBool SFNode_toString(JSContext * cx, JSObject * obj, uintN argc,
+                              jsval * argv, jsval * rval)
+{
+  // Check if the JS object has already been garbage collected. This
+  // must be done to prevent a Java script from crashing the
+  // application.
+  if (garbagecollectedobjects->find(obj) != -1) {
+    if (SoJavaScriptEngine::debug())
+      SoDebugError::postInfo("SFNode_toString", "WARNING! Trying to access "
+                             "an already deleted node.");
+    return JSVAL_FALSE;
+  }
+
+  SoNode *node = (SoNode *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+  SoOutput out;
+  out.setHeaderString("#VRML V2.0 utf8");
+  size_t buffer_size = 1024;
+  void *buffer = (void *)malloc(buffer_size);
+  out.setBuffer(buffer, buffer_size, buffer_realloc);
+  
+  SoWriteAction wa(&out);
+  wa.apply(node);
+  
+  out.getBuffer(buffer, buffer_size);
+
+  *rval = STRING_TO_JSVAL(spidermonkey()->JS_NewStringCopyZ(cx, 
+    (char *)buffer));
+
+  free(buffer);
+
+  return JSVAL_TRUE;
+}
+
+static void SFNode_deleteCB(void * data, SoSensor * sensor)
+{
+  SoNode * node = ((SoNodeSensor *) sensor)->getAttachedNode();
+  void * tmp;
+  if(!CoinVrmlJs_sensorinfohash->get((unsigned long) node, tmp)) {
+    assert(FALSE && "Trying to delete an unregistered SoNodeSensor. Internal error.");
+    return;
+  }
+
+  CoinVrmlJs_SensorInfo * si = (CoinVrmlJs_SensorInfo *) tmp;
+
+  // Delete all JSObjects which were connected to this SoNode
+  while (si->objects.getLength()) {
+    JSObject * obj = si->objects[0];
+    garbagecollectedobjects->append(obj);
+    si->objects.removeFast(0);
+  }
+
+  // Store the sensor-pointer so that it can be properly deleted later
+  nodesensorstobedeleted->append((SoNodeSensor *) sensor);
+  CoinVrmlJs_sensorinfohash->remove((unsigned long) node);
+  delete si;
+}
+
+static void cleanupObsoleteNodeSensors(void)
+{
+  // Delete all SoNodeSensors which no longer have a node attached.
+  while(nodesensorstobedeleted->getLength() > 0) {
+    SoNodeSensor * ns = (SoNodeSensor *) (*nodesensorstobedeleted)[0];
+    nodesensorstobedeleted->removeItem(ns);
+    delete ns;
+  }
+}
+
+static JSBool SFVec2f_add(JSContext * cx, JSObject * obj, uintN argc,
+                          jsval * argv, jsval * rval)
+{
+  SbVec2f & vec1 = *(SbVec2f *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+  if (argc >= 1 && JSVAL_IS_SFVEC2F(cx, argv[0])) {
+    SbVec2f & vec2 = *(SbVec2f *)spidermonkey()->JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[0]));
+    SbVec2f result = vec1 + vec2;
+    *rval = OBJECT_TO_JSVAL(SFVec2fFactory(cx, result));
+    return JS_TRUE;
+  }
+
+  return JS_FALSE;
+}
+
+static JSBool SFVec3f_add(JSContext * cx, JSObject * obj, uintN argc,
+                          jsval * argv, jsval * rval)
+{
+  SbVec3f & vec1 = *(SbVec3f *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+  if (argc >= 1 && JSVAL_IS_SFVEC3F(cx, argv[0])) {
+    SbVec3f & vec2 = *(SbVec3f *)spidermonkey()->JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[0]));
+    SbVec3f result = vec1 + vec2;
+    *rval = OBJECT_TO_JSVAL(SFVec3fFactory(cx, result));
+    return JS_TRUE;
+  }
+
+  return JS_FALSE;
+}
+
+static JSBool SFVec3d_add(JSContext * cx, JSObject * obj, uintN argc,
+                          jsval * argv, jsval * rval)
+{
+  SbVec3d & vec1 = *(SbVec3d *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+  if (argc >= 1 && JSVAL_IS_SFVEC3D(cx, argv[0])) {
+    SbVec3d & vec2 = *(SbVec3d *)spidermonkey()->JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[0]));
+    SbVec3d result = vec1 + vec2;
+    *rval = OBJECT_TO_JSVAL(SFVec3dFactory(cx, result));
+    return JS_TRUE;
+  }
+
+  return JS_FALSE;
+}
+
+static JSBool SFVec2f_divide(JSContext * cx, JSObject * obj, uintN argc,
+                             jsval * argv, jsval * rval)
+{
+  SbVec2f & vec = *(SbVec2f *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+  double number;
+  if (argc >= 1 && jsval2double(cx, argv[0], number)) {
+    SbVec2f newVec = vec / (float)number;
+    *rval = OBJECT_TO_JSVAL(SFVec2fFactory(cx, newVec));
+    return JS_TRUE;
+  }
+  return JS_FALSE;
+}
+
+static JSBool SFVec3f_divide(JSContext * cx, JSObject * obj, uintN argc,
+                             jsval * argv, jsval * rval)
+{
+  SbVec3f & vec = *(SbVec3f *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+  double number;
+  if (argc >= 1 && jsval2double(cx, argv[0], number)) {
+    SbVec3f newVec = vec / (float)number;
+    *rval = OBJECT_TO_JSVAL(SFVec3fFactory(cx, newVec));
+    return JS_TRUE;
+  }
+  return JS_FALSE;
+}
+
+static JSBool SFVec3d_divide(JSContext * cx, JSObject * obj, uintN argc,
+                             jsval * argv, jsval * rval)
+{
+  SbVec3d & vec = *(SbVec3d *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+  double number;
+  if (argc >= 1 && jsval2double(cx, argv[0], number)) {
+    SbVec3d newVec = vec / number;
+    *rval = OBJECT_TO_JSVAL(SFVec3dFactory(cx, newVec));
+    return JS_TRUE;
+  }
+  return JS_FALSE;
+}
+
+static JSBool SFVec2f_dot(JSContext *cx, JSObject *obj, uintN argc,
+                          jsval *argv, jsval *rval)
+{
+  SbVec2f & vec1 = *(SbVec2f *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+  if (argc >= 1 && JSVAL_IS_SFVEC2F(cx, argv[0])) {
+    SbVec2f & vec2 = *(SbVec2f *)spidermonkey()->JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[0]));
+
+    float dot = vec1.dot(vec2);
+    JSBool ok = spidermonkey()->JS_NewDoubleValue(cx, dot, rval);
+    return JS_TRUE;
+  }
+  return JS_FALSE;
+}
+
+static JSBool SFVec3f_dot(JSContext *cx, JSObject *obj, uintN argc,
+                          jsval *argv, jsval *rval)
+{
+  SbVec3f & vec = *(SbVec3f *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+  if (argc >= 1 && JSVAL_IS_SFVEC3F(cx, argv[0])) {
+
+    SbVec3f & vec2 = *(SbVec3f *)spidermonkey()->JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[0]));
+
+    float dot = vec.dot(vec2);
+    JSBool ok = spidermonkey()->JS_NewDoubleValue(cx, dot, rval);
+    return JS_TRUE;
+  }
+  return JS_FALSE;
+}
+
+static JSBool SFVec3d_dot(JSContext *cx, JSObject *obj, uintN argc,
+                          jsval *argv, jsval *rval)
+{
+  SbVec3d & vec = *(SbVec3d *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+  if (argc >= 1 && JSVAL_IS_SFVEC3D(cx, argv[0])) {
+
+    SbVec3d & vec2 = *(SbVec3d *)spidermonkey()->JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[0]));
+
+    double dot = vec.dot(vec2);
+    JSBool ok = spidermonkey()->JS_NewDoubleValue(cx, dot, rval);
+    return JS_TRUE;
+  }
+  return JS_FALSE;
+}
+
+static JSBool SFVec2_length(JSContext * cx, JSObject * obj, uintN argc,
+                            jsval * argv, jsval * rval)
+{
+  SbVec2f * vec = (SbVec2f *)spidermonkey()->JS_GetPrivate(cx, obj);
+  JSBool ok = spidermonkey()->JS_NewDoubleValue(cx, vec->length(), rval);
+  return JS_TRUE;
+}
+
+static JSBool SFVec3f_length(JSContext * cx, JSObject * obj, uintN argc,
+                            jsval * argv, jsval * rval)
+{
+  SbVec3f * vec = (SbVec3f *)spidermonkey()->JS_GetPrivate(cx, obj);
+  JSBool ok = spidermonkey()->JS_NewDoubleValue(cx, vec->length(), rval);
+  return JS_TRUE;
+}
+
+static JSBool SFVec3d_length(JSContext * cx, JSObject * obj, uintN argc,
+                            jsval * argv, jsval * rval)
+{
+  SbVec3d * vec = (SbVec3d *)spidermonkey()->JS_GetPrivate(cx, obj);
+  JSBool ok = spidermonkey()->JS_NewDoubleValue(cx, vec->length(), rval);
+  return JS_TRUE;
+}
+
+static JSBool SFVec2f_multiply(JSContext * cx, JSObject * obj, uintN argc,
+                               jsval * argv, jsval * rval)
+{
+
+  SbVec2f & vec = *(SbVec2f *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+  if (argc >= 1 && JSVAL_IS_NUMBER(argv[0])) {
+    double number;
+    spidermonkey()->JS_ValueToNumber(cx, argv[0], &number);
+
+    SbVec2f newVec = vec * (float)number;
+
+    *rval = OBJECT_TO_JSVAL(SFVec2fFactory(cx, newVec));
+
+    return JS_TRUE;
+  }
+  return JS_FALSE;
+}
+
+static JSBool SFVec3f_multiply(JSContext * cx, JSObject * obj, uintN argc,
+                               jsval * argv, jsval * rval)
+{
+  SbVec3f & vec = *(SbVec3f *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+  double number;
+  if (argc >= 1 && jsval2double(cx, argv[0], number)) {
+    SbVec3f newVec = vec * (float)number;
+    *rval = OBJECT_TO_JSVAL(SFVec3fFactory(cx, newVec));
+    return JS_TRUE;
+  }
+  return JS_FALSE;
+}
+
+static JSBool SFVec3d_multiply(JSContext * cx, JSObject * obj, uintN argc,
+                               jsval * argv, jsval * rval)
+{
+  SbVec3d & vec = *(SbVec3d *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+  double number;
+  if (argc >= 1 && jsval2double(cx, argv[0], number)) {
+    SbVec3d newVec = vec * number;
+    *rval = OBJECT_TO_JSVAL(SFVec3dFactory(cx, newVec));
+    return JS_TRUE;
+  }
+  return JS_FALSE;
+}
+
+static JSBool SFVec2f_normalize(JSContext * cx, JSObject * obj, uintN argc,
+                                jsval * argv, jsval * rval)
+{
+  SbVec2f vec = *(SbVec2f *)spidermonkey()->JS_GetPrivate(cx, obj);
+  vec.normalize();
+  *rval = OBJECT_TO_JSVAL(SFVec2fFactory(cx, vec));
+  return JS_TRUE;
+}
+
+static JSBool SFVec3f_normalize(JSContext * cx, JSObject * obj, uintN argc,
+                                jsval * argv, jsval * rval)
+{
+  SbVec3f vec = *(SbVec3f *)spidermonkey()->JS_GetPrivate(cx, obj);
+  vec.normalize();
+  *rval = OBJECT_TO_JSVAL(SFVec3fFactory(cx, vec));
+  return JS_TRUE;
+}
+
+static JSBool SFVec3d_normalize(JSContext * cx, JSObject * obj, uintN argc,
+                                jsval * argv, jsval * rval)
+{
+  SbVec3d vec = *(SbVec3d *)spidermonkey()->JS_GetPrivate(cx, obj);
+  vec.normalize();
+  *rval = OBJECT_TO_JSVAL(SFVec3dFactory(cx, vec));
+  return JS_TRUE;
+}
+
+static JSBool SFVec3f_negate(JSContext * cx, JSObject * obj, uintN argc,
+                                     jsval * argv, jsval * rval)
+{
+  SbVec3f vec = *(SbVec3f *)spidermonkey()->JS_GetPrivate(cx, obj);
+  vec.negate();
+  *rval = OBJECT_TO_JSVAL(SFVec3fFactory(cx, vec));
+  return JS_TRUE;
+}
+
+static JSBool SFVec3d_negate(JSContext * cx, JSObject * obj, uintN argc,
+                                     jsval * argv, jsval * rval)
+{
+  SbVec3d vec = *(SbVec3d *)spidermonkey()->JS_GetPrivate(cx, obj);
+  vec.negate();
+  *rval = OBJECT_TO_JSVAL(SFVec3dFactory(cx, vec));
+  return JS_TRUE;
+}
+
+static JSBool SFVec2f_subtract(JSContext * cx, JSObject * obj, uintN argc,
+                               jsval * argv, jsval * rval)
+{
+  SbVec2f & vec1 = *(SbVec2f *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+  if (argc >= 1 && JSVAL_IS_SFVEC2F(cx, argv[0])) {
+    SbVec2f & vec2 = *(SbVec2f *)spidermonkey()->JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[0]));
+    SbVec2f result = vec1 - vec2;
+    *rval = OBJECT_TO_JSVAL(SFVec2fFactory(cx, result));
+    return JS_TRUE;
+  }
+  return JS_FALSE;
+}
+
+static JSBool SFVec3f_subtract(JSContext * cx, JSObject * obj, uintN argc,
+                               jsval * argv, jsval * rval)
+{
+  SbVec3f & vec1 = *(SbVec3f *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+  if (argc >= 1 && JSVAL_IS_SFVEC3F(cx, argv[0])) {
+    SbVec3f & vec2 = *(SbVec3f *)spidermonkey()->JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[0]));
+    SbVec3f result = vec1 - vec2;
+    *rval = OBJECT_TO_JSVAL(SFVec3fFactory(cx, result));
+    return JS_TRUE;
+  }
+
+  return JS_FALSE;
+}
+
+static JSBool SFVec3d_subtract(JSContext * cx, JSObject * obj, uintN argc,
+                               jsval * argv, jsval * rval)
+{
+  SbVec3d & vec1 = *(SbVec3d *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+  if (argc >= 1 && JSVAL_IS_SFVEC3D(cx, argv[0])) {
+    SbVec3d & vec2 = *(SbVec3d *)spidermonkey()->JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[0]));
+    SbVec3d result = vec1 - vec2;
+    *rval = OBJECT_TO_JSVAL(SFVec3dFactory(cx, result));
+    return JS_TRUE;
+  }
+
+  return JS_FALSE;
+}
+
+static JSBool SFColor_setHSV(JSContext * cx, JSObject * obj, uintN argc,
+                             jsval * argv, jsval * rval)
+{
+  if (argc != 3) {
+    return JS_FALSE;
+  }
+  SbColor & color = *(SbColor *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+  float vals[3];
+  int i;
+
+  for (i=0; i<3; ++i) {
+    double number;
+    spidermonkey()->JS_ValueToNumber(cx, argv[i], &number);
+    vals[i] = (float)number;
+  }
+
+  color.setHSVValue(vals);
+
+  *rval = JSVAL_VOID;
+  return JS_TRUE;
+}
+
+static JSBool SFColor_getHSV(JSContext * cx, JSObject * obj, uintN argc,
+                             jsval * argv, jsval * rval)
+{
+  SbColor & color = *(SbColor *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+  float vals[3];
+  color.getHSVValue(vals);
+
+  jsval vector[3];
+  for (int i=0; i<3; ++i) {
+    spidermonkey()->JS_NewDoubleValue(cx, vals[i], &vector[i]);
+  }
+
+  *rval = OBJECT_TO_JSVAL(spidermonkey()->JS_NewArrayObject(cx, 3, vector));
+
+  return JS_TRUE;
+}
+
+static JSBool SFRotation_getAxis(JSContext * cx, JSObject * obj, uintN argc,
+                                 jsval * argv, jsval * rval)
+{
+  SbVec4f & rot = *(SbVec4f *)spidermonkey()->JS_GetPrivate(cx, obj);
+  SbVec3f axis(rot[0], rot[1], rot[2]);
+  *rval = OBJECT_TO_JSVAL(SFVec3fFactory(cx, axis));
+  return JS_TRUE;
+}
+
+static JSBool SFRotation_inverse(JSContext * cx, JSObject * obj, uintN argc,
+                                 jsval * argv, jsval * rval)
+{
+  SbVec4f & rot = *(SbVec4f *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+  SbVec3f axis(rot[0], rot[1], rot[2]);
+  SbRotation newRot(axis, rot[3]);
+  newRot.invert();
+
+  *rval = OBJECT_TO_JSVAL(SFRotationFactory(cx, newRot));
+  return JS_TRUE;
+}
+
+static JSBool SFRotation_multiply(JSContext * cx, JSObject * obj, uintN argc,
+                                  jsval * argv, jsval * rval)
+{
+  SbVec4f & vec1 = *(SbVec4f *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+  if (argc >= 1 && JSVAL_IS_SFROTATION(cx, argv[0])) {
+    SbVec4f & vec2 = *(SbVec4f *)spidermonkey()->JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[0]));
+    SbVec3f axis1(vec1[0], vec1[1], vec1[2]);
+    SbVec3f axis2(vec2[0], vec2[1], vec2[2]);
+    SbRotation result = SbRotation(axis1, vec1[3]) * SbRotation(axis2, vec2[3]);
+
+    *rval = OBJECT_TO_JSVAL(SFRotationFactory(cx, result));
+    return JS_TRUE;
+  }
+  return JS_FALSE;
+}
+
+static JSBool SFRotation_multVec(JSContext * cx, JSObject * obj, uintN argc,
+                                 jsval * argv, jsval * rval)
+{
+  SbVec4f & vec = *(SbVec4f *)spidermonkey()->JS_GetPrivate(cx, obj);
+  SbVec3f axis(vec[0], vec[1], vec[2]);
+  SbRotation rot(axis, vec[3]);
+
+  if (argc >= 1 && JSVAL_IS_SFVEC3F(cx, argv[0])) {
+    SbVec3f & src = *(SbVec3f *)spidermonkey()->JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[0]));
+    SbVec3f dst;
+    rot.multVec(src, dst);
+
+    *rval = OBJECT_TO_JSVAL(SFVec3fFactory(cx, dst));
+    return JS_TRUE;
+  }
+  return JS_FALSE;
+}
+
+static JSBool SFRotation_setAxis(JSContext * cx, JSObject * obj, uintN argc,
+                                 jsval * argv, jsval * rval)
+{
+  SbVec4f & rot = *(SbVec4f *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+  if (argc >= 1 && JSVAL_IS_SFVEC3F(cx, argv[0])) {
+    SbVec3f & axis = *(SbVec3f *)spidermonkey()->JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[0]));
+    rot[0] = axis[0];
+    rot[1] = axis[1];
+    rot[2] = axis[2];
+
+    *rval = JSVAL_VOID;
+    return JS_TRUE;
+  }
+  return JS_FALSE;
+}
+
+static JSBool SFRotation_slerp(JSContext * cx, JSObject * obj, uintN argc,
+                               jsval * argv, jsval * rval)
+{
+  SbVec4f & vec = *(SbVec4f *)spidermonkey()->JS_GetPrivate(cx, obj);
+  SbVec3f axis(vec[0], vec[1], vec[2]);
+  SbRotation rot(axis, vec[3]);
+
+  double number;
+  if (argc >= 2 && JSVAL_IS_SFROTATION(cx, argv[0]) && jsval2double(cx, argv[1], number)) {
+    SbVec4f & vec2 = *(SbVec4f *)spidermonkey()->JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[0]));
+    SbVec3f axis2(vec2[0], vec2[1], vec2[2]);
+    SbRotation dest(axis2, vec2[3]);
+
+    SbRotation result = SbRotation::slerp(rot, dest, (float)number);
+
+    *rval = OBJECT_TO_JSVAL(SFRotationFactory(cx, result));
+    return JS_TRUE;
+  }
+  return JS_FALSE;
+}
+
+static JSFunctionSpec SFNodeFunctions[] = {
+  {"ref", SFNode_ref, 0, 0, 0},
+  {"unref", SFNode_unref, 0, 0, 0},
+  {"toString", SFNode_toString, 0, 0, 0},
+  {NULL, NULL, 0, 0, 0}
+};
+
+static JSFunctionSpec SFVec2fFunctions[] = {
+  {"add", SFVec2f_add, 1, 0, 0},
+  {"divide", SFVec2f_divide, 1, 0, 0},
+  {"dot", SFVec2f_dot, 1, 0, 0},
+  {"length", SFVec2_length, 0, 0, 0},
+  {"multiply", SFVec2f_multiply, 1, 0, 0},
+  {"normalize", SFVec2f_normalize, 0, 0, 0},
+  {"subtract", SFVec2f_subtract, 1, 0, 0},
+  {NULL, NULL, 0, 0, 0}
+};
+
+static JSFunctionSpec SFVec3fFunctions[] = {
+  {"add", SFVec3f_add, 1, 0, 0},
+  {"divide", SFVec3f_divide, 1, 0, 0},
+  {"dot", SFVec3f_dot, 1, 0, 0},
+  {"length", SFVec3f_length, 0, 0, 0},
+  {"multiply", SFVec3f_multiply, 1, 0, 0},
+  {"normalize", SFVec3f_normalize, 0, 0, 0},
+  {"negate", SFVec3f_negate, 0, 0, 0},
+  {"subtract", SFVec3f_subtract, 1, 0, 0},
+  {NULL, NULL, 0, 0, 0}
+};
+
+static JSFunctionSpec SFVec3dFunctions[] = {
+  {"add", SFVec3d_add, 1, 0, 0},
+  {"divide", SFVec3d_divide, 1, 0, 0},
+  {"dot", SFVec3d_dot, 1, 0, 0},
+  {"length", SFVec3d_length, 0, 0, 0},
+  {"multiply", SFVec3d_multiply, 1, 0, 0},
+  {"normalize", SFVec3d_normalize, 0, 0, 0},
+  {"negate", SFVec3d_negate, 0, 0, 0},
+  {"subtract", SFVec3d_subtract, 1, 0, 0},
+  {NULL, NULL, 0, 0, 0}
+};
+
+static JSFunctionSpec SFColorFunctions[] = {
+  {"setHSV", SFColor_setHSV, 3, 0, 0},
+  {"getHSV", SFColor_getHSV, 0, 0, 0},
+  {NULL, NULL, 0, 0, 0}
+};
+
+static JSFunctionSpec SFRotationFunctions[] = {
+  {"getAxis", SFRotation_getAxis, 0, 0, 0},
+  {"inverse", SFRotation_inverse, 0, 0, 0},
+  {"multiply", SFRotation_multiply, 1, 0, 0},
+  {"multVec", SFRotation_multVec, 1, 0, 0},
+  {"setAxis", SFRotation_setAxis, 1, 0, 0},
+  {"slerp", SFRotation_slerp, 2, 0, 0},
+  {NULL, NULL, 0, 0, 0}
+};
+
+// *************************************************************************
+// factory
+
+static JSObject * SFColorFactory(JSContext * cx, const SbColor & self)
+{
+  JSObject * obj =
+    spidermonkey()->JS_NewObject(cx, &CoinVrmlJs::SFColor.cls, NULL, NULL);
+  spidermonkey()->JS_DefineFunctions(cx, obj, SFColorFunctions);
+
+  SbColor * color = new SbColor(self);
+  spidermonkey()->JS_SetPrivate(cx, obj, color);
+
+  return obj;
+}
+
+static JSObject * SFRotationFactory(JSContext * cx, const SbRotation & self)
+{
+  JSObject * obj =
+    spidermonkey()->JS_NewObject(cx, &CoinVrmlJs::SFRotation.cls, NULL, NULL);
+  spidermonkey()->JS_DefineFunctions(cx, obj, SFRotationFunctions);
+
+  SbVec3f axis;
+  float angle;
+  self.getValue(axis, angle);
+  SbVec4f * data = new SbVec4f(axis[0], axis[1], axis[2], angle);
+  spidermonkey()->JS_SetPrivate(cx, obj, data);
+
+  return obj;
+}
+
+static JSObject * SFVec2fFactory(JSContext * cx, const SbVec2f & self)
+{
+  JSObject * obj =
+    spidermonkey()->JS_NewObject(cx, &CoinVrmlJs::SFVec2f.cls, NULL, NULL);
+  spidermonkey()->JS_DefineFunctions(cx, obj, SFVec2fFunctions);
+
+  SbVec2f * data = new SbVec2f(self);
+  spidermonkey()->JS_SetPrivate(cx, obj, data);
+  return obj;
+}
+
+static JSObject * SFVec3fFactory(JSContext * cx, const SbVec3f & self)
+{
+  JSObject * obj =
+    spidermonkey()->JS_NewObject(cx, &CoinVrmlJs::SFVec3f.cls, NULL, NULL);
+  spidermonkey()->JS_DefineFunctions(cx, obj, SFVec3fFunctions);
+
+  SbVec3f * data = new SbVec3f(self);
+  spidermonkey()->JS_SetPrivate(cx, obj, data);
+
+  return obj;
+}
+
+static JSObject * SFVec3dFactory(JSContext * cx, const SbVec3d & self)
+{
+  JSObject * obj =
+    spidermonkey()->JS_NewObject(cx, &CoinVrmlJs::SFVec3d.cls, NULL, NULL);
+  spidermonkey()->JS_DefineFunctions(cx, obj, SFVec3dFunctions);
+
+  SbVec3d * data = new SbVec3d(self);
+  spidermonkey()->JS_SetPrivate(cx, obj, data);
+
+  return obj;
+}
+
+static JSObject * SFVec2f_init(JSContext * cx, JSObject * obj)
+{
+  return spidermonkey()->JS_InitClass(cx, obj, NULL, &CoinVrmlJs::SFVec2f.cls,
+                                      SFVec2fHandler::constructor, 0,
+                                      NULL, SFVec2fFunctions, NULL, NULL);
+}
+
+static JSObject * SFVec3f_init(JSContext * cx, JSObject * obj)
+{
+  return spidermonkey()->JS_InitClass(cx, obj, NULL, &CoinVrmlJs::SFVec3f.cls,
+                                      SFVec3fHandler::constructor, 0,
+                                      NULL, SFVec3fFunctions, NULL, NULL);
+}
+
+static JSObject * SFVec3d_init(JSContext * cx, JSObject * obj)
+{
+  return spidermonkey()->JS_InitClass(cx, obj, NULL, &CoinVrmlJs::SFVec3d.cls,
+                                      SFVec3dHandler::constructor, 0,
+                                      NULL, SFVec3dFunctions, NULL, NULL);
+}
+
+static JSObject * SFColor_init(JSContext * cx, JSObject * obj)
+{
+  return spidermonkey()->JS_InitClass(cx, obj, NULL, &CoinVrmlJs::SFColor.cls,
+                                      SFColorHandler::constructor, 0,
+                                      NULL, SFColorFunctions, NULL, NULL);
+}
+
+static JSObject * SFRotation_init(JSContext * cx, JSObject * obj)
+{
+  return spidermonkey()->JS_InitClass(cx, obj, NULL, &CoinVrmlJs::SFRotation.cls,
+                                      SFRotationConstructor, 0,
+                                      NULL, SFRotationFunctions, NULL, NULL);
+}
+
+// *************************************************************************
+// SFNode
+
+static JSBool SFNode_get(JSContext * cx, JSObject * obj, jsval id, jsval * rval)
+{
+
+  if (garbagecollectedobjects->find(obj) != -1) {
+    spidermonkey()->JS_ReportError(cx, "Trying to access an object with refcount=0.");
+    return JS_FALSE;
+  }
+
+  SoNode * container = (SoNode *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+  if (container == NULL) {
+    // this will only happen when JS_NewObject calls "constructor"
+    // or the node is "undefined"
+
+    if (JSVAL_IS_STRING(id)) {
+      const char * str = spidermonkey()->JS_GetStringBytes(JSVAL_TO_STRING(id));
+      if (SbName("constructor") == str) {
+        return JS_TRUE;
+      }
+    }
+    spidermonkey()->JS_ReportError(cx, "node is undefined");
+    return JS_FALSE;
+  }
+
+  if (JSVAL_IS_STRING(id)) {
+    SbString str(spidermonkey()->JS_GetStringBytes(JSVAL_TO_STRING(id)));
+
+    SoField * out = container->getField(SbName(str));
+
+    int len = str.getLength();
+    static const char post[] = "_changed";
+    static const size_t postLen = sizeof(post) - 1;
+
+    if (out == NULL && len > (int)postLen &&
+        str.getSubString(len - postLen) == post) {
+      out = container->getField(SbName(str.getSubString(0, len - postLen - 1)));
+    }
+
+    if (out != NULL) {
+      SoJavaScriptEngine::getEngine(cx)->field2jsval(out, rval);
+      return JS_TRUE;
+    }
+  }
+
+  /* Note: If we're unable to find the field, we return JS_TRUE
+     instead of JS_FALSE, which might seem as the logical choice
+     for indicating a failure. If we return JS_FALSE, execution of
+     the script will halt. One side-effect of this is that it is not
+     possible to extend the SFNode JavaScript object by adding
+     properties, which can be very useful in some cases. This is also
+     more in line with the JavaScript philosophy that one can
+     dynamically add and remove properties for any object at any time.
+
+     2005-11-23 thammer.
+
+     Update: We should look more closely into the return values 
+     JS_TRUE / JS_FALSE for all getters and setters, and possibly for
+     other functions as well. It might be more robust to report the
+     error (using JS_ReportError) and return JS_TRUE to allow the
+     script to continue running than to abort the script.
+
+     2006-06-21 thammer.
+  */
+  return JS_TRUE;
+}
+
+static JSBool SFNode_set(JSContext * cx, JSObject * obj, jsval id, jsval * rval)
+{
+  SoNode * container = (SoNode *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+  if (container == NULL) {
+    spidermonkey()->JS_ReportError(cx, "node is undefined");
+    return JS_FALSE;
+  }
+
+  if (JSVAL_IS_STRING(id)) {
+    SbString str(spidermonkey()->JS_GetStringBytes(JSVAL_TO_STRING(id)));
+
+    SoField * in = container->getField(SbName(str));
+
+    int len = str.getLength();
+    static const char pre[] = "set_";
+    static const size_t preLen = sizeof(pre) - 1;
+
+    if (in == NULL && len > (int)preLen &&
+        str.getSubString(0, preLen - 1) == pre) {
+      in = container->getField(SbName(str.getSubString(preLen)));
+    }
+
+    if (in != NULL) {
+      SoJavaScriptEngine::getEngine(cx)->jsval2field(*rval, in);
+      if (SoJavaScriptEngine::debug()) {
+        SoDebugError::postInfo("SFNode_set", "setting field %s", str.getString());
+      }
+    } else if (SoJavaScriptEngine::debug())
+      SoDebugError::postWarning("SFNode_set", "no such field %s", str.getString());
+  }
+
+  // See note in SFNode_get() about return value. 2005-11-23 thammer.
+  return JS_TRUE;
+}
+
+static void SFNodeDestructor(JSContext * cx, JSObject * obj)
+{
+  // Delete all SoNodeSensors which no longer has a node attached.
+  cleanupObsoleteNodeSensors();
+  if(garbagecollectedobjects->find(obj) != -1) { // Pointer is marked as garbage-collected
+    garbagecollectedobjects->removeItem(obj);
+  }
+
+  SoNode * container = (SoNode *)spidermonkey()->JS_GetPrivate(cx, obj);
+  // FIXME: We cannot assume this since the class object itself is an
+  // instance of this JSClass. kintel 20050804.
+  //  assert(container != NULL);
+  if (SoJavaScriptEngine::getEngine(cx)->getAutoNodeUnrefState())
+    if (container) container->unref();
+}
+
+// Called via coin_atexit() when Coin exits.
+static void deleteSensorInfoHash(void)
+{
+  CoinVrmlJs_sensorinfohash->clear();
+  delete CoinVrmlJs_sensorinfohash;
+}
+
+/*
+  Attach an SoNodeSensor to node. Adds a 'delete callback' to the
+  sensor which includes the 'obj' parameter.
+*/
+static void attachSensorToNode(SoNode * node, JSObject * obj)
+{
+  // Has the hash-table been initialized?
+  if (!CoinVrmlJs_sensorinfohash) {
+    CoinVrmlJs_sensorinfohash = new SbHash <void *, unsigned long>;
+    coin_atexit(deleteSensorInfoHash, CC_ATEXIT_NORMAL);
+  }
+
+  // Is a sensor already attached to this SoNode?
+  void * tmp;
+  if (CoinVrmlJs_sensorinfohash->get((unsigned long) node, tmp)) {
+    CoinVrmlJs_SensorInfo * si = (CoinVrmlJs_SensorInfo *) tmp;
+    si->objects.append(obj);
+  }
+  else {
+    SoNodeSensor * ns = new SoNodeSensor();
+    ns->setDeleteCallback(SFNode_deleteCB, obj);
+    ns->attach(node);
+    CoinVrmlJs_SensorInfo * si = new CoinVrmlJs_SensorInfo;
+    si->objects.append(obj);
+    CoinVrmlJs_sensorinfohash->put((unsigned long) node, si);
+  }
+}
+
+static JSObject * SFNodeFactory(JSContext * cx, SoNode * container)
+{
+  // Delete all SoNodeSensors which no longer has a node attached.
+  cleanupObsoleteNodeSensors();
+
+  JSObject * obj = spidermonkey()->JS_NewObject(cx, &CoinVrmlJs::SFNode.cls, NULL, NULL);
+
+  if(garbagecollectedobjects->find(obj) != -1) // Pointer has been used before. Remove from list.
+    garbagecollectedobjects->removeItem(obj);
+
+  spidermonkey()->JS_SetPrivate(cx, obj, container);
+  spidermonkey()->JS_DefineFunctions(cx, obj, SFNodeFunctions);
+
+  // FIXME: If the node has enums, define them here. 2007-03-08 thammer.
+
+  attachSensorToNode(container, obj);
+
+  if (SoJavaScriptEngine::getEngine(cx)->getAutoNodeUnrefState())
+    container->ref();
+
+  return obj;
+}
+
+static JSBool SFNodeConstructor(JSContext * cx, JSObject * obj,
+                                uintN argc, jsval * argv, jsval *rval)
+{
+  // Delete all SoNodeSensors which no longer has a node attached.
+  cleanupObsoleteNodeSensors();
+
+  // spidermonkey ignores the return value
+  if (argc >= 1 && JSVAL_IS_STRING(argv[0])) {
+    JSString * js = JSVAL_TO_STRING(argv[0]);
+    char * str = spidermonkey()->JS_GetStringBytes(js);
+    size_t len = spidermonkey()->JS_GetStringLength(js);
+
+    // FIXME: what about UTF8? 20050701 erikgors.
+
+    if (SoJavaScriptEngine::debug()) {
+      SoDebugError::postInfo("SFNodeConstructor",
+                             "creating new node with str = '%s'", str);
+    }
+
+    SoInput input;
+    const char * array[2];
+    array[0] = str;
+    array[1] = NULL;
+    input.setStringArray(array);
+
+    SoGroup * group;
+    
+    if (input.isFileVRML2())
+      group = SoDB::readAllVRML(&input);
+    else
+      group = SoDB::readAll(&input);
+
+    if (group == NULL) {
+      spidermonkey()->JS_ReportError(cx, "input is not legal VRML string");
+      return JS_FALSE;
+    }
+    if (group->getNumChildren() == 0) {
+      spidermonkey()->JS_ReportError(cx, "no top-level node, result is undefined");
+      *rval = JSVAL_VOID;
+      return JS_FALSE;
+    }
+
+    if(garbagecollectedobjects->find(obj) != -1) { // Pointer has been used before. Remove from list.
+      garbagecollectedobjects->removeItem(obj);
+    }
+
+    attachSensorToNode(group, obj);
+
+    if (SoJavaScriptEngine::getEngine(cx)->getAutoNodeUnrefState())
+      group->ref();
+
+    spidermonkey()->JS_SetPrivate(cx, obj, group);
+    spidermonkey()->JS_DefineFunctions(cx, obj, SFNodeFunctions);
+
+    return JS_TRUE;
+  }
+  return JS_FALSE;
+}
+
+static JSObject * SFNode_init(JSContext * cx, JSObject * obj)
+{
+  return spidermonkey()->JS_InitClass(cx, obj, NULL, &CoinVrmlJs::SFNode.cls,
+                                      SFNodeConstructor, 0,
+                                      NULL, NULL, NULL, NULL);
+}
+
+
+// *************************************************************************
+// jsval2field
+
+static SbBool SFBool_jsval2field(JSContext * cx, const jsval v, SoField * f)
+{
+  if (JSVAL_IS_BOOLEAN(v)) {
+    const SbBool b = JSVAL_TO_BOOLEAN(v);
+    ((SoSFBool *)f)->setValue(b);
+    return TRUE;
+  }
+  else {
+    JSBool b;
+    if (spidermonkey()->JS_ValueToBoolean(cx, v, &b)) {
+      ((SoSFBool *)f)->setValue(b);
+      return TRUE;
+    }
+  }
+  return FALSE;
+}
+
+static SbBool SFColor_jsval2field(JSContext * cx, const jsval v, SoField * f)
+{
+  if (JSVAL_IS_SFCOLOR(cx, v)) {
+    SbColor * color = (SbColor *)spidermonkey()->JS_GetPrivate(cx, JSVAL_TO_OBJECT(v));
+    assert(color != NULL);
+    ((SoSFColor *)f)->setValue(*color);
+    return TRUE;
+  }
+  return FALSE;
+}
+
+static SbBool SFFloat_jsval2field(JSContext * cx, const jsval v, SoField * f)
+{
+  double number;
+  if (jsval2double(cx, v, number)) {
+    ((SoSFFloat *)f)->setValue((float)number);
+    return TRUE;
+  }
+  return FALSE;
+}
+
+static SbBool SFInt32_jsval2field(JSContext * cx, const jsval v, SoField * f)
+{
+  int32_t val;
+  if (jsval2int(cx, v, val)) {
+    ((SoSFInt32 *)f)->setValue(val);
+    return TRUE;
+  }
+  return FALSE;
+}
+
+static SbBool SFEnum_jsval2field(JSContext * cx, const jsval v, SoField * f)
+{
+  int32_t val;
+  if (jsval2int(cx, v, val)) {
+    ((SoSFInt32 *)f)->setValue(val);
+    return TRUE;
+  }
+  return FALSE;
+}
+
+static SbBool SFNode_jsval2field(JSContext * cx, const jsval v, SoField * f)
+{
+  if (JSVAL_IS_NULL(v)) {
+    ((SoSFNode *)f)->setValue(NULL);
+    return TRUE;
+  }
+  if (JSVAL_IS_OBJECT(v) &&
+      spidermonkey()->JS_InstanceOf(cx, JSVAL_TO_OBJECT(v), &CoinVrmlJs::SFNode.cls, NULL)) {
+    SoNode * node = (SoNode *)spidermonkey()->JS_GetPrivate(cx, JSVAL_TO_OBJECT(v));
+    ((SoSFNode *)f)->setValue(node);
+    return TRUE;
+  }
+  return FALSE;
+}
+
+static SbBool SFRotation_jsval2field(JSContext * cx, const jsval v, SoField * f)
+{
+  if (JSVAL_IS_SFROTATION(cx, v)) {
+    SbVec4f * rot = (SbVec4f *)spidermonkey()->JS_GetPrivate(cx, JSVAL_TO_OBJECT(v));
+    assert(rot != NULL);
+    SbVec3f axis((*rot)[0], (*rot)[1], (*rot)[2]);
+    ((SoSFRotation *)f)->setValue(SbRotation(axis, (*rot)[3]));
+    return TRUE;
+  }
+  return FALSE;
+}
+
+static SbBool SFString_jsval2field(JSContext * cx, const jsval v, SoField * f)
+{
+  if (JSVAL_IS_STRING(v)) {
+    const char * str = spidermonkey()->JS_GetStringBytes(JSVAL_TO_STRING(v));
+    ((SoSFString *)f)->setValue(str);
+    return TRUE;
+  }
+  return FALSE;
+}
+
+static SbBool SFTime_jsval2field(JSContext * cx, const jsval v, SoField * f)
+{
+  double number;
+  if (jsval2double(cx, v, number)) {
+    spidermonkey()->JS_ValueToNumber(cx, v, &number);
+    ((SoSFTime*)f)->setValue(SbTime(number));
+    return TRUE;
+  }
+  return FALSE;
+}
+
+static SbBool SFVec2f_jsval2field(JSContext * cx, const jsval v, SoField * f)
+{
+  if (JSVAL_IS_SFVEC2F(cx, v)) {
+    SbVec2f * vec = (SbVec2f *)spidermonkey()->JS_GetPrivate(cx, JSVAL_TO_OBJECT(v));
+    assert(vec != NULL);
+    ((SoSFVec2f *)f)->setValue(*vec);
+    return TRUE;
+  }
+  return FALSE;
+}
+
+static SbBool SFVec3f_jsval2field(JSContext * cx, const jsval v, SoField * f)
+{
+  if (JSVAL_IS_SFVEC3F(cx, v)) {
+    SbVec3f * vec = (SbVec3f *)spidermonkey()->JS_GetPrivate(cx, JSVAL_TO_OBJECT(v));
+    assert(vec != NULL);
+    ((SoSFVec3f *)f)->setValue(*vec);
+    return TRUE;
+  }
+  return FALSE;
+}
+
+static SbBool SFVec3d_jsval2field(JSContext * cx, const jsval v, SoField * f)
+{
+  if (JSVAL_IS_SFVEC3D(cx, v)) {
+    SbVec3d * vec = (SbVec3d *)spidermonkey()->JS_GetPrivate(cx, JSVAL_TO_OBJECT(v));
+    assert(vec != NULL);
+    ((SoSFVec3d *)f)->setValue(*vec);
+    return TRUE;
+  }
+  return FALSE;
+}
+
+// *************************************************************************
+// field2jsval
+
+static void SFBool_field2jsval(JSContext * cx, const SoField * f, jsval * v)
+{
+  const SbBool val = ((SoSFBool *)f)->getValue();
+  *v = BOOLEAN_TO_JSVAL(val);
+}
+
+static void SFColor_field2jsval(JSContext * cx, const SoField * f, jsval *v)
+{
+  const SbColor & val = ((SoSFColor *)f)->getValue();
+  JSObject * obj = SFColorFactory(cx, val);
+  *v = OBJECT_TO_JSVAL(obj);
+}
+
+static void SFFloat_field2jsval(JSContext * cx, const SoField * f, jsval * v)
+{
+  const float val = ((SoSFFloat *)f)->getValue();
+  JSBool ok = spidermonkey()->JS_NewDoubleValue(cx, val, v);
+}
+
+static void SFInt32_field2jsval(JSContext * cx, const SoField * f, jsval * v)
+{
+  const int32_t val = ((SoSFInt32 *)f)->getValue();
+  *v = INT_TO_JSVAL(val);
+}
+
+static void SFEnum_field2jsval(JSContext * cx, const SoField * f, jsval * v)
+{
+  const int32_t val = ((SoSFInt32 *)f)->getValue();
+  *v = INT_TO_JSVAL(val);
+}
+
+static void SFNode_field2jsval(JSContext * cx, const SoField * f, jsval * v)
+{
+  SoNode * node = ((SoSFNode *)f)->getValue();
+  if (node == NULL)
+    *v = JSVAL_NULL;
+  else {
+    JSObject * obj = SFNodeFactory(cx, node);
+    *v = OBJECT_TO_JSVAL(obj);
+  }
+}
+
+static void SFRotation_field2jsval(JSContext * cx, const SoField * f, jsval *v)
+{
+  const SbRotation & val = ((SoSFRotation *)f)->getValue();
+  JSObject * obj = SFRotationFactory(cx, val);
+  *v = OBJECT_TO_JSVAL(obj);
+}
+
+static void SFString_field2jsval(JSContext * cx, const SoField * f, jsval * v)
+{
+  const SbString & val = ((SoSFString *)f)->getValue();
+  JSString * str = spidermonkey()->JS_NewStringCopyZ(cx, val.getString());
+  *v = STRING_TO_JSVAL(str);
+}
+
+static void SFTime_field2jsval(JSContext * cx, const SoField * f, jsval * v)
+{
+  const SbTime & time = ((SoSFTime *)f)->getValue();
+  spidermonkey()->JS_NewDoubleValue(cx, time.getValue(), v);
+}
+
+static void SFVec2f_field2jsval(JSContext * cx, const SoField * f, jsval *v)
+{
+  const SbVec2f & val = ((SoSFVec2f *)f)->getValue();
+  JSObject * obj = SFVec2fFactory(cx, val);
+  *v = OBJECT_TO_JSVAL(obj);
+}
+
+static void SFVec3f_field2jsval(JSContext * cx, const SoField * f, jsval *v)
+{
+  const SbVec3f & val = ((SoSFVec3f *)f)->getValue();
+  JSObject * obj = SFVec3fFactory(cx, val);
+  *v = OBJECT_TO_JSVAL(obj);
+}
+
+static void SFVec3d_field2jsval(JSContext * cx, const SoField * f, jsval *v)
+{
+  const SbVec3d & val = ((SoSFVec3d *)f)->getValue();
+  JSObject * obj = SFVec3dFactory(cx, val);
+  *v = OBJECT_TO_JSVAL(obj);
+}
+
+// *************************************************************************
+// classes
+
+CoinVrmlJs::ClassDescriptor CoinVrmlJs::SFColor = {
+  {
+    "SFColor", JSCLASS_HAS_PRIVATE, NULL, NULL,
+    SFColorHandler::get, SFColorHandler::set,
+    NULL, NULL, NULL,
+    SFColorHandler::destructor,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
+  },
+  SFColorFunctions
+};
+
+CoinVrmlJs::ClassDescriptor CoinVrmlJs::SFNode = {
+  {
+    "SFNode", JSCLASS_HAS_PRIVATE, NULL, NULL,
+    SFNode_get, SFNode_set,
+    NULL, NULL, NULL,
+    SFNodeDestructor,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
+  },
+  NULL
+};
+
+
+CoinVrmlJs::ClassDescriptor CoinVrmlJs::SFRotation = {
+  {
+    "SFRotation", JSCLASS_HAS_PRIVATE, NULL, NULL,
+    SFRotationHandler::get, SFRotationHandler::set,
+    NULL, NULL, NULL,
+    SFRotationHandler::destructor,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
+  },
+  SFRotationFunctions
+};
+
+CoinVrmlJs::ClassDescriptor CoinVrmlJs::SFVec2f = {
+  {
+    "SFVec2f", JSCLASS_HAS_PRIVATE, NULL, NULL,
+    SFVec2fHandler::get, SFVec2fHandler::set,
+    NULL, NULL, NULL,
+    SFVec2fHandler::destructor,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
+  },
+  SFVec2fFunctions
+};
+
+CoinVrmlJs::ClassDescriptor CoinVrmlJs::SFVec3f = {
+  {
+    "SFVec3f", JSCLASS_HAS_PRIVATE, NULL, NULL,
+    SFVec3fHandler::get, SFVec3fHandler::set,
+    NULL, NULL, NULL,
+    SFVec3fHandler::destructor,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
+  },
+  SFVec3fFunctions
+};
+
+CoinVrmlJs::ClassDescriptor CoinVrmlJs::SFVec3d = {
+  {
+    "SFVec3d", JSCLASS_HAS_PRIVATE, NULL, NULL,
+    SFVec3dHandler::get, SFVec3dHandler::set,
+    NULL, NULL, NULL,
+    SFVec3dHandler::destructor,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
+  },
+  SFVec3dFunctions
+};
+
+CoinVrmlJs::ClassDescriptor CoinVrmlJs::MFColor = {
+  {
+    "MFColor", JSCLASS_HAS_PRIVATE, NULL, NULL,
+    MFColorHandler::get, MFColorHandler::set,
+    NULL, NULL, NULL,
+    MFColorHandler::destructor,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
+  },
+  MFFunctions,
+};
+
+CoinVrmlJs::ClassDescriptor CoinVrmlJs::MFFloat = {
+  {
+    "MFFloat", JSCLASS_HAS_PRIVATE, NULL, NULL,
+    MFFloatHandler::get, MFFloatHandler::set,
+    NULL, NULL, NULL,
+    MFFloatHandler::destructor,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
+  },
+  MFFunctions,
+};
+
+CoinVrmlJs::ClassDescriptor CoinVrmlJs::MFInt32 = {
+  {
+    "MFInt32", JSCLASS_HAS_PRIVATE, NULL, NULL,
+    MFInt32Handler::get, MFInt32Handler::set,
+    NULL, NULL, NULL,
+    MFInt32Handler::destructor,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
+  },
+  MFFunctions,
+};
+
+CoinVrmlJs::ClassDescriptor CoinVrmlJs::MFNode = {
+  {
+    "MFNode", JSCLASS_HAS_PRIVATE, NULL, NULL,
+    MFNodeHandler::get, MFNodeHandler::set,
+    NULL, NULL, NULL,
+    MFNodeHandler::destructor,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
+  },
+  MFFunctions,
+};
+
+CoinVrmlJs::ClassDescriptor CoinVrmlJs::MFRotation = {
+  {
+    "MFRotation", JSCLASS_HAS_PRIVATE, NULL, NULL,
+    MFRotationHandler::get, MFRotationHandler::set,
+    NULL, NULL, NULL,
+    MFRotationHandler::destructor,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
+  },
+  MFFunctions,
+};
+
+CoinVrmlJs::ClassDescriptor CoinVrmlJs::MFString = {
+  {
+    "MFString", JSCLASS_HAS_PRIVATE, NULL, NULL,
+    MFStringHandler::get, MFStringHandler::set,
+    NULL, NULL, NULL,
+    MFStringHandler::destructor,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
+  },
+  MFFunctions,
+};
+
+CoinVrmlJs::ClassDescriptor CoinVrmlJs::MFTime = {
+  {
+    "MFTime", JSCLASS_HAS_PRIVATE, NULL, NULL,
+    MFTimeHandler::get, MFTimeHandler::set,
+    NULL, NULL, NULL,
+    MFTimeHandler::destructor,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
+  },
+  MFFunctions,
+};
+
+CoinVrmlJs::ClassDescriptor CoinVrmlJs::MFVec2f = {
+  {
+    "MFVec2f", JSCLASS_HAS_PRIVATE, NULL, NULL,
+    MFVec2fHandler::get, MFVec2fHandler::set,
+    NULL, NULL, NULL,
+    MFVec2fHandler::destructor,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
+  },
+  MFFunctions,
+};
+
+CoinVrmlJs::ClassDescriptor CoinVrmlJs::MFVec3f = {
+  {
+    "MFVec3f", JSCLASS_HAS_PRIVATE, NULL, NULL,
+    MFVec3fHandler::get, MFVec3fHandler::set,
+    NULL, NULL, NULL,
+    MFVec3fHandler::destructor,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
+  },
+  MFFunctions,
+};
+
+CoinVrmlJs::ClassDescriptor CoinVrmlJs::MFVec3d = {
+  {
+    "MFVec3d", JSCLASS_HAS_PRIVATE, NULL, NULL,
+    MFVec3dHandler::get, MFVec3dHandler::set,
+    NULL, NULL, NULL,
+    MFVec3dHandler::destructor,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
+  },
+  MFFunctions,
+};
+
+
+CoinVrmlJs::ClassDescriptor * CLASSDESCRIPTORS[] = {
+  &CoinVrmlJs::SFColor, &CoinVrmlJs::SFNode, &CoinVrmlJs::SFRotation,
+  &CoinVrmlJs::SFVec2f, &CoinVrmlJs::SFVec3f, &CoinVrmlJs::SFVec3d, 
+  &CoinVrmlJs::MFColor, 
+  &CoinVrmlJs::MFFloat, &CoinVrmlJs::MFInt32, &CoinVrmlJs::MFNode,
+  &CoinVrmlJs::MFRotation, &CoinVrmlJs::MFString, &CoinVrmlJs::MFTime,
+  &CoinVrmlJs::MFVec2f, &CoinVrmlJs::MFVec3f, &CoinVrmlJs::MFVec3d
+};
+
+// *************************************************************************
+
+// cleans up static / one-off resource allocations
+static void
+js_vrmlclasses_cleanup(void)
+{
+  delete garbagecollectedobjects;
+  delete nodesensorstobedeleted;
+
+  garbagecollectedobjects = NULL;
+  nodesensorstobedeleted = NULL;
+}
+
+// *************************************************************************
+// helper function to add all classes to engine
+
+void
+JS_addVRMLclasses(SoJavaScriptEngine * engine)
+{
+  // init static data
+  if (garbagecollectedobjects == NULL) {
+    garbagecollectedobjects = new SbList <JSObject *>;
+    nodesensorstobedeleted = new SbList <SoNodeSensor *>;
+    coin_atexit((coin_atexit_f *)js_vrmlclasses_cleanup, CC_ATEXIT_NORMAL);
+
+    // set up default function stubs for Spidermonkey classes we
+    // make. must be done at run-time to avoid calling spidermonkey()
+    // early (i.e. not on demand).
+    const size_t NRELEMENTS = sizeof(CLASSDESCRIPTORS) / sizeof(CLASSDESCRIPTORS[0]);
+    for (size_t i=0; i < NRELEMENTS; i++) {
+      CoinVrmlJs::ClassDescriptor * desc = CLASSDESCRIPTORS[i];
+      desc->cls.addProperty = spidermonkey()->JS_PropertyStub;
+      desc->cls.delProperty = spidermonkey()->JS_PropertyStub;
+      desc->cls.enumerate = spidermonkey()->JS_EnumerateStub;
+      desc->cls.resolve = spidermonkey()->JS_ResolveStub;
+      desc->cls.convert = spidermonkey()->JS_ConvertStub;
+    }
+  }
+
+  // Bool
+  engine->addHandler(
+    SoSFBool::getClassTypeId(), NULL,
+    SFBool_field2jsval, SFBool_jsval2field);
+
+  // Color
+  engine->addHandler(
+    SoSFColor::getClassTypeId(), SFColor_init,
+    SFColor_field2jsval, SFColor_jsval2field);
+  engine->addHandler(
+    SoMFColor::getClassTypeId(),
+    MFColorHandler::init,
+    MFColorHandler::field2jsval,
+    MFColorHandler::jsval2field);
+
+  // Float
+  engine->addHandler(
+    SoSFFloat::getClassTypeId(), NULL,
+    SFFloat_field2jsval, SFFloat_jsval2field);
+  engine->addHandler(
+    SoMFFloat::getClassTypeId(),
+    MFFloatHandler::init,
+    MFFloatHandler::field2jsval,
+    MFFloatHandler::jsval2field);
+
+  // Int32
+  engine->addHandler(
+    SoSFInt32::getClassTypeId(), NULL,
+    SFInt32_field2jsval, SFInt32_jsval2field);
+  engine->addHandler(
+    SoMFInt32::getClassTypeId(),
+    MFInt32Handler::init,
+    MFInt32Handler::field2jsval,
+    MFInt32Handler::jsval2field);
+
+  // Enum 
+  engine->addHandler(
+    SoSFEnum::getClassTypeId(), NULL,
+    SFEnum_field2jsval, SFEnum_jsval2field);
+
+  // Node
+  engine->addHandler(
+    SoSFNode::getClassTypeId(), SFNode_init,
+    SFNode_field2jsval, SFNode_jsval2field);
+  engine->addHandler(
+    SoMFNode::getClassTypeId(),
+    MFNodeHandler::init,
+    MFNodeHandler::field2jsval,
+    MFNodeHandler::jsval2field);
+
+  // Rotation
+  engine->addHandler(
+    SoSFRotation::getClassTypeId(), SFRotation_init,
+    SFRotation_field2jsval, SFRotation_jsval2field);
+  engine->addHandler(
+    SoMFRotation::getClassTypeId(),
+    MFRotationHandler::init,
+    MFRotationHandler::field2jsval,
+    MFRotationHandler::jsval2field);
+
+  // String
+  engine->addHandler(
+    SoSFString::getClassTypeId(), NULL,
+    SFString_field2jsval, SFString_jsval2field);
+  engine->addHandler(
+    SoMFString::getClassTypeId(),
+    MFStringHandler::init,
+    MFStringHandler::field2jsval,
+    MFStringHandler::jsval2field);
+
+  // Time
+  engine->addHandler(
+    SoSFTime::getClassTypeId(), NULL,
+    SFTime_field2jsval, SFTime_jsval2field);
+  engine->addHandler(
+    SoMFTime::getClassTypeId(),
+    MFTimeHandler::init,
+    MFTimeHandler::field2jsval,
+    MFTimeHandler::jsval2field);
+
+  // Vec2f
+  engine->addHandler(
+    SoSFVec2f::getClassTypeId(), SFVec2f_init,
+    SFVec2f_field2jsval, SFVec2f_jsval2field);
+  engine->addHandler(
+    SoMFVec2f::getClassTypeId(),
+    MFVec2fHandler::init,
+    MFVec2fHandler::field2jsval,
+    MFVec2fHandler::jsval2field);
+
+  // Vec3f
+  engine->addHandler(
+    SoSFVec3f::getClassTypeId(), SFVec3f_init,
+    SFVec3f_field2jsval, SFVec3f_jsval2field);
+  engine->addHandler(
+    SoMFVec3f::getClassTypeId(),
+    MFVec3fHandler::init,
+    MFVec3fHandler::field2jsval,
+    MFVec3fHandler::jsval2field);
+
+  // Vec3d
+  engine->addHandler(
+    SoSFVec3d::getClassTypeId(), SFVec3d_init,
+    SFVec3d_field2jsval, SFVec3d_jsval2field);
+  engine->addHandler(
+    SoMFVec3d::getClassTypeId(),
+    MFVec3dHandler::init,
+    MFVec3dHandler::field2jsval,
+    MFVec3dHandler::jsval2field);
+}
+
+#endif // HAVE_VRML97

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Tony Theodore <tonyt@logyst.com>
Date: Sat, 18 Nov 2017 20:45:31 +1100
Subject: [PATCH 2/2] gcc 4.7 fixes

This patch was taken from Gentoo:
https://gitweb.gentoo.org/repo/gentoo.git/tree/media-libs/coin/files/coin-3.1.3-gcc-4.7.patch?id=17d7c853393ff83e3422e48e9ad2810f23889bbf

diff --git a/include/Inventor/SbBasic.h b/include/Inventor/SbBasic.h
index 1111111..2222222 100644
--- a/include/Inventor/SbBasic.h
+++ b/include/Inventor/SbBasic.h
@@ -24,6 +24,7 @@
  *
 \**************************************************************************/
 
+#include <Inventor/C/errors/debugerror.h>
 #include <Inventor/C/basic.h>
 
 /* ********************************************************************** */
