63 |
|
|
64 |
extern jsdouble js_NaN; |
extern jsdouble js_NaN; |
65 |
|
|
66 |
|
JS_FRIEND_API(void) |
67 |
|
js_SetTraceableNativeFailed(JSContext *cx) |
68 |
|
{ |
69 |
|
js_SetBuiltinError(cx); |
70 |
|
} |
71 |
|
|
72 |
/* |
/* |
73 |
* NB: bool FASTCALL is not compatible with Nanojit's calling convention usage. |
* NB: bool FASTCALL is not compatible with Nanojit's calling convention usage. |
74 |
* Do not use bool FASTCALL, use JSBool only! |
* Do not use bool FASTCALL, use JSBool only! |
188 |
jsdouble d; |
jsdouble d; |
189 |
|
|
190 |
JSSTRING_CHARS_AND_END(str, bp, end); |
JSSTRING_CHARS_AND_END(str, bp, end); |
191 |
if (!js_strtod(cx, bp, end, &ep, &d) || js_SkipWhiteSpace(ep, end) != end) |
if ((!js_strtod(cx, bp, end, &ep, &d) || |
192 |
|
js_SkipWhiteSpace(ep, end) != end) && |
193 |
|
(!js_strtointeger(cx, bp, end, &ep, 0, &d) || |
194 |
|
js_SkipWhiteSpace(ep, end) != end)) { |
195 |
return 0; |
return 0; |
|
return js_DoubleToECMAInt32(d); |
|
|
} |
|
|
|
|
|
static inline JSBool |
|
|
js_Int32ToId(JSContext* cx, int32 index, jsid* id) |
|
|
{ |
|
|
if (index <= JSVAL_INT_MAX) { |
|
|
*id = INT_TO_JSID(index); |
|
|
return JS_TRUE; |
|
196 |
} |
} |
197 |
JSString* str = js_NumberToString(cx, index); |
return js_DoubleToECMAInt32(d); |
|
if (!str) |
|
|
return JS_FALSE; |
|
|
return js_ValueToStringId(cx, STRING_TO_JSVAL(str), id); |
|
|
} |
|
|
|
|
|
jsval FASTCALL |
|
|
js_Any_getprop(JSContext* cx, JSObject* obj, JSString* idstr) |
|
|
{ |
|
|
jsval v; |
|
|
jsid id; |
|
|
|
|
|
if (!js_ValueToStringId(cx, STRING_TO_JSVAL(idstr), &id)) |
|
|
return JSVAL_ERROR_COOKIE; |
|
|
if (!OBJ_GET_PROPERTY(cx, obj, id, &v)) |
|
|
return JSVAL_ERROR_COOKIE; |
|
|
return v; |
|
|
} |
|
|
|
|
|
JSBool FASTCALL |
|
|
js_Any_setprop(JSContext* cx, JSObject* obj, JSString* idstr, jsval v) |
|
|
{ |
|
|
jsid id; |
|
|
if (!js_ValueToStringId(cx, STRING_TO_JSVAL(idstr), &id)) |
|
|
return JS_FALSE; |
|
|
return OBJ_SET_PROPERTY(cx, obj, id, &v); |
|
|
} |
|
|
|
|
|
jsval FASTCALL |
|
|
js_Any_getelem(JSContext* cx, JSObject* obj, int32 index) |
|
|
{ |
|
|
jsval v; |
|
|
jsid id; |
|
|
if (!js_Int32ToId(cx, index, &id)) |
|
|
return JSVAL_ERROR_COOKIE; |
|
|
if (!OBJ_GET_PROPERTY(cx, obj, id, &v)) |
|
|
return JSVAL_ERROR_COOKIE; |
|
|
return v; |
|
|
} |
|
|
|
|
|
JSBool FASTCALL |
|
|
js_Any_setelem(JSContext* cx, JSObject* obj, int32 index, jsval v) |
|
|
{ |
|
|
jsid id; |
|
|
if (!js_Int32ToId(cx, index, &id)) |
|
|
return JSVAL_ERROR_COOKIE; |
|
|
return OBJ_SET_PROPERTY(cx, obj, id, &v); |
|
|
} |
|
|
|
|
|
JSObject* FASTCALL |
|
|
js_FastValueToIterator(JSContext* cx, jsuint flags, jsval v) |
|
|
{ |
|
|
if (!js_ValueToIterator(cx, flags, &v)) |
|
|
return NULL; |
|
|
return JSVAL_TO_OBJECT(v); |
|
|
} |
|
|
|
|
|
jsval FASTCALL |
|
|
js_FastCallIteratorNext(JSContext* cx, JSObject* iterobj) |
|
|
{ |
|
|
jsval v; |
|
|
if (!js_CallIteratorNext(cx, iterobj, &v)) |
|
|
return JSVAL_ERROR_COOKIE; |
|
|
return v; |
|
198 |
} |
} |
199 |
|
|
200 |
SideExit* FASTCALL |
SideExit* FASTCALL |
219 |
the outer tree the failing call was in starting at that guard. */ |
the outer tree the failing call was in starting at that guard. */ |
220 |
if (!state->lastTreeCallGuard) { |
if (!state->lastTreeCallGuard) { |
221 |
state->lastTreeCallGuard = lr; |
state->lastTreeCallGuard = lr; |
222 |
FrameInfo* rp = (FrameInfo*)state->rp; |
FrameInfo** rp = (FrameInfo**)state->rp; |
223 |
state->rpAtLastTreeCall = rp + lr->calldepth; |
state->rpAtLastTreeCall = rp + lr->calldepth; |
224 |
} |
} |
225 |
} else { |
} else { |
232 |
return lr; |
return lr; |
233 |
} |
} |
234 |
|
|
|
JSObject* FASTCALL |
|
|
js_FastNewObject(JSContext* cx, JSObject* ctor) |
|
|
{ |
|
|
JS_ASSERT(HAS_FUNCTION_CLASS(ctor)); |
|
|
JSFunction* fun = GET_FUNCTION_PRIVATE(cx, ctor); |
|
|
JSClass* clasp = (FUN_INTERPRETED(fun) || (fun->flags & JSFUN_TRACEABLE)) |
|
|
? &js_ObjectClass |
|
|
: FUN_CLASP(fun); |
|
|
JS_ASSERT(clasp != &js_ArrayClass); |
|
|
|
|
|
JS_LOCK_OBJ(cx, ctor); |
|
|
JSScope *scope = OBJ_SCOPE(ctor); |
|
|
JS_ASSERT(scope->object == ctor); |
|
|
JSAtom* atom = cx->runtime->atomState.classPrototypeAtom; |
|
|
|
|
|
JSScopeProperty *sprop = SCOPE_GET_PROPERTY(scope, ATOM_TO_JSID(atom)); |
|
|
JS_ASSERT(SPROP_HAS_VALID_SLOT(sprop, scope)); |
|
|
jsval v = LOCKED_OBJ_GET_SLOT(ctor, sprop->slot); |
|
|
JS_UNLOCK_SCOPE(cx, scope); |
|
|
|
|
|
JSObject* proto; |
|
|
if (JSVAL_IS_PRIMITIVE(v)) { |
|
|
if (!js_GetClassPrototype(cx, JSVAL_TO_OBJECT(ctor->fslots[JSSLOT_PARENT]), |
|
|
INT_TO_JSID(JSProto_Object), &proto)) { |
|
|
return NULL; |
|
|
} |
|
|
} else { |
|
|
proto = JSVAL_TO_OBJECT(v); |
|
|
} |
|
|
|
|
|
JS_ASSERT(JS_ON_TRACE(cx)); |
|
|
JSObject* obj = (JSObject*) js_NewGCThing(cx, GCX_OBJECT, sizeof(JSObject)); |
|
|
if (!obj) |
|
|
return NULL; |
|
|
|
|
|
obj->classword = jsuword(clasp); |
|
|
obj->fslots[JSSLOT_PROTO] = OBJECT_TO_JSVAL(proto); |
|
|
obj->fslots[JSSLOT_PARENT] = ctor->fslots[JSSLOT_PARENT]; |
|
|
for (unsigned i = JSSLOT_PRIVATE; i != JS_INITIAL_NSLOTS; ++i) |
|
|
obj->fslots[i] = JSVAL_VOID; |
|
|
|
|
|
obj->map = js_HoldObjectMap(cx, proto->map); |
|
|
obj->dslots = NULL; |
|
|
return obj; |
|
|
} |
|
|
|
|
235 |
JSBool FASTCALL |
JSBool FASTCALL |
236 |
js_AddProperty(JSContext* cx, JSObject* obj, JSScopeProperty* sprop) |
js_AddProperty(JSContext* cx, JSObject* obj, JSScopeProperty* sprop) |
237 |
{ |
{ |
|
JSScopeProperty* sprop2 = NULL; // initialize early to make MSVC happy |
|
|
|
|
238 |
JS_ASSERT(OBJ_IS_NATIVE(obj)); |
JS_ASSERT(OBJ_IS_NATIVE(obj)); |
239 |
JS_ASSERT(SPROP_HAS_STUB_SETTER(sprop)); |
JS_ASSERT(SPROP_HAS_STUB_SETTER(sprop)); |
240 |
|
|
241 |
JS_LOCK_OBJ(cx, obj); |
JS_LOCK_OBJ(cx, obj); |
242 |
|
|
243 |
JSScope* scope = OBJ_SCOPE(obj); |
JSScope* scope = OBJ_SCOPE(obj); |
244 |
|
uint32 slot; |
245 |
if (scope->object == obj) { |
if (scope->object == obj) { |
246 |
JS_ASSERT(!SCOPE_HAS_PROPERTY(scope, sprop)); |
JS_ASSERT(!SCOPE_HAS_PROPERTY(scope, sprop)); |
247 |
} else { |
} else { |
248 |
scope = js_GetMutableScope(cx, obj); |
scope = js_GetMutableScope(cx, obj); |
249 |
if (!scope) { |
if (!scope) |
250 |
JS_UNLOCK_OBJ(cx, obj); |
goto exit_trace; |
|
return JS_FALSE; |
|
|
} |
|
251 |
} |
} |
252 |
|
|
253 |
uint32 slot = sprop->slot; |
slot = sprop->slot; |
254 |
if (!scope->table && sprop->parent == scope->lastProp && slot == scope->map.freeslot) { |
if (!scope->table && sprop->parent == scope->lastProp && slot == scope->freeslot) { |
255 |
if (slot < STOBJ_NSLOTS(obj) && !OBJ_GET_CLASS(cx, obj)->reserveSlots) { |
if (slot < STOBJ_NSLOTS(obj) && !OBJ_GET_CLASS(cx, obj)->reserveSlots) { |
256 |
JS_ASSERT(JSVAL_IS_VOID(STOBJ_GET_SLOT(obj, scope->map.freeslot))); |
JS_ASSERT(JSVAL_IS_VOID(STOBJ_GET_SLOT(obj, scope->freeslot))); |
257 |
++scope->map.freeslot; |
++scope->freeslot; |
258 |
} else { |
} else { |
259 |
if (!js_AllocSlot(cx, obj, &slot)) { |
if (!js_AllocSlot(cx, obj, &slot)) |
260 |
JS_UNLOCK_SCOPE(cx, scope); |
goto exit_trace; |
|
return JS_FALSE; |
|
|
} |
|
261 |
|
|
262 |
if (slot != sprop->slot) |
if (slot != sprop->slot) { |
263 |
goto slot_changed; |
js_FreeSlot(cx, obj, slot); |
264 |
|
goto exit_trace; |
265 |
|
} |
266 |
} |
} |
267 |
|
|
268 |
SCOPE_EXTEND_SHAPE(cx, scope, sprop); |
js_ExtendScopeShape(cx, scope, sprop); |
269 |
++scope->entryCount; |
++scope->entryCount; |
270 |
scope->lastProp = sprop; |
scope->lastProp = sprop; |
271 |
JS_UNLOCK_SCOPE(cx, scope); |
} else { |
272 |
return JS_TRUE; |
JSScopeProperty *sprop2 = js_AddScopeProperty(cx, scope, sprop->id, |
273 |
|
sprop->getter, |
274 |
|
sprop->setter, |
275 |
|
SPROP_INVALID_SLOT, |
276 |
|
sprop->attrs, |
277 |
|
sprop->flags, |
278 |
|
sprop->shortid); |
279 |
|
if (sprop2 != sprop) |
280 |
|
goto exit_trace; |
281 |
} |
} |
282 |
|
|
283 |
sprop2 = js_AddScopeProperty(cx, scope, sprop->id, |
if (js_IsPropertyCacheDisabled(cx)) |
284 |
sprop->getter, sprop->setter, SPROP_INVALID_SLOT, |
goto exit_trace; |
285 |
sprop->attrs, sprop->flags, sprop->shortid); |
|
286 |
if (sprop2 == sprop) { |
JS_UNLOCK_SCOPE(cx, scope); |
287 |
JS_UNLOCK_SCOPE(cx, scope); |
return JS_TRUE; |
|
return JS_TRUE; |
|
|
} |
|
|
slot = sprop2->slot; |
|
288 |
|
|
289 |
slot_changed: |
exit_trace: |
|
js_FreeSlot(cx, obj, slot); |
|
290 |
JS_UNLOCK_SCOPE(cx, scope); |
JS_UNLOCK_SCOPE(cx, scope); |
291 |
return JS_FALSE; |
return JS_FALSE; |
292 |
} |
} |
293 |
|
|
294 |
JSBool FASTCALL |
static JSBool |
295 |
js_HasNamedProperty(JSContext* cx, JSObject* obj, JSString* idstr) |
HasProperty(JSContext* cx, JSObject* obj, jsid id) |
296 |
{ |
{ |
297 |
jsid id; |
// Check that we know how the lookup op will behave. |
298 |
if (!obj || !js_ValueToStringId(cx, STRING_TO_JSVAL(idstr), &id)) |
for (JSObject* pobj = obj; pobj; pobj = OBJ_GET_PROTO(cx, pobj)) { |
299 |
return JSVAL_TO_BOOLEAN(JSVAL_VOID); |
if (pobj->map->ops->lookupProperty != js_LookupProperty) |
300 |
|
return JSVAL_TO_PSEUDO_BOOLEAN(JSVAL_VOID); |
301 |
|
JSClass* clasp = OBJ_GET_CLASS(cx, pobj); |
302 |
|
if (clasp->resolve != JS_ResolveStub && clasp != &js_StringClass) |
303 |
|
return JSVAL_TO_PSEUDO_BOOLEAN(JSVAL_VOID); |
304 |
|
} |
305 |
|
|
306 |
JSObject* obj2; |
JSObject* obj2; |
307 |
JSProperty* prop; |
JSProperty* prop; |
308 |
if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop)) |
if (!js_LookupPropertyWithFlags(cx, obj, id, JSRESOLVE_QUALIFIED, &obj2, &prop)) |
309 |
return JSVAL_TO_BOOLEAN(JSVAL_VOID); |
return JSVAL_TO_PSEUDO_BOOLEAN(JSVAL_VOID); |
310 |
if (prop) |
if (prop) |
311 |
OBJ_DROP_PROPERTY(cx, obj2, prop); |
OBJ_DROP_PROPERTY(cx, obj2, prop); |
312 |
return prop != NULL; |
return prop != NULL; |
313 |
} |
} |
314 |
|
|
315 |
JSBool FASTCALL |
JSBool FASTCALL |
316 |
js_HasNamedPropertyInt32(JSContext* cx, JSObject* obj, int32 index) |
js_HasNamedProperty(JSContext* cx, JSObject* obj, JSString* idstr) |
317 |
{ |
{ |
318 |
jsid id; |
jsid id; |
319 |
if (!obj || !js_Int32ToId(cx, index, &id)) |
if (!js_ValueToStringId(cx, STRING_TO_JSVAL(idstr), &id)) |
320 |
return JSVAL_TO_BOOLEAN(JSVAL_VOID); |
return JSVAL_TO_BOOLEAN(JSVAL_VOID); |
321 |
|
|
322 |
JSObject* obj2; |
return HasProperty(cx, obj, id); |
323 |
JSProperty* prop; |
} |
324 |
if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop)) |
|
325 |
|
JSBool FASTCALL |
326 |
|
js_HasNamedPropertyInt32(JSContext* cx, JSObject* obj, int32 index) |
327 |
|
{ |
328 |
|
jsid id; |
329 |
|
if (!js_Int32ToId(cx, index, &id)) |
330 |
return JSVAL_TO_BOOLEAN(JSVAL_VOID); |
return JSVAL_TO_BOOLEAN(JSVAL_VOID); |
331 |
if (prop) |
|
332 |
OBJ_DROP_PROPERTY(cx, obj2, prop); |
return HasProperty(cx, obj, id); |
|
return prop != NULL; |
|
333 |
} |
} |
334 |
|
|
335 |
jsval FASTCALL |
jsval FASTCALL |
337 |
{ |
{ |
338 |
JS_ASSERT(!SPROP_HAS_STUB_GETTER(sprop)); |
JS_ASSERT(!SPROP_HAS_STUB_GETTER(sprop)); |
339 |
jsval v; |
jsval v; |
340 |
if (!SPROP_GET(cx, sprop, obj, obj, &v)) |
if (!js_GetSprop(cx, sprop, obj, &v)) |
341 |
return JSVAL_ERROR_COOKIE; |
return JSVAL_ERROR_COOKIE; |
342 |
return v; |
return v; |
343 |
} |
} |
352 |
JSString* FASTCALL |
JSString* FASTCALL |
353 |
js_TypeOfBoolean(JSContext* cx, int32 unboxed) |
js_TypeOfBoolean(JSContext* cx, int32 unboxed) |
354 |
{ |
{ |
355 |
jsval boxed = BOOLEAN_TO_JSVAL(unboxed); |
/* Watch out for pseudo-booleans. */ |
356 |
|
jsval boxed = PSEUDO_BOOLEAN_TO_JSVAL(unboxed); |
357 |
JS_ASSERT(JSVAL_IS_VOID(boxed) || JSVAL_IS_BOOLEAN(boxed)); |
JS_ASSERT(JSVAL_IS_VOID(boxed) || JSVAL_IS_BOOLEAN(boxed)); |
358 |
JSType type = JS_TypeOfValue(cx, boxed); |
JSType type = JS_TypeOfValue(cx, boxed); |
359 |
return ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[type]); |
return ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[type]); |
362 |
jsdouble FASTCALL |
jsdouble FASTCALL |
363 |
js_BooleanOrUndefinedToNumber(JSContext* cx, int32 unboxed) |
js_BooleanOrUndefinedToNumber(JSContext* cx, int32 unboxed) |
364 |
{ |
{ |
365 |
if (unboxed == JSVAL_TO_BOOLEAN(JSVAL_VOID)) |
if (unboxed == JSVAL_TO_PSEUDO_BOOLEAN(JSVAL_VOID)) |
366 |
return js_NaN; |
return js_NaN; |
367 |
|
JS_ASSERT(unboxed == JS_TRUE || unboxed == JS_FALSE); |
368 |
return unboxed; |
return unboxed; |
369 |
} |
} |
370 |
|
|
375 |
return ATOM_TO_STRING(cx->runtime->atomState.booleanAtoms[unboxed]); |
return ATOM_TO_STRING(cx->runtime->atomState.booleanAtoms[unboxed]); |
376 |
} |
} |
377 |
|
|
378 |
JSString* FASTCALL |
JSObject* FASTCALL |
379 |
js_ObjectToString(JSContext* cx, JSObject* obj) |
js_Arguments(JSContext* cx) |
380 |
{ |
{ |
381 |
if (!obj) |
return NULL; |
|
return ATOM_TO_STRING(cx->runtime->atomState.nullAtom); |
|
|
jsval v; |
|
|
if (!OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_STRING, &v)) |
|
|
return NULL; |
|
|
JS_ASSERT(JSVAL_IS_STRING(v)); |
|
|
return JSVAL_TO_STRING(v); |
|
382 |
} |
} |
383 |
|
|
384 |
JSObject* FASTCALL |
JSObject* FASTCALL |
385 |
js_Arguments(JSContext* cx) |
js_NewNullClosure(JSContext* cx, JSObject* funobj, JSObject* proto, JSObject* parent) |
386 |
{ |
{ |
387 |
return NULL; |
JS_ASSERT(HAS_FUNCTION_CLASS(funobj)); |
388 |
|
JS_ASSERT(HAS_FUNCTION_CLASS(proto)); |
389 |
|
JS_ASSERT(JS_ON_TRACE(cx)); |
390 |
|
|
391 |
|
JSFunction *fun = (JSFunction*) funobj; |
392 |
|
JS_ASSERT(GET_FUNCTION_PRIVATE(cx, funobj) == fun); |
393 |
|
|
394 |
|
JSObject* closure = (JSObject*) js_NewGCThing(cx, GCX_OBJECT, sizeof(JSObject)); |
395 |
|
if (!closure) |
396 |
|
return NULL; |
397 |
|
|
398 |
|
js_HoldScope(OBJ_SCOPE(proto)); |
399 |
|
closure->map = proto->map; |
400 |
|
closure->classword = jsuword(&js_FunctionClass); |
401 |
|
closure->fslots[JSSLOT_PROTO] = OBJECT_TO_JSVAL(proto); |
402 |
|
closure->fslots[JSSLOT_PARENT] = OBJECT_TO_JSVAL(parent); |
403 |
|
closure->fslots[JSSLOT_PRIVATE] = PRIVATE_TO_JSVAL(fun); |
404 |
|
for (unsigned i = JSSLOT_PRIVATE + 1; i != JS_INITIAL_NSLOTS; ++i) |
405 |
|
closure->fslots[i] = JSVAL_VOID; |
406 |
|
closure->dslots = NULL; |
407 |
|
return closure; |
408 |
} |
} |
409 |
|
|
410 |
#define BUILTIN1 JS_DEFINE_CALLINFO_1 |
#define BUILTIN1 JS_DEFINE_CALLINFO_1 |