Forráskód Böngészése

app_jsdt: updated embedded duktape js interpreter from 2.0.0 to 2.0.2

Daniel-Constantin Mierla 8 éve
szülő
commit
81741d652c

+ 88 - 21
src/modules/app_jsdt/duk_config.h

@@ -1,9 +1,9 @@
 /*
  *  duk_config.h configuration header generated by genconfig.py.
  *
- *  Git commit: 4180966c47d6d87106008dd4338de8d507c8072b
- *  Git describe: v2.0.0
- *  Git branch: master
+ *  Git commit: 12e0741b105e53174202b7c15f55a95f6aa0bfb0
+ *  Git describe: v2.0.2
+ *  Git branch: v2.0-maintenance
  *
  *  Supported platforms:
  *      - Mac OSX, iPhone, Darwin
@@ -19,6 +19,8 @@
  *      - Emscripten
  *      - Linux
  *      - Solaris
+ *      - AIX
+ *      - HPUX
  *      - Generic POSIX
  *      - Cygwin
  *      - Generic UNIX
@@ -170,6 +172,28 @@
 /* illumos / Solaris */
 #if defined(__sun) && defined(__SVR4)
 #define DUK_F_SUN
+#if defined(__SUNPRO_C) && (__SUNPRO_C < 0x550)
+#define DUK_F_OLD_SOLARIS
+/* Defines _ILP32 / _LP64 required by DUK_F_X86/DUK_F_X64.  Platforms
+ * are processed before architectures, so this happens before the
+ * DUK_F_X86/DUK_F_X64 detection is emitted.
+ */
+#include <sys/isa_defs.h>
+#endif
+#endif
+
+/* AIX */
+#if defined(_AIX)
+/* defined(__xlc__) || defined(__IBMC__): works but too wide */
+#define DUK_F_AIX
+#endif
+
+/* HPUX */
+#if defined(__hpux)
+#define DUK_F_HPUX
+#if defined(__ia64)
+#define DUK_F_HPUX_ITANIUM
+#endif
 #endif
 
 /* POSIX */
@@ -188,17 +212,6 @@
 #define DUK_F_UNIX
 #endif
 
-/* stdint.h not available */
-#if defined(DUK_F_WINDOWS) && defined(_MSC_VER)
-#if (_MSC_VER < 1700)
-/* VS2012+ has stdint.h, < VS2012 does not (but it's available for download). */
-#define DUK_F_NO_STDINT_H
-#endif
-#endif
-#if !defined(DUK_F_NO_STDINT_H) && (defined(DUK_F_TOS) || defined(DUK_F_BCC))
-#define DUK_F_NO_STDINT_H
-#endif
-
 /* C++ */
 #undef DUK_F_CPP
 #if defined(__cplusplus)
@@ -208,6 +221,9 @@
 /* Intel x86 (32-bit), x64 (64-bit) or x32 (64-bit but 32-bit pointers),
  * define only one of DUK_F_X86, DUK_F_X64, DUK_F_X32.
  * https://sites.google.com/site/x32abi/
+ *
+ * With DUK_F_OLD_SOLARIS the <sys/isa_defs.h> header must be included
+ * before this.
  */
 #if defined(__amd64__) || defined(__amd64) || \
     defined(__x86_64__) || defined(__x86_64) || \
@@ -334,6 +350,10 @@
 #define DUK_F_VBCC
 #endif
 
+#if defined(ANDROID) || defined(__ANDROID__)
+#define DUK_F_ANDROID
+#endif
+
 /*
  *  Platform autodetection
  */
@@ -607,12 +627,50 @@
 #define DUK_USE_DATE_FMT_STRFTIME
 
 #include <sys/types.h>
+#if defined(DUK_F_OLD_SOLARIS)
+/* Old Solaris with no endian.h, stdint.h */
+#define DUK_F_NO_STDINT_H
+#if !defined(DUK_USE_BYTEORDER)
+#define DUK_USE_BYTEORDER 3
+#endif
+#else  /* DUK_F_OLD_SOLARIS */
 #include <ast/endian.h>
+#endif  /* DUK_F_OLD_SOLARIS */
+
 #include <sys/param.h>
 #include <sys/time.h>
 #include <time.h>
 
 #define DUK_USE_OS_STRING "solaris"
+#elif defined(DUK_F_AIX)
+/* --- AIX --- */
+#if !defined(DUK_USE_BYTEORDER)
+#define DUK_USE_BYTEORDER 3
+#endif
+#define DUK_USE_DATE_NOW_GETTIMEOFDAY
+#define DUK_USE_DATE_TZO_GMTIME_R
+#define DUK_USE_DATE_PRS_STRPTIME
+#define DUK_USE_DATE_FMT_STRFTIME
+#include <sys/param.h>
+#include <sys/time.h>
+#include <time.h>
+
+#define DUK_USE_OS_STRING "aix"
+#elif defined(DUK_F_HPUX)
+/* --- HPUX --- */
+#define DUK_F_NO_STDINT_H
+#if !defined(DUK_USE_BYTEORDER)
+#define DUK_USE_BYTEORDER 3
+#endif
+#define DUK_USE_DATE_NOW_GETTIMEOFDAY
+#define DUK_USE_DATE_TZO_GMTIME_R
+#define DUK_USE_DATE_PRS_STRPTIME
+#define DUK_USE_DATE_FMT_STRFTIME
+#include <sys/param.h>
+#include <sys/time.h>
+#include <time.h>
+
+#define DUK_USE_OS_STRING "hpux"
 #elif defined(DUK_F_POSIX)
 /* --- Generic POSIX --- */
 #define DUK_USE_DATE_NOW_GETTIMEOFDAY
@@ -1424,10 +1482,14 @@
 #if defined(DUK_F_X86) || defined(DUK_F_X32) || \
     defined(DUK_F_M68K) || defined(DUK_F_PPC32) || \
     defined(DUK_F_BCC) || \
-    (defined(__WORDSIZE) && (__WORDSIZE == 32))
+    (defined(__WORDSIZE) && (__WORDSIZE == 32)) || \
+    ((defined(DUK_F_OLD_SOLARIS) || defined(DUK_F_AIX) || \
+      defined(DUK_F_HPUX)) && defined(_ILP32))
 #define DUK_F_32BIT_PTRS
 #elif defined(DUK_F_X64) || \
-      (defined(__WORDSIZE) && (__WORDSIZE == 64))
+      (defined(__WORDSIZE) && (__WORDSIZE == 64)) || \
+   ((defined(DUK_F_OLD_SOLARIS) || defined(DUK_F_AIX) || \
+     defined(DUK_F_HPUX)) && defined(_LP64))
 #define DUK_F_64BIT_PTRS
 #else
 /* not sure, not needed with C99 anyway */
@@ -2050,7 +2112,8 @@ typedef struct duk_hthread duk_context;
 #define DUK_DOUBLE_INFINITY  (__builtin_inf())
 #elif defined(INFINITY)
 #define DUK_DOUBLE_INFINITY  ((double) INFINITY)
-#elif !defined(DUK_F_VBCC) && !defined(DUK_F_MSVC) && !defined(DUK_F_BCC)
+#elif !defined(DUK_F_VBCC) && !defined(DUK_F_MSVC) && !defined(DUK_F_BCC) && \
+      !defined(DUK_F_OLD_SOLARIS) && !defined(DUK_F_AIX)
 #define DUK_DOUBLE_INFINITY  (1.0 / 0.0)
 #else
 /* In VBCC (1.0 / 0.0) results in a warning and 0.0 instead of infinity.
@@ -2066,7 +2129,8 @@ typedef struct duk_hthread duk_context;
 #undef DUK_USE_COMPUTED_NAN
 #if defined(NAN)
 #define DUK_DOUBLE_NAN       NAN
-#elif !defined(DUK_F_VBCC) && !defined(DUK_F_MSVC) && !defined(DUK_F_BCC)
+#elif !defined(DUK_F_VBCC) && !defined(DUK_F_MSVC) && !defined(DUK_F_BCC) && \
+      !defined(DUK_F_OLD_SOLARIS) && !defined(DUK_F_AIX)
 #define DUK_DOUBLE_NAN       (0.0 / 0.0)
 #else
 /* In VBCC (0.0 / 0.0) results in a warning and 0.0 instead of NaN.
@@ -2115,6 +2179,9 @@ typedef struct duk_hthread duk_context;
  * To be safe, use replacements.
  */
 #define DUK_F_USE_REPL_ALL
+#elif defined(DUK_F_AIX)
+/* Older versions may be missing isnan(), etc. */
+#define DUK_F_USE_REPL_ALL
 #endif
 
 #if defined(DUK_F_USE_REPL_ALL)
@@ -2203,9 +2270,9 @@ typedef struct duk_hthread duk_context;
 /* The functions below exist only in C99/C++11 or later and need a workaround
  * for platforms that don't include them.  MSVC isn't detected as C99, but
  * these functions also exist in MSVC 2013 and later so include a clause for
- * that too.
+ * that too.  Android doesn't have log2; disable all of these for Android.
  */
-#if defined(DUK_F_C99) || defined(DUK_F_CPP11) || (defined(_MSC_VER) && (_MSC_VER >= 1800))
+#if (defined(DUK_F_C99) || defined(DUK_F_CPP11) || (defined(_MSC_VER) && (_MSC_VER >= 1800))) && !defined(DUK_F_ANDROID)
 #if !defined(DUK_CBRT)
 #define DUK_CBRT             cbrt
 #endif
@@ -2218,7 +2285,7 @@ typedef struct duk_hthread duk_context;
 #if !defined(DUK_TRUNC)
 #define DUK_TRUNC            trunc
 #endif
-#endif  /* DUK_F_C99 */
+#endif  /* DUK_F_C99 etc */
 
 /* NetBSD 6.0 x86 (at least) has a few problems with pow() semantics,
  * see test-bug-netbsd-math-pow.js.  MinGW has similar (but different)

+ 233 - 70
src/modules/app_jsdt/duktape.c

@@ -1,8 +1,8 @@
 /*
- *  Single source autogenerated distributable for Duktape 2.0.0.
+ *  Single source autogenerated distributable for Duktape 2.0.2.
  *
- *  Git commit 4180966c47d6d87106008dd4338de8d507c8072b (v2.0.0).
- *  Git branch master.
+ *  Git commit 12e0741b105e53174202b7c15f55a95f6aa0bfb0 (v2.0.2).
+ *  Git branch v2.0-maintenance.
  *
  *  See Duktape AUTHORS.rst and LICENSE.txt for copyright and
  *  licensing information.
@@ -9919,9 +9919,9 @@ DUK_INTERNAL const duk_uint8_t duk_builtins_data[3790] = {
 98,112,145,139,163,165,8,211,136,14,228,72,82,68,141,17,56,72,197,209,212,
 132,105,196,5,242,88,108,193,126,18,49,116,117,161,26,113,1,60,158,30,78,
 18,49,116,118,33,26,113,1,29,164,80,78,198,46,142,212,36,68,51,71,224,59,
-147,60,93,110,79,15,39,9,24,186,33,13,63,79,185,39,26,121,223,110,77,66,53,
-116,1,120,248,186,248,136,67,76,196,200,134,186,137,177,13,31,192,174,79,
-15,32,248,8,196,24,8,107,254,39,97,161,175,248,159,16,215,252,80,186,26,
+147,60,93,110,79,15,39,9,24,186,33,13,63,79,185,38,154,121,223,110,76,66,
+53,116,1,120,248,186,248,136,67,76,196,200,134,186,137,177,13,31,192,174,
+79,15,32,248,8,196,24,8,107,254,39,97,161,175,248,159,16,215,252,80,186,26,
 255,138,57,136,107,254,41,100,33,175,248,167,170,134,191,226,166,138,26,
 255,138,187,40,107,254,43,111,33,171,86,181,16,209,241,11,228,201,121,240,
 141,19,134,72,196,52,123,168,95,38,75,207,131,32,156,50,70,33,195,3,152,
@@ -10017,7 +10017,7 @@ DUK_INTERNAL const duk_uint8_t duk_builtins_data[3790] = {
 42,240,27,221,109,66,32,104,129,163,115,52,224,5,139,168,209,233,138,32,57,
 33,186,98,138,18,80,140,244,197,24,28,192,221,49,71,11,56,209,162,211,20,
 183,1,66,188,17,145,52,40,9,148,226,134,153,5,198,137,136,32,14,12,30,164,
-140,144,230,192,0,0,0,0,0,136,211,64,182,120,43,135,126,16,68,52,174,195,
+140,144,230,192,0,0,0,0,128,136,211,64,182,120,43,135,126,16,68,52,174,195,
 144,12,2,158,4,128,70,22,24,128,101,67,112,163,192,100,104,176,131,192,99,
 32,176,99,192,226,115,30,1,79,4,68,28,16,54,0,0,41,254,232,116,62,204,7,21,
 35,18,54,127,80,28,192,132,28,32,14,96,197,212,243,193,48,188,240,39,130,
@@ -10096,9 +10096,9 @@ DUK_INTERNAL const duk_uint8_t duk_builtins_data[3790] = {
 98,112,145,139,163,165,8,211,136,14,228,72,82,68,141,17,56,72,197,209,212,
 132,105,196,5,242,88,108,193,126,18,49,116,117,161,26,113,1,60,158,30,78,
 18,49,116,118,33,26,113,1,29,164,80,78,198,46,142,212,36,68,51,71,224,59,
-147,60,93,110,79,15,39,9,24,186,33,13,63,79,185,39,26,121,223,110,77,66,53,
-116,1,120,248,186,248,136,67,76,196,200,134,186,137,177,13,31,192,174,79,
-15,32,248,8,196,24,8,107,254,39,97,161,175,248,159,16,215,252,80,186,26,
+147,60,93,110,79,15,39,9,24,186,33,13,63,79,185,38,154,121,223,110,76,66,
+53,116,1,120,248,186,248,136,67,76,196,200,134,186,137,177,13,31,192,174,
+79,15,32,248,8,196,24,8,107,254,39,97,161,175,248,159,16,215,252,80,186,26,
 255,138,57,136,107,254,41,100,33,175,248,167,170,134,191,226,166,138,26,
 255,138,187,40,107,254,43,111,33,171,86,181,16,209,241,11,228,201,121,240,
 141,19,134,72,196,52,123,168,95,38,75,207,131,32,156,50,70,33,195,3,152,
@@ -10194,7 +10194,7 @@ DUK_INTERNAL const duk_uint8_t duk_builtins_data[3790] = {
 240,27,221,109,66,32,104,129,163,115,52,224,5,139,168,209,233,138,32,57,33,
 186,98,138,18,80,140,244,197,24,28,192,221,49,71,11,56,209,162,211,20,183,
 1,66,188,17,145,52,40,9,148,226,134,153,5,198,137,136,32,14,12,30,164,140,
-144,230,192,64,211,136,0,0,0,0,0,182,120,43,135,126,16,68,52,174,195,144,
+144,230,192,64,211,136,128,0,0,0,0,182,120,43,135,126,16,68,52,174,195,144,
 12,2,158,4,128,70,22,24,128,101,67,112,163,192,100,104,176,131,192,99,32,
 176,99,192,226,115,30,1,79,4,68,28,16,54,0,0,41,254,232,116,62,204,7,21,35,
 18,54,127,80,28,192,132,28,32,14,96,197,212,243,193,48,188,240,39,130,236,
@@ -10273,9 +10273,9 @@ DUK_INTERNAL const duk_uint8_t duk_builtins_data[3790] = {
 98,112,145,139,163,165,8,211,136,14,228,72,82,68,141,17,56,72,197,209,212,
 132,105,196,5,242,88,108,193,126,18,49,116,117,161,26,113,1,60,158,30,78,
 18,49,116,118,33,26,113,1,29,164,80,78,198,46,142,212,36,68,51,71,224,59,
-147,60,93,110,79,15,39,9,24,186,33,13,63,79,185,39,26,121,223,110,77,66,53,
-116,1,120,248,186,248,136,67,76,196,200,134,186,137,177,13,31,192,174,79,
-15,32,248,8,196,24,8,107,254,39,97,161,175,248,159,16,215,252,80,186,26,
+147,60,93,110,79,15,39,9,24,186,33,13,63,79,185,38,154,121,223,110,76,66,
+53,116,1,120,248,186,248,136,67,76,196,200,134,186,137,177,13,31,192,174,
+79,15,32,248,8,196,24,8,107,254,39,97,161,175,248,159,16,215,252,80,186,26,
 255,138,57,136,107,254,41,100,33,175,248,167,170,134,191,226,166,138,26,
 255,138,187,40,107,254,43,111,33,171,86,181,16,209,241,11,228,201,121,240,
 141,19,134,72,196,52,123,168,95,38,75,207,131,32,156,50,70,33,195,3,152,
@@ -10371,7 +10371,7 @@ DUK_INTERNAL const duk_uint8_t duk_builtins_data[3790] = {
 42,240,27,221,109,66,32,104,129,163,115,52,224,5,139,168,209,233,138,32,57,
 33,186,98,138,18,80,140,244,197,24,28,192,221,49,71,11,56,209,162,211,20,
 183,1,66,188,17,145,52,40,9,148,226,134,153,5,198,137,136,32,14,12,30,164,
-140,144,230,192,0,136,211,64,0,0,0,0,182,120,43,135,126,16,68,52,174,195,
+140,144,230,192,128,136,211,64,0,0,0,0,182,120,43,135,126,16,68,52,174,195,
 144,12,2,158,4,128,70,22,24,128,101,67,112,163,192,100,104,176,131,192,99,
 32,176,99,192,226,115,30,1,79,4,68,28,16,54,0,0,41,254,232,116,62,204,7,21,
 35,18,54,127,80,28,192,132,28,32,14,96,197,212,243,193,48,188,240,39,130,
@@ -13742,8 +13742,10 @@ DUK_EXTERNAL duk_bool_t duk_is_constructor_call(duk_context *ctx) {
 	DUK_ASSERT_DISABLE(thr->callstack_top >= 0);
 
 	act = duk_hthread_get_current_activation(thr);
-	DUK_ASSERT(act != NULL);  /* because callstack_top > 0 */
-	return ((act->flags & DUK_ACT_FLAG_CONSTRUCT) != 0 ? 1 : 0);
+	if (act != NULL) {
+		return ((act->flags & DUK_ACT_FLAG_CONSTRUCT) != 0 ? 1 : 0);
+	}
+	return 0;
 }
 
 /* XXX: Make this obsolete by adding a function flag for rejecting a
@@ -20844,6 +20846,86 @@ DUK_INTERNAL void *duk_push_fixed_buffer_zero(duk_context *ctx, duk_size_t len)
 	return ptr;
 }
 
+#if defined(DUK_USE_ASSERTIONS)
+DUK_LOCAL void duk__validate_push_heapptr(duk_context *ctx, void *ptr) {
+	duk_heaphdr *h;
+	duk_heaphdr *curr;
+	duk_hthread *thr;
+	duk_bool_t found = 0;
+
+	thr = (duk_hthread *) ctx;
+	h = (duk_heaphdr *) ptr;
+	if (h == NULL) {
+		/* Allowed. */
+		return;
+	}
+	DUK_ASSERT(h != NULL);
+	DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
+
+	/* One particular problem case is where an object has been
+	 * queued for finalization but the finalizer hasn't yet been
+	 * executed.
+	 *
+	 * Corner case: we're running in a finalizer for object X, and
+	 * user code calls duk_push_heapptr() for X itself.  In this
+	 * case X will be in finalize_list, and we can detect the case
+	 * by seeing that X's FINALIZED flag is set (which is done before
+	 * the finalizer starts executing).
+	 */
+	for (curr = thr->heap->finalize_list;
+	     curr != NULL;
+	     curr = DUK_HEAPHDR_GET_NEXT(thr->heap, curr)) {
+		if (curr == h) {
+			if (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) h)) {
+				/* Object is currently being finalized. */
+				DUK_ASSERT(found == 0);  /* Would indicate corrupted lists. */
+				found = 1;
+			} else {
+				DUK_ASSERT(0);
+			}
+		}
+	}
+
+	/* Also check for the refzero_list; must not be there unless it is
+	 * being finalized when duk_push_heapptr() is called.
+	 *
+	 * Corner case: similar to finalize_list.
+	 */
+#if defined(DUK_USE_REFERENCE_COUNTING)
+	for (curr = thr->heap->refzero_list;
+	     curr != NULL;
+	     curr = DUK_HEAPHDR_GET_NEXT(thr->heap, curr)) {
+		if (curr == h) {
+			if (DUK_HEAPHDR_HAS_FINALIZED((duk_heaphdr *) h)) {
+				/* Object is currently being finalized. */
+				DUK_ASSERT(found == 0);  /* Would indicate corrupted lists. */
+				found = 1;
+			} else {
+				DUK_ASSERT(0);
+			}
+		}
+	}
+#endif
+
+	/* If not present in finalize_list or refzero_list, the pointer
+	 * must be either in heap_allocated or the string table.
+	 */
+	if (DUK_HEAPHDR_GET_TYPE(h) == DUK_HTYPE_STRING) {
+		/* Omitted from Duktape 2.0.x maintenance backport. */
+	} else {
+		for (curr = thr->heap->heap_allocated;
+		     curr != NULL;
+		     curr = DUK_HEAPHDR_GET_NEXT(thr->heap, curr)) {
+			if (curr == h) {
+				DUK_ASSERT(found == 0);  /* Would indicate corrupted lists. */
+				found = 1;
+			}
+		}
+		DUK_ASSERT(found != 0);
+	}
+}
+#endif  /* DUK_USE_ASSERTIONS */
+
 DUK_EXTERNAL duk_idx_t duk_push_heapptr(duk_context *ctx, void *ptr) {
 	duk_hthread *thr = (duk_hthread *) ctx;
 	duk_idx_t ret;
@@ -20858,18 +20940,7 @@ DUK_EXTERNAL duk_idx_t duk_push_heapptr(duk_context *ctx, void *ptr) {
 	 */
 
 #if defined(DUK_USE_ASSERTIONS)
-	{
-		/* One particular problem case is where an object has been
-		 * queued for finalization but the finalizer hasn't been
-		 * executed.
-		 */
-		duk_heaphdr *curr;
-		for (curr = thr->heap->finalize_list;
-		     curr != NULL;
-		     curr = DUK_HEAPHDR_GET_NEXT(thr->heap, curr)) {
-			DUK_ASSERT(curr != (duk_heaphdr *) ptr);
-		}
-	}
+	duk__validate_push_heapptr(ctx, ptr);
 #endif
 
 	ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
@@ -25417,7 +25488,7 @@ DUK_INTERNAL duk_ret_t duk_bi_typedarray_set(duk_context *ctx) {
 	}
 
 	duk_hbufobj_promote_plain(ctx, 0);
-	h_obj = duk_known_hobject(ctx, 0);
+	h_obj = duk_require_hobject(ctx, 0);
 
 	/* XXX: V8 throws a TypeError for negative values.  Would it
 	 * be more useful to interpret negative offsets here from the
@@ -29422,7 +29493,6 @@ DUK_INTERNAL duk_ret_t duk_bi_textencoder_prototype_encode(duk_context *ctx) {
 	DUK_ASSERT_TOP(ctx, 1);
 	if (duk_is_undefined(ctx, 0)) {
 		len = 0;
-		final_len = len;
 	} else {
 		duk_hstring *h_input;
 
@@ -29480,6 +29550,8 @@ DUK_INTERNAL duk_ret_t duk_bi_textencoder_prototype_encode(duk_context *ctx) {
 		final_len = (duk_size_t) (enc_ctx.out - output);
 		duk_resize_buffer(ctx, -1, final_len);
 		/* 'output' and 'enc_ctx.out' are potentially invalidated by the resize. */
+	} else {
+		final_len = 0;
 	}
 
 	/* Standard WHATWG output is a Uint8Array.  Here the Uint8Array will
@@ -30933,7 +31005,6 @@ DUK_INTERNAL duk_ret_t duk_bi_global_object_eval(duk_context *ctx) {
 			                     "var_env and lex_env to a fresh env, "
 			                     "this_binding to caller's this_binding"));
 
-			act = thr->callstack + thr->callstack_top + level;  /* caller */
 			act_lex_env = act->lex_env;
 			act = NULL;  /* invalidated */
 
@@ -37757,10 +37828,10 @@ DUK_INTERNAL duk_ret_t duk_bi_string_prototype_repeat(duk_context *ctx) {
 		} else {
 			DUK_MEMCPY((void *) p, (const void *) src, copy_size);
 			p += copy_size;
-			copy_size *= 2;
 		}
 
 		src = (const duk_uint8_t *) buf;  /* Use buf as source for larger copies. */
+		copy_size = (duk_size_t) (p - buf);
 	}
 #endif  /* DUK_USE_PREFER_SIZE */
 
@@ -40451,6 +40522,7 @@ DUK_INTERNAL void duk_debug_send_status(duk_hthread *thr) {
 		duk_pop_3(ctx);
 		/* Report next pc/line to be executed. */
 		duk_debug_write_uint(thr, (duk_uint32_t) duk_debug_curr_line(thr));
+		act = thr->callstack + thr->callstack_top - 1;
 		duk_debug_write_uint(thr, (duk_uint32_t) duk_hthread_get_act_curr_pc(thr, act));
 	}
 
@@ -40483,18 +40555,29 @@ DUK_INTERNAL void duk_debug_send_throw(duk_hthread *thr, duk_bool_t fatal) {
 		duk__debug_write_hstring_safe_top(thr);
 		duk_get_prop_stridx_short(ctx, -2, DUK_STRIDX_LINE_NUMBER);
 		duk_debug_write_uint(thr, duk_get_uint(ctx, -1));
+		duk_pop_2(ctx);
 	} else {
-		/* For anything other than an Error instance, we calculate the error
-		 * location directly from the current activation.
+		/* For anything other than an Error instance, we calculate the
+		 * error location directly from the current activation if one
+		 * exists.
 		 */
-		act = thr->callstack + thr->callstack_top - 1;
-		duk_push_tval(ctx, &act->tv_func);
-		duk_get_prop_string(ctx, -1, "fileName");
-		duk__debug_write_hstring_safe_top(thr);
-		pc = duk_hthread_get_act_prev_pc(thr, act);
-		duk_debug_write_uint(thr, (duk_uint32_t) duk_hobject_pc2line_query(ctx, -2, pc));
+		if (thr->callstack_top > 0) {
+			act = thr->callstack + thr->callstack_top - 1;
+			duk_push_tval(ctx, &act->tv_func);
+			duk_get_prop_string(ctx, -1, "fileName");
+			duk__debug_write_hstring_safe_top(thr);
+			act = thr->callstack + thr->callstack_top - 1;
+			pc = duk_hthread_get_act_prev_pc(thr, act);
+			duk_debug_write_uint(thr, (duk_uint32_t) duk_hobject_pc2line_query(ctx, -2, pc));
+			duk_pop_2(ctx);
+		} else {
+			/* Can happen if duk_throw() is called on an empty
+			 * callstack.
+			 */
+			duk_debug_write_cstring(thr, "");
+			duk_debug_write_uint(thr, 0);
+		}
 	}
-	duk_pop_2(ctx);  /* shared pop */
 
 	duk_debug_write_eom(thr);
 }
@@ -45126,7 +45209,7 @@ DUK_LOCAL void duk__clear_refzero_list_flags(duk_heap *heap) {
 	while (hdr) {
 		DUK_HEAPHDR_CLEAR_REACHABLE(hdr);
 		DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(hdr));
-		DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(hdr));
+		/* DUK_HEAPHDR_HAS_FINALIZED may or may not be set. */
 		DUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(hdr));
 		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
 	}
@@ -45532,6 +45615,12 @@ DUK_LOCAL void duk__run_object_finalizers(duk_heap *heap, duk_small_uint_t flags
 		DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(curr));
 		DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY(curr));  /* No finalizers for ROM objects */
 
+		/* Keep heap->finalize_list up-to-date during the list walk.
+		 * This has no functional impact, but does matter e.g. for
+		 * duk_push_heapptr() asserts when assertions are enabled.
+		 */
+		heap->finalize_list = curr;
+
 		if (DUK_LIKELY((flags & DUK_MS_FLAG_SKIP_FINALIZERS) == 0)) {
 			/* Run the finalizer, duk_hobject_run_finalizer() sets FINALIZED.
 			 * Next mark-and-sweep will collect the object unless it has
@@ -45540,6 +45629,10 @@ DUK_LOCAL void duk__run_object_finalizers(duk_heap *heap, duk_small_uint_t flags
 			 */
 			duk_hobject_run_finalizer(thr, (duk_hobject *) curr);  /* must never longjmp */
 			DUK_ASSERT(DUK_HEAPHDR_HAS_FINALIZED(curr));
+
+			/* XXX: could clear FINALIZED already here; now cleared in
+			 * next mark-and-sweep.
+			 */
 		} else {
 			/* Used during heap destruction: don't actually run finalizers
 			 * because we're heading into forced finalization.  Instead,
@@ -45693,7 +45786,11 @@ DUK_LOCAL void duk__assert_heaphdr_flags(duk_heap *heap) {
 		DUK_ASSERT(!DUK_HEAPHDR_HAS_REACHABLE(hdr));
 		DUK_ASSERT(!DUK_HEAPHDR_HAS_TEMPROOT(hdr));
 		DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZABLE(hdr));
-		DUK_ASSERT(!DUK_HEAPHDR_HAS_FINALIZED(hdr));
+		/* DUK_HEAPHDR_HAS_FINALIZED may be set if we're doing a
+		 * refzero finalization and mark-and-sweep gets triggered
+		 * during the finalizer.
+		 */
+		/* DUK_HEAPHDR_HAS_FINALIZED may or may not be set. */
 		hdr = DUK_HEAPHDR_GET_NEXT(heap, hdr);
 	}
 #endif  /* DUK_USE_REFERENCE_COUNTING */
@@ -45796,6 +45893,11 @@ DUK_INTERNAL duk_bool_t duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t
 	duk_size_t tmp;
 #endif
 
+	if (DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap)) {
+		DUK_D(DUK_DPRINT("refuse to do a recursive mark-and-sweep"));
+		return 0;
+	}
+
 	/* XXX: thread selection for mark-and-sweep is currently a hack.
 	 * If we don't have a thread, the entire mark-and-sweep is now
 	 * skipped (although we could just skip finalizations).
@@ -46920,12 +47022,17 @@ DUK_INTERNAL void duk_refzero_free_pending(duk_hthread *thr) {
 	 */
 	heap->mark_and_sweep_trigger_counter -= count;
 	if (heap->mark_and_sweep_trigger_counter <= 0) {
-		duk_bool_t rc;
-		duk_small_uint_t flags = 0;  /* not emergency */
-		DUK_D(DUK_DPRINT("refcount triggering mark-and-sweep"));
-		rc = duk_heap_mark_and_sweep(heap, flags);
-		DUK_UNREF(rc);
-		DUK_D(DUK_DPRINT("refcount triggered mark-and-sweep => rc %ld", (long) rc));
+		if (DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap)) {
+			DUK_D(DUK_DPRINT("mark-and-sweep in progress -> skip voluntary mark-and-sweep now"));
+		} else {
+			duk_bool_t rc;
+			duk_small_uint_t flags = 0;  /* not emergency */
+
+			DUK_D(DUK_DPRINT("refcount triggering mark-and-sweep"));
+			rc = duk_heap_mark_and_sweep(heap, flags);
+			DUK_UNREF(rc);
+			DUK_D(DUK_DPRINT("refcount triggered mark-and-sweep => rc %ld", (long) rc));
+		}
 	}
 #endif  /* DUK_USE_VOLUNTARY_GC */
 }
@@ -47143,7 +47250,7 @@ DUK_INTERNAL void duk_tval_decref_norz(duk_hthread *thr, duk_tval *tv) {
 		}
 		duk_heaphdr_refzero_norz(thr, h);
 #else
-		duk_heaphdr_decref(thr, h);
+		duk_heaphdr_decref_norz(thr, h);
 #endif
 	}
 }
@@ -47157,6 +47264,12 @@ DUK_INTERNAL void duk_tval_decref_norz(duk_hthread *thr, duk_tval *tv) {
 		DUK_ASSERT(DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) h) >= 1); \
 	} while (0)
 #if defined(DUK_USE_ROM_OBJECTS)
+#define DUK__INCREF_SHARED() do { \
+		if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h)) { \
+			return; \
+		} \
+		DUK_HEAPHDR_PREINC_REFCOUNT((duk_heaphdr *) h); \
+	} while (0)
 #define DUK__DECREF_SHARED() do { \
 		if (DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) h)) { \
 			return; \
@@ -47166,6 +47279,9 @@ DUK_INTERNAL void duk_tval_decref_norz(duk_hthread *thr, duk_tval *tv) {
 		} \
 	} while (0)
 #else
+#define DUK__INCREF_SHARED() do { \
+		DUK_HEAPHDR_PREINC_REFCOUNT((duk_heaphdr *) h); \
+	} while (0)
 #define DUK__DECREF_SHARED() do { \
 		if (DUK_HEAPHDR_PREDEC_REFCOUNT((duk_heaphdr *) h) != 0) { \
 			return; \
@@ -47182,7 +47298,7 @@ DUK_INTERNAL void duk_heaphdr_incref(duk_heaphdr *h) {
 	DUK_ASSERT(DUK_HEAPHDR_HTYPE_VALID(h));
 	DUK_ASSERT_DISABLE(DUK_HEAPHDR_GET_REFCOUNT(h) >= 0);
 
-	DUK_HEAPHDR_PREINC_REFCOUNT(h);
+	DUK__INCREF_SHARED();
 }
 
 DUK_INTERNAL void duk_heaphdr_decref(duk_hthread *thr, duk_heaphdr *h) {
@@ -47239,6 +47355,7 @@ DUK_INTERNAL void duk_hobject_decref_norz(duk_hthread *thr, duk_hobject *h) {
 /* automatic undefs */
 #undef DUK__DECREF_ASSERTS
 #undef DUK__DECREF_SHARED
+#undef DUK__INCREF_SHARED
 #undef DUK__RZ_BUFFER
 #undef DUK__RZ_INLINE
 #undef DUK__RZ_OBJECT
@@ -56437,10 +56554,9 @@ DUK_LOCAL void duk__duplicate_ram_global_object(duk_hthread *thr) {
 	                            DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJENV),
 	                            -1);  /* no prototype */
 	DUK_ASSERT(h1 != NULL);
-	duk_dup_m2(ctx);
-	duk_dup_top(ctx);  /* -> [ ... new_global new_globalenv new_global new_global ] */
-	duk_xdef_prop_stridx_short(thr, -3, DUK_STRIDX_INT_TARGET, DUK_PROPDESC_FLAGS_NONE);
-	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_THIS, DUK_PROPDESC_FLAGS_NONE);  /* always provideThis=true */
+	duk_dup_m2(ctx);  /* -> [ ... new_global new_globalenv new_global ] */
+	duk_xdef_prop_stridx_short(thr, -2, DUK_STRIDX_INT_TARGET, DUK_PROPDESC_FLAGS_NONE);
+	/* provideThis=false */
 
 	duk_hobject_compact_props(thr, h1);
 	DUK_ASSERT(thr->builtins[DUK_BIDX_GLOBAL_ENV] != NULL);
@@ -59307,8 +59423,8 @@ DUK_LOCAL void duk__handle_call_inner(duk_hthread *thr,
 #if defined(DUK_USE_NONSTD_FUNC_CALLER_PROPERTY)
 	if (func) {
 		duk__update_func_caller_prop(thr, func);
+		act = thr->callstack + thr->callstack_top - 1;
 	}
-	act = thr->callstack + thr->callstack_top - 1;
 #endif
 
 	/* [ ... func this arg1 ... argN ] */
@@ -59368,6 +59484,7 @@ DUK_LOCAL void duk__handle_call_inner(duk_hthread *thr,
 			DUK_ASSERT(!DUK_HOBJECT_HAS_CREATEARGS(func));
 
 			duk__handle_oldenv_for_call(thr, func, act);
+			/* No need to re-lookup 'act' at present: no side effects. */
 
 			DUK_ASSERT(act->lex_env != NULL);
 			DUK_ASSERT(act->var_env != NULL);
@@ -59404,6 +59521,7 @@ DUK_LOCAL void duk__handle_call_inner(duk_hthread *thr,
 	 *  new value stack bottom, and call the target.
 	 */
 
+	act = thr->callstack + thr->callstack_top - 1;
 	if (func != NULL && DUK_HOBJECT_IS_COMPFUNC(func)) {
 		/*
 		 *  Ecmascript call
@@ -60533,6 +60651,7 @@ DUK_INTERNAL duk_bool_t duk_handle_ecma_call_setup(duk_hthread *thr,
 		 */
 
 		duk__handle_oldenv_for_call(thr, func, act);
+		/* No need to re-lookup 'act' at present: no side effects. */
 
 		DUK_ASSERT(act->lex_env != NULL);
 		DUK_ASSERT(act->var_env != NULL);
@@ -68816,7 +68935,7 @@ DUK_LOCAL DUK__INLINE_PERF void duk__vm_arith_binary_op(duk_hthread *thr, duk_tv
 			break;
 		}
 		default: {
-			DUK_UNREACHABLE();
+			/* Possible with DUK_OP_EXP. */
 			goto skip_fastint;
 		}
 		}
@@ -69288,11 +69407,13 @@ DUK_LOCAL DUK__INLINE_PERF void duk__prepost_incdec_var_helper(duk_hthread *thr,
 
 	if (op & 0x02) {
 		duk_push_number(ctx, y);  /* -> [ ... x this y ] */
+		act = thr->callstack + thr->callstack_top - 1;
 		duk_js_putvar_activation(thr, act, name, DUK_GET_TVAL_NEGIDX(ctx, -1), is_strict);
 		duk_pop_2(ctx);  /* -> [ ... x ] */
 	} else {
 		duk_pop_2(ctx);  /* -> [ ... ] */
 		duk_push_number(ctx, y);  /* -> [ ... y ] */
+		act = thr->callstack + thr->callstack_top - 1;
 		duk_js_putvar_activation(thr, act, name, DUK_GET_TVAL_NEGIDX(ctx, -1), is_strict);
 	}
 
@@ -69675,7 +69796,9 @@ duk_small_uint_t duk__handle_longjmp(duk_hthread *thr,
 			 *  which we simply ignore.
 			 */
 
+			DUK_ASSERT(resumee->resumer == NULL);
 			resumee->resumer = thr;
+			DUK_HTHREAD_INCREF(thr, thr);
 			resumee->state = DUK_HTHREAD_STATE_RUNNING;
 			thr->state = DUK_HTHREAD_STATE_RESUMED;
 			DUK_HEAP_SWITCH_THREAD(thr->heap, resumee);
@@ -69705,7 +69828,9 @@ duk_small_uint_t duk__handle_longjmp(duk_hthread *thr,
 
 			duk__reconfig_valstack_ecma_return(resumee, act_idx);
 
+			DUK_ASSERT(resumee->resumer == NULL);
 			resumee->resumer = thr;
+			DUK_HTHREAD_INCREF(thr, thr);
 			resumee->state = DUK_HTHREAD_STATE_RUNNING;
 			thr->state = DUK_HTHREAD_STATE_RESUMED;
 			DUK_HEAP_SWITCH_THREAD(thr->heap, resumee);
@@ -69741,7 +69866,9 @@ duk_small_uint_t duk__handle_longjmp(duk_hthread *thr,
 				DUK_ERROR_INTERNAL(thr);
 			}
 
+			DUK_ASSERT(resumee->resumer == NULL);
 			resumee->resumer = thr;
+			DUK_HTHREAD_INCREF(thr, thr);
 			resumee->state = DUK_HTHREAD_STATE_RUNNING;
 			thr->state = DUK_HTHREAD_STATE_RESUMED;
 			DUK_HEAP_SWITCH_THREAD(thr->heap, resumee);
@@ -69796,6 +69923,7 @@ duk_small_uint_t duk__handle_longjmp(duk_hthread *thr,
 		if (thr->heap->lj.iserror) {
 			thr->state = DUK_HTHREAD_STATE_YIELDED;
 			thr->resumer = NULL;
+			DUK_HTHREAD_DECREF_NORZ(thr, resumer);
 			resumer->state = DUK_HTHREAD_STATE_RUNNING;
 			DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
 			thr = resumer;
@@ -69811,6 +69939,7 @@ duk_small_uint_t duk__handle_longjmp(duk_hthread *thr,
 
 			thr->state = DUK_HTHREAD_STATE_YIELDED;
 			thr->resumer = NULL;
+			DUK_HTHREAD_DECREF_NORZ(thr, resumer);
 			resumer->state = DUK_HTHREAD_STATE_RUNNING;
 			DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
 #if 0
@@ -69927,6 +70056,7 @@ duk_small_uint_t duk__handle_longjmp(duk_hthread *thr,
 		DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_TERMINATED);
 
 		thr->resumer = NULL;
+		DUK_HTHREAD_DECREF_NORZ(thr, resumer);
 		resumer->state = DUK_HTHREAD_STATE_RUNNING;
 		DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
 		thr = resumer;
@@ -70188,6 +70318,7 @@ DUK_LOCAL duk_small_uint_t duk__handle_return(duk_hthread *thr,
 	DUK_ASSERT(thr->state == DUK_HTHREAD_STATE_TERMINATED);
 
 	thr->resumer = NULL;
+	DUK_HTHREAD_DECREF(thr, resumer);
 	resumer->state = DUK_HTHREAD_STATE_RUNNING;
 	DUK_HEAP_SWITCH_THREAD(thr->heap, resumer);
 #if 0
@@ -72201,9 +72332,15 @@ DUK_LOCAL DUK_NOINLINE void duk__js_execute_bytecode_inner(duk_hthread *entry_th
 
 			act = thr->callstack + thr->callstack_top - 1;
 			if (duk_js_declvar_activation(thr, act, name, tv1, prop_flags, is_func_decl)) {
-				/* already declared, must update binding value */
-				tv1 = DUK_GET_TVAL_NEGIDX(ctx, -1);
-				duk_js_putvar_activation(thr, act, name, tv1, DUK__STRICT());
+				if (is_undef_value) {
+					/* Already declared but no initializer value
+					 * (e.g. 'var xyz;'), no-op.
+					 */
+				} else {
+					/* Already declared, update value. */
+					tv1 = DUK_GET_TVAL_NEGIDX(ctx, -1);
+					duk_js_putvar_activation(thr, act, name, tv1, DUK__STRICT());
+				}
 			}
 
 			duk_pop(ctx);
@@ -72296,6 +72433,7 @@ DUK_LOCAL DUK_NOINLINE void duk__js_execute_bytecode_inner(duk_hthread *entry_th
 			if (act->lex_env == NULL) {
 				DUK_ASSERT(act->var_env == NULL);
 				duk_js_init_activation_environment_records_delayed(thr, act);
+				act = thr->callstack + thr->callstack_top - 1;
 			}
 			DUK_ASSERT(act->lex_env != NULL);
 			DUK_ASSERT(act->var_env != NULL);
@@ -72637,11 +72775,11 @@ DUK_LOCAL DUK_NOINLINE void duk__js_execute_bytecode_inner(duk_hthread *entry_th
 
 				DUK_DDD(DUK_DDDPRINT("activating object env: %!iT",
 				                     (duk_tval *) duk_get_tval(ctx, -1)));
-				DUK_ASSERT(act->lex_env != NULL);
 				new_env = DUK_GET_HOBJECT_NEGIDX(ctx, -1);
 				DUK_ASSERT(new_env != NULL);
 
 				act = thr->callstack + thr->callstack_top - 1;  /* relookup (side effects) */
+				DUK_ASSERT(act->lex_env != NULL);
 				DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, new_env, act->lex_env);  /* side effects */
 
 				act = thr->callstack + thr->callstack_top - 1;  /* relookup (side effects) */
@@ -74975,12 +75113,12 @@ DUK_INTERNAL duk_small_uint_t duk_js_typeof_stridx(duk_tval *tv_x) {
  */
 
 DUK_INTERNAL duk_small_int_t duk_js_to_arrayindex_raw_string(const duk_uint8_t *str, duk_uint32_t blen, duk_uarridx_t *out_idx) {
-	duk_uarridx_t res, new_res;
+	duk_uarridx_t res;
 
 	if (blen == 0 || blen > 10) {
 		goto parse_fail;
 	}
-	if (str[0] == (duk_uint8_t) '0' && blen > 1) {
+	if (str[0] == DUK_ASC_0 && blen > 1) {
 		goto parse_fail;
 	}
 
@@ -74992,13 +75130,29 @@ DUK_INTERNAL duk_small_int_t duk_js_to_arrayindex_raw_string(const duk_uint8_t *
 	res = 0;
 	while (blen-- > 0) {
 		duk_uint8_t c = *str++;
-		if (c >= (duk_uint8_t) '0' && c <= (duk_uint8_t) '9') {
-			new_res = res * 10 + (duk_uint32_t) (c - (duk_uint8_t) '0');
-			if (new_res < res) {
-				/* overflow, more than 32 bits -> not an array index */
-				goto parse_fail;
+		if (c >= DUK_ASC_0 && c <= DUK_ASC_9) {
+			/* Careful overflow handling.  When multiplying by 10:
+			 * - 0x19999998 x 10 = 0xfffffff0: no overflow, and adding
+			 *   0...9 is safe.
+			 * - 0x19999999 x 10 = 0xfffffffa: no overflow, adding
+			 *   0...5 is safe, 6...9 overflows.
+			 * - 0x1999999a x 10 = 0x100000004: always overflow.
+			 */
+			if (DUK_UNLIKELY(res >= 0x19999999UL)) {
+				if (res >= 0x1999999aUL) {
+					/* Always overflow. */
+					goto parse_fail;
+				}
+				DUK_ASSERT(res == 0x19999999UL);
+				c -= DUK_ASC_0;
+				if (c >= 6) {
+					goto parse_fail;
+				}
+				res = 0xfffffffaUL + c;
+				DUK_ASSERT(res >= 0xfffffffaUL && res <= 0xffffffffUL);
+			} else {
+				res = res * 10U + (duk_uint32_t) (c - DUK_ASC_0);
 			}
-			res = new_res;
 		} else {
 			goto parse_fail;
 		}
@@ -75566,7 +75720,10 @@ void duk_js_init_activation_environment_records_delayed(duk_hthread *thr,
 	duk_context *ctx = (duk_context *) thr;
 	duk_hobject *func;
 	duk_hobject *env;
+	duk_size_t act_off;
 
+	DUK_ASSERT(act != NULL);
+	act_off = (duk_size_t) ((duk_uint8_t *) act - (duk_uint8_t *) thr->callstack);
 	func = DUK_ACT_GET_FUNC(act);
 	DUK_ASSERT(func != NULL);
 	DUK_ASSERT(!DUK_HOBJECT_HAS_BOUNDFUNC(func));  /* bound functions are never in act 'func' */
@@ -75581,6 +75738,7 @@ void duk_js_init_activation_environment_records_delayed(duk_hthread *thr,
 
 	env = duk_create_activation_environment_record(thr, func, act->idx_bottom);
 	DUK_ASSERT(env != NULL);
+	act = (duk_activation *) ((duk_uint8_t *) thr->callstack + act_off);
 
 	DUK_DDD(DUK_DDDPRINT("created delayed fresh env: %!ipO", (duk_heaphdr *) env));
 #if defined(DUK_USE_DEBUG_LEVEL) && (DUK_USE_DEBUG_LEVEL >= 2)
@@ -76828,6 +76986,10 @@ duk_bool_t duk_js_declvar_activation(duk_hthread *thr,
                                      duk_bool_t is_func_decl) {
 	duk_hobject *env;
 	duk_tval tv_val_copy;
+	duk_size_t act_off;
+
+	DUK_ASSERT(act != NULL);
+	act_off = (duk_size_t) ((duk_uint8_t *) act - (duk_uint8_t *) thr->callstack);
 
 	/*
 	 *  Make a value copy of the input val.  This ensures that
@@ -76844,6 +77006,7 @@ duk_bool_t duk_js_declvar_activation(duk_hthread *thr,
 	if (!act->var_env) {
 		DUK_ASSERT(act->lex_env == NULL);
 		duk_js_init_activation_environment_records_delayed(thr, act);
+		act = (duk_activation *) ((duk_uint8_t *) thr->callstack + act_off);
 	}
 	DUK_ASSERT(act->lex_env != NULL);
 	DUK_ASSERT(act->var_env != NULL);

+ 7 - 7
src/modules/app_jsdt/duktape.h

@@ -1,13 +1,13 @@
 /*
- *  Duktape public API for Duktape 2.0.0.
+ *  Duktape public API for Duktape 2.0.2.
  *
  *  See the API reference for documentation on call semantics.
  *  The exposed API is inside the DUK_API_PUBLIC_H_INCLUDED
  *  include guard.  Other parts of the header are Duktape
  *  internal and related to platform/compiler/feature detection.
  *
- *  Git commit 4180966c47d6d87106008dd4338de8d507c8072b (v2.0.0).
- *  Git branch master.
+ *  Git commit 12e0741b105e53174202b7c15f55a95f6aa0bfb0 (v2.0.2).
+ *  Git branch v2.0-maintenance.
  *
  *  See Duktape AUTHORS.rst and LICENSE.txt for copyright and
  *  licensing information.
@@ -253,16 +253,16 @@ struct duk_time_components {
  * development snapshots have 99 for patch level (e.g. 0.10.99 would be a
  * development version after 0.10.0 but before the next official release).
  */
-#define DUK_VERSION                       20000L
+#define DUK_VERSION                       20002L
 
 /* Git commit, describe, and branch for Duktape build.  Useful for
  * non-official snapshot builds so that application code can easily log
  * which Duktape snapshot was used.  Not available in the Ecmascript
  * environment.
  */
-#define DUK_GIT_COMMIT                    "4180966c47d6d87106008dd4338de8d507c8072b"
-#define DUK_GIT_DESCRIBE                  "v2.0.0"
-#define DUK_GIT_BRANCH                    "master"
+#define DUK_GIT_COMMIT                    "12e0741b105e53174202b7c15f55a95f6aa0bfb0"
+#define DUK_GIT_DESCRIBE                  "v2.0.2"
+#define DUK_GIT_BRANCH                    "v2.0-maintenance"
 
 /* Duktape debug protocol version used by this build. */
 #define DUK_DEBUG_PROTOCOL_VERSION        2