jbarnette-johnson 1.0.0.20090326161333 → 1.0.0.20090402144841

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -305,3 +305,4 @@ MSG_DEF(JSMSG_NULL_OR_UNDEFINED, 222, 2, JSEXN_TYPEERR, "{0} is {1}")
305
305
  MSG_DEF(JSMSG_LET_DECL_NOT_IN_BLOCK, 223, 0, JSEXN_SYNTAXERR, "let declaration not directly within block")
306
306
  MSG_DEF(JSMSG_BAD_OBJECT_INIT, 224, 0, JSEXN_SYNTAXERR, "invalid object initializer")
307
307
  MSG_DEF(JSMSG_CANT_SET_ARRAY_ATTRS, 225, 0, JSEXN_INTERNALERR, "can't set attributes on indexed array properties")
308
+ MSG_DEF(JSMSG_EVAL_ARITY, 226, 0, JSEXN_TYPEERR, "eval accepts only one parameter")
@@ -1173,7 +1173,7 @@ JS_ToggleOptions(JSContext *cx, uint32 options)
1173
1173
  JS_PUBLIC_API(const char *)
1174
1174
  JS_GetImplementationVersion(void)
1175
1175
  {
1176
- return "JavaScript-C 1.8.0 pre-release 1 2007-10-03";
1176
+ return "JavaScript-C 1.8.0 pre-release 1 2009-02-16";
1177
1177
  }
1178
1178
 
1179
1179
 
@@ -116,11 +116,8 @@
116
116
 
117
117
  JS_STATIC_ASSERT(sizeof(JSScopeProperty) > 4 * sizeof(jsval));
118
118
 
119
- static JSBool
120
- MakeArraySlow(JSContext *cx, JSObject *obj);
121
-
122
119
  #define ENSURE_SLOW_ARRAY(cx, obj) \
123
- (OBJ_GET_CLASS(cx, obj) == &js_SlowArrayClass || MakeArraySlow(cx, obj))
120
+ (OBJ_GET_CLASS(cx, obj) == &js_SlowArrayClass || js_MakeArraySlow(cx, obj))
124
121
 
125
122
  /*
126
123
  * Determine if the id represents an array index or an XML property index.
@@ -417,7 +414,7 @@ SetArrayElement(JSContext *cx, JSObject *obj, jsuint index, jsval v)
417
414
 
418
415
  if (OBJ_IS_DENSE_ARRAY(cx, obj)) {
419
416
  if (INDEX_TOO_SPARSE(obj, index)) {
420
- if (!MakeArraySlow(cx, obj))
417
+ if (!js_MakeArraySlow(cx, obj))
421
418
  return JS_FALSE;
422
419
  } else {
423
420
 
@@ -586,7 +583,9 @@ array_length_setter(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
586
583
  }
587
584
 
588
585
  if (OBJ_IS_DENSE_ARRAY(cx, obj)) {
589
- if (ARRAY_DENSE_LENGTH(obj) && !ResizeSlots(cx, obj, oldlen, newlen))
586
+ /* Don't reallocate if we're not actually shrinking our slots. */
587
+ jsuint oldsize = ARRAY_DENSE_LENGTH(obj);
588
+ if (oldsize >= newlen && !ResizeSlots(cx, obj, oldsize, newlen))
590
589
  return JS_FALSE;
591
590
  } else if (oldlen - newlen < (1 << 24)) {
592
591
  do {
@@ -646,11 +645,11 @@ array_lookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
646
645
  * We have only indexed properties up to DENSELEN (excepting holes), plus
647
646
  * the length property. For all else, we delegate to the prototype.
648
647
  */
649
- if ((!js_IdIsIndex(id, &i) &&
650
- id != ATOM_TO_JSID(cx->runtime->atomState.lengthAtom)) ||
651
- obj->fslots[JSSLOT_ARRAY_LENGTH] == 0 ||
652
- i >= ARRAY_DENSE_LENGTH(obj) ||
653
- obj->dslots[i] == JSVAL_HOLE)
648
+ if (id != ATOM_TO_JSID(cx->runtime->atomState.lengthAtom) &&
649
+ (!js_IdIsIndex(id, &i) ||
650
+ obj->fslots[JSSLOT_ARRAY_LENGTH] == 0 ||
651
+ i >= ARRAY_DENSE_LENGTH(obj) ||
652
+ obj->dslots[i] == JSVAL_HOLE))
654
653
  {
655
654
  JSObject *proto = STOBJ_GET_PROTO(obj);
656
655
 
@@ -701,13 +700,29 @@ array_getProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
701
700
 
702
701
  if (!js_IdIsIndex(ID_TO_VALUE(id), &i) || i >= ARRAY_DENSE_LENGTH(obj) ||
703
702
  obj->dslots[i] == JSVAL_HOLE) {
703
+ JSObject *obj2;
704
+ JSProperty *prop;
705
+ JSScopeProperty *sprop;
706
+
704
707
  JSObject *proto = STOBJ_GET_PROTO(obj);
705
708
  if (!proto) {
706
709
  *vp = JSVAL_VOID;
707
710
  return JS_TRUE;
708
711
  }
709
712
 
710
- return OBJ_GET_PROPERTY(cx, proto, id, vp);
713
+ *vp = JSVAL_VOID;
714
+ if (js_LookupPropertyWithFlags(cx, proto, id, 0, &obj2, &prop) < 0)
715
+ return JS_FALSE;
716
+
717
+ if (prop && OBJ_IS_NATIVE(obj2)) {
718
+ sprop = (JSScopeProperty *) prop;
719
+ if (!js_NativeGet(cx, obj, obj2, sprop, vp))
720
+ return JS_FALSE;
721
+ }
722
+
723
+ if (prop)
724
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
725
+ return JS_TRUE;
711
726
  }
712
727
 
713
728
  *vp = obj->dslots[i];
@@ -763,7 +778,7 @@ array_setProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
763
778
  return js_SetProperty(cx, obj, id, vp);
764
779
 
765
780
  if (!js_IdIsIndex(id, &i) || INDEX_TOO_SPARSE(obj, i)) {
766
- if (!MakeArraySlow(cx, obj))
781
+ if (!js_MakeArraySlow(cx, obj))
767
782
  return JS_FALSE;
768
783
  return js_SetProperty(cx, obj, id, vp);
769
784
  }
@@ -1109,8 +1124,8 @@ JSClass js_SlowArrayClass = {
1109
1124
  /*
1110
1125
  * Convert an array object from fast-and-dense to slow-and-flexible.
1111
1126
  */
1112
- static JSBool
1113
- MakeArraySlow(JSContext *cx, JSObject *obj)
1127
+ JSBool
1128
+ js_MakeArraySlow(JSContext *cx, JSObject *obj)
1114
1129
  {
1115
1130
  JSObjectMap *map, *oldmap;
1116
1131
  uint32 i, length;
@@ -2048,7 +2063,7 @@ array_push(JSContext *cx, uintN argc, jsval *vp)
2048
2063
 
2049
2064
  length = obj->fslots[JSSLOT_ARRAY_LENGTH];
2050
2065
  if (INDEX_TOO_SPARSE(obj, length)) {
2051
- if (!MakeArraySlow(cx, obj))
2066
+ if (!js_MakeArraySlow(cx, obj))
2052
2067
  return JS_FALSE;
2053
2068
  return array_push_slowly(cx, obj, argc, vp);
2054
2069
  }
@@ -2074,23 +2089,16 @@ array_pop(JSContext *cx, uintN argc, jsval *vp)
2074
2089
  if (!obj)
2075
2090
  return JS_FALSE;
2076
2091
  if (OBJ_IS_DENSE_ARRAY(cx, obj)) {
2077
- *vp = JSVAL_VOID;
2078
2092
  index = obj->fslots[JSSLOT_ARRAY_LENGTH];
2079
- if (index == 0)
2093
+ if (index == 0) {
2094
+ *vp = JSVAL_VOID;
2080
2095
  return JS_TRUE;
2081
- index--;
2082
- if (index < ARRAY_DENSE_LENGTH(obj)) {
2083
- *vp = obj->dslots[index];
2084
- JS_ASSERT(*vp != JSVAL_HOLE);
2085
- if (index == 0) {
2086
- JS_free(cx, obj->dslots - 1);
2087
- obj->dslots = NULL;
2088
- } else {
2089
- ARRAY_SET_DENSE_LENGTH(obj, index);
2090
- }
2091
- obj->fslots[JSSLOT_ARRAY_COUNT]--;
2092
2096
  }
2093
-
2097
+ index--;
2098
+ if (!GetArrayElement(cx, obj, index, &hole, vp))
2099
+ return JS_FALSE;
2100
+ if (!hole && !DeleteArrayElement(cx, obj, index))
2101
+ return JS_FALSE;
2094
2102
  obj->fslots[JSSLOT_ARRAY_LENGTH] = index;
2095
2103
  return JS_TRUE;
2096
2104
  }
@@ -70,6 +70,9 @@ js_NewArrayObject(JSContext *cx, jsuint length, jsval *vector);
70
70
  extern JSObject *
71
71
  js_NewSlowArrayObject(JSContext *cx);
72
72
 
73
+ extern JSBool
74
+ js_MakeArraySlow(JSContext *cx, JSObject *obj);
75
+
73
76
  #define JSSLOT_ARRAY_LENGTH JSSLOT_PRIVATE
74
77
  #define JSSLOT_ARRAY_COUNT (JSSLOT_ARRAY_LENGTH + 1)
75
78
  #define JSSLOT_ARRAY_LOOKUP_HOLDER (JSSLOT_ARRAY_COUNT + 1)
@@ -183,7 +183,20 @@ int main(int argc, char **argv)
183
183
  printf("/* AUTOMATICALLY GENERATED - DO NOT EDIT */\n\n");
184
184
 
185
185
  #ifdef CROSS_COMPILE
186
- #if defined(IS_LITTLE_ENDIAN)
186
+ #if defined(__APPLE__)
187
+ /*
188
+ * Darwin NSPR uses the same MDCPUCFG (_darwin.cfg) for multiple
189
+ * processors, and determines which processor to configure for based
190
+ * on compiler predefined macros. We do the same thing here.
191
+ */
192
+ printf("#ifdef __LITTLE_ENDIAN__\n");
193
+ printf("#define IS_LITTLE_ENDIAN 1\n");
194
+ printf("#undef IS_BIG_ENDIAN\n");
195
+ printf("#else\n");
196
+ printf("#undef IS_LITTLE_ENDIAN\n");
197
+ printf("#define IS_BIG_ENDIAN 1\n");
198
+ printf("#endif\n\n");
199
+ #elif defined(IS_LITTLE_ENDIAN)
187
200
  printf("#define IS_LITTLE_ENDIAN 1\n");
188
201
  printf("#undef IS_BIG_ENDIAN\n\n");
189
202
  #elif defined(IS_BIG_ENDIAN)
@@ -478,12 +478,15 @@ msFromTime(jsdouble t)
478
478
  * We use the first reseved slot to store UTC time, and the second for caching
479
479
  * the local time. The initial value of the cache entry is NaN.
480
480
  */
481
- #define UTC_TIME_SLOT 0
482
- #define LOCAL_TIME_SLOT 1
481
+ #define JSSLOT_UTC_TIME JSSLOT_PRIVATE
482
+ #define JSSLOT_LOCAL_TIME (JSSLOT_PRIVATE + 1)
483
+
484
+ #define DATE_RESERVED_SLOTS 2
483
485
 
484
486
  JSClass js_DateClass = {
485
487
  js_Date_str,
486
- JSCLASS_HAS_RESERVED_SLOTS(2) | JSCLASS_HAS_CACHED_PROTO(JSProto_Date),
488
+ JSCLASS_HAS_RESERVED_SLOTS(DATE_RESERVED_SLOTS) |
489
+ JSCLASS_HAS_CACHED_PROTO(JSProto_Date),
487
490
  JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
488
491
  JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
489
492
  JSCLASS_NO_OPTIONAL_MEMBERS
@@ -926,14 +929,9 @@ date_now(JSContext *cx, uintN argc, jsval *vp)
926
929
  static JSBool
927
930
  GetUTCTime(JSContext *cx, JSObject *obj, jsval *vp, jsdouble *dp)
928
931
  {
929
- jsval v;
930
-
931
- if (vp && !JS_InstanceOf(cx, obj, &js_DateClass, vp + 2))
932
- return JS_FALSE;
933
- if (!JS_GetReservedSlot(cx, obj, UTC_TIME_SLOT, &v))
932
+ if (!JS_InstanceOf(cx, obj, &js_DateClass, vp ? vp + 2 : NULL))
934
933
  return JS_FALSE;
935
-
936
- *dp = *JSVAL_TO_DOUBLE(v);
934
+ *dp = *JSVAL_TO_DOUBLE(obj->fslots[JSSLOT_UTC_TIME]);
937
935
  return JS_TRUE;
938
936
  }
939
937
 
@@ -948,14 +946,12 @@ SetUTCTimePtr(JSContext *cx, JSObject *obj, jsval *vp, jsdouble *dp)
948
946
  {
949
947
  if (vp && !JS_InstanceOf(cx, obj, &js_DateClass, vp + 2))
950
948
  return JS_FALSE;
949
+ JS_ASSERT_IF(!vp, STOBJ_GET_CLASS(obj) == &js_DateClass);
951
950
 
952
951
  /* Invalidate local time cache. */
953
- if (!JS_SetReservedSlot(cx, obj, LOCAL_TIME_SLOT,
954
- DOUBLE_TO_JSVAL(cx->runtime->jsNaN))) {
955
- return JS_FALSE;
956
- }
957
-
958
- return JS_SetReservedSlot(cx, obj, UTC_TIME_SLOT, DOUBLE_TO_JSVAL(dp));
952
+ obj->fslots[JSSLOT_LOCAL_TIME] = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
953
+ obj->fslots[JSSLOT_UTC_TIME] = DOUBLE_TO_JSVAL(dp);
954
+ return JS_TRUE;
959
955
  }
960
956
 
961
957
  /*
@@ -981,8 +977,9 @@ GetAndCacheLocalTime(JSContext *cx, JSObject *obj, jsval *vp, jsdouble *dp)
981
977
  jsdouble result;
982
978
  jsdouble *cached;
983
979
 
984
- if (!obj || !JS_GetReservedSlot(cx, obj, LOCAL_TIME_SLOT, &v))
980
+ if (!obj || !JS_InstanceOf(cx, obj, &js_DateClass, vp ? vp + 2 : NULL))
985
981
  return JS_FALSE;
982
+ v = obj->fslots[JSSLOT_LOCAL_TIME];
986
983
 
987
984
  result = *JSVAL_TO_DOUBLE(v);
988
985
 
@@ -998,10 +995,7 @@ GetAndCacheLocalTime(JSContext *cx, JSObject *obj, jsval *vp, jsdouble *dp)
998
995
  if (!cached)
999
996
  return JS_FALSE;
1000
997
 
1001
- if (!JS_SetReservedSlot(cx, obj, LOCAL_TIME_SLOT,
1002
- DOUBLE_TO_JSVAL(cached))) {
1003
- return JS_FALSE;
1004
- }
998
+ obj->fslots[JSSLOT_LOCAL_TIME] = DOUBLE_TO_JSVAL(cached);
1005
999
  }
1006
1000
 
1007
1001
  *dp = result;
@@ -2028,10 +2022,8 @@ date_constructor(JSContext *cx, JSObject* obj)
2028
2022
  if (!date)
2029
2023
  return NULL;
2030
2024
 
2031
- JS_SetReservedSlot(cx, obj, UTC_TIME_SLOT,
2032
- DOUBLE_TO_JSVAL(date));
2033
- JS_SetReservedSlot(cx, obj, LOCAL_TIME_SLOT,
2034
- DOUBLE_TO_JSVAL(cx->runtime->jsNaN));
2025
+ obj->fslots[JSSLOT_UTC_TIME] = DOUBLE_TO_JSVAL(date);
2026
+ obj->fslots[JSSLOT_LOCAL_TIME] = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
2035
2027
  return date;
2036
2028
  }
2037
2029
 
@@ -732,10 +732,13 @@ JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsval idval,
732
732
  return JS_FALSE;
733
733
  }
734
734
 
735
- if (JSVAL_IS_INT(idval))
735
+ if (JSVAL_IS_INT(idval)) {
736
736
  propid = INT_JSVAL_TO_JSID(idval);
737
- else if (!js_ValueToStringId(cx, idval, &propid))
738
- return JS_FALSE;
737
+ } else {
738
+ if (!js_ValueToStringId(cx, idval, &propid))
739
+ return JS_FALSE;
740
+ CHECK_FOR_STRING_INDEX(propid);
741
+ }
739
742
 
740
743
  if (!js_LookupProperty(cx, obj, propid, &pobj, &prop))
741
744
  return JS_FALSE;
@@ -3020,8 +3020,16 @@ js_GC(JSContext *cx, JSGCInvocationKind gckind)
3020
3020
  ok = callback(cx, JSGC_BEGIN);
3021
3021
  if (gckind & GC_LOCK_HELD)
3022
3022
  JS_LOCK_GC(rt);
3023
- if (!ok && gckind != GC_LAST_CONTEXT)
3023
+ if (!ok && gckind != GC_LAST_CONTEXT) {
3024
+ /*
3025
+ * It's possible that we've looped back to this code from the 'goto
3026
+ * restart_at_beginning' below in the GC_SET_SLOT_REQUEST code and
3027
+ * that rt->gcLevel is now 0. Don't return without notifying!
3028
+ */
3029
+ if (rt->gcLevel == 0 && (gckind & GC_LOCK_HELD))
3030
+ JS_NOTIFY_GC_DONE(rt);
3024
3031
  return;
3032
+ }
3025
3033
  }
3026
3034
 
3027
3035
  /* Lock out other GC allocator and collector invocations. */
@@ -3471,7 +3479,7 @@ js_GC(JSContext *cx, JSGCInvocationKind gckind)
3471
3479
  goto restart;
3472
3480
  }
3473
3481
 
3474
- if (!(rt->shapeGen & SHAPE_OVERFLOW_BIT)) {
3482
+ if (rt->shapeGen < SHAPE_OVERFLOW_BIT - 1) {
3475
3483
  js_EnablePropertyCache(cx);
3476
3484
  #ifdef JS_THREADSAFE
3477
3485
  iter = NULL;
@@ -80,17 +80,22 @@
80
80
  #ifdef js_invoke_c__
81
81
 
82
82
  uint32
83
- js_GenerateShape(JSContext *cx, JSBool gcLocked)
83
+ js_GenerateShape(JSContext *cx, JSBool gcLocked, JSScopeProperty *sprop)
84
84
  {
85
85
  JSRuntime *rt;
86
86
  uint32 shape;
87
+ JSTempValueRooter tvr;
87
88
 
88
89
  rt = cx->runtime;
89
90
  shape = JS_ATOMIC_INCREMENT(&rt->shapeGen);
90
91
  JS_ASSERT(shape != 0);
91
92
  if (shape & SHAPE_OVERFLOW_BIT) {
92
93
  rt->gcPoke = JS_TRUE;
94
+ if (sprop)
95
+ JS_PUSH_TEMP_ROOT_SPROP(cx, sprop, &tvr);
93
96
  js_GC(cx, gcLocked ? GC_LOCK_HELD : GC_NORMAL);
97
+ if (sprop)
98
+ JS_POP_TEMP_ROOT(cx, &tvr);
94
99
  shape = JS_ATOMIC_INCREMENT(&rt->shapeGen);
95
100
  JS_ASSERT(shape != 0);
96
101
  JS_ASSERT_IF(shape & SHAPE_OVERFLOW_BIT,
@@ -825,8 +830,10 @@ ComputeThis(JSContext *cx, JSBool lazy, jsval *argv)
825
830
  thisp = JSVAL_TO_OBJECT(argv[-1]);
826
831
  } else {
827
832
  thisp = JSVAL_TO_OBJECT(argv[-1]);
828
- if (OBJ_GET_CLASS(cx, thisp) == &js_CallClass)
833
+ if (OBJ_GET_CLASS(cx, thisp) == &js_CallClass ||
834
+ OBJ_GET_CLASS(cx, thisp) == &js_BlockClass) {
829
835
  return js_ComputeGlobalThis(cx, lazy, argv);
836
+ }
830
837
 
831
838
  if (thisp->map->ops->thisObject) {
832
839
  /* Some objects (e.g., With) delegate 'this' to another object. */
@@ -1473,12 +1480,6 @@ js_Execute(JSContext *cx, JSObject *chain, JSScript *script,
1473
1480
  frame.callee = NULL;
1474
1481
  frame.fun = NULL;
1475
1482
  frame.thisp = chain;
1476
- OBJ_TO_OUTER_OBJECT(cx, frame.thisp);
1477
- if (!frame.thisp) {
1478
- ok = JS_FALSE;
1479
- goto out;
1480
- }
1481
- flags |= JSFRAME_COMPUTED_THIS;
1482
1483
  frame.argc = 0;
1483
1484
  frame.argv = NULL;
1484
1485
  frame.nvars = script->ngvars;
@@ -1528,6 +1529,15 @@ js_Execute(JSContext *cx, JSObject *chain, JSScript *script,
1528
1529
  }
1529
1530
 
1530
1531
  cx->fp = &frame;
1532
+ if (!down) {
1533
+ OBJ_TO_OUTER_OBJECT(cx, frame.thisp);
1534
+ if (!frame.thisp) {
1535
+ ok = JS_FALSE;
1536
+ goto out2;
1537
+ }
1538
+ frame.flags |= JSFRAME_COMPUTED_THIS;
1539
+ }
1540
+
1531
1541
  if (hook) {
1532
1542
  hookData = hook(cx, &frame, JS_TRUE, 0,
1533
1543
  cx->debugHooks->executeHookData);
@@ -1541,6 +1551,8 @@ js_Execute(JSContext *cx, JSObject *chain, JSScript *script,
1541
1551
  if (hook)
1542
1552
  hook(cx, &frame, JS_FALSE, &ok, hookData);
1543
1553
  }
1554
+
1555
+ out2:
1544
1556
  if (mark)
1545
1557
  js_FreeRawStack(cx, mark);
1546
1558
  cx->fp = oldfp;
@@ -1677,63 +1689,84 @@ js_CheckRedeclaration(JSContext *cx, JSObject *obj, jsid id, uintN attrs,
1677
1689
  jsval value;
1678
1690
  const char *type, *name;
1679
1691
 
1692
+ /*
1693
+ * Both objp and propp must be either null or given. When given, *propp
1694
+ * must be null. This way we avoid an extra "if (propp) *propp = NULL" for
1695
+ * the common case of a non-existing property.
1696
+ */
1697
+ JS_ASSERT(!objp == !propp);
1698
+ JS_ASSERT_IF(propp, !*propp);
1699
+
1700
+ /* The JSPROP_INITIALIZER case below may generate a warning. Since we must
1701
+ * drop the property before reporting it, we insists on !propp to avoid
1702
+ * looking up the property again after the reporting is done.
1703
+ */
1704
+ JS_ASSERT_IF(attrs & JSPROP_INITIALIZER, attrs == JSPROP_INITIALIZER);
1705
+ JS_ASSERT_IF(attrs == JSPROP_INITIALIZER, !propp);
1706
+
1680
1707
  if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop))
1681
1708
  return JS_FALSE;
1682
- if (propp) {
1683
- *objp = obj2;
1684
- *propp = prop;
1685
- }
1686
1709
  if (!prop)
1687
1710
  return JS_TRUE;
1688
1711
 
1689
- /*
1690
- * Use prop as a speedup hint to OBJ_GET_ATTRIBUTES, but drop it on error.
1691
- * An assertion at label bad: will insist that it is null.
1692
- */
1712
+ /* Use prop as a speedup hint to OBJ_GET_ATTRIBUTES. */
1693
1713
  if (!OBJ_GET_ATTRIBUTES(cx, obj2, id, prop, &oldAttrs)) {
1694
1714
  OBJ_DROP_PROPERTY(cx, obj2, prop);
1695
- #ifdef DEBUG
1696
- prop = NULL;
1697
- #endif
1698
- goto bad;
1715
+ return JS_FALSE;
1699
1716
  }
1700
1717
 
1701
1718
  /*
1702
- * From here, return true, or else goto bad on failure to null out params.
1703
1719
  * If our caller doesn't want prop, drop it (we don't need it any longer).
1704
1720
  */
1705
1721
  if (!propp) {
1706
1722
  OBJ_DROP_PROPERTY(cx, obj2, prop);
1707
1723
  prop = NULL;
1724
+ } else {
1725
+ *objp = obj2;
1726
+ *propp = prop;
1708
1727
  }
1709
1728
 
1710
1729
  if (attrs == JSPROP_INITIALIZER) {
1711
1730
  /* Allow the new object to override properties. */
1712
1731
  if (obj2 != obj)
1713
1732
  return JS_TRUE;
1733
+
1734
+ /* The property must be dropped already. */
1735
+ JS_ASSERT(!prop);
1714
1736
  report = JSREPORT_WARNING | JSREPORT_STRICT;
1715
1737
  } else {
1716
1738
  /* We allow redeclaring some non-readonly properties. */
1717
1739
  if (((oldAttrs | attrs) & JSPROP_READONLY) == 0) {
1718
- /*
1719
- * Allow redeclaration of variables and functions, but insist that
1720
- * the new value is not a getter if the old value was, ditto for
1721
- * setters -- unless prop is impermanent (in which case anyone
1722
- * could delete it and redefine it, willy-nilly).
1723
- */
1740
+ /* Allow redeclaration of variables and functions. */
1724
1741
  if (!(attrs & (JSPROP_GETTER | JSPROP_SETTER)))
1725
1742
  return JS_TRUE;
1743
+
1744
+ /*
1745
+ * Allow adding a getter only if a property already has a setter
1746
+ * but no getter and similarly for adding a setter. That is, we
1747
+ * allow only the following transitions:
1748
+ *
1749
+ * no-property --> getter --> getter + setter
1750
+ * no-property --> setter --> getter + setter
1751
+ */
1726
1752
  if ((~(oldAttrs ^ attrs) & (JSPROP_GETTER | JSPROP_SETTER)) == 0)
1727
1753
  return JS_TRUE;
1754
+
1755
+ /*
1756
+ * Allow redeclaration of an impermanent property (in which case
1757
+ * anyone could delete it and redefine it, willy-nilly).
1758
+ */
1728
1759
  if (!(oldAttrs & JSPROP_PERMANENT))
1729
1760
  return JS_TRUE;
1730
1761
  }
1762
+ if (prop)
1763
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
1731
1764
 
1732
1765
  report = JSREPORT_ERROR;
1733
1766
  isFunction = (oldAttrs & (JSPROP_GETTER | JSPROP_SETTER)) != 0;
1734
1767
  if (!isFunction) {
1735
1768
  if (!OBJ_GET_PROPERTY(cx, obj, id, &value))
1736
- goto bad;
1769
+ return JS_FALSE;
1737
1770
  isFunction = VALUE_IS_FUNCTION(cx, value);
1738
1771
  }
1739
1772
  }
@@ -1751,19 +1784,11 @@ js_CheckRedeclaration(JSContext *cx, JSObject *obj, jsid id, uintN attrs,
1751
1784
  : js_var_str;
1752
1785
  name = js_ValueToPrintableString(cx, ID_TO_VALUE(id));
1753
1786
  if (!name)
1754
- goto bad;
1787
+ return JS_FALSE;
1755
1788
  return JS_ReportErrorFlagsAndNumber(cx, report,
1756
1789
  js_GetErrorMessage, NULL,
1757
1790
  JSMSG_REDECLARED_VAR,
1758
1791
  type, name);
1759
-
1760
- bad:
1761
- if (propp) {
1762
- *objp = NULL;
1763
- *propp = NULL;
1764
- }
1765
- JS_ASSERT(!prop);
1766
- return JS_FALSE;
1767
1792
  }
1768
1793
 
1769
1794
  JSBool
@@ -4743,16 +4768,6 @@ interrupt:
4743
4768
  newifp->frame.regs = NULL;
4744
4769
  newifp->frame.spbase = NULL;
4745
4770
 
4746
- /* Call the debugger hook if present. */
4747
- hook = cx->debugHooks->callHook;
4748
- if (hook) {
4749
- newifp->hookData = hook(cx, &newifp->frame, JS_TRUE, 0,
4750
- cx->debugHooks->callHookData);
4751
- LOAD_INTERRUPT_HANDLER(cx);
4752
- } else {
4753
- newifp->hookData = NULL;
4754
- }
4755
-
4756
4771
  /* Scope with a call object parented by callee's parent. */
4757
4772
  if (JSFUN_HEAVYWEIGHT_TEST(fun->flags) &&
4758
4773
  !js_GetCallObject(cx, &newifp->frame, parent)) {
@@ -4775,6 +4790,16 @@ interrupt:
4775
4790
  newifp->frame.regs = &regs;
4776
4791
  cx->fp = fp = &newifp->frame;
4777
4792
 
4793
+ /* Call the debugger hook if present. */
4794
+ hook = cx->debugHooks->callHook;
4795
+ if (hook) {
4796
+ newifp->hookData = hook(cx, &newifp->frame, JS_TRUE, 0,
4797
+ cx->debugHooks->callHookData);
4798
+ LOAD_INTERRUPT_HANDLER(cx);
4799
+ } else {
4800
+ newifp->hookData = NULL;
4801
+ }
4802
+
4778
4803
  inlineCallCount++;
4779
4804
  JS_RUNTIME_METER(rt, inlineCalls);
4780
4805
 
@@ -5093,7 +5118,7 @@ interrupt:
5093
5118
  funobj = fp->callee;
5094
5119
  slot += JSCLASS_RESERVED_SLOTS(&js_FunctionClass);
5095
5120
  if (!JS_GetReservedSlot(cx, funobj, slot, &rval))
5096
- return JS_FALSE;
5121
+ goto error;
5097
5122
  if (JSVAL_IS_VOID(rval))
5098
5123
  rval = JSVAL_NULL;
5099
5124
  } else {
@@ -5151,7 +5176,7 @@ interrupt:
5151
5176
  /* Store the regexp object value in its cloneIndex slot. */
5152
5177
  if (fp->fun) {
5153
5178
  if (!JS_SetReservedSlot(cx, funobj, slot, rval))
5154
- return JS_FALSE;
5179
+ goto error;
5155
5180
  } else {
5156
5181
  fp->vars[slot] = rval;
5157
5182
  }
@@ -5524,6 +5549,7 @@ interrupt:
5524
5549
 
5525
5550
  /* Lookup id in order to check for redeclaration problems. */
5526
5551
  id = ATOM_TO_JSID(atom);
5552
+ prop = NULL;
5527
5553
  if (!js_CheckRedeclaration(cx, obj, id, attrs, &obj2, &prop))
5528
5554
  goto error;
5529
5555
 
@@ -5545,11 +5571,11 @@ interrupt:
5545
5571
  * by the JSOP_*GVAR opcodes.
5546
5572
  */
5547
5573
  if (index < script->ngvars &&
5548
- (attrs & JSPROP_PERMANENT) &&
5549
5574
  obj2 == obj &&
5550
5575
  OBJ_IS_NATIVE(obj)) {
5551
5576
  sprop = (JSScopeProperty *) prop;
5552
- if (SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(obj)) &&
5577
+ if ((sprop->attrs & JSPROP_PERMANENT) &&
5578
+ SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(obj)) &&
5553
5579
  SPROP_HAS_STUB_GETTER(sprop) &&
5554
5580
  SPROP_HAS_STUB_SETTER(sprop)) {
5555
5581
  /*
@@ -162,8 +162,12 @@ typedef struct JSInlineFrame {
162
162
 
163
163
  #define SHAPE_OVERFLOW_BIT JS_BIT(32 - PCVCAP_TAGBITS)
164
164
 
165
+ /*
166
+ * When sprop is not null and the shape generation triggers the GC due to a
167
+ * shape overflow, the functions roots sprop.
168
+ */
165
169
  extern uint32
166
- js_GenerateShape(JSContext *cx, JSBool gcLocked);
170
+ js_GenerateShape(JSContext *cx, JSBool gcLocked, JSScopeProperty *sprop);
167
171
 
168
172
  struct JSPropCacheEntry {
169
173
  jsbytecode *kpc; /* pc if vcap tag is <= 1, else atom */
@@ -556,8 +556,7 @@ js_InitMathClass(JSContext *cx, JSObject *obj)
556
556
  {
557
557
  JSObject *Math;
558
558
 
559
- Math = JS_DefineObject(cx, obj, js_Math_str, &js_MathClass, NULL,
560
- JSPROP_READONLY | JSPROP_PERMANENT);
559
+ Math = JS_DefineObject(cx, obj, js_Math_str, &js_MathClass, NULL, 0);
561
560
  if (!Math)
562
561
  return NULL;
563
562
  if (!JS_DefineFunctions(cx, Math, math_static_methods))
@@ -309,7 +309,7 @@ num_toLocaleString(JSContext *cx, uintN argc, jsval *vp)
309
309
  JSString *numStr, *str;
310
310
  const char *num, *end, *tmpSrc;
311
311
  char *buf, *tmpDest;
312
- const char *dec;
312
+ const char *nint;
313
313
  int digits, size, remainder, nrepeat;
314
314
 
315
315
  /*
@@ -324,17 +324,28 @@ num_toLocaleString(JSContext *cx, uintN argc, jsval *vp)
324
324
  if (!num)
325
325
  return JS_FALSE;
326
326
 
327
- /* Find bit before the decimal. */
328
- dec = strchr(num, '.');
329
- digits = dec ? dec - num : (int)strlen(num);
327
+ /*
328
+ * Find the first non-integer value, whether it be a letter as in
329
+ * 'Infinite', a decimal point, or an 'e' from exponential notation.
330
+ */
331
+ nint = num;
332
+ if (*nint == '-')
333
+ nint++;
334
+ while (*nint >= '0' && *nint <= '9')
335
+ nint++;
336
+ digits = nint - num;
330
337
  end = num + digits;
338
+ if (!digits)
339
+ return JS_TRUE;
331
340
 
332
341
  rt = cx->runtime;
333
342
  thousandsLength = strlen(rt->thousandsSeparator);
334
343
  decimalLength = strlen(rt->decimalSeparator);
335
344
 
336
345
  /* Figure out how long resulting string will be. */
337
- size = digits + (dec ? decimalLength + strlen(dec + 1) : 0);
346
+ size = digits + (*nint ? strlen(nint + 1) + 1 : 0);
347
+ if (*nint == '.')
348
+ size += decimalLength;
338
349
 
339
350
  numGrouping = tmpGroup = rt->numGrouping;
340
351
  remainder = digits;
@@ -376,12 +387,12 @@ num_toLocaleString(JSContext *cx, uintN argc, jsval *vp)
376
387
  tmpGroup--;
377
388
  }
378
389
 
379
- if (dec) {
390
+ if (*nint == '.') {
380
391
  strcpy(tmpDest, rt->decimalSeparator);
381
392
  tmpDest += decimalLength;
382
- strcpy(tmpDest, dec + 1);
393
+ strcpy(tmpDest, nint + 1);
383
394
  } else {
384
- *tmpDest++ = '\0';
395
+ strcpy(tmpDest, nint);
385
396
  }
386
397
 
387
398
  if (cx->localeCallbacks && cx->localeCallbacks->localeToUnicode)