jbarnette-johnson 1.0.0.20090326161333 → 1.0.0.20090402144841

Sign up to get free protection for your applications and to get access to all the features.
@@ -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)