1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=8 sw=4 et tw=78:
3 : *
4 : * ***** BEGIN LICENSE BLOCK *****
5 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 : *
7 : * The contents of this file are subject to the Mozilla Public License Version
8 : * 1.1 (the "License"); you may not use this file except in compliance with
9 : * the License. You may obtain a copy of the License at
10 : * http://www.mozilla.org/MPL/
11 : *
12 : * Software distributed under the License is distributed on an "AS IS" basis,
13 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 : * for the specific language governing rights and limitations under the
15 : * License.
16 : *
17 : * The Original Code is Mozilla Communicator client code, released
18 : * March 31, 1998.
19 : *
20 : * The Initial Developer of the Original Code is
21 : * Netscape Communications Corporation.
22 : * Portions created by the Initial Developer are Copyright (C) 1998
23 : * the Initial Developer. All Rights Reserved.
24 : *
25 : * Contributor(s):
26 : *
27 : * Alternatively, the contents of this file may be used under the terms of
28 : * either of the GNU General Public License Version 2 or later (the "GPL"),
29 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 : * in which case the provisions of the GPL or the LGPL are applicable instead
31 : * of those above. If you wish to allow use of your version of this file only
32 : * under the terms of either the GPL or the LGPL, and not to allow others to
33 : * use your version of this file under the terms of the MPL, indicate your
34 : * decision by deleting the provisions above and replace them with the notice
35 : * and other provisions required by the GPL or the LGPL. If you do not delete
36 : * the provisions above, a recipient may use your version of this file under
37 : * the terms of any one of the MPL, the GPL or the LGPL.
38 : *
39 : * ***** END LICENSE BLOCK ***** */
40 :
41 : /*
42 : * JavaScript API.
43 : */
44 : #include <ctype.h>
45 : #include <stdarg.h>
46 : #include <stdlib.h>
47 : #include <string.h>
48 : #include <sys/stat.h>
49 : #include "jstypes.h"
50 : #include "jsutil.h"
51 : #include "jsclist.h"
52 : #include "jsdhash.h"
53 : #include "jsprf.h"
54 : #include "jsapi.h"
55 : #include "jsarray.h"
56 : #include "jsatom.h"
57 : #include "jsbool.h"
58 : #include "jsclone.h"
59 : #include "jscntxt.h"
60 : #include "jsversion.h"
61 : #include "jsdate.h"
62 : #include "jsdtoa.h"
63 : #include "jsexn.h"
64 : #include "jsfun.h"
65 : #include "jsgc.h"
66 : #include "jsgcmark.h"
67 : #include "jsinterp.h"
68 : #include "jsiter.h"
69 : #include "jslock.h"
70 : #include "jsmath.h"
71 : #include "jsnativestack.h"
72 : #include "jsnum.h"
73 : #include "json.h"
74 : #include "jsobj.h"
75 : #include "jsopcode.h"
76 : #include "jsprobes.h"
77 : #include "jsproxy.h"
78 : #include "jsscope.h"
79 : #include "jsscript.h"
80 : #include "jsstr.h"
81 : #include "prmjtime.h"
82 : #include "jsweakmap.h"
83 : #include "jswrapper.h"
84 : #include "jstypedarray.h"
85 :
86 : #include "ds/LifoAlloc.h"
87 : #include "builtin/MapObject.h"
88 : #include "builtin/RegExp.h"
89 : #include "frontend/BytecodeCompiler.h"
90 : #include "frontend/BytecodeEmitter.h"
91 : #include "gc/Memory.h"
92 : #include "js/MemoryMetrics.h"
93 : #include "mozilla/Util.h"
94 : #include "yarr/BumpPointerAllocator.h"
95 : #include "vm/MethodGuard.h"
96 :
97 : #include "jsatominlines.h"
98 : #include "jsinferinlines.h"
99 : #include "jsobjinlines.h"
100 : #include "jsscopeinlines.h"
101 : #include "jsscriptinlines.h"
102 :
103 : #include "vm/RegExpObject-inl.h"
104 : #include "vm/RegExpStatics-inl.h"
105 : #include "vm/Stack-inl.h"
106 : #include "vm/String-inl.h"
107 : #include "vm/StringBuffer-inl.h"
108 :
109 : #if ENABLE_YARR_JIT
110 : #include "assembler/jit/ExecutableAllocator.h"
111 : #include "methodjit/Logging.h"
112 : #endif
113 :
114 : #if JS_HAS_XML_SUPPORT
115 : #include "jsxml.h"
116 : #endif
117 :
118 : using namespace js;
119 : using namespace js::gc;
120 : using namespace js::types;
121 :
122 : /*
123 : * This class is a version-establising barrier at the head of a VM entry or
124 : * re-entry. It ensures that:
125 : *
126 : * - |newVersion| is the starting (default) version used for the context.
127 : * - The starting version state is not an override.
128 : * - Overrides in the VM session are not propagated to the caller.
129 : */
130 : class AutoVersionAPI
131 : {
132 : JSContext * const cx;
133 : JSVersion oldDefaultVersion;
134 : bool oldHasVersionOverride;
135 : JSVersion oldVersionOverride;
136 : #ifdef DEBUG
137 : unsigned oldCompileOptions;
138 : #endif
139 : JSVersion newVersion;
140 :
141 : public:
142 23786 : explicit AutoVersionAPI(JSContext *cx, JSVersion newVersion)
143 : : cx(cx),
144 23786 : oldDefaultVersion(cx->getDefaultVersion()),
145 23786 : oldHasVersionOverride(cx->isVersionOverridden()),
146 : oldVersionOverride(oldHasVersionOverride ? cx->findVersion() : JSVERSION_UNKNOWN)
147 : #ifdef DEBUG
148 71358 : , oldCompileOptions(cx->getCompileOptions())
149 : #endif
150 : {
151 23786 : this->newVersion = newVersion;
152 23786 : cx->clearVersionOverride();
153 23786 : cx->setDefaultVersion(newVersion);
154 23786 : }
155 :
156 23786 : ~AutoVersionAPI() {
157 23786 : cx->setDefaultVersion(oldDefaultVersion);
158 23786 : if (oldHasVersionOverride)
159 1 : cx->overrideVersion(oldVersionOverride);
160 : else
161 23785 : cx->clearVersionOverride();
162 23786 : JS_ASSERT(oldCompileOptions == cx->getCompileOptions());
163 23786 : }
164 :
165 : /* The version that this scoped-entity establishes. */
166 46 : JSVersion version() const { return newVersion; }
167 : };
168 :
169 : #ifdef HAVE_VA_LIST_AS_ARRAY
170 : #define JS_ADDRESSOF_VA_LIST(ap) ((va_list *)(ap))
171 : #else
172 : #define JS_ADDRESSOF_VA_LIST(ap) (&(ap))
173 : #endif
174 :
175 : #ifdef JS_USE_JSID_STRUCT_TYPES
176 : jsid JS_DEFAULT_XML_NAMESPACE_ID = { size_t(JSID_TYPE_DEFAULT_XML_NAMESPACE) };
177 : jsid JSID_VOID = { size_t(JSID_TYPE_VOID) };
178 : jsid JSID_EMPTY = { size_t(JSID_TYPE_OBJECT) };
179 : #endif
180 :
181 19870 : const jsval JSVAL_NULL = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_NULL, 0));
182 19870 : const jsval JSVAL_ZERO = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_INT32, 0));
183 19870 : const jsval JSVAL_ONE = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_INT32, 1));
184 19870 : const jsval JSVAL_FALSE = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_BOOLEAN, JS_FALSE));
185 19870 : const jsval JSVAL_TRUE = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_BOOLEAN, JS_TRUE));
186 19870 : const jsval JSVAL_VOID = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_UNDEFINED, 0));
187 :
188 : /* Make sure that jschar is two bytes unsigned integer */
189 : JS_STATIC_ASSERT((jschar)-1 > 0);
190 : JS_STATIC_ASSERT(sizeof(jschar) == 2);
191 :
192 : JS_PUBLIC_API(int64_t)
193 3316 : JS_Now()
194 : {
195 3316 : return PRMJ_Now();
196 : }
197 :
198 : JS_PUBLIC_API(jsval)
199 1 : JS_GetNaNValue(JSContext *cx)
200 : {
201 1 : return cx->runtime->NaNValue;
202 : }
203 :
204 : JS_PUBLIC_API(jsval)
205 0 : JS_GetNegativeInfinityValue(JSContext *cx)
206 : {
207 0 : return cx->runtime->negativeInfinityValue;
208 : }
209 :
210 : JS_PUBLIC_API(jsval)
211 0 : JS_GetPositiveInfinityValue(JSContext *cx)
212 : {
213 0 : return cx->runtime->positiveInfinityValue;
214 : }
215 :
216 : JS_PUBLIC_API(jsval)
217 8874 : JS_GetEmptyStringValue(JSContext *cx)
218 : {
219 8874 : return STRING_TO_JSVAL(cx->runtime->emptyString);
220 : }
221 :
222 : JS_PUBLIC_API(JSString *)
223 0 : JS_GetEmptyString(JSRuntime *rt)
224 : {
225 0 : JS_ASSERT(rt->hasContexts());
226 0 : return rt->emptyString;
227 : }
228 :
229 : static JSBool
230 0 : TryArgumentFormatter(JSContext *cx, const char **formatp, JSBool fromJS, jsval **vpp, va_list *app)
231 : {
232 : const char *format;
233 : JSArgumentFormatMap *map;
234 :
235 0 : format = *formatp;
236 0 : for (map = cx->argumentFormatMap; map; map = map->next) {
237 0 : if (!strncmp(format, map->format, map->length)) {
238 0 : *formatp = format + map->length;
239 0 : return map->formatter(cx, format, fromJS, vpp, app);
240 : }
241 : }
242 0 : JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_CHAR, format);
243 0 : return JS_FALSE;
244 : }
245 :
246 : static void
247 1008978534 : AssertNoGC(JSRuntime *rt)
248 : {
249 1008978534 : JS_ASSERT(!rt->gcRunning);
250 1008978534 : }
251 :
252 : static void
253 1008973742 : AssertNoGC(JSContext *cx)
254 : {
255 1008973742 : AssertNoGC(cx->runtime);
256 1008973742 : }
257 :
258 : static void
259 2419682 : AssertNoGCOrFlatString(JSContext *cx, JSString *str)
260 : {
261 : /*
262 : * We allow some functions to be called during a GC as long as the argument
263 : * is a flat string, since that will not cause allocation.
264 : */
265 2419682 : JS_ASSERT_IF(cx->runtime->gcRunning, str->isFlat());
266 2419682 : }
267 :
268 : JS_PUBLIC_API(JSBool)
269 1871 : JS_ConvertArguments(JSContext *cx, unsigned argc, jsval *argv, const char *format, ...)
270 : {
271 : va_list ap;
272 : JSBool ok;
273 :
274 1871 : AssertNoGC(cx);
275 :
276 1871 : va_start(ap, format);
277 1871 : ok = JS_ConvertArgumentsVA(cx, argc, argv, format, ap);
278 1871 : va_end(ap);
279 1871 : return ok;
280 : }
281 :
282 : JS_PUBLIC_API(JSBool)
283 1871 : JS_ConvertArgumentsVA(JSContext *cx, unsigned argc, jsval *argv, const char *format, va_list ap)
284 : {
285 : jsval *sp;
286 : JSBool required;
287 : char c;
288 : JSFunction *fun;
289 : double d;
290 : JSString *str;
291 : JSObject *obj;
292 :
293 1871 : AssertNoGC(cx);
294 3742 : CHECK_REQUEST(cx);
295 1871 : assertSameCompartment(cx, JSValueArray(argv - 2, argc + 2));
296 1871 : sp = argv;
297 1871 : required = JS_TRUE;
298 9680 : while ((c = *format++) != '\0') {
299 6233 : if (isspace(c))
300 2023 : continue;
301 4210 : if (c == '/') {
302 1835 : required = JS_FALSE;
303 1835 : continue;
304 : }
305 2375 : if (sp == argv + argc) {
306 295 : if (required) {
307 0 : fun = js_ValueToFunction(cx, &argv[-2], 0);
308 0 : if (fun) {
309 : char numBuf[12];
310 0 : JS_snprintf(numBuf, sizeof numBuf, "%u", argc);
311 0 : JSAutoByteString funNameBytes;
312 0 : if (const char *name = GetFunctionNameBytes(cx, fun, &funNameBytes)) {
313 : JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_MORE_ARGS_NEEDED,
314 0 : name, numBuf, (argc == 1) ? "" : "s");
315 : }
316 : }
317 0 : return JS_FALSE;
318 : }
319 295 : break;
320 : }
321 2080 : switch (c) {
322 : case 'b':
323 65 : *va_arg(ap, JSBool *) = js_ValueToBoolean(*sp);
324 65 : break;
325 : case 'c':
326 0 : if (!JS_ValueToUint16(cx, *sp, va_arg(ap, uint16_t *)))
327 0 : return JS_FALSE;
328 0 : break;
329 : case 'i':
330 1402 : if (!JS_ValueToECMAInt32(cx, *sp, va_arg(ap, int32_t *)))
331 0 : return JS_FALSE;
332 1402 : break;
333 : case 'u':
334 9 : if (!JS_ValueToECMAUint32(cx, *sp, va_arg(ap, uint32_t *)))
335 0 : return JS_FALSE;
336 9 : break;
337 : case 'j':
338 0 : if (!JS_ValueToInt32(cx, *sp, va_arg(ap, int32_t *)))
339 0 : return JS_FALSE;
340 0 : break;
341 : case 'd':
342 0 : if (!JS_ValueToNumber(cx, *sp, va_arg(ap, double *)))
343 0 : return JS_FALSE;
344 0 : break;
345 : case 'I':
346 0 : if (!JS_ValueToNumber(cx, *sp, &d))
347 0 : return JS_FALSE;
348 0 : *va_arg(ap, double *) = js_DoubleToInteger(d);
349 0 : break;
350 : case 'S':
351 : case 'W':
352 306 : str = ToString(cx, *sp);
353 306 : if (!str)
354 0 : return JS_FALSE;
355 306 : *sp = STRING_TO_JSVAL(str);
356 306 : if (c == 'W') {
357 0 : JSFixedString *fixed = str->ensureFixed(cx);
358 0 : if (!fixed)
359 0 : return JS_FALSE;
360 0 : *va_arg(ap, const jschar **) = fixed->chars();
361 : } else {
362 306 : *va_arg(ap, JSString **) = str;
363 : }
364 306 : break;
365 : case 'o':
366 99 : if (!js_ValueToObjectOrNull(cx, *sp, &obj))
367 0 : return JS_FALSE;
368 99 : *sp = OBJECT_TO_JSVAL(obj);
369 99 : *va_arg(ap, JSObject **) = obj;
370 99 : break;
371 : case 'f':
372 0 : obj = js_ValueToFunction(cx, sp, 0);
373 0 : if (!obj)
374 0 : return JS_FALSE;
375 0 : *sp = OBJECT_TO_JSVAL(obj);
376 0 : *va_arg(ap, JSFunction **) = obj->toFunction();
377 0 : break;
378 : case 'v':
379 199 : *va_arg(ap, jsval *) = *sp;
380 199 : break;
381 : case '*':
382 0 : break;
383 : default:
384 0 : format--;
385 0 : if (!TryArgumentFormatter(cx, &format, JS_TRUE, &sp,
386 0 : JS_ADDRESSOF_VA_LIST(ap))) {
387 0 : return JS_FALSE;
388 : }
389 : /* NB: the formatter already updated sp, so we continue here. */
390 0 : continue;
391 : }
392 2080 : sp++;
393 : }
394 1871 : return JS_TRUE;
395 : }
396 :
397 : JS_PUBLIC_API(JSBool)
398 0 : JS_AddArgumentFormatter(JSContext *cx, const char *format, JSArgumentFormatter formatter)
399 : {
400 : size_t length;
401 : JSArgumentFormatMap **mpp, *map;
402 :
403 0 : length = strlen(format);
404 0 : mpp = &cx->argumentFormatMap;
405 0 : while ((map = *mpp) != NULL) {
406 : /* Insert before any shorter string to match before prefixes. */
407 0 : if (map->length < length)
408 0 : break;
409 0 : if (map->length == length && !strcmp(map->format, format))
410 0 : goto out;
411 0 : mpp = &map->next;
412 : }
413 0 : map = (JSArgumentFormatMap *) cx->malloc_(sizeof *map);
414 0 : if (!map)
415 0 : return JS_FALSE;
416 0 : map->format = format;
417 0 : map->length = length;
418 0 : map->next = *mpp;
419 0 : *mpp = map;
420 : out:
421 0 : map->formatter = formatter;
422 0 : return JS_TRUE;
423 : }
424 :
425 : JS_PUBLIC_API(void)
426 0 : JS_RemoveArgumentFormatter(JSContext *cx, const char *format)
427 : {
428 : size_t length;
429 : JSArgumentFormatMap **mpp, *map;
430 :
431 0 : length = strlen(format);
432 0 : mpp = &cx->argumentFormatMap;
433 0 : while ((map = *mpp) != NULL) {
434 0 : if (map->length == length && !strcmp(map->format, format)) {
435 0 : *mpp = map->next;
436 0 : cx->free_(map);
437 0 : return;
438 : }
439 0 : mpp = &map->next;
440 : }
441 : }
442 :
443 : JS_PUBLIC_API(JSBool)
444 36 : JS_ConvertValue(JSContext *cx, jsval v, JSType type, jsval *vp)
445 : {
446 : JSBool ok;
447 : JSObject *obj;
448 : JSString *str;
449 : double d;
450 :
451 36 : AssertNoGC(cx);
452 72 : CHECK_REQUEST(cx);
453 36 : assertSameCompartment(cx, v);
454 36 : switch (type) {
455 : case JSTYPE_VOID:
456 0 : *vp = JSVAL_VOID;
457 0 : ok = JS_TRUE;
458 0 : break;
459 : case JSTYPE_OBJECT:
460 0 : ok = js_ValueToObjectOrNull(cx, v, &obj);
461 0 : if (ok)
462 0 : *vp = OBJECT_TO_JSVAL(obj);
463 0 : break;
464 : case JSTYPE_FUNCTION:
465 0 : *vp = v;
466 0 : obj = js_ValueToFunction(cx, vp, JSV2F_SEARCH_STACK);
467 0 : ok = (obj != NULL);
468 0 : break;
469 : case JSTYPE_STRING:
470 36 : str = ToString(cx, v);
471 36 : ok = (str != NULL);
472 36 : if (ok)
473 36 : *vp = STRING_TO_JSVAL(str);
474 36 : break;
475 : case JSTYPE_NUMBER:
476 0 : ok = JS_ValueToNumber(cx, v, &d);
477 0 : if (ok)
478 0 : *vp = DOUBLE_TO_JSVAL(d);
479 0 : break;
480 : case JSTYPE_BOOLEAN:
481 0 : *vp = BOOLEAN_TO_JSVAL(js_ValueToBoolean(v));
482 0 : return JS_TRUE;
483 : default: {
484 : char numBuf[12];
485 0 : JS_snprintf(numBuf, sizeof numBuf, "%d", (int)type);
486 0 : JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_TYPE, numBuf);
487 0 : ok = JS_FALSE;
488 0 : break;
489 : }
490 : }
491 36 : return ok;
492 : }
493 :
494 : JS_PUBLIC_API(JSBool)
495 92099 : JS_ValueToObject(JSContext *cx, jsval v, JSObject **objp)
496 : {
497 92099 : AssertNoGC(cx);
498 184198 : CHECK_REQUEST(cx);
499 92099 : assertSameCompartment(cx, v);
500 92099 : return js_ValueToObjectOrNull(cx, v, objp);
501 : }
502 :
503 : JS_PUBLIC_API(JSFunction *)
504 2360 : JS_ValueToFunction(JSContext *cx, jsval v)
505 : {
506 2360 : AssertNoGC(cx);
507 4720 : CHECK_REQUEST(cx);
508 2360 : assertSameCompartment(cx, v);
509 2360 : return js_ValueToFunction(cx, &v, JSV2F_SEARCH_STACK);
510 : }
511 :
512 : JS_PUBLIC_API(JSFunction *)
513 0 : JS_ValueToConstructor(JSContext *cx, jsval v)
514 : {
515 0 : AssertNoGC(cx);
516 0 : CHECK_REQUEST(cx);
517 0 : assertSameCompartment(cx, v);
518 0 : return js_ValueToFunction(cx, &v, JSV2F_SEARCH_STACK);
519 : }
520 :
521 : JS_PUBLIC_API(JSString *)
522 3031679 : JS_ValueToString(JSContext *cx, jsval v)
523 : {
524 3031679 : AssertNoGC(cx);
525 6063358 : CHECK_REQUEST(cx);
526 3031679 : assertSameCompartment(cx, v);
527 3031679 : return ToString(cx, v);
528 : }
529 :
530 : JS_PUBLIC_API(JSString *)
531 1032 : JS_ValueToSource(JSContext *cx, jsval v)
532 : {
533 1032 : AssertNoGC(cx);
534 2064 : CHECK_REQUEST(cx);
535 1032 : assertSameCompartment(cx, v);
536 1032 : return js_ValueToSource(cx, v);
537 : }
538 :
539 : JS_PUBLIC_API(JSBool)
540 23516 : JS_ValueToNumber(JSContext *cx, jsval v, double *dp)
541 : {
542 23516 : AssertNoGC(cx);
543 47032 : CHECK_REQUEST(cx);
544 23516 : assertSameCompartment(cx, v);
545 :
546 47032 : AutoValueRooter tvr(cx, v);
547 23516 : return ToNumber(cx, tvr.value(), dp);
548 : }
549 :
550 : JS_PUBLIC_API(JSBool)
551 30 : JS_DoubleIsInt32(double d, int32_t *ip)
552 : {
553 30 : return JSDOUBLE_IS_INT32(d, ip);
554 : }
555 :
556 : JS_PUBLIC_API(int32_t)
557 0 : JS_DoubleToInt32(double d)
558 : {
559 0 : return js_DoubleToECMAInt32(d);
560 : }
561 :
562 : JS_PUBLIC_API(uint32_t)
563 0 : JS_DoubleToUint32(double d)
564 : {
565 0 : return js_DoubleToECMAUint32(d);
566 : }
567 :
568 : JS_PUBLIC_API(JSBool)
569 53418 : JS_ValueToECMAInt32(JSContext *cx, jsval v, int32_t *ip)
570 : {
571 53418 : AssertNoGC(cx);
572 106836 : CHECK_REQUEST(cx);
573 53418 : assertSameCompartment(cx, v);
574 :
575 106836 : AutoValueRooter tvr(cx, v);
576 53418 : return ToInt32(cx, tvr.value(), (int32_t *)ip);
577 : }
578 :
579 : JS_PUBLIC_API(JSBool)
580 5146284 : JS_ValueToECMAUint32(JSContext *cx, jsval v, uint32_t *ip)
581 : {
582 5146284 : AssertNoGC(cx);
583 10292568 : CHECK_REQUEST(cx);
584 5146284 : assertSameCompartment(cx, v);
585 :
586 10292568 : AutoValueRooter tvr(cx, v);
587 5146284 : return ToUint32(cx, tvr.value(), (uint32_t *)ip);
588 : }
589 :
590 : JS_PUBLIC_API(JSBool)
591 405 : JS_ValueToInt32(JSContext *cx, jsval v, int32_t *ip)
592 : {
593 405 : AssertNoGC(cx);
594 810 : CHECK_REQUEST(cx);
595 405 : assertSameCompartment(cx, v);
596 :
597 810 : AutoValueRooter tvr(cx, v);
598 405 : return NonstandardToInt32(cx, tvr.value(), (int32_t *)ip);
599 : }
600 :
601 : JS_PUBLIC_API(JSBool)
602 0 : JS_ValueToUint16(JSContext *cx, jsval v, uint16_t *ip)
603 : {
604 0 : AssertNoGC(cx);
605 0 : CHECK_REQUEST(cx);
606 0 : assertSameCompartment(cx, v);
607 :
608 0 : AutoValueRooter tvr(cx, v);
609 0 : return ValueToUint16(cx, tvr.value(), (uint16_t *)ip);
610 : }
611 :
612 : JS_PUBLIC_API(JSBool)
613 577091 : JS_ValueToBoolean(JSContext *cx, jsval v, JSBool *bp)
614 : {
615 577091 : AssertNoGC(cx);
616 1154182 : CHECK_REQUEST(cx);
617 577091 : assertSameCompartment(cx, v);
618 577091 : *bp = js_ValueToBoolean(v);
619 577091 : return JS_TRUE;
620 : }
621 :
622 : JS_PUBLIC_API(JSType)
623 7243404 : JS_TypeOfValue(JSContext *cx, jsval v)
624 : {
625 7243404 : AssertNoGC(cx);
626 14486808 : CHECK_REQUEST(cx);
627 7243404 : assertSameCompartment(cx, v);
628 7243404 : return TypeOfValue(cx, v);
629 : }
630 :
631 : JS_PUBLIC_API(const char *)
632 0 : JS_GetTypeName(JSContext *cx, JSType type)
633 : {
634 0 : if ((unsigned)type >= (unsigned)JSTYPE_LIMIT)
635 0 : return NULL;
636 0 : return JS_TYPE_STR(type);
637 : }
638 :
639 : JS_PUBLIC_API(JSBool)
640 1 : JS_StrictlyEqual(JSContext *cx, jsval v1, jsval v2, JSBool *equal)
641 : {
642 1 : AssertNoGC(cx);
643 2 : CHECK_REQUEST(cx);
644 1 : assertSameCompartment(cx, v1, v2);
645 : bool eq;
646 1 : if (!StrictlyEqual(cx, v1, v2, &eq))
647 0 : return false;
648 1 : *equal = eq;
649 1 : return true;
650 : }
651 :
652 : JS_PUBLIC_API(JSBool)
653 77 : JS_LooselyEqual(JSContext *cx, jsval v1, jsval v2, JSBool *equal)
654 : {
655 77 : AssertNoGC(cx);
656 154 : CHECK_REQUEST(cx);
657 77 : assertSameCompartment(cx, v1, v2);
658 : bool eq;
659 77 : if (!LooselyEqual(cx, v1, v2, &eq))
660 0 : return false;
661 77 : *equal = eq;
662 77 : return true;
663 : }
664 :
665 : JS_PUBLIC_API(JSBool)
666 4106419 : JS_SameValue(JSContext *cx, jsval v1, jsval v2, JSBool *same)
667 : {
668 4106419 : AssertNoGC(cx);
669 8212838 : CHECK_REQUEST(cx);
670 4106419 : assertSameCompartment(cx, v1, v2);
671 : bool s;
672 4106419 : if (!SameValue(cx, v1, v2, &s))
673 0 : return false;
674 4106419 : *same = s;
675 4106419 : return true;
676 : }
677 :
678 : JS_PUBLIC_API(JSBool)
679 40 : JS_IsBuiltinEvalFunction(JSFunction *fun)
680 : {
681 40 : return IsAnyBuiltinEval(fun);
682 : }
683 :
684 : JS_PUBLIC_API(JSBool)
685 40 : JS_IsBuiltinFunctionConstructor(JSFunction *fun)
686 : {
687 40 : return IsBuiltinFunctionConstructor(fun);
688 : }
689 :
690 : /************************************************************************/
691 :
692 : /*
693 : * Has a new runtime ever been created? This flag is used to detect unsafe
694 : * changes to js_CStringsAreUTF8 after a runtime has been created, and to
695 : * control things that should happen only once across all runtimes.
696 : */
697 : static JSBool js_NewRuntimeWasCalled = JS_FALSE;
698 :
699 : static const JSSecurityCallbacks NullSecurityCallbacks = { };
700 :
701 19910 : JSRuntime::JSRuntime()
702 : : atomsCompartment(NULL),
703 : #ifdef JS_THREADSAFE
704 : ownerThread_(NULL),
705 : #endif
706 : tempLifoAlloc(TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
707 : execAlloc_(NULL),
708 : bumpAlloc_(NULL),
709 : nativeStackBase(0),
710 : nativeStackQuota(0),
711 : interpreterFrames(NULL),
712 : cxCallback(NULL),
713 : compartmentCallback(NULL),
714 : activityCallback(NULL),
715 : activityCallbackArg(NULL),
716 : #ifdef JS_THREADSAFE
717 : suspendCount(0),
718 : requestDepth(0),
719 : # ifdef DEBUG
720 : checkRequestDepth(0),
721 : # endif
722 : #endif
723 : gcSystemAvailableChunkListHead(NULL),
724 : gcUserAvailableChunkListHead(NULL),
725 : gcKeepAtoms(0),
726 : gcBytes(0),
727 : gcMaxBytes(0),
728 : gcMaxMallocBytes(0),
729 : gcNumArenasFreeCommitted(0),
730 : gcVerifyData(NULL),
731 : gcChunkAllocationSinceLastGC(false),
732 : gcNextFullGCTime(0),
733 : gcJitReleaseTime(0),
734 : gcMode(JSGC_MODE_GLOBAL),
735 : gcIsNeeded(0),
736 : gcWeakMapList(NULL),
737 : gcStats(thisFromCtor()),
738 : gcNumber(0),
739 : gcStartNumber(0),
740 : gcTriggerReason(gcreason::NO_REASON),
741 : gcTriggerCompartment(NULL),
742 : gcCurrentCompartment(NULL),
743 : gcCheckCompartment(NULL),
744 : gcIncrementalState(gc::NO_INCREMENTAL),
745 : gcCompartmentCreated(false),
746 : gcLastMarkSlice(false),
747 : gcInterFrameGC(0),
748 : gcSliceBudget(SliceBudget::Unlimited),
749 : gcIncrementalEnabled(true),
750 : gcIncrementalCompartment(NULL),
751 : gcPoke(false),
752 : gcRunning(false),
753 : #ifdef JS_GC_ZEAL
754 : gcZeal_(0),
755 : gcZealFrequency(0),
756 : gcNextScheduled(0),
757 : gcDebugCompartmentGC(false),
758 : gcDeterministicOnly(false),
759 : #endif
760 : gcCallback(NULL),
761 : gcSliceCallback(NULL),
762 : gcFinalizeCallback(NULL),
763 : gcMallocBytes(0),
764 : gcBlackRootsTraceOp(NULL),
765 : gcBlackRootsData(NULL),
766 : gcGrayRootsTraceOp(NULL),
767 : gcGrayRootsData(NULL),
768 : autoGCRooters(NULL),
769 : scriptPCCounters(NULL),
770 : NaNValue(UndefinedValue()),
771 : negativeInfinityValue(UndefinedValue()),
772 : positiveInfinityValue(UndefinedValue()),
773 : emptyString(NULL),
774 : debugMode(false),
775 : profilingScripts(false),
776 : hadOutOfMemory(false),
777 : data(NULL),
778 : #ifdef JS_THREADSAFE
779 : gcLock(NULL),
780 : gcHelperThread(thisFromCtor()),
781 : #endif
782 : debuggerMutations(0),
783 : securityCallbacks(const_cast<JSSecurityCallbacks *>(&NullSecurityCallbacks)),
784 : destroyPrincipals(NULL),
785 : structuredCloneCallbacks(NULL),
786 : telemetryCallback(NULL),
787 : propertyRemovals(0),
788 : thousandsSeparator(0),
789 : decimalSeparator(0),
790 : numGrouping(0),
791 : anynameObject(NULL),
792 : functionNamespaceObject(NULL),
793 : waiveGCQuota(false),
794 : dtoaState(NULL),
795 : pendingProxyOperation(NULL),
796 : trustedPrincipals_(NULL),
797 : wrapObjectCallback(TransparentObjectWrapper),
798 : preWrapObjectCallback(NULL),
799 : preserveWrapperCallback(NULL),
800 : #ifdef DEBUG
801 : noGCOrAllocationCheck(0),
802 : #endif
803 : inOOMReport(0),
804 19910 : jitHardening(false)
805 : {
806 : /* Initialize infallibly first, so we can goto bad and JS_DestroyRuntime. */
807 19910 : JS_INIT_CLIST(&contextList);
808 19910 : JS_INIT_CLIST(&debuggerList);
809 :
810 19910 : PodZero(&debugHooks);
811 19910 : PodZero(&atomState);
812 :
813 : #if JS_STACK_GROWTH_DIRECTION > 0
814 : nativeStackLimit = UINTPTR_MAX;
815 : #endif
816 19910 : }
817 :
818 : bool
819 19910 : JSRuntime::init(uint32_t maxbytes)
820 : {
821 : #ifdef JS_THREADSAFE
822 19910 : ownerThread_ = PR_GetCurrentThread();
823 : #endif
824 :
825 : #ifdef JS_METHODJIT_SPEW
826 19910 : JMCheckLogging();
827 : #endif
828 :
829 19910 : if (!js_InitGC(this, maxbytes))
830 0 : return false;
831 :
832 19910 : if (!gcMarker.init())
833 0 : return false;
834 :
835 19910 : const char *size = getenv("JSGC_MARK_STACK_LIMIT");
836 19910 : if (size)
837 0 : SetMarkStackLimit(this, atoi(size));
838 :
839 59730 : if (!(atomsCompartment = this->new_<JSCompartment>(this)) ||
840 19910 : !atomsCompartment->init(NULL) ||
841 19910 : !compartments.append(atomsCompartment)) {
842 0 : Foreground::delete_(atomsCompartment);
843 0 : return false;
844 : }
845 :
846 19910 : atomsCompartment->isSystemCompartment = true;
847 19910 : atomsCompartment->setGCLastBytes(8192, 8192, GC_NORMAL);
848 :
849 19910 : if (!js_InitAtomState(this))
850 0 : return false;
851 :
852 19910 : if (!InitRuntimeNumberState(this))
853 0 : return false;
854 :
855 19910 : dtoaState = js_NewDtoaState();
856 19910 : if (!dtoaState)
857 0 : return false;
858 :
859 19910 : if (!stackSpace.init())
860 0 : return false;
861 :
862 19910 : nativeStackBase = GetNativeStackBase();
863 19910 : return true;
864 : }
865 :
866 39816 : JSRuntime::~JSRuntime()
867 : {
868 19908 : JS_ASSERT(onOwnerThread());
869 :
870 19908 : delete_<JSC::ExecutableAllocator>(execAlloc_);
871 19908 : delete_<WTF::BumpPointerAllocator>(bumpAlloc_);
872 :
873 : #ifdef DEBUG
874 : /* Don't hurt everyone in leaky ol' Mozilla with a fatal JS_ASSERT! */
875 19908 : if (!JS_CLIST_IS_EMPTY(&contextList)) {
876 0 : unsigned cxcount = 0;
877 0 : for (ContextIter acx(this); !acx.done(); acx.next()) {
878 : fprintf(stderr,
879 : "JS API usage error: found live context at %p\n",
880 0 : (void *) acx.get());
881 0 : cxcount++;
882 : }
883 : fprintf(stderr,
884 : "JS API usage error: %u context%s left in runtime upon JS_DestroyRuntime.\n",
885 0 : cxcount, (cxcount == 1) ? "" : "s");
886 : }
887 : #endif
888 :
889 19908 : FinishRuntimeNumberState(this);
890 19908 : js_FinishAtomState(this);
891 :
892 19908 : if (dtoaState)
893 19908 : js_DestroyDtoaState(dtoaState);
894 :
895 19908 : js_FinishGC(this);
896 : #ifdef JS_THREADSAFE
897 19908 : if (gcLock)
898 19908 : PR_DestroyLock(gcLock);
899 : #endif
900 19908 : }
901 :
902 : #ifdef JS_THREADSAFE
903 : void
904 6 : JSRuntime::setOwnerThread()
905 : {
906 6 : JS_ASSERT(ownerThread_ == (void *)0xc1ea12); /* "clear" */
907 6 : JS_ASSERT(requestDepth == 0);
908 6 : ownerThread_ = PR_GetCurrentThread();
909 6 : nativeStackBase = GetNativeStackBase();
910 6 : if (nativeStackQuota)
911 6 : JS_SetNativeStackQuota(this, nativeStackQuota);
912 6 : }
913 :
914 : void
915 6 : JSRuntime::clearOwnerThread()
916 : {
917 6 : JS_ASSERT(onOwnerThread());
918 6 : JS_ASSERT(requestDepth == 0);
919 6 : ownerThread_ = (void *)0xc1ea12; /* "clear" */
920 6 : nativeStackBase = 0;
921 : #if JS_STACK_GROWTH_DIRECTION > 0
922 : nativeStackLimit = UINTPTR_MAX;
923 : #else
924 6 : nativeStackLimit = 0;
925 : #endif
926 6 : }
927 :
928 : JS_FRIEND_API(bool)
929 1087078385 : JSRuntime::onOwnerThread() const
930 : {
931 1087078385 : return ownerThread_ == PR_GetCurrentThread();
932 : }
933 : #endif /* JS_THREADSAFE */
934 :
935 : JS_PUBLIC_API(JSRuntime *)
936 19910 : JS_NewRuntime(uint32_t maxbytes)
937 : {
938 19910 : if (!js_NewRuntimeWasCalled) {
939 : #ifdef DEBUG
940 : /*
941 : * This code asserts that the numbers associated with the error names
942 : * in jsmsg.def are monotonically increasing. It uses values for the
943 : * error names enumerated in jscntxt.c. It's not a compile-time check
944 : * but it's better than nothing.
945 : */
946 19811 : int errorNumber = 0;
947 : #define MSG_DEF(name, number, count, exception, format) \
948 : JS_ASSERT(name == errorNumber++);
949 : #include "js.msg"
950 : #undef MSG_DEF
951 :
952 : #define MSG_DEF(name, number, count, exception, format) \
953 : JS_BEGIN_MACRO \
954 : unsigned numfmtspecs = 0; \
955 : const char *fmt; \
956 : for (fmt = format; *fmt != '\0'; fmt++) { \
957 : if (*fmt == '{' && isdigit(fmt[1])) \
958 : ++numfmtspecs; \
959 : } \
960 : JS_ASSERT(count == numfmtspecs); \
961 : JS_END_MACRO;
962 : #include "js.msg"
963 : #undef MSG_DEF
964 : #endif /* DEBUG */
965 :
966 19811 : InitMemorySubsystem();
967 :
968 19811 : js_NewRuntimeWasCalled = JS_TRUE;
969 : }
970 :
971 19910 : JSRuntime *rt = OffTheBooks::new_<JSRuntime>();
972 19910 : if (!rt)
973 0 : return NULL;
974 :
975 19910 : if (!rt->init(maxbytes)) {
976 0 : JS_DestroyRuntime(rt);
977 0 : return NULL;
978 : }
979 :
980 19910 : Probes::createRuntime(rt);
981 19910 : return rt;
982 : }
983 :
984 : JS_PUBLIC_API(void)
985 19908 : JS_DestroyRuntime(JSRuntime *rt)
986 : {
987 19908 : Probes::destroyRuntime(rt);
988 19908 : Foreground::delete_(rt);
989 19908 : }
990 :
991 : JS_PUBLIC_API(void)
992 19808 : JS_ShutDown(void)
993 : {
994 19808 : Probes::shutdown();
995 : PRMJ_NowShutdown();
996 19808 : }
997 :
998 : JS_PUBLIC_API(void *)
999 0 : JS_GetRuntimePrivate(JSRuntime *rt)
1000 : {
1001 0 : return rt->data;
1002 : }
1003 :
1004 : JS_PUBLIC_API(void)
1005 0 : JS_SetRuntimePrivate(JSRuntime *rt, void *data)
1006 : {
1007 0 : rt->data = data;
1008 0 : }
1009 :
1010 : #ifdef JS_THREADSAFE
1011 : static void
1012 4956489 : StartRequest(JSContext *cx)
1013 : {
1014 4956489 : JSRuntime *rt = cx->runtime;
1015 4956489 : JS_ASSERT(rt->onOwnerThread());
1016 :
1017 4956489 : if (rt->requestDepth) {
1018 4531941 : rt->requestDepth++;
1019 : } else {
1020 : /* Indicate that a request is running. */
1021 424548 : rt->requestDepth = 1;
1022 :
1023 424548 : if (rt->activityCallback)
1024 387342 : rt->activityCallback(rt->activityCallbackArg, true);
1025 : }
1026 4956489 : }
1027 :
1028 : static void
1029 4956489 : StopRequest(JSContext *cx)
1030 : {
1031 4956489 : JSRuntime *rt = cx->runtime;
1032 4956489 : JS_ASSERT(rt->onOwnerThread());
1033 4956489 : JS_ASSERT(rt->requestDepth != 0);
1034 4956489 : if (rt->requestDepth != 1) {
1035 4531941 : rt->requestDepth--;
1036 : } else {
1037 424548 : rt->conservativeGC.updateForRequestEnd(rt->suspendCount);
1038 424548 : rt->requestDepth = 0;
1039 :
1040 424548 : if (rt->activityCallback)
1041 387342 : rt->activityCallback(rt->activityCallbackArg, false);
1042 : }
1043 4956489 : }
1044 : #endif /* JS_THREADSAFE */
1045 :
1046 : JS_PUBLIC_API(void)
1047 4789002 : JS_BeginRequest(JSContext *cx)
1048 : {
1049 : #ifdef JS_THREADSAFE
1050 4789002 : cx->outstandingRequests++;
1051 4789002 : StartRequest(cx);
1052 : #endif
1053 4789002 : }
1054 :
1055 : JS_PUBLIC_API(void)
1056 4789002 : JS_EndRequest(JSContext *cx)
1057 : {
1058 : #ifdef JS_THREADSAFE
1059 4789002 : JS_ASSERT(cx->outstandingRequests != 0);
1060 4789002 : cx->outstandingRequests--;
1061 4789002 : StopRequest(cx);
1062 : #endif
1063 4789002 : }
1064 :
1065 : /* Yield to pending GC operations, regardless of request depth */
1066 : JS_PUBLIC_API(void)
1067 2010 : JS_YieldRequest(JSContext *cx)
1068 : {
1069 : #ifdef JS_THREADSAFE
1070 4020 : CHECK_REQUEST(cx);
1071 2010 : JS_ResumeRequest(cx, JS_SuspendRequest(cx));
1072 : #endif
1073 2010 : }
1074 :
1075 : JS_PUBLIC_API(unsigned)
1076 167487 : JS_SuspendRequest(JSContext *cx)
1077 : {
1078 : #ifdef JS_THREADSAFE
1079 167487 : JSRuntime *rt = cx->runtime;
1080 167487 : JS_ASSERT(rt->onOwnerThread());
1081 :
1082 167487 : unsigned saveDepth = rt->requestDepth;
1083 167487 : if (!saveDepth)
1084 0 : return 0;
1085 :
1086 167487 : rt->suspendCount++;
1087 167487 : rt->requestDepth = 1;
1088 167487 : StopRequest(cx);
1089 167487 : return saveDepth;
1090 : #else
1091 : return 0;
1092 : #endif
1093 : }
1094 :
1095 : JS_PUBLIC_API(void)
1096 167487 : JS_ResumeRequest(JSContext *cx, unsigned saveDepth)
1097 : {
1098 : #ifdef JS_THREADSAFE
1099 167487 : JSRuntime *rt = cx->runtime;
1100 167487 : JS_ASSERT(rt->onOwnerThread());
1101 167487 : if (saveDepth == 0)
1102 0 : return;
1103 167487 : JS_ASSERT(saveDepth >= 1);
1104 167487 : JS_ASSERT(!rt->requestDepth);
1105 167487 : JS_ASSERT(rt->suspendCount);
1106 167487 : StartRequest(cx);
1107 167487 : rt->requestDepth = saveDepth;
1108 167487 : rt->suspendCount--;
1109 : #endif
1110 : }
1111 :
1112 : JS_PUBLIC_API(JSBool)
1113 48 : JS_IsInRequest(JSRuntime *rt)
1114 : {
1115 : #ifdef JS_THREADSAFE
1116 48 : JS_ASSERT(rt->onOwnerThread());
1117 48 : return rt->requestDepth != 0;
1118 : #else
1119 : return false;
1120 : #endif
1121 : }
1122 :
1123 : JS_PUBLIC_API(JSBool)
1124 48 : JS_IsInSuspendedRequest(JSRuntime *rt)
1125 : {
1126 : #ifdef JS_THREADSAFE
1127 48 : JS_ASSERT(rt->onOwnerThread());
1128 48 : return rt->suspendCount != 0;
1129 : #else
1130 : return false;
1131 : #endif
1132 : }
1133 :
1134 : JS_PUBLIC_API(JSContextCallback)
1135 4182 : JS_SetContextCallback(JSRuntime *rt, JSContextCallback cxCallback)
1136 : {
1137 : JSContextCallback old;
1138 :
1139 4182 : old = rt->cxCallback;
1140 4182 : rt->cxCallback = cxCallback;
1141 4182 : return old;
1142 : }
1143 :
1144 : JS_PUBLIC_API(JSContext *)
1145 26231 : JS_NewContext(JSRuntime *rt, size_t stackChunkSize)
1146 : {
1147 26231 : return js_NewContext(rt, stackChunkSize);
1148 : }
1149 :
1150 : JS_PUBLIC_API(void)
1151 24233 : JS_DestroyContext(JSContext *cx)
1152 : {
1153 24233 : js_DestroyContext(cx, JSDCM_FORCE_GC);
1154 24233 : }
1155 :
1156 : JS_PUBLIC_API(void)
1157 1995 : JS_DestroyContextNoGC(JSContext *cx)
1158 : {
1159 1995 : js_DestroyContext(cx, JSDCM_NO_GC);
1160 1995 : }
1161 :
1162 : JS_PUBLIC_API(void)
1163 0 : JS_DestroyContextMaybeGC(JSContext *cx)
1164 : {
1165 0 : js_DestroyContext(cx, JSDCM_MAYBE_GC);
1166 0 : }
1167 :
1168 : JS_PUBLIC_API(void *)
1169 18432 : JS_GetContextPrivate(JSContext *cx)
1170 : {
1171 18432 : return cx->data;
1172 : }
1173 :
1174 : JS_PUBLIC_API(void)
1175 37421 : JS_SetContextPrivate(JSContext *cx, void *data)
1176 : {
1177 37421 : cx->data = data;
1178 37421 : }
1179 :
1180 : JS_PUBLIC_API(void *)
1181 32149526 : JS_GetSecondContextPrivate(JSContext *cx)
1182 : {
1183 32149526 : return cx->data2;
1184 : }
1185 :
1186 : JS_PUBLIC_API(void)
1187 15428 : JS_SetSecondContextPrivate(JSContext *cx, void *data)
1188 : {
1189 15428 : cx->data2 = data;
1190 15428 : }
1191 :
1192 : JS_PUBLIC_API(JSRuntime *)
1193 339940 : JS_GetRuntime(JSContext *cx)
1194 : {
1195 339940 : return cx->runtime;
1196 : }
1197 :
1198 : JS_PUBLIC_API(JSContext *)
1199 103148 : JS_ContextIterator(JSRuntime *rt, JSContext **iterp)
1200 : {
1201 103148 : JSContext *cx = *iterp;
1202 103148 : JSCList *next = cx ? cx->link.next : rt->contextList.next;
1203 103148 : cx = (next == &rt->contextList) ? NULL : JSContext::fromLinkField(next);
1204 103148 : *iterp = cx;
1205 103148 : return cx;
1206 : }
1207 :
1208 : JS_PUBLIC_API(JSVersion)
1209 721 : JS_GetVersion(JSContext *cx)
1210 : {
1211 721 : return VersionNumber(cx->findVersion());
1212 : }
1213 :
1214 : JS_PUBLIC_API(JSVersion)
1215 26037 : JS_SetVersion(JSContext *cx, JSVersion newVersion)
1216 : {
1217 26037 : JS_ASSERT(VersionIsKnown(newVersion));
1218 26037 : JS_ASSERT(!VersionHasFlags(newVersion));
1219 26037 : JSVersion newVersionNumber = newVersion;
1220 :
1221 : #ifdef DEBUG
1222 26037 : unsigned coptsBefore = cx->getCompileOptions();
1223 : #endif
1224 26037 : JSVersion oldVersion = cx->findVersion();
1225 26037 : JSVersion oldVersionNumber = VersionNumber(oldVersion);
1226 26037 : if (oldVersionNumber == newVersionNumber)
1227 1204 : return oldVersionNumber; /* No override actually occurs! */
1228 :
1229 : /* We no longer support 1.4 or below. */
1230 24833 : if (newVersionNumber != JSVERSION_DEFAULT && newVersionNumber <= JSVERSION_1_4)
1231 0 : return oldVersionNumber;
1232 :
1233 24833 : VersionCopyFlags(&newVersion, oldVersion);
1234 24833 : cx->maybeOverrideVersion(newVersion);
1235 24833 : JS_ASSERT(cx->getCompileOptions() == coptsBefore);
1236 24833 : return oldVersionNumber;
1237 : }
1238 :
1239 : static struct v2smap {
1240 : JSVersion version;
1241 : const char *string;
1242 : } v2smap[] = {
1243 : {JSVERSION_1_0, "1.0"},
1244 : {JSVERSION_1_1, "1.1"},
1245 : {JSVERSION_1_2, "1.2"},
1246 : {JSVERSION_1_3, "1.3"},
1247 : {JSVERSION_1_4, "1.4"},
1248 : {JSVERSION_ECMA_3, "ECMAv3"},
1249 : {JSVERSION_1_5, "1.5"},
1250 : {JSVERSION_1_6, "1.6"},
1251 : {JSVERSION_1_7, "1.7"},
1252 : {JSVERSION_1_8, "1.8"},
1253 : {JSVERSION_ECMA_5, "ECMAv5"},
1254 : {JSVERSION_DEFAULT, js_default_str},
1255 : {JSVERSION_UNKNOWN, NULL}, /* must be last, NULL is sentinel */
1256 : };
1257 :
1258 : JS_PUBLIC_API(const char *)
1259 0 : JS_VersionToString(JSVersion version)
1260 : {
1261 : int i;
1262 :
1263 0 : for (i = 0; v2smap[i].string; i++)
1264 0 : if (v2smap[i].version == version)
1265 0 : return v2smap[i].string;
1266 0 : return "unknown";
1267 : }
1268 :
1269 : JS_PUBLIC_API(JSVersion)
1270 243 : JS_StringToVersion(const char *string)
1271 : {
1272 : int i;
1273 :
1274 2673 : for (i = 0; v2smap[i].string; i++)
1275 2673 : if (strcmp(v2smap[i].string, string) == 0)
1276 243 : return v2smap[i].version;
1277 0 : return JSVERSION_UNKNOWN;
1278 : }
1279 :
1280 : JS_PUBLIC_API(uint32_t)
1281 2209371 : JS_GetOptions(JSContext *cx)
1282 : {
1283 : /*
1284 : * Can't check option/version synchronization here.
1285 : * We may have been synchronized with a script version that was formerly on
1286 : * the stack, but has now been popped.
1287 : */
1288 2209371 : return cx->allOptions();
1289 : }
1290 :
1291 : static unsigned
1292 1329240 : SetOptionsCommon(JSContext *cx, unsigned options)
1293 : {
1294 1329240 : JS_ASSERT((options & JSALLOPTION_MASK) == options);
1295 1329240 : unsigned oldopts = cx->allOptions();
1296 1329240 : unsigned newropts = options & JSRUNOPTION_MASK;
1297 1329240 : unsigned newcopts = options & JSCOMPILEOPTION_MASK;
1298 1329240 : cx->setRunOptions(newropts);
1299 1329240 : cx->setCompileOptions(newcopts);
1300 1329240 : cx->updateJITEnabled();
1301 1329240 : return oldopts;
1302 : }
1303 :
1304 : JS_PUBLIC_API(uint32_t)
1305 1284517 : JS_SetOptions(JSContext *cx, uint32_t options)
1306 : {
1307 1284517 : return SetOptionsCommon(cx, options);
1308 : }
1309 :
1310 : JS_PUBLIC_API(uint32_t)
1311 44723 : JS_ToggleOptions(JSContext *cx, uint32_t options)
1312 : {
1313 44723 : unsigned oldopts = cx->allOptions();
1314 44723 : unsigned newopts = oldopts ^ options;
1315 44723 : return SetOptionsCommon(cx, newopts);
1316 : }
1317 :
1318 : JS_PUBLIC_API(void)
1319 0 : JS_SetJitHardening(JSRuntime *rt, JSBool enabled)
1320 : {
1321 0 : rt->setJitHardening(!!enabled);
1322 0 : }
1323 :
1324 : JS_PUBLIC_API(const char *)
1325 18405 : JS_GetImplementationVersion(void)
1326 : {
1327 18405 : return "JavaScript-C 1.8.5+ 2011-04-16";
1328 : }
1329 :
1330 : JS_PUBLIC_API(JSCompartmentCallback)
1331 1404 : JS_SetCompartmentCallback(JSRuntime *rt, JSCompartmentCallback callback)
1332 : {
1333 1404 : JSCompartmentCallback old = rt->compartmentCallback;
1334 1404 : rt->compartmentCallback = callback;
1335 1404 : return old;
1336 : }
1337 :
1338 : JS_PUBLIC_API(JSWrapObjectCallback)
1339 1405 : JS_SetWrapObjectCallbacks(JSRuntime *rt,
1340 : JSWrapObjectCallback callback,
1341 : JSPreWrapCallback precallback)
1342 : {
1343 1405 : JSWrapObjectCallback old = rt->wrapObjectCallback;
1344 1405 : rt->wrapObjectCallback = callback;
1345 1405 : rt->preWrapObjectCallback = precallback;
1346 1405 : return old;
1347 : }
1348 :
1349 : JS_PUBLIC_API(JSCrossCompartmentCall *)
1350 402 : JS_EnterCrossCompartmentCall(JSContext *cx, JSObject *target)
1351 : {
1352 402 : AssertNoGC(cx);
1353 804 : CHECK_REQUEST(cx);
1354 :
1355 402 : JS_ASSERT(target);
1356 402 : AutoCompartment *call = cx->new_<AutoCompartment>(cx, target);
1357 402 : if (!call)
1358 0 : return NULL;
1359 402 : if (!call->enter()) {
1360 0 : Foreground::delete_(call);
1361 0 : return NULL;
1362 : }
1363 402 : return reinterpret_cast<JSCrossCompartmentCall *>(call);
1364 : }
1365 :
1366 : namespace js {
1367 :
1368 : // Declared in jscompartment.h
1369 : Class dummy_class = {
1370 : "jdummy",
1371 : JSCLASS_GLOBAL_FLAGS,
1372 : JS_PropertyStub, JS_PropertyStub,
1373 : JS_PropertyStub, JS_StrictPropertyStub,
1374 : JS_EnumerateStub, JS_ResolveStub,
1375 : JS_ConvertStub
1376 : };
1377 :
1378 : } /*namespace js */
1379 :
1380 : JS_PUBLIC_API(JSCrossCompartmentCall *)
1381 12 : JS_EnterCrossCompartmentCallScript(JSContext *cx, JSScript *target)
1382 : {
1383 12 : AssertNoGC(cx);
1384 24 : CHECK_REQUEST(cx);
1385 12 : JS_ASSERT(!target->isCachedEval);
1386 12 : GlobalObject *global = target->globalObject;
1387 12 : if (!global) {
1388 16 : SwitchToCompartment sc(cx, target->compartment());
1389 8 : global = GlobalObject::create(cx, &dummy_class);
1390 8 : if (!global)
1391 0 : return NULL;
1392 : }
1393 12 : return JS_EnterCrossCompartmentCall(cx, global);
1394 : }
1395 :
1396 : JS_PUBLIC_API(JSCrossCompartmentCall *)
1397 12 : JS_EnterCrossCompartmentCallStackFrame(JSContext *cx, JSStackFrame *target)
1398 : {
1399 12 : AssertNoGC(cx);
1400 24 : CHECK_REQUEST(cx);
1401 :
1402 12 : return JS_EnterCrossCompartmentCall(cx, &Valueify(target)->scopeChain().global());
1403 : }
1404 :
1405 : JS_PUBLIC_API(void)
1406 402 : JS_LeaveCrossCompartmentCall(JSCrossCompartmentCall *call)
1407 : {
1408 402 : AutoCompartment *realcall = reinterpret_cast<AutoCompartment *>(call);
1409 402 : AssertNoGC(realcall->context);
1410 804 : CHECK_REQUEST(realcall->context);
1411 402 : realcall->leave();
1412 402 : Foreground::delete_(realcall);
1413 402 : }
1414 :
1415 : bool
1416 6934718 : JSAutoEnterCompartment::enter(JSContext *cx, JSObject *target)
1417 : {
1418 6934718 : AssertNoGC(cx);
1419 6934718 : JS_ASSERT(state == STATE_UNENTERED);
1420 6934718 : if (cx->compartment == target->compartment()) {
1421 6793385 : state = STATE_SAME_COMPARTMENT;
1422 6793385 : return true;
1423 : }
1424 :
1425 : JS_STATIC_ASSERT(sizeof(bytes) == sizeof(AutoCompartment));
1426 282666 : CHECK_REQUEST(cx);
1427 141333 : AutoCompartment *call = new (bytes) AutoCompartment(cx, target);
1428 141333 : if (call->enter()) {
1429 141333 : state = STATE_OTHER_COMPARTMENT;
1430 141333 : return true;
1431 : }
1432 0 : return false;
1433 : }
1434 :
1435 : void
1436 622539 : JSAutoEnterCompartment::enterAndIgnoreErrors(JSContext *cx, JSObject *target)
1437 : {
1438 622539 : (void) enter(cx, target);
1439 622539 : }
1440 :
1441 6939060 : JSAutoEnterCompartment::~JSAutoEnterCompartment()
1442 : {
1443 6939060 : if (state == STATE_OTHER_COMPARTMENT) {
1444 141333 : AutoCompartment* ac = reinterpret_cast<AutoCompartment*>(bytes);
1445 282666 : CHECK_REQUEST(ac->context);
1446 141333 : ac->~AutoCompartment();
1447 : }
1448 6939060 : }
1449 :
1450 : namespace JS {
1451 :
1452 : bool
1453 0 : AutoEnterScriptCompartment::enter(JSContext *cx, JSScript *target)
1454 : {
1455 0 : JS_ASSERT(!call);
1456 0 : if (cx->compartment == target->compartment()) {
1457 0 : call = reinterpret_cast<JSCrossCompartmentCall*>(1);
1458 0 : return true;
1459 : }
1460 0 : call = JS_EnterCrossCompartmentCallScript(cx, target);
1461 0 : return call != NULL;
1462 : }
1463 :
1464 : bool
1465 1496110 : AutoEnterFrameCompartment::enter(JSContext *cx, JSStackFrame *target)
1466 : {
1467 1496110 : JS_ASSERT(!call);
1468 1496110 : if (cx->compartment == Valueify(target)->scopeChain().compartment()) {
1469 1496098 : call = reinterpret_cast<JSCrossCompartmentCall*>(1);
1470 1496098 : return true;
1471 : }
1472 12 : call = JS_EnterCrossCompartmentCallStackFrame(cx, target);
1473 12 : return call != NULL;
1474 : }
1475 :
1476 : } /* namespace JS */
1477 :
1478 : JS_PUBLIC_API(void)
1479 6736 : JS_SetCompartmentPrivate(JSCompartment *compartment, void *data)
1480 : {
1481 6736 : compartment->data = data;
1482 6736 : }
1483 :
1484 : JS_PUBLIC_API(void *)
1485 74008 : JS_GetCompartmentPrivate(JSCompartment *compartment)
1486 : {
1487 74008 : return compartment->data;
1488 : }
1489 :
1490 : JS_PUBLIC_API(JSBool)
1491 1526822 : JS_WrapObject(JSContext *cx, JSObject **objp)
1492 : {
1493 1526822 : AssertNoGC(cx);
1494 3053644 : CHECK_REQUEST(cx);
1495 1526822 : return cx->compartment->wrap(cx, objp);
1496 : }
1497 :
1498 : JS_PUBLIC_API(JSBool)
1499 441232 : JS_WrapValue(JSContext *cx, jsval *vp)
1500 : {
1501 441232 : AssertNoGC(cx);
1502 882464 : CHECK_REQUEST(cx);
1503 441232 : return cx->compartment->wrap(cx, vp);
1504 : }
1505 :
1506 : JS_PUBLIC_API(JSObject *)
1507 1 : JS_TransplantObject(JSContext *cx, JSObject *origobj, JSObject *target)
1508 : {
1509 1 : AssertNoGC(cx);
1510 :
1511 : // This function is called when an object moves between two
1512 : // different compartments. In that case, we need to "move" the
1513 : // window from origobj's compartment to target's compartment.
1514 1 : JSCompartment *destination = target->compartment();
1515 1 : WrapperMap &map = destination->crossCompartmentWrappers;
1516 1 : Value origv = ObjectValue(*origobj);
1517 : JSObject *obj;
1518 :
1519 1 : if (origobj->compartment() == destination) {
1520 : // If the original object is in the same compartment as the
1521 : // destination, then we know that we won't find wrapper in the
1522 : // destination's cross compartment map and that the same
1523 : // object will continue to work. Note the rare case where
1524 : // |origobj == target|. In that case, we can just treat this
1525 : // as a same compartment navigation. The effect is to clear
1526 : // all of the wrappers and their holders if they have
1527 : // them. This would be cleaner as a separate API.
1528 0 : if (origobj != target && !origobj->swap(cx, target))
1529 0 : return NULL;
1530 0 : obj = origobj;
1531 1 : } else if (WrapperMap::Ptr p = map.lookup(origv)) {
1532 : // There might already be a wrapper for the original object in
1533 : // the new compartment. If there is, make it the primary outer
1534 : // window proxy around the inner (accomplished by swapping
1535 : // target's innards with the old, possibly security wrapper,
1536 : // innards).
1537 1 : obj = &p->value.toObject();
1538 1 : map.remove(p);
1539 1 : if (!obj->swap(cx, target))
1540 0 : return NULL;
1541 : } else {
1542 : // Otherwise, this is going to be our outer window proxy in
1543 : // the new compartment.
1544 0 : obj = target;
1545 : }
1546 :
1547 : // Now, iterate through other scopes looking for references to the
1548 : // old outer window. They need to be updated to point at the new
1549 : // outer window. They also might transition between different
1550 : // types of security wrappers based on whether the new compartment
1551 : // is same origin with them.
1552 1 : Value targetv = ObjectValue(*obj);
1553 1 : CompartmentVector &vector = cx->runtime->compartments;
1554 2 : AutoValueVector toTransplant(cx);
1555 1 : if (!toTransplant.reserve(vector.length()))
1556 0 : return NULL;
1557 :
1558 6 : for (JSCompartment **p = vector.begin(), **end = vector.end(); p != end; ++p) {
1559 5 : WrapperMap &pmap = (*p)->crossCompartmentWrappers;
1560 5 : if (WrapperMap::Ptr wp = pmap.lookup(origv)) {
1561 : // We found a wrapper. Remember and root it.
1562 2 : toTransplant.infallibleAppend(wp->value);
1563 : }
1564 : }
1565 :
1566 3 : for (Value *begin = toTransplant.begin(), *end = toTransplant.end(); begin != end; ++begin) {
1567 2 : JSObject *wobj = &begin->toObject();
1568 2 : JSCompartment *wcompartment = wobj->compartment();
1569 2 : WrapperMap &pmap = wcompartment->crossCompartmentWrappers;
1570 2 : JS_ASSERT(pmap.lookup(origv));
1571 2 : pmap.remove(origv);
1572 :
1573 : // First, we wrap it in the new compartment. This will return
1574 : // a new wrapper.
1575 4 : AutoCompartment ac(cx, wobj);
1576 2 : JSObject *tobj = obj;
1577 2 : if (!ac.enter() || !wcompartment->wrap(cx, &tobj))
1578 0 : return NULL;
1579 :
1580 : // Now, because we need to maintain object identity, we do a
1581 : // brain transplant on the old object. At the same time, we
1582 : // update the entry in the compartment's wrapper map to point
1583 : // to the old wrapper.
1584 2 : JS_ASSERT(tobj != wobj);
1585 2 : if (!wobj->swap(cx, tobj))
1586 0 : return NULL;
1587 4 : pmap.put(targetv, ObjectValue(*wobj));
1588 : }
1589 :
1590 : // Lastly, update the original object to point to the new one.
1591 1 : if (origobj->compartment() != destination) {
1592 2 : AutoCompartment ac(cx, origobj);
1593 1 : JSObject *tobj = obj;
1594 1 : if (!ac.enter() || !JS_WrapObject(cx, &tobj))
1595 0 : return NULL;
1596 1 : if (!origobj->swap(cx, tobj))
1597 0 : return NULL;
1598 2 : origobj->compartment()->crossCompartmentWrappers.put(targetv, origv);
1599 : }
1600 :
1601 1 : return obj;
1602 : }
1603 :
1604 : /*
1605 : * The location object is special. There is the location object itself and
1606 : * then the location object wrapper. Because there are no direct references to
1607 : * the location object itself, we don't want the old obj (|origobj| here) to
1608 : * become the new wrapper but the wrapper itself instead. This leads to very
1609 : * subtle differences between js_TransplantObjectWithWrapper and
1610 : * JS_TransplantObject.
1611 : */
1612 : JS_FRIEND_API(JSObject *)
1613 0 : js_TransplantObjectWithWrapper(JSContext *cx,
1614 : JSObject *origobj,
1615 : JSObject *origwrapper,
1616 : JSObject *targetobj,
1617 : JSObject *targetwrapper)
1618 : {
1619 0 : AssertNoGC(cx);
1620 :
1621 : JSObject *obj;
1622 0 : JSCompartment *destination = targetobj->compartment();
1623 0 : WrapperMap &map = destination->crossCompartmentWrappers;
1624 :
1625 : // |origv| is the map entry we're looking up. The map entries are going to
1626 : // be for the location object itself.
1627 0 : Value origv = ObjectValue(*origobj);
1628 :
1629 : // There might already be a wrapper for the original object in the new
1630 : // compartment.
1631 0 : if (WrapperMap::Ptr p = map.lookup(origv)) {
1632 : // There is. Make the existing wrapper a same compartment location
1633 : // wrapper (swapping it with the given new wrapper).
1634 0 : obj = &p->value.toObject();
1635 0 : map.remove(p);
1636 0 : if (!obj->swap(cx, targetwrapper))
1637 0 : return NULL;
1638 : } else {
1639 : // Otherwise, use the passed-in wrapper as the same compartment
1640 : // location wrapper.
1641 0 : obj = targetwrapper;
1642 : }
1643 :
1644 : // Now, iterate through other scopes looking for references to the old
1645 : // location object. Note that the entries in the maps are for |origobj|
1646 : // and not |origwrapper|. They need to be updated to point at the new
1647 : // location object.
1648 0 : Value targetv = ObjectValue(*targetobj);
1649 0 : CompartmentVector &vector = cx->runtime->compartments;
1650 0 : AutoValueVector toTransplant(cx);
1651 0 : if (!toTransplant.reserve(vector.length()))
1652 0 : return NULL;
1653 :
1654 0 : for (JSCompartment **p = vector.begin(), **end = vector.end(); p != end; ++p) {
1655 0 : WrapperMap &pmap = (*p)->crossCompartmentWrappers;
1656 0 : if (WrapperMap::Ptr wp = pmap.lookup(origv)) {
1657 : // We found a wrapper. Remember and root it.
1658 0 : toTransplant.infallibleAppend(wp->value);
1659 : }
1660 : }
1661 :
1662 0 : for (Value *begin = toTransplant.begin(), *end = toTransplant.end(); begin != end; ++begin) {
1663 0 : JSObject *wobj = &begin->toObject();
1664 0 : JSCompartment *wcompartment = wobj->compartment();
1665 0 : WrapperMap &pmap = wcompartment->crossCompartmentWrappers;
1666 0 : JS_ASSERT(pmap.lookup(origv));
1667 0 : pmap.remove(origv);
1668 :
1669 : // First, we wrap it in the new compartment. This will return a
1670 : // new wrapper.
1671 0 : AutoCompartment ac(cx, wobj);
1672 :
1673 0 : JSObject *tobj = targetobj;
1674 0 : if (!ac.enter() || !wcompartment->wrap(cx, &tobj))
1675 0 : return NULL;
1676 :
1677 : // Now, because we need to maintain object identity, we do a brain
1678 : // transplant on the old object. At the same time, we update the
1679 : // entry in the compartment's wrapper map to point to the old
1680 : // wrapper.
1681 0 : JS_ASSERT(tobj != wobj);
1682 0 : if (!wobj->swap(cx, tobj))
1683 0 : return NULL;
1684 0 : pmap.put(targetv, ObjectValue(*wobj));
1685 : }
1686 :
1687 : // Lastly, update the original object to point to the new one. However, as
1688 : // mentioned above, we do the transplant on the wrapper, not the object
1689 : // itself, since all of the references are to the object itself.
1690 : {
1691 0 : AutoCompartment ac(cx, origobj);
1692 0 : JSObject *tobj = obj;
1693 0 : if (!ac.enter() || !JS_WrapObject(cx, &tobj))
1694 0 : return NULL;
1695 0 : if (!origwrapper->swap(cx, tobj))
1696 0 : return NULL;
1697 0 : origwrapper->compartment()->crossCompartmentWrappers.put(targetv,
1698 0 : ObjectValue(*origwrapper));
1699 : }
1700 :
1701 0 : return obj;
1702 : }
1703 :
1704 : JS_PUBLIC_API(JSObject *)
1705 38917 : JS_GetGlobalObject(JSContext *cx)
1706 : {
1707 38917 : return cx->globalObject;
1708 : }
1709 :
1710 : JS_PUBLIC_API(void)
1711 64233 : JS_SetGlobalObject(JSContext *cx, JSObject *obj)
1712 : {
1713 64233 : AssertNoGC(cx);
1714 128466 : CHECK_REQUEST(cx);
1715 :
1716 64233 : cx->globalObject = obj;
1717 64233 : if (!cx->hasfp())
1718 32238 : cx->resetCompartment();
1719 64233 : }
1720 :
1721 : JS_PUBLIC_API(JSBool)
1722 533 : JS_InitStandardClasses(JSContext *cx, JSObject *obj)
1723 : {
1724 533 : JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
1725 533 : AssertNoGC(cx);
1726 1066 : CHECK_REQUEST(cx);
1727 :
1728 : /*
1729 : * JS_SetGlobalObject might or might not change cx's compartment, so call
1730 : * it before assertSameCompartment. (The API contract is that *after* this,
1731 : * cx and obj must be in the same compartment.)
1732 : */
1733 533 : if (!cx->globalObject)
1734 373 : JS_SetGlobalObject(cx, obj);
1735 :
1736 533 : assertSameCompartment(cx, obj);
1737 :
1738 533 : return obj->global().initStandardClasses(cx);
1739 : }
1740 :
1741 : #define CLASP(name) (&name##Class)
1742 : #define TYPED_ARRAY_CLASP(type) (&TypedArray::fastClasses[TypedArray::type])
1743 : #define EAGER_ATOM(name) ATOM_OFFSET(name), NULL
1744 : #define EAGER_CLASS_ATOM(name) CLASS_ATOM_OFFSET(name), NULL
1745 : #define EAGER_ATOM_AND_CLASP(name) EAGER_CLASS_ATOM(name), CLASP(name)
1746 : #define LAZY_ATOM(name) ATOM_OFFSET(lazy.name), js_##name##_str
1747 :
1748 : typedef struct JSStdName {
1749 : JSObjectOp init;
1750 : size_t atomOffset; /* offset of atom pointer in JSAtomState */
1751 : const char *name; /* null if atom is pre-pinned, else name */
1752 : Class *clasp;
1753 : } JSStdName;
1754 :
1755 : static JSAtom *
1756 52131167 : StdNameToAtom(JSContext *cx, JSStdName *stdn)
1757 : {
1758 : size_t offset;
1759 : JSAtom *atom;
1760 : const char *name;
1761 :
1762 52131167 : offset = stdn->atomOffset;
1763 52131167 : atom = OFFSET_TO_ATOM(cx->runtime, offset);
1764 52131167 : if (!atom) {
1765 422993 : name = stdn->name;
1766 422993 : if (name) {
1767 422993 : atom = js_Atomize(cx, name, strlen(name), InternAtom);
1768 422993 : OFFSET_TO_ATOM(cx->runtime, offset) = atom;
1769 : }
1770 : }
1771 52131167 : return atom;
1772 : }
1773 :
1774 : /*
1775 : * Table of class initializers and their atom offsets in rt->atomState.
1776 : * If you add a "standard" class, remember to update this table.
1777 : */
1778 : static JSStdName standard_class_atoms[] = {
1779 : {js_InitFunctionClass, EAGER_ATOM_AND_CLASP(Function)},
1780 : {js_InitObjectClass, EAGER_ATOM_AND_CLASP(Object)},
1781 : {js_InitArrayClass, EAGER_ATOM_AND_CLASP(Array)},
1782 : {js_InitBooleanClass, EAGER_ATOM_AND_CLASP(Boolean)},
1783 : {js_InitDateClass, EAGER_ATOM_AND_CLASP(Date)},
1784 : {js_InitMathClass, EAGER_ATOM_AND_CLASP(Math)},
1785 : {js_InitNumberClass, EAGER_ATOM_AND_CLASP(Number)},
1786 : {js_InitStringClass, EAGER_ATOM_AND_CLASP(String)},
1787 : {js_InitExceptionClasses, EAGER_ATOM_AND_CLASP(Error)},
1788 : {js_InitRegExpClass, EAGER_ATOM_AND_CLASP(RegExp)},
1789 : #if JS_HAS_XML_SUPPORT
1790 : {js_InitXMLClass, EAGER_ATOM_AND_CLASP(XML)},
1791 : {js_InitNamespaceClass, EAGER_ATOM_AND_CLASP(Namespace)},
1792 : {js_InitQNameClass, EAGER_ATOM_AND_CLASP(QName)},
1793 : #endif
1794 : #if JS_HAS_GENERATORS
1795 : {js_InitIteratorClasses, EAGER_ATOM_AND_CLASP(StopIteration)},
1796 : #endif
1797 : {js_InitJSONClass, EAGER_ATOM_AND_CLASP(JSON)},
1798 : {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(ArrayBuffer), &js::ArrayBuffer::slowClass},
1799 : {js_InitWeakMapClass, EAGER_CLASS_ATOM(WeakMap), &js::WeakMapClass},
1800 : {js_InitMapClass, EAGER_CLASS_ATOM(Map), &js::MapObject::class_},
1801 : {js_InitSetClass, EAGER_CLASS_ATOM(Set), &js::SetObject::class_},
1802 : {NULL, 0, NULL, NULL}
1803 : };
1804 :
1805 : /*
1806 : * Table of top-level function and constant names and their init functions.
1807 : * If you add a "standard" global function or property, remember to update
1808 : * this table.
1809 : */
1810 : static JSStdName standard_class_names[] = {
1811 : {js_InitObjectClass, EAGER_ATOM(eval), CLASP(Object)},
1812 :
1813 : /* Global properties and functions defined by the Number class. */
1814 : {js_InitNumberClass, EAGER_ATOM(NaN), CLASP(Number)},
1815 : {js_InitNumberClass, EAGER_ATOM(Infinity), CLASP(Number)},
1816 : {js_InitNumberClass, LAZY_ATOM(isNaN), CLASP(Number)},
1817 : {js_InitNumberClass, LAZY_ATOM(isFinite), CLASP(Number)},
1818 : {js_InitNumberClass, LAZY_ATOM(parseFloat), CLASP(Number)},
1819 : {js_InitNumberClass, LAZY_ATOM(parseInt), CLASP(Number)},
1820 :
1821 : /* String global functions. */
1822 : {js_InitStringClass, LAZY_ATOM(escape), CLASP(String)},
1823 : {js_InitStringClass, LAZY_ATOM(unescape), CLASP(String)},
1824 : {js_InitStringClass, LAZY_ATOM(decodeURI), CLASP(String)},
1825 : {js_InitStringClass, LAZY_ATOM(encodeURI), CLASP(String)},
1826 : {js_InitStringClass, LAZY_ATOM(decodeURIComponent), CLASP(String)},
1827 : {js_InitStringClass, LAZY_ATOM(encodeURIComponent), CLASP(String)},
1828 : #if JS_HAS_UNEVAL
1829 : {js_InitStringClass, LAZY_ATOM(uneval), CLASP(String)},
1830 : #endif
1831 :
1832 : /* Exception constructors. */
1833 : {js_InitExceptionClasses, EAGER_CLASS_ATOM(Error), CLASP(Error)},
1834 : {js_InitExceptionClasses, EAGER_CLASS_ATOM(InternalError), CLASP(Error)},
1835 : {js_InitExceptionClasses, EAGER_CLASS_ATOM(EvalError), CLASP(Error)},
1836 : {js_InitExceptionClasses, EAGER_CLASS_ATOM(RangeError), CLASP(Error)},
1837 : {js_InitExceptionClasses, EAGER_CLASS_ATOM(ReferenceError), CLASP(Error)},
1838 : {js_InitExceptionClasses, EAGER_CLASS_ATOM(SyntaxError), CLASP(Error)},
1839 : {js_InitExceptionClasses, EAGER_CLASS_ATOM(TypeError), CLASP(Error)},
1840 : {js_InitExceptionClasses, EAGER_CLASS_ATOM(URIError), CLASP(Error)},
1841 :
1842 : #if JS_HAS_XML_SUPPORT
1843 : {js_InitXMLClass, LAZY_ATOM(XMLList), CLASP(XML)},
1844 : {js_InitXMLClass, LAZY_ATOM(isXMLName), CLASP(XML)},
1845 : #endif
1846 :
1847 : #if JS_HAS_GENERATORS
1848 : {js_InitIteratorClasses, EAGER_ATOM_AND_CLASP(Iterator)},
1849 : #endif
1850 :
1851 : /* Typed Arrays */
1852 : {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(ArrayBuffer), &ArrayBufferClass},
1853 : {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Int8Array), TYPED_ARRAY_CLASP(TYPE_INT8)},
1854 : {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Uint8Array), TYPED_ARRAY_CLASP(TYPE_UINT8)},
1855 : {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Int16Array), TYPED_ARRAY_CLASP(TYPE_INT16)},
1856 : {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Uint16Array), TYPED_ARRAY_CLASP(TYPE_UINT16)},
1857 : {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Int32Array), TYPED_ARRAY_CLASP(TYPE_INT32)},
1858 : {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Uint32Array), TYPED_ARRAY_CLASP(TYPE_UINT32)},
1859 : {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Float32Array), TYPED_ARRAY_CLASP(TYPE_FLOAT32)},
1860 : {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Float64Array), TYPED_ARRAY_CLASP(TYPE_FLOAT64)},
1861 : {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Uint8ClampedArray),
1862 : TYPED_ARRAY_CLASP(TYPE_UINT8_CLAMPED)},
1863 :
1864 : {js_InitWeakMapClass, EAGER_ATOM_AND_CLASP(WeakMap)},
1865 : {js_InitProxyClass, EAGER_ATOM_AND_CLASP(Proxy)},
1866 :
1867 : {NULL, 0, NULL, NULL}
1868 : };
1869 :
1870 : static JSStdName object_prototype_names[] = {
1871 : /* Object.prototype properties (global delegates to Object.prototype). */
1872 : {js_InitObjectClass, EAGER_ATOM(proto), CLASP(Object)},
1873 : #if JS_HAS_TOSOURCE
1874 : {js_InitObjectClass, EAGER_ATOM(toSource), CLASP(Object)},
1875 : #endif
1876 : {js_InitObjectClass, EAGER_ATOM(toString), CLASP(Object)},
1877 : {js_InitObjectClass, EAGER_ATOM(toLocaleString), CLASP(Object)},
1878 : {js_InitObjectClass, EAGER_ATOM(valueOf), CLASP(Object)},
1879 : #if JS_HAS_OBJ_WATCHPOINT
1880 : {js_InitObjectClass, LAZY_ATOM(watch), CLASP(Object)},
1881 : {js_InitObjectClass, LAZY_ATOM(unwatch), CLASP(Object)},
1882 : #endif
1883 : {js_InitObjectClass, LAZY_ATOM(hasOwnProperty), CLASP(Object)},
1884 : {js_InitObjectClass, LAZY_ATOM(isPrototypeOf), CLASP(Object)},
1885 : {js_InitObjectClass, LAZY_ATOM(propertyIsEnumerable), CLASP(Object)},
1886 : #if OLD_GETTER_SETTER_METHODS
1887 : {js_InitObjectClass, LAZY_ATOM(defineGetter), CLASP(Object)},
1888 : {js_InitObjectClass, LAZY_ATOM(defineSetter), CLASP(Object)},
1889 : {js_InitObjectClass, LAZY_ATOM(lookupGetter), CLASP(Object)},
1890 : {js_InitObjectClass, LAZY_ATOM(lookupSetter), CLASP(Object)},
1891 : #endif
1892 :
1893 : {NULL, 0, NULL, NULL}
1894 : };
1895 :
1896 : JS_PUBLIC_API(JSBool)
1897 1507716 : JS_ResolveStandardClass(JSContext *cx, JSObject *obj, jsid id, JSBool *resolved)
1898 : {
1899 : JSString *idstr;
1900 : JSRuntime *rt;
1901 : JSAtom *atom;
1902 : JSStdName *stdnm;
1903 : unsigned i;
1904 :
1905 3015432 : RootObject objRoot(cx, &obj);
1906 :
1907 1507716 : AssertNoGC(cx);
1908 3015432 : CHECK_REQUEST(cx);
1909 1507716 : assertSameCompartment(cx, obj, id);
1910 1507716 : *resolved = JS_FALSE;
1911 :
1912 1507716 : rt = cx->runtime;
1913 1507716 : if (!rt->hasContexts() || !JSID_IS_ATOM(id))
1914 90343 : return JS_TRUE;
1915 :
1916 1417373 : idstr = JSID_TO_STRING(id);
1917 :
1918 : /* Check whether we're resolving 'undefined', and define it if so. */
1919 1417373 : atom = rt->atomState.typeAtoms[JSTYPE_VOID];
1920 1417373 : if (idstr == atom) {
1921 5070 : *resolved = JS_TRUE;
1922 : return obj->defineProperty(cx, atom->asPropertyName(), UndefinedValue(),
1923 : JS_PropertyStub, JS_StrictPropertyStub,
1924 5070 : JSPROP_PERMANENT | JSPROP_READONLY);
1925 : }
1926 :
1927 : /* Try for class constructors/prototypes named by well-known atoms. */
1928 1412303 : stdnm = NULL;
1929 28137159 : for (i = 0; standard_class_atoms[i].init; i++) {
1930 26734510 : JS_ASSERT(standard_class_atoms[i].clasp);
1931 26734510 : atom = OFFSET_TO_ATOM(rt, standard_class_atoms[i].atomOffset);
1932 26734510 : if (idstr == atom) {
1933 9654 : stdnm = &standard_class_atoms[i];
1934 9654 : break;
1935 : }
1936 : }
1937 :
1938 1412303 : if (!stdnm) {
1939 : /* Try less frequently used top-level functions and constants. */
1940 53225501 : for (i = 0; standard_class_names[i].init; i++) {
1941 51826697 : JS_ASSERT(standard_class_names[i].clasp);
1942 51826697 : atom = StdNameToAtom(cx, &standard_class_names[i]);
1943 51826697 : if (!atom)
1944 0 : return JS_FALSE;
1945 51826697 : if (idstr == atom) {
1946 3845 : stdnm = &standard_class_names[i];
1947 3845 : break;
1948 : }
1949 : }
1950 :
1951 1402649 : if (!stdnm && !obj->getProto()) {
1952 : /*
1953 : * Try even less frequently used names delegated from the global
1954 : * object to Object.prototype, but only if the Object class hasn't
1955 : * yet been initialized.
1956 : */
1957 326214 : for (i = 0; object_prototype_names[i].init; i++) {
1958 304470 : JS_ASSERT(object_prototype_names[i].clasp);
1959 304470 : atom = StdNameToAtom(cx, &object_prototype_names[i]);
1960 304470 : if (!atom)
1961 0 : return JS_FALSE;
1962 304470 : if (idstr == atom) {
1963 9 : stdnm = &object_prototype_names[i];
1964 9 : break;
1965 : }
1966 : }
1967 : }
1968 : }
1969 :
1970 1412303 : if (stdnm) {
1971 : /*
1972 : * If this standard class is anonymous, then we don't want to resolve
1973 : * by name.
1974 : */
1975 13508 : JS_ASSERT(obj->isGlobal());
1976 13508 : if (stdnm->clasp->flags & JSCLASS_IS_ANONYMOUS)
1977 0 : return JS_TRUE;
1978 :
1979 13508 : if (IsStandardClassResolved(obj, stdnm->clasp))
1980 274 : return JS_TRUE;
1981 :
1982 13234 : if (!stdnm->init(cx, obj))
1983 0 : return JS_FALSE;
1984 13234 : *resolved = JS_TRUE;
1985 : }
1986 1412029 : return JS_TRUE;
1987 : }
1988 :
1989 : JS_PUBLIC_API(JSBool)
1990 144450 : JS_EnumerateStandardClasses(JSContext *cx, JSObject *obj)
1991 : {
1992 : JSRuntime *rt;
1993 : unsigned i;
1994 :
1995 144450 : AssertNoGC(cx);
1996 288900 : CHECK_REQUEST(cx);
1997 144450 : assertSameCompartment(cx, obj);
1998 144450 : rt = cx->runtime;
1999 :
2000 : /*
2001 : * Check whether we need to bind 'undefined' and define it if so.
2002 : * Since ES5 15.1.1.3 undefined can't be deleted.
2003 : */
2004 144450 : PropertyName *name = rt->atomState.typeAtoms[JSTYPE_VOID];
2005 144630 : if (!obj->nativeContains(cx, ATOM_TO_JSID(name)) &&
2006 : !obj->defineProperty(cx, name, UndefinedValue(),
2007 : JS_PropertyStub, JS_StrictPropertyStub,
2008 180 : JSPROP_PERMANENT | JSPROP_READONLY)) {
2009 0 : return JS_FALSE;
2010 : }
2011 :
2012 : /* Initialize any classes that have not been initialized yet. */
2013 2889000 : for (i = 0; standard_class_atoms[i].init; i++) {
2014 2747313 : if (!js::IsStandardClassResolved(obj, standard_class_atoms[i].clasp) &&
2015 2763 : !standard_class_atoms[i].init(cx, obj))
2016 : {
2017 0 : return JS_FALSE;
2018 : }
2019 : }
2020 :
2021 144450 : return JS_TRUE;
2022 : }
2023 :
2024 : static JSIdArray *
2025 0 : NewIdArray(JSContext *cx, int length)
2026 : {
2027 : JSIdArray *ida;
2028 :
2029 : ida = (JSIdArray *)
2030 0 : cx->calloc_(offsetof(JSIdArray, vector) + length * sizeof(jsval));
2031 0 : if (ida)
2032 0 : ida->length = length;
2033 0 : return ida;
2034 : }
2035 :
2036 : /*
2037 : * Unlike realloc(3), this function frees ida on failure.
2038 : */
2039 : static JSIdArray *
2040 0 : SetIdArrayLength(JSContext *cx, JSIdArray *ida, int length)
2041 : {
2042 : JSIdArray *rida;
2043 :
2044 : rida = (JSIdArray *)
2045 : JS_realloc(cx, ida,
2046 0 : offsetof(JSIdArray, vector) + length * sizeof(jsval));
2047 0 : if (!rida) {
2048 0 : JS_DestroyIdArray(cx, ida);
2049 : } else {
2050 0 : rida->length = length;
2051 : }
2052 0 : return rida;
2053 : }
2054 :
2055 : static JSIdArray *
2056 0 : AddAtomToArray(JSContext *cx, JSAtom *atom, JSIdArray *ida, int *ip)
2057 : {
2058 0 : int i = *ip;
2059 0 : int length = ida->length;
2060 0 : if (i >= length) {
2061 0 : ida = SetIdArrayLength(cx, ida, JS_MAX(length * 2, 8));
2062 0 : if (!ida)
2063 0 : return NULL;
2064 0 : JS_ASSERT(i < ida->length);
2065 : }
2066 0 : ida->vector[i].init(ATOM_TO_JSID(atom));
2067 0 : *ip = i + 1;
2068 0 : return ida;
2069 : }
2070 :
2071 : static JSIdArray *
2072 0 : EnumerateIfResolved(JSContext *cx, JSObject *obj, JSAtom *atom, JSIdArray *ida,
2073 : int *ip, JSBool *foundp)
2074 : {
2075 0 : *foundp = obj->nativeContains(cx, ATOM_TO_JSID(atom));
2076 0 : if (*foundp)
2077 0 : ida = AddAtomToArray(cx, atom, ida, ip);
2078 0 : return ida;
2079 : }
2080 :
2081 : JS_PUBLIC_API(JSIdArray *)
2082 0 : JS_EnumerateResolvedStandardClasses(JSContext *cx, JSObject *obj, JSIdArray *ida)
2083 : {
2084 : JSRuntime *rt;
2085 : int i, j, k;
2086 : JSAtom *atom;
2087 : JSBool found;
2088 : JSObjectOp init;
2089 :
2090 0 : AssertNoGC(cx);
2091 0 : CHECK_REQUEST(cx);
2092 0 : assertSameCompartment(cx, obj, ida);
2093 0 : rt = cx->runtime;
2094 0 : if (ida) {
2095 0 : i = ida->length;
2096 : } else {
2097 0 : ida = NewIdArray(cx, 8);
2098 0 : if (!ida)
2099 0 : return NULL;
2100 0 : i = 0;
2101 : }
2102 :
2103 : /* Check whether 'undefined' has been resolved and enumerate it if so. */
2104 0 : atom = rt->atomState.typeAtoms[JSTYPE_VOID];
2105 0 : ida = EnumerateIfResolved(cx, obj, atom, ida, &i, &found);
2106 0 : if (!ida)
2107 0 : return NULL;
2108 :
2109 : /* Enumerate only classes that *have* been resolved. */
2110 0 : for (j = 0; standard_class_atoms[j].init; j++) {
2111 0 : atom = OFFSET_TO_ATOM(rt, standard_class_atoms[j].atomOffset);
2112 0 : ida = EnumerateIfResolved(cx, obj, atom, ida, &i, &found);
2113 0 : if (!ida)
2114 0 : return NULL;
2115 :
2116 0 : if (found) {
2117 0 : init = standard_class_atoms[j].init;
2118 :
2119 0 : for (k = 0; standard_class_names[k].init; k++) {
2120 0 : if (standard_class_names[k].init == init) {
2121 0 : atom = StdNameToAtom(cx, &standard_class_names[k]);
2122 0 : ida = AddAtomToArray(cx, atom, ida, &i);
2123 0 : if (!ida)
2124 0 : return NULL;
2125 : }
2126 : }
2127 :
2128 0 : if (init == js_InitObjectClass) {
2129 0 : for (k = 0; object_prototype_names[k].init; k++) {
2130 0 : atom = StdNameToAtom(cx, &object_prototype_names[k]);
2131 0 : ida = AddAtomToArray(cx, atom, ida, &i);
2132 0 : if (!ida)
2133 0 : return NULL;
2134 : }
2135 : }
2136 : }
2137 : }
2138 :
2139 : /* Trim to exact length. */
2140 0 : return SetIdArrayLength(cx, ida, i);
2141 : }
2142 :
2143 : #undef CLASP
2144 : #undef EAGER_ATOM
2145 : #undef EAGER_CLASS_ATOM
2146 : #undef EAGER_ATOM_CLASP
2147 : #undef LAZY_ATOM
2148 :
2149 : JS_PUBLIC_API(JSBool)
2150 0 : JS_GetClassObject(JSContext *cx, JSObject *obj, JSProtoKey key, JSObject **objp)
2151 : {
2152 0 : AssertNoGC(cx);
2153 0 : CHECK_REQUEST(cx);
2154 0 : assertSameCompartment(cx, obj);
2155 0 : return js_GetClassObject(cx, obj, key, objp);
2156 : }
2157 :
2158 : JS_PUBLIC_API(JSObject *)
2159 15749 : JS_GetObjectPrototype(JSContext *cx, JSObject *forObj)
2160 : {
2161 31498 : CHECK_REQUEST(cx);
2162 15749 : assertSameCompartment(cx, forObj);
2163 15749 : return forObj->global().getOrCreateObjectPrototype(cx);
2164 : }
2165 :
2166 : JS_PUBLIC_API(JSObject *)
2167 0 : JS_GetFunctionPrototype(JSContext *cx, JSObject *forObj)
2168 : {
2169 0 : CHECK_REQUEST(cx);
2170 0 : assertSameCompartment(cx, forObj);
2171 0 : return forObj->global().getOrCreateFunctionPrototype(cx);
2172 : }
2173 :
2174 : JS_PUBLIC_API(JSObject *)
2175 679204 : JS_GetGlobalForObject(JSContext *cx, JSObject *obj)
2176 : {
2177 679204 : AssertNoGC(cx);
2178 679204 : assertSameCompartment(cx, obj);
2179 679204 : return &obj->global();
2180 : }
2181 :
2182 : JS_PUBLIC_API(JSObject *)
2183 910589576 : JS_GetGlobalForScopeChain(JSContext *cx)
2184 : {
2185 910589576 : AssertNoGC(cx);
2186 1821179152 : CHECK_REQUEST(cx);
2187 910589576 : return GetGlobalForScopeChain(cx);
2188 : }
2189 :
2190 : JS_PUBLIC_API(jsval)
2191 4401 : JS_ComputeThis(JSContext *cx, jsval *vp)
2192 : {
2193 4401 : AssertNoGC(cx);
2194 4401 : assertSameCompartment(cx, JSValueArray(vp, 2));
2195 4401 : CallReceiver call = CallReceiverFromVp(vp);
2196 4401 : if (!BoxNonStrictThis(cx, call))
2197 0 : return JSVAL_NULL;
2198 4401 : return call.thisv();
2199 : }
2200 :
2201 : JS_PUBLIC_API(void)
2202 0 : JS_MallocInCompartment(JSCompartment *comp, size_t nbytes)
2203 : {
2204 0 : comp->mallocInCompartment(nbytes);
2205 0 : }
2206 :
2207 : JS_PUBLIC_API(void)
2208 0 : JS_FreeInCompartment(JSCompartment *comp, size_t nbytes)
2209 : {
2210 0 : comp->freeInCompartment(nbytes);
2211 0 : }
2212 :
2213 : JS_PUBLIC_API(void *)
2214 1260223 : JS_malloc(JSContext *cx, size_t nbytes)
2215 : {
2216 1260223 : AssertNoGC(cx);
2217 2520446 : CHECK_REQUEST(cx);
2218 1260223 : return cx->malloc_(nbytes);
2219 : }
2220 :
2221 : JS_PUBLIC_API(void *)
2222 0 : JS_realloc(JSContext *cx, void *p, size_t nbytes)
2223 : {
2224 0 : AssertNoGC(cx);
2225 0 : CHECK_REQUEST(cx);
2226 0 : return cx->realloc_(p, nbytes);
2227 : }
2228 :
2229 : JS_PUBLIC_API(void)
2230 24421 : JS_free(JSContext *cx, void *p)
2231 : {
2232 24421 : return cx->free_(p);
2233 : }
2234 :
2235 : JS_PUBLIC_API(void)
2236 1256303 : JS_updateMallocCounter(JSContext *cx, size_t nbytes)
2237 : {
2238 1256303 : return cx->runtime->updateMallocCounter(cx, nbytes);
2239 : }
2240 :
2241 : JS_PUBLIC_API(char *)
2242 49992 : JS_strdup(JSContext *cx, const char *s)
2243 : {
2244 49992 : AssertNoGC(cx);
2245 49992 : size_t n = strlen(s) + 1;
2246 49992 : void *p = cx->malloc_(n);
2247 49992 : if (!p)
2248 0 : return NULL;
2249 49992 : return (char *)js_memcpy(p, s, n);
2250 : }
2251 :
2252 : JS_PUBLIC_API(JSBool)
2253 90868 : JS_NewNumberValue(JSContext *cx, double d, jsval *rval)
2254 : {
2255 90868 : AssertNoGC(cx);
2256 90868 : d = JS_CANONICALIZE_NAN(d);
2257 90868 : rval->setNumber(d);
2258 90868 : return JS_TRUE;
2259 : }
2260 :
2261 : #undef JS_AddRoot
2262 :
2263 : JS_PUBLIC_API(JSBool)
2264 441414 : JS_AddValueRoot(JSContext *cx, jsval *vp)
2265 : {
2266 441414 : AssertNoGC(cx);
2267 882828 : CHECK_REQUEST(cx);
2268 441414 : return js_AddRoot(cx, vp, NULL);
2269 : }
2270 :
2271 : JS_PUBLIC_API(JSBool)
2272 0 : JS_AddStringRoot(JSContext *cx, JSString **rp)
2273 : {
2274 0 : AssertNoGC(cx);
2275 0 : CHECK_REQUEST(cx);
2276 0 : return js_AddGCThingRoot(cx, (void **)rp, NULL);
2277 : }
2278 :
2279 : JS_PUBLIC_API(JSBool)
2280 0 : JS_AddObjectRoot(JSContext *cx, JSObject **rp)
2281 : {
2282 0 : AssertNoGC(cx);
2283 0 : CHECK_REQUEST(cx);
2284 0 : return js_AddGCThingRoot(cx, (void **)rp, NULL);
2285 : }
2286 :
2287 : JS_PUBLIC_API(JSBool)
2288 0 : JS_AddGCThingRoot(JSContext *cx, void **rp)
2289 : {
2290 0 : AssertNoGC(cx);
2291 0 : CHECK_REQUEST(cx);
2292 0 : return js_AddGCThingRoot(cx, (void **)rp, NULL);
2293 : }
2294 :
2295 : JS_PUBLIC_API(JSBool)
2296 2 : JS_AddNamedValueRoot(JSContext *cx, jsval *vp, const char *name)
2297 : {
2298 2 : AssertNoGC(cx);
2299 4 : CHECK_REQUEST(cx);
2300 2 : return js_AddRoot(cx, vp, name);
2301 : }
2302 :
2303 : JS_PUBLIC_API(JSBool)
2304 0 : JS_AddNamedStringRoot(JSContext *cx, JSString **rp, const char *name)
2305 : {
2306 0 : AssertNoGC(cx);
2307 0 : CHECK_REQUEST(cx);
2308 0 : return js_AddGCThingRoot(cx, (void **)rp, name);
2309 : }
2310 :
2311 : JS_PUBLIC_API(JSBool)
2312 30230 : JS_AddNamedObjectRoot(JSContext *cx, JSObject **rp, const char *name)
2313 : {
2314 30230 : AssertNoGC(cx);
2315 60460 : CHECK_REQUEST(cx);
2316 30230 : return js_AddGCThingRoot(cx, (void **)rp, name);
2317 : }
2318 :
2319 : JS_PUBLIC_API(JSBool)
2320 0 : JS_AddNamedScriptRoot(JSContext *cx, JSScript **rp, const char *name)
2321 : {
2322 0 : AssertNoGC(cx);
2323 0 : CHECK_REQUEST(cx);
2324 0 : return js_AddGCThingRoot(cx, (void **)rp, name);
2325 : }
2326 :
2327 : JS_PUBLIC_API(JSBool)
2328 0 : JS_AddNamedGCThingRoot(JSContext *cx, void **rp, const char *name)
2329 : {
2330 0 : AssertNoGC(cx);
2331 0 : CHECK_REQUEST(cx);
2332 0 : return js_AddGCThingRoot(cx, (void **)rp, name);
2333 : }
2334 :
2335 : /* We allow unrooting from finalizers within the GC */
2336 :
2337 : JS_PUBLIC_API(JSBool)
2338 441417 : JS_RemoveValueRoot(JSContext *cx, jsval *vp)
2339 : {
2340 882834 : CHECK_REQUEST(cx);
2341 441417 : return js_RemoveRoot(cx->runtime, (void *)vp);
2342 : }
2343 :
2344 : JS_PUBLIC_API(JSBool)
2345 0 : JS_RemoveStringRoot(JSContext *cx, JSString **rp)
2346 : {
2347 0 : CHECK_REQUEST(cx);
2348 0 : return js_RemoveRoot(cx->runtime, (void *)rp);
2349 : }
2350 :
2351 : JS_PUBLIC_API(JSBool)
2352 30230 : JS_RemoveObjectRoot(JSContext *cx, JSObject **rp)
2353 : {
2354 60460 : CHECK_REQUEST(cx);
2355 30230 : return js_RemoveRoot(cx->runtime, (void *)rp);
2356 : }
2357 :
2358 : JS_PUBLIC_API(JSBool)
2359 0 : JS_RemoveScriptRoot(JSContext *cx, JSScript **rp)
2360 : {
2361 0 : CHECK_REQUEST(cx);
2362 0 : return js_RemoveRoot(cx->runtime, (void *)rp);
2363 : }
2364 :
2365 : JS_PUBLIC_API(JSBool)
2366 0 : JS_RemoveGCThingRoot(JSContext *cx, void **rp)
2367 : {
2368 0 : CHECK_REQUEST(cx);
2369 0 : return js_RemoveRoot(cx->runtime, (void *)rp);
2370 : }
2371 :
2372 : JS_NEVER_INLINE JS_PUBLIC_API(void)
2373 0 : JS_AnchorPtr(void *p)
2374 : {
2375 0 : }
2376 :
2377 : #ifdef DEBUG
2378 :
2379 : JS_PUBLIC_API(void)
2380 0 : JS_DumpNamedRoots(JSRuntime *rt,
2381 : void (*dump)(const char *name, void *rp, JSGCRootType type, void *data),
2382 : void *data)
2383 : {
2384 0 : js_DumpNamedRoots(rt, dump, data);
2385 0 : }
2386 :
2387 : #endif /* DEBUG */
2388 :
2389 : JS_PUBLIC_API(uint32_t)
2390 0 : JS_MapGCRoots(JSRuntime *rt, JSGCRootMapFun map, void *data)
2391 : {
2392 0 : return js_MapGCRoots(rt, map, data);
2393 : }
2394 :
2395 : JS_PUBLIC_API(JSBool)
2396 0 : JS_LockGCThing(JSContext *cx, void *thing)
2397 : {
2398 : JSBool ok;
2399 :
2400 0 : AssertNoGC(cx);
2401 0 : CHECK_REQUEST(cx);
2402 0 : ok = js_LockGCThingRT(cx->runtime, thing);
2403 0 : if (!ok)
2404 0 : JS_ReportOutOfMemory(cx);
2405 0 : return ok;
2406 : }
2407 :
2408 : JS_PUBLIC_API(JSBool)
2409 0 : JS_LockGCThingRT(JSRuntime *rt, void *thing)
2410 : {
2411 0 : return js_LockGCThingRT(rt, thing);
2412 : }
2413 :
2414 : JS_PUBLIC_API(JSBool)
2415 0 : JS_UnlockGCThing(JSContext *cx, void *thing)
2416 : {
2417 0 : AssertNoGC(cx);
2418 0 : CHECK_REQUEST(cx);
2419 0 : js_UnlockGCThingRT(cx->runtime, thing);
2420 0 : return true;
2421 : }
2422 :
2423 : JS_PUBLIC_API(JSBool)
2424 0 : JS_UnlockGCThingRT(JSRuntime *rt, void *thing)
2425 : {
2426 0 : js_UnlockGCThingRT(rt, thing);
2427 0 : return true;
2428 : }
2429 :
2430 : JS_PUBLIC_API(void)
2431 1404 : JS_SetExtraGCRootsTracer(JSRuntime *rt, JSTraceDataOp traceOp, void *data)
2432 : {
2433 1404 : AssertNoGC(rt);
2434 1404 : rt->gcBlackRootsTraceOp = traceOp;
2435 1404 : rt->gcBlackRootsData = data;
2436 1404 : }
2437 :
2438 : JS_PUBLIC_API(void)
2439 810360 : JS_TracerInit(JSTracer *trc, JSRuntime *rt, JSTraceCallback callback)
2440 : {
2441 810360 : InitTracer(trc, rt, callback);
2442 810360 : }
2443 :
2444 : JS_PUBLIC_API(void)
2445 567 : JS_TraceRuntime(JSTracer *trc)
2446 : {
2447 567 : AssertNoGC(trc->runtime);
2448 567 : TraceRuntime(trc);
2449 567 : }
2450 :
2451 : JS_PUBLIC_API(void)
2452 26044482 : JS_TraceChildren(JSTracer *trc, void *thing, JSGCTraceKind kind)
2453 : {
2454 26044482 : js::TraceChildren(trc, thing, kind);
2455 26044482 : }
2456 :
2457 : JS_PUBLIC_API(void)
2458 8642335 : JS_CallTracer(JSTracer *trc, void *thing, JSGCTraceKind kind)
2459 : {
2460 8642335 : js::CallTracer(trc, thing, kind);
2461 8642335 : }
2462 :
2463 : #ifdef DEBUG
2464 :
2465 : JS_PUBLIC_API(void)
2466 0 : JS_PrintTraceThingInfo(char *buf, size_t bufsize, JSTracer *trc, void *thing,
2467 : JSGCTraceKind kind, JSBool details)
2468 : {
2469 0 : const char *name = NULL; /* silence uninitialized warning */
2470 : size_t n;
2471 :
2472 0 : if (bufsize == 0)
2473 0 : return;
2474 :
2475 0 : switch (kind) {
2476 : case JSTRACE_OBJECT:
2477 : {
2478 0 : name = static_cast<JSObject *>(thing)->getClass()->name;
2479 0 : break;
2480 : }
2481 :
2482 : case JSTRACE_STRING:
2483 0 : name = ((JSString *)thing)->isDependent()
2484 : ? "substring"
2485 0 : : "string";
2486 0 : break;
2487 :
2488 : case JSTRACE_SCRIPT:
2489 0 : name = "script";
2490 0 : break;
2491 :
2492 : case JSTRACE_SHAPE:
2493 0 : name = "shape";
2494 0 : break;
2495 :
2496 : case JSTRACE_BASE_SHAPE:
2497 0 : name = "base_shape";
2498 0 : break;
2499 :
2500 : case JSTRACE_TYPE_OBJECT:
2501 0 : name = "type_object";
2502 0 : break;
2503 :
2504 : #if JS_HAS_XML_SUPPORT
2505 : case JSTRACE_XML:
2506 0 : name = "xml";
2507 0 : break;
2508 : #endif
2509 : }
2510 :
2511 0 : n = strlen(name);
2512 0 : if (n > bufsize - 1)
2513 0 : n = bufsize - 1;
2514 0 : js_memcpy(buf, name, n + 1);
2515 0 : buf += n;
2516 0 : bufsize -= n;
2517 0 : *buf = '\0';
2518 :
2519 0 : if (details && bufsize > 2) {
2520 0 : switch (kind) {
2521 : case JSTRACE_OBJECT:
2522 : {
2523 0 : JSObject *obj = (JSObject *)thing;
2524 0 : Class *clasp = obj->getClass();
2525 0 : if (clasp == &FunctionClass) {
2526 0 : JSFunction *fun = obj->toFunction();
2527 0 : if (!fun) {
2528 0 : JS_snprintf(buf, bufsize, " <newborn>");
2529 0 : } else if (fun != obj) {
2530 0 : JS_snprintf(buf, bufsize, " %p", fun);
2531 : } else {
2532 0 : if (fun->atom) {
2533 0 : *buf++ = ' ';
2534 0 : bufsize--;
2535 0 : PutEscapedString(buf, bufsize, fun->atom, 0);
2536 : }
2537 : }
2538 0 : } else if (clasp->flags & JSCLASS_HAS_PRIVATE) {
2539 0 : JS_snprintf(buf, bufsize, " %p", obj->getPrivate());
2540 : } else {
2541 0 : JS_snprintf(buf, bufsize, " <no private>");
2542 : }
2543 0 : break;
2544 : }
2545 :
2546 : case JSTRACE_STRING:
2547 : {
2548 0 : *buf++ = ' ';
2549 0 : bufsize--;
2550 0 : JSString *str = (JSString *)thing;
2551 0 : if (str->isLinear())
2552 0 : PutEscapedString(buf, bufsize, &str->asLinear(), 0);
2553 : else
2554 0 : JS_snprintf(buf, bufsize, "<rope: length %d>", (int)str->length());
2555 0 : break;
2556 : }
2557 :
2558 : case JSTRACE_SCRIPT:
2559 : {
2560 0 : JSScript *script = static_cast<JSScript *>(thing);
2561 0 : JS_snprintf(buf, bufsize, " %s:%u", script->filename, unsigned(script->lineno));
2562 0 : break;
2563 : }
2564 :
2565 : case JSTRACE_SHAPE:
2566 : case JSTRACE_BASE_SHAPE:
2567 : case JSTRACE_TYPE_OBJECT:
2568 0 : break;
2569 :
2570 : #if JS_HAS_XML_SUPPORT
2571 : case JSTRACE_XML:
2572 : {
2573 : extern const char *js_xml_class_str[];
2574 0 : JSXML *xml = (JSXML *)thing;
2575 :
2576 0 : JS_snprintf(buf, bufsize, " %s", js_xml_class_str[xml->xml_class]);
2577 0 : break;
2578 : }
2579 : #endif
2580 : }
2581 : }
2582 0 : buf[bufsize - 1] = '\0';
2583 : }
2584 :
2585 : extern JS_PUBLIC_API(const char *)
2586 0 : JS_GetTraceEdgeName(JSTracer *trc, char *buffer, int bufferSize)
2587 : {
2588 0 : if (trc->debugPrinter) {
2589 0 : trc->debugPrinter(trc, buffer, bufferSize);
2590 0 : return buffer;
2591 : }
2592 0 : if (trc->debugPrintIndex != (size_t) - 1) {
2593 : JS_snprintf(buffer, bufferSize, "%s[%lu]",
2594 : (const char *)trc->debugPrintArg,
2595 0 : trc->debugPrintIndex);
2596 0 : return buffer;
2597 : }
2598 0 : return (const char*)trc->debugPrintArg;
2599 : }
2600 :
2601 : typedef struct JSHeapDumpNode JSHeapDumpNode;
2602 :
2603 : struct JSHeapDumpNode {
2604 : void *thing;
2605 : JSGCTraceKind kind;
2606 : JSHeapDumpNode *next; /* next sibling */
2607 : JSHeapDumpNode *parent; /* node with the thing that refer to thing
2608 : from this node */
2609 : char edgeName[1]; /* name of the edge from parent->thing
2610 : into thing */
2611 : };
2612 :
2613 : typedef struct JSDumpingTracer {
2614 : JSTracer base;
2615 : JSDHashTable visited;
2616 : bool ok;
2617 : void *startThing;
2618 : void *thingToFind;
2619 : void *thingToIgnore;
2620 : JSHeapDumpNode *parentNode;
2621 : JSHeapDumpNode **lastNodep;
2622 : char buffer[200];
2623 : } JSDumpingTracer;
2624 :
2625 : static void
2626 0 : DumpNotify(JSTracer *trc, void **thingp, JSGCTraceKind kind)
2627 : {
2628 0 : void *thing = *thingp;
2629 : JSDumpingTracer *dtrc;
2630 : JSDHashEntryStub *entry;
2631 :
2632 0 : JS_ASSERT(trc->callback == DumpNotify);
2633 0 : dtrc = (JSDumpingTracer *)trc;
2634 :
2635 0 : if (!dtrc->ok || thing == dtrc->thingToIgnore)
2636 0 : return;
2637 :
2638 : /*
2639 : * Check if we have already seen thing unless it is thingToFind to include
2640 : * it to the graph each time we reach it and print all live things that
2641 : * refer to thingToFind.
2642 : *
2643 : * This does not print all possible paths leading to thingToFind since
2644 : * when a thing A refers directly or indirectly to thingToFind and A is
2645 : * present several times in the graph, we will print only the first path
2646 : * leading to A and thingToFind, other ways to reach A will be ignored.
2647 : */
2648 0 : if (dtrc->thingToFind != thing) {
2649 : /*
2650 : * The startThing check allows to avoid putting startThing into the
2651 : * hash table before tracing startThing in JS_DumpHeap.
2652 : */
2653 0 : if (thing == dtrc->startThing)
2654 0 : return;
2655 : entry = (JSDHashEntryStub *)
2656 0 : JS_DHashTableOperate(&dtrc->visited, thing, JS_DHASH_ADD);
2657 0 : if (!entry) {
2658 0 : dtrc->ok = false;
2659 0 : return;
2660 : }
2661 0 : if (entry->key)
2662 0 : return;
2663 0 : entry->key = thing;
2664 : }
2665 :
2666 0 : const char *edgeName = JS_GetTraceEdgeName(&dtrc->base, dtrc->buffer, sizeof(dtrc->buffer));
2667 0 : size_t edgeNameSize = strlen(edgeName) + 1;
2668 0 : size_t bytes = offsetof(JSHeapDumpNode, edgeName) + edgeNameSize;
2669 0 : JSHeapDumpNode *node = (JSHeapDumpNode *) OffTheBooks::malloc_(bytes);
2670 0 : if (!node) {
2671 0 : dtrc->ok = false;
2672 0 : return;
2673 : }
2674 :
2675 0 : node->thing = thing;
2676 0 : node->kind = kind;
2677 0 : node->next = NULL;
2678 0 : node->parent = dtrc->parentNode;
2679 0 : js_memcpy(node->edgeName, edgeName, edgeNameSize);
2680 :
2681 0 : JS_ASSERT(!*dtrc->lastNodep);
2682 0 : *dtrc->lastNodep = node;
2683 0 : dtrc->lastNodep = &node->next;
2684 : }
2685 :
2686 : /* Dump node and the chain that leads to thing it contains. */
2687 : static JSBool
2688 0 : DumpNode(JSDumpingTracer *dtrc, FILE* fp, JSHeapDumpNode *node)
2689 : {
2690 : JSHeapDumpNode *prev, *following;
2691 : size_t chainLimit;
2692 : enum { MAX_PARENTS_TO_PRINT = 10 };
2693 :
2694 : JS_PrintTraceThingInfo(dtrc->buffer, sizeof dtrc->buffer,
2695 0 : &dtrc->base, node->thing, node->kind, JS_TRUE);
2696 0 : if (fprintf(fp, "%p %-22s via ", node->thing, dtrc->buffer) < 0)
2697 0 : return JS_FALSE;
2698 :
2699 : /*
2700 : * We need to print the parent chain in the reverse order. To do it in
2701 : * O(N) time where N is the chain length we first reverse the chain while
2702 : * searching for the top and then print each node while restoring the
2703 : * chain order.
2704 : */
2705 0 : chainLimit = MAX_PARENTS_TO_PRINT;
2706 0 : prev = NULL;
2707 0 : for (;;) {
2708 0 : following = node->parent;
2709 0 : node->parent = prev;
2710 0 : prev = node;
2711 0 : node = following;
2712 0 : if (!node)
2713 0 : break;
2714 0 : if (chainLimit == 0) {
2715 0 : if (fputs("...", fp) < 0)
2716 0 : return JS_FALSE;
2717 0 : break;
2718 : }
2719 0 : --chainLimit;
2720 : }
2721 :
2722 0 : node = prev;
2723 0 : prev = following;
2724 0 : bool ok = true;
2725 0 : do {
2726 : /* Loop must continue even when !ok to restore the parent chain. */
2727 0 : if (ok) {
2728 0 : if (!prev) {
2729 : /* Print edge from some runtime root or startThing. */
2730 0 : if (fputs(node->edgeName, fp) < 0)
2731 0 : ok = false;
2732 : } else {
2733 : JS_PrintTraceThingInfo(dtrc->buffer, sizeof dtrc->buffer,
2734 : &dtrc->base, prev->thing, prev->kind,
2735 0 : JS_FALSE);
2736 0 : if (fprintf(fp, "(%p %s).%s",
2737 0 : prev->thing, dtrc->buffer, node->edgeName) < 0) {
2738 0 : ok = false;
2739 : }
2740 : }
2741 : }
2742 0 : following = node->parent;
2743 0 : node->parent = prev;
2744 0 : prev = node;
2745 0 : node = following;
2746 : } while (node);
2747 :
2748 0 : return ok && putc('\n', fp) >= 0;
2749 : }
2750 :
2751 : JS_PUBLIC_API(JSBool)
2752 0 : JS_DumpHeap(JSRuntime *rt, FILE *fp, void* startThing, JSGCTraceKind startKind,
2753 : void *thingToFind, size_t maxDepth, void *thingToIgnore)
2754 : {
2755 : JSDumpingTracer dtrc;
2756 : JSHeapDumpNode *node, *children, *next, *parent;
2757 : size_t depth;
2758 : JSBool thingToFindWasTraced;
2759 :
2760 0 : if (maxDepth == 0)
2761 0 : return JS_TRUE;
2762 :
2763 0 : JS_TracerInit(&dtrc.base, rt, DumpNotify);
2764 0 : if (!JS_DHashTableInit(&dtrc.visited, JS_DHashGetStubOps(),
2765 : NULL, sizeof(JSDHashEntryStub),
2766 0 : JS_DHASH_DEFAULT_CAPACITY(100))) {
2767 0 : return false;
2768 : }
2769 0 : dtrc.ok = JS_TRUE;
2770 0 : dtrc.startThing = startThing;
2771 0 : dtrc.thingToFind = thingToFind;
2772 0 : dtrc.thingToIgnore = thingToIgnore;
2773 0 : dtrc.parentNode = NULL;
2774 0 : node = NULL;
2775 0 : dtrc.lastNodep = &node;
2776 0 : if (!startThing) {
2777 0 : JS_ASSERT(startKind == JSTRACE_OBJECT);
2778 0 : TraceRuntime(&dtrc.base);
2779 : } else {
2780 0 : JS_TraceChildren(&dtrc.base, startThing, startKind);
2781 : }
2782 :
2783 0 : depth = 1;
2784 0 : if (!node)
2785 0 : goto dump_out;
2786 :
2787 0 : thingToFindWasTraced = thingToFind && thingToFind == startThing;
2788 0 : for (;;) {
2789 : /*
2790 : * Loop must continue even when !dtrc.ok to free all nodes allocated
2791 : * so far.
2792 : */
2793 0 : if (dtrc.ok) {
2794 0 : if (thingToFind == NULL || thingToFind == node->thing)
2795 0 : dtrc.ok = DumpNode(&dtrc, fp, node);
2796 :
2797 : /* Descend into children. */
2798 0 : if (dtrc.ok &&
2799 : depth < maxDepth &&
2800 : (thingToFind != node->thing || !thingToFindWasTraced)) {
2801 0 : dtrc.parentNode = node;
2802 0 : children = NULL;
2803 0 : dtrc.lastNodep = &children;
2804 0 : JS_TraceChildren(&dtrc.base, node->thing, node->kind);
2805 0 : if (thingToFind == node->thing)
2806 0 : thingToFindWasTraced = JS_TRUE;
2807 0 : if (children != NULL) {
2808 0 : ++depth;
2809 0 : node = children;
2810 0 : continue;
2811 : }
2812 : }
2813 : }
2814 :
2815 : /* Move to next or parents next and free the node. */
2816 0 : for (;;) {
2817 0 : next = node->next;
2818 0 : parent = node->parent;
2819 0 : Foreground::free_(node);
2820 0 : node = next;
2821 0 : if (node)
2822 0 : break;
2823 0 : if (!parent)
2824 0 : goto dump_out;
2825 0 : JS_ASSERT(depth > 1);
2826 0 : --depth;
2827 0 : node = parent;
2828 : }
2829 : }
2830 :
2831 : dump_out:
2832 0 : JS_ASSERT(depth == 1);
2833 0 : JS_DHashTableFinish(&dtrc.visited);
2834 0 : return dtrc.ok;
2835 : }
2836 :
2837 : #endif /* DEBUG */
2838 :
2839 : extern JS_PUBLIC_API(JSBool)
2840 2779809 : JS_IsGCMarkingTracer(JSTracer *trc)
2841 : {
2842 2779809 : return IS_GC_MARKING_TRACER(trc);
2843 : }
2844 :
2845 : JS_PUBLIC_API(void)
2846 14358 : JS_CompartmentGC(JSContext *cx, JSCompartment *comp)
2847 : {
2848 14358 : AssertNoGC(cx);
2849 :
2850 : /* We cannot GC the atoms compartment alone; use a full GC instead. */
2851 14358 : JS_ASSERT(comp != cx->runtime->atomsCompartment);
2852 :
2853 14358 : GC(cx, comp, GC_NORMAL, gcreason::API);
2854 14358 : }
2855 :
2856 : JS_PUBLIC_API(void)
2857 5740 : JS_GC(JSContext *cx)
2858 : {
2859 5740 : JS_CompartmentGC(cx, NULL);
2860 5740 : }
2861 :
2862 : JS_PUBLIC_API(void)
2863 0 : JS_MaybeGC(JSContext *cx)
2864 : {
2865 0 : MaybeGC(cx);
2866 0 : }
2867 :
2868 : JS_PUBLIC_API(void)
2869 1404 : JS_SetGCCallback(JSRuntime *rt, JSGCCallback cb)
2870 : {
2871 1404 : AssertNoGC(rt);
2872 1404 : rt->gcCallback = cb;
2873 1404 : }
2874 :
2875 : JS_PUBLIC_API(void)
2876 1405 : JS_SetFinalizeCallback(JSRuntime *rt, JSFinalizeCallback cb)
2877 : {
2878 1405 : AssertNoGC(rt);
2879 1405 : rt->gcFinalizeCallback = cb;
2880 1405 : }
2881 :
2882 : JS_PUBLIC_API(JSBool)
2883 496873 : JS_IsAboutToBeFinalized(void *thing)
2884 : {
2885 496873 : gc::Cell *t = static_cast<gc::Cell *>(thing);
2886 496873 : return IsAboutToBeFinalized(t);
2887 : }
2888 :
2889 : JS_PUBLIC_API(void)
2890 38474 : JS_SetGCParameter(JSRuntime *rt, JSGCParamKey key, uint32_t value)
2891 : {
2892 38474 : switch (key) {
2893 : case JSGC_MAX_BYTES: {
2894 19869 : JS_ASSERT(value >= rt->gcBytes);
2895 19869 : rt->gcMaxBytes = value;
2896 19869 : break;
2897 : }
2898 : case JSGC_MAX_MALLOC_BYTES:
2899 50 : rt->setGCMaxMallocBytes(value);
2900 50 : break;
2901 : case JSGC_SLICE_TIME_BUDGET:
2902 50 : rt->gcSliceBudget = SliceBudget::TimeBudget(value);
2903 50 : break;
2904 : case JSGC_MARK_STACK_LIMIT:
2905 0 : js::SetMarkStackLimit(rt, value);
2906 0 : break;
2907 : default:
2908 18505 : JS_ASSERT(key == JSGC_MODE);
2909 18505 : rt->gcMode = JSGCMode(value);
2910 0 : JS_ASSERT(rt->gcMode == JSGC_MODE_GLOBAL ||
2911 : rt->gcMode == JSGC_MODE_COMPARTMENT ||
2912 18505 : rt->gcMode == JSGC_MODE_INCREMENTAL);
2913 18505 : return;
2914 : }
2915 : }
2916 :
2917 : JS_PUBLIC_API(uint32_t)
2918 1434 : JS_GetGCParameter(JSRuntime *rt, JSGCParamKey key)
2919 : {
2920 1434 : switch (key) {
2921 : case JSGC_MAX_BYTES:
2922 0 : return uint32_t(rt->gcMaxBytes);
2923 : case JSGC_MAX_MALLOC_BYTES:
2924 0 : return rt->gcMaxMallocBytes;
2925 : case JSGC_BYTES:
2926 18 : return uint32_t(rt->gcBytes);
2927 : case JSGC_MODE:
2928 0 : return uint32_t(rt->gcMode);
2929 : case JSGC_UNUSED_CHUNKS:
2930 3 : return uint32_t(rt->gcChunkPool.getEmptyCount());
2931 : case JSGC_TOTAL_CHUNKS:
2932 9 : return uint32_t(rt->gcChunkSet.count() + rt->gcChunkPool.getEmptyCount());
2933 : case JSGC_SLICE_TIME_BUDGET:
2934 0 : return uint32_t(rt->gcSliceBudget > 0 ? rt->gcSliceBudget / PRMJ_USEC_PER_MSEC : 0);
2935 : case JSGC_MARK_STACK_LIMIT:
2936 0 : return rt->gcMarker.sizeLimit();
2937 : default:
2938 1404 : JS_ASSERT(key == JSGC_NUMBER);
2939 1404 : return uint32_t(rt->gcNumber);
2940 : }
2941 : }
2942 :
2943 : JS_PUBLIC_API(void)
2944 19809 : JS_SetGCParameterForThread(JSContext *cx, JSGCParamKey key, uint32_t value)
2945 : {
2946 19809 : JS_ASSERT(key == JSGC_MAX_CODE_CACHE_BYTES);
2947 19809 : }
2948 :
2949 : JS_PUBLIC_API(uint32_t)
2950 0 : JS_GetGCParameterForThread(JSContext *cx, JSGCParamKey key)
2951 : {
2952 0 : JS_ASSERT(key == JSGC_MAX_CODE_CACHE_BYTES);
2953 0 : return 0;
2954 : }
2955 :
2956 : JS_PUBLIC_API(void)
2957 0 : JS_FlushCaches(JSContext *cx)
2958 : {
2959 0 : }
2960 :
2961 : JS_PUBLIC_API(JSString *)
2962 977008 : JS_NewExternalString(JSContext *cx, const jschar *chars, size_t length,
2963 : const JSStringFinalizer *fin)
2964 : {
2965 977008 : AssertNoGC(cx);
2966 1954016 : CHECK_REQUEST(cx);
2967 977008 : JSString *s = JSExternalString::new_(cx, chars, length, fin);
2968 977008 : Probes::createString(cx, s, length);
2969 977008 : return s;
2970 : }
2971 :
2972 : extern JS_PUBLIC_API(JSBool)
2973 0 : JS_IsExternalString(JSString *str)
2974 : {
2975 0 : return str->isExternal();
2976 : }
2977 :
2978 : extern JS_PUBLIC_API(const JSStringFinalizer *)
2979 0 : JS_GetExternalStringFinalizer(JSString *str)
2980 : {
2981 0 : return str->asExternal().externalFinalizer();
2982 : }
2983 :
2984 : JS_PUBLIC_API(void)
2985 19905 : JS_SetNativeStackQuota(JSRuntime *rt, size_t stackSize)
2986 : {
2987 19905 : rt->nativeStackQuota = stackSize;
2988 19905 : if (!rt->nativeStackBase)
2989 0 : return;
2990 :
2991 : #if JS_STACK_GROWTH_DIRECTION > 0
2992 : if (stackSize == 0) {
2993 : rt->nativeStackLimit = UINTPTR_MAX;
2994 : } else {
2995 : JS_ASSERT(rt->nativeStackBase <= size_t(-1) - stackSize);
2996 : rt->nativeStackLimit = rt->nativeStackBase + stackSize - 1;
2997 : }
2998 : #else
2999 19905 : if (stackSize == 0) {
3000 0 : rt->nativeStackLimit = 0;
3001 : } else {
3002 19905 : JS_ASSERT(rt->nativeStackBase >= stackSize);
3003 19905 : rt->nativeStackLimit = rt->nativeStackBase - (stackSize - 1);
3004 : }
3005 : #endif
3006 : }
3007 :
3008 : /************************************************************************/
3009 :
3010 : JS_PUBLIC_API(int)
3011 0 : JS_IdArrayLength(JSContext *cx, JSIdArray *ida)
3012 : {
3013 0 : return ida->length;
3014 : }
3015 :
3016 : JS_PUBLIC_API(jsid)
3017 0 : JS_IdArrayGet(JSContext *cx, JSIdArray *ida, int index)
3018 : {
3019 0 : JS_ASSERT(index >= 0 && index < ida->length);
3020 0 : return ida->vector[index];
3021 : }
3022 :
3023 : JS_PUBLIC_API(void)
3024 2449 : JS_DestroyIdArray(JSContext *cx, JSIdArray *ida)
3025 : {
3026 2449 : cx->free_(ida);
3027 2449 : }
3028 :
3029 : JS_PUBLIC_API(JSBool)
3030 250204 : JS_ValueToId(JSContext *cx, jsval v, jsid *idp)
3031 : {
3032 250204 : AssertNoGC(cx);
3033 500408 : CHECK_REQUEST(cx);
3034 250204 : assertSameCompartment(cx, v);
3035 250204 : return ValueToId(cx, v, idp);
3036 : }
3037 :
3038 : JS_PUBLIC_API(JSBool)
3039 33 : JS_IdToValue(JSContext *cx, jsid id, jsval *vp)
3040 : {
3041 33 : AssertNoGC(cx);
3042 66 : CHECK_REQUEST(cx);
3043 33 : *vp = IdToJsval(id);
3044 33 : assertSameCompartment(cx, *vp);
3045 33 : return JS_TRUE;
3046 : }
3047 :
3048 : JS_PUBLIC_API(JSBool)
3049 0 : JS_DefaultValue(JSContext *cx, JSObject *obj, JSType hint, jsval *vp)
3050 : {
3051 0 : AssertNoGC(cx);
3052 0 : CHECK_REQUEST(cx);
3053 0 : JS_ASSERT(obj != NULL);
3054 0 : JS_ASSERT(hint == JSTYPE_VOID || hint == JSTYPE_STRING || hint == JSTYPE_NUMBER);
3055 0 : return obj->defaultValue(cx, hint, vp);
3056 : }
3057 :
3058 : JS_PUBLIC_API(JSBool)
3059 1688863 : JS_PropertyStub(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
3060 : {
3061 1688863 : return JS_TRUE;
3062 : }
3063 :
3064 : JS_PUBLIC_API(JSBool)
3065 0 : JS_StrictPropertyStub(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp)
3066 : {
3067 0 : return JS_TRUE;
3068 : }
3069 :
3070 : JS_PUBLIC_API(JSBool)
3071 2015561 : JS_EnumerateStub(JSContext *cx, JSObject *obj)
3072 : {
3073 2015561 : return JS_TRUE;
3074 : }
3075 :
3076 : JS_PUBLIC_API(JSBool)
3077 0 : JS_ResolveStub(JSContext *cx, JSObject *obj, jsid id)
3078 : {
3079 0 : return JS_TRUE;
3080 : }
3081 :
3082 : JS_PUBLIC_API(JSBool)
3083 127 : JS_ConvertStub(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
3084 : {
3085 127 : JS_ASSERT(type != JSTYPE_OBJECT && type != JSTYPE_FUNCTION);
3086 127 : JS_ASSERT(obj);
3087 127 : return DefaultValue(cx, obj, type, vp);
3088 : }
3089 :
3090 : JS_PUBLIC_API(void)
3091 5722142 : JS_FinalizeStub(JSContext *cx, JSObject *obj)
3092 5722142 : {}
3093 :
3094 : JS_PUBLIC_API(JSObject *)
3095 69759 : JS_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
3096 : JSClass *clasp, JSNative constructor, unsigned nargs,
3097 : JSPropertySpec *ps, JSFunctionSpec *fs,
3098 : JSPropertySpec *static_ps, JSFunctionSpec *static_fs)
3099 : {
3100 69759 : AssertNoGC(cx);
3101 139518 : CHECK_REQUEST(cx);
3102 69759 : assertSameCompartment(cx, obj, parent_proto);
3103 139518 : RootObject objRoot(cx, &obj);
3104 : return js_InitClass(cx, objRoot, parent_proto, Valueify(clasp), constructor,
3105 69759 : nargs, ps, fs, static_ps, static_fs);
3106 : }
3107 :
3108 : JS_PUBLIC_API(JSBool)
3109 274 : JS_LinkConstructorAndPrototype(JSContext *cx, JSObject *ctor, JSObject *proto)
3110 : {
3111 274 : return LinkConstructorAndPrototype(cx, ctor, proto);
3112 : }
3113 :
3114 : JS_PUBLIC_API(JSClass *)
3115 4513979 : JS_GetClass(JSObject *obj)
3116 : {
3117 4513979 : return obj->getJSClass();
3118 : }
3119 :
3120 : JS_PUBLIC_API(JSBool)
3121 861 : JS_InstanceOf(JSContext *cx, JSObject *obj, JSClass *clasp, jsval *argv)
3122 : {
3123 861 : AssertNoGC(cx);
3124 1722 : CHECK_REQUEST(cx);
3125 : #ifdef DEBUG
3126 861 : if (argv) {
3127 0 : assertSameCompartment(cx, obj);
3128 0 : assertSameCompartment(cx, JSValueArray(argv - 2, 2));
3129 : }
3130 : #endif
3131 861 : if (!obj || obj->getJSClass() != clasp) {
3132 0 : if (argv)
3133 0 : ReportIncompatibleMethod(cx, CallReceiverFromArgv(argv), Valueify(clasp));
3134 0 : return false;
3135 : }
3136 861 : return true;
3137 : }
3138 :
3139 : JS_PUBLIC_API(JSBool)
3140 0 : JS_HasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
3141 : {
3142 0 : AssertNoGC(cx);
3143 0 : assertSameCompartment(cx, obj, v);
3144 0 : return HasInstance(cx, obj, &v, bp);
3145 : }
3146 :
3147 : JS_PUBLIC_API(void *)
3148 148936 : JS_GetPrivate(JSObject *obj)
3149 : {
3150 : /* This function can be called by a finalizer. */
3151 148936 : return obj->getPrivate();
3152 : }
3153 :
3154 : JS_PUBLIC_API(void)
3155 1499751 : JS_SetPrivate(JSObject *obj, void *data)
3156 : {
3157 : /* This function can be called by a finalizer. */
3158 1499751 : obj->setPrivate(data);
3159 1499751 : }
3160 :
3161 : JS_PUBLIC_API(void *)
3162 9 : JS_GetInstancePrivate(JSContext *cx, JSObject *obj, JSClass *clasp, jsval *argv)
3163 : {
3164 9 : if (!JS_InstanceOf(cx, obj, clasp, argv))
3165 0 : return NULL;
3166 9 : return obj->getPrivate();
3167 : }
3168 :
3169 : JS_PUBLIC_API(JSObject *)
3170 92271 : JS_GetPrototype(JSObject *obj)
3171 : {
3172 92271 : return obj->getProto();
3173 : }
3174 :
3175 : JS_PUBLIC_API(JSBool)
3176 36315 : JS_SetPrototype(JSContext *cx, JSObject *obj, JSObject *proto)
3177 : {
3178 36315 : AssertNoGC(cx);
3179 72630 : CHECK_REQUEST(cx);
3180 36315 : assertSameCompartment(cx, obj, proto);
3181 36315 : return SetProto(cx, obj, proto, JS_FALSE);
3182 : }
3183 :
3184 : JS_PUBLIC_API(JSObject *)
3185 741180 : JS_GetParent(JSObject *obj)
3186 : {
3187 741180 : JS_ASSERT(!obj->isScope());
3188 741180 : return obj->getParent();
3189 : }
3190 :
3191 : JS_PUBLIC_API(JSBool)
3192 0 : JS_SetParent(JSContext *cx, JSObject *obj, JSObject *parent)
3193 : {
3194 0 : AssertNoGC(cx);
3195 0 : CHECK_REQUEST(cx);
3196 0 : JS_ASSERT(!obj->isScope());
3197 0 : JS_ASSERT(parent || !obj->getParent());
3198 0 : assertSameCompartment(cx, obj, parent);
3199 0 : return obj->setParent(cx, parent);
3200 : }
3201 :
3202 : JS_PUBLIC_API(JSObject *)
3203 139748 : JS_GetConstructor(JSContext *cx, JSObject *proto)
3204 : {
3205 : Value cval;
3206 :
3207 139748 : AssertNoGC(cx);
3208 279496 : CHECK_REQUEST(cx);
3209 139748 : assertSameCompartment(cx, proto);
3210 : {
3211 279496 : JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
3212 :
3213 139748 : if (!proto->getProperty(cx, cx->runtime->atomState.constructorAtom, &cval))
3214 0 : return NULL;
3215 : }
3216 139748 : if (!IsFunctionObject(cval)) {
3217 : JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NO_CONSTRUCTOR,
3218 0 : proto->getClass()->name);
3219 0 : return NULL;
3220 : }
3221 139748 : return &cval.toObject();
3222 : }
3223 :
3224 : JS_PUBLIC_API(JSBool)
3225 0 : JS_GetObjectId(JSContext *cx, JSObject *obj, jsid *idp)
3226 : {
3227 0 : AssertNoGC(cx);
3228 0 : assertSameCompartment(cx, obj);
3229 0 : *idp = OBJECT_TO_JSID(obj);
3230 0 : return JS_TRUE;
3231 : }
3232 :
3233 : JS_PUBLIC_API(JSObject *)
3234 38627 : JS_NewGlobalObject(JSContext *cx, JSClass *clasp)
3235 : {
3236 38627 : JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
3237 38627 : AssertNoGC(cx);
3238 77254 : CHECK_REQUEST(cx);
3239 :
3240 38627 : return GlobalObject::create(cx, Valueify(clasp));
3241 : }
3242 :
3243 : class AutoHoldCompartment {
3244 : public:
3245 25666 : explicit AutoHoldCompartment(JSCompartment *compartment JS_GUARD_OBJECT_NOTIFIER_PARAM)
3246 25666 : : holdp(&compartment->hold)
3247 : {
3248 25666 : JS_GUARD_OBJECT_NOTIFIER_INIT;
3249 25666 : *holdp = true;
3250 25666 : }
3251 :
3252 51332 : ~AutoHoldCompartment() {
3253 25666 : *holdp = false;
3254 25666 : }
3255 : private:
3256 : bool *holdp;
3257 : JS_DECL_USE_GUARD_OBJECT_NOTIFIER
3258 : };
3259 :
3260 : JS_PUBLIC_API(JSObject *)
3261 25666 : JS_NewCompartmentAndGlobalObject(JSContext *cx, JSClass *clasp, JSPrincipals *principals)
3262 : {
3263 25666 : AssertNoGC(cx);
3264 51332 : CHECK_REQUEST(cx);
3265 25666 : JSCompartment *compartment = NewCompartment(cx, principals);
3266 25666 : if (!compartment)
3267 0 : return NULL;
3268 :
3269 51332 : AutoHoldCompartment hold(compartment);
3270 :
3271 25666 : JSCompartment *saved = cx->compartment;
3272 25666 : cx->setCompartment(compartment);
3273 25666 : JSObject *obj = JS_NewGlobalObject(cx, clasp);
3274 25666 : cx->setCompartment(saved);
3275 :
3276 25666 : return obj;
3277 : }
3278 :
3279 : JS_PUBLIC_API(JSObject *)
3280 3197888 : JS_NewObject(JSContext *cx, JSClass *jsclasp, JSObject *proto, JSObject *parent)
3281 : {
3282 3197888 : JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
3283 3197888 : AssertNoGC(cx);
3284 6395776 : CHECK_REQUEST(cx);
3285 3197888 : assertSameCompartment(cx, proto, parent);
3286 :
3287 3197888 : Class *clasp = Valueify(jsclasp);
3288 3197888 : if (!clasp)
3289 9326 : clasp = &ObjectClass; /* default class is Object */
3290 :
3291 3197888 : JS_ASSERT(clasp != &FunctionClass);
3292 3197888 : JS_ASSERT(!(clasp->flags & JSCLASS_IS_GLOBAL));
3293 :
3294 3197888 : if (proto && !proto->setNewTypeUnknown(cx))
3295 0 : return NULL;
3296 :
3297 3197888 : JSObject *obj = NewObjectWithClassProto(cx, clasp, proto, parent);
3298 3197888 : if (obj) {
3299 3197888 : if (clasp->ext.equality)
3300 1236058 : MarkTypeObjectFlags(cx, obj, OBJECT_FLAG_SPECIAL_EQUALITY);
3301 3197888 : MarkTypeObjectUnknownProperties(cx, obj->type());
3302 : }
3303 :
3304 3197888 : JS_ASSERT_IF(obj, obj->getParent());
3305 3197888 : return obj;
3306 : }
3307 :
3308 : JS_PUBLIC_API(JSObject *)
3309 90 : JS_NewObjectWithGivenProto(JSContext *cx, JSClass *jsclasp, JSObject *proto, JSObject *parent)
3310 : {
3311 90 : JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
3312 90 : AssertNoGC(cx);
3313 180 : CHECK_REQUEST(cx);
3314 90 : assertSameCompartment(cx, proto, parent);
3315 :
3316 90 : Class *clasp = Valueify(jsclasp);
3317 90 : if (!clasp)
3318 0 : clasp = &ObjectClass; /* default class is Object */
3319 :
3320 90 : JS_ASSERT(clasp != &FunctionClass);
3321 90 : JS_ASSERT(!(clasp->flags & JSCLASS_IS_GLOBAL));
3322 :
3323 90 : JSObject *obj = NewObjectWithGivenProto(cx, clasp, proto, parent);
3324 90 : if (obj)
3325 90 : MarkTypeObjectUnknownProperties(cx, obj->type());
3326 90 : return obj;
3327 : }
3328 :
3329 : JS_PUBLIC_API(JSObject *)
3330 19 : JS_NewObjectForConstructor(JSContext *cx, const jsval *vp)
3331 : {
3332 19 : AssertNoGC(cx);
3333 38 : CHECK_REQUEST(cx);
3334 19 : assertSameCompartment(cx, *vp);
3335 :
3336 19 : return js_CreateThis(cx, JSVAL_TO_OBJECT(*vp));
3337 : }
3338 :
3339 : JS_PUBLIC_API(JSBool)
3340 0 : JS_IsExtensible(JSObject *obj)
3341 : {
3342 0 : return obj->isExtensible();
3343 : }
3344 :
3345 : JS_PUBLIC_API(JSBool)
3346 0 : JS_IsNative(JSObject *obj)
3347 : {
3348 0 : return obj->isNative();
3349 : }
3350 :
3351 : JS_PUBLIC_API(JSRuntime *)
3352 5600 : JS_GetObjectRuntime(JSObject *obj)
3353 : {
3354 5600 : return obj->compartment()->rt;
3355 : }
3356 :
3357 : JS_PUBLIC_API(JSBool)
3358 1214548 : JS_FreezeObject(JSContext *cx, JSObject *obj)
3359 : {
3360 1214548 : AssertNoGC(cx);
3361 2429096 : CHECK_REQUEST(cx);
3362 1214548 : assertSameCompartment(cx, obj);
3363 :
3364 1214548 : return obj->freeze(cx);
3365 : }
3366 :
3367 : JS_PUBLIC_API(JSBool)
3368 10007 : JS_DeepFreezeObject(JSContext *cx, JSObject *obj)
3369 : {
3370 10007 : AssertNoGC(cx);
3371 20014 : CHECK_REQUEST(cx);
3372 10007 : assertSameCompartment(cx, obj);
3373 :
3374 : /* Assume that non-extensible objects are already deep-frozen, to avoid divergence. */
3375 10007 : if (!obj->isExtensible())
3376 5003 : return true;
3377 :
3378 5004 : if (!obj->freeze(cx))
3379 0 : return false;
3380 :
3381 : /* Walk slots in obj and if any value is a non-null object, seal it. */
3382 15008 : for (uint32_t i = 0, n = obj->slotSpan(); i < n; ++i) {
3383 10004 : const Value &v = obj->getSlot(i);
3384 10004 : if (v.isPrimitive())
3385 0 : continue;
3386 10004 : if (!JS_DeepFreezeObject(cx, &v.toObject()))
3387 0 : return false;
3388 : }
3389 :
3390 5004 : return true;
3391 : }
3392 :
3393 : JS_PUBLIC_API(JSObject *)
3394 0 : JS_ConstructObject(JSContext *cx, JSClass *jsclasp, JSObject *parent)
3395 : {
3396 0 : return JS_ConstructObjectWithArguments(cx, jsclasp, parent, 0, NULL);
3397 : }
3398 :
3399 : JS_PUBLIC_API(JSObject *)
3400 7855 : JS_ConstructObjectWithArguments(JSContext *cx, JSClass *jsclasp, JSObject *parent,
3401 : unsigned argc, jsval *argv)
3402 : {
3403 7855 : AssertNoGC(cx);
3404 15710 : CHECK_REQUEST(cx);
3405 7855 : assertSameCompartment(cx, parent, JSValueArray(argv, argc));
3406 :
3407 15710 : AutoArrayRooter argtvr(cx, argc, argv);
3408 :
3409 7855 : Class *clasp = Valueify(jsclasp);
3410 7855 : if (!clasp)
3411 0 : clasp = &ObjectClass; /* default class is Object */
3412 :
3413 7855 : JSProtoKey protoKey = GetClassProtoKey(clasp);
3414 :
3415 : /* Protect constructor in case a crazy getter for .prototype uproots it. */
3416 15710 : AutoValueRooter tvr(cx);
3417 7855 : if (!js_FindClassObject(cx, parent, protoKey, tvr.addr(), clasp))
3418 0 : return NULL;
3419 :
3420 : Value rval;
3421 7855 : if (!InvokeConstructor(cx, tvr.value(), argc, argv, &rval))
3422 0 : return NULL;
3423 :
3424 : /*
3425 : * If the instance's class differs from what was requested, throw a type
3426 : * error.
3427 : */
3428 7855 : if (!rval.isObject() || rval.toObject().getClass() != clasp) {
3429 : JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
3430 0 : JSMSG_WRONG_CONSTRUCTOR, clasp->name);
3431 0 : return NULL;
3432 : }
3433 7855 : return &rval.toObject();
3434 : }
3435 :
3436 : static JSBool
3437 21955 : LookupPropertyById(JSContext *cx, JSObject *obj, jsid id, unsigned flags,
3438 : JSObject **objp, JSProperty **propp)
3439 : {
3440 21955 : AssertNoGC(cx);
3441 43910 : CHECK_REQUEST(cx);
3442 21955 : assertSameCompartment(cx, obj, id);
3443 :
3444 43910 : JSAutoResolveFlags rf(cx, flags);
3445 21955 : id = js_CheckForStringIndex(id);
3446 21955 : return obj->lookupGeneric(cx, id, objp, propp);
3447 : }
3448 :
3449 : #define AUTO_NAMELEN(s,n) (((n) == (size_t)-1) ? js_strlen(s) : (n))
3450 :
3451 : static JSBool
3452 303 : LookupResult(JSContext *cx, JSObject *obj, JSObject *obj2, jsid id,
3453 : JSProperty *prop, Value *vp)
3454 : {
3455 303 : if (!prop) {
3456 : /* XXX bad API: no way to tell "not defined" from "void value" */
3457 0 : vp->setUndefined();
3458 0 : return JS_TRUE;
3459 : }
3460 :
3461 303 : if (obj2->isNative()) {
3462 303 : Shape *shape = (Shape *) prop;
3463 :
3464 303 : if (shape->isMethod()) {
3465 0 : vp->setObject(*obj2->nativeGetMethod(shape));
3466 0 : return !!obj2->methodReadBarrier(cx, *shape, vp);
3467 : }
3468 :
3469 : /* Peek at the native property's slot value, without doing a Get. */
3470 303 : if (shape->hasSlot()) {
3471 282 : *vp = obj2->nativeGetSlot(shape->slot());
3472 282 : return true;
3473 : }
3474 : } else {
3475 0 : if (obj2->isDenseArray())
3476 0 : return js_GetDenseArrayElementValue(cx, obj2, id, vp);
3477 0 : if (obj2->isProxy()) {
3478 0 : AutoPropertyDescriptorRooter desc(cx);
3479 0 : if (!Proxy::getPropertyDescriptor(cx, obj2, id, false, &desc))
3480 0 : return false;
3481 0 : if (!(desc.attrs & JSPROP_SHARED)) {
3482 0 : *vp = desc.value;
3483 0 : return true;
3484 : }
3485 : }
3486 : }
3487 :
3488 : /* XXX bad API: no way to return "defined but value unknown" */
3489 21 : vp->setBoolean(true);
3490 21 : return true;
3491 : }
3492 :
3493 : JS_PUBLIC_API(JSBool)
3494 303 : JS_LookupPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
3495 : {
3496 : JSObject *obj2;
3497 : JSProperty *prop;
3498 303 : return LookupPropertyById(cx, obj, id, JSRESOLVE_QUALIFIED, &obj2, &prop) &&
3499 303 : LookupResult(cx, obj, obj2, id, prop, vp);
3500 : }
3501 :
3502 : JS_PUBLIC_API(JSBool)
3503 0 : JS_LookupElement(JSContext *cx, JSObject *obj, uint32_t index, jsval *vp)
3504 : {
3505 0 : CHECK_REQUEST(cx);
3506 : jsid id;
3507 0 : if (!IndexToId(cx, index, &id))
3508 0 : return false;
3509 0 : return JS_LookupPropertyById(cx, obj, id, vp);
3510 : }
3511 :
3512 : JS_PUBLIC_API(JSBool)
3513 1 : JS_LookupProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp)
3514 : {
3515 1 : JSAtom *atom = js_Atomize(cx, name, strlen(name));
3516 1 : return atom && JS_LookupPropertyById(cx, obj, ATOM_TO_JSID(atom), vp);
3517 : }
3518 :
3519 : JS_PUBLIC_API(JSBool)
3520 0 : JS_LookupUCProperty(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen, jsval *vp)
3521 : {
3522 0 : JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
3523 0 : return atom && JS_LookupPropertyById(cx, obj, ATOM_TO_JSID(atom), vp);
3524 : }
3525 :
3526 : JS_PUBLIC_API(JSBool)
3527 0 : JS_LookupPropertyWithFlagsById(JSContext *cx, JSObject *obj, jsid id, unsigned flags,
3528 : JSObject **objp, jsval *vp)
3529 : {
3530 : JSBool ok;
3531 : JSProperty *prop;
3532 :
3533 0 : AssertNoGC(cx);
3534 0 : CHECK_REQUEST(cx);
3535 0 : assertSameCompartment(cx, obj, id);
3536 0 : ok = obj->isNative()
3537 0 : ? LookupPropertyWithFlags(cx, obj, id, flags, objp, &prop)
3538 0 : : obj->lookupGeneric(cx, id, objp, &prop);
3539 0 : return ok && LookupResult(cx, obj, *objp, id, prop, vp);
3540 : }
3541 :
3542 : JS_PUBLIC_API(JSBool)
3543 0 : JS_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, const char *name, unsigned flags, jsval *vp)
3544 : {
3545 : JSObject *obj2;
3546 0 : JSAtom *atom = js_Atomize(cx, name, strlen(name));
3547 0 : return atom && JS_LookupPropertyWithFlagsById(cx, obj, ATOM_TO_JSID(atom), flags, &obj2, vp);
3548 : }
3549 :
3550 : JS_PUBLIC_API(JSBool)
3551 2754 : JS_HasPropertyById(JSContext *cx, JSObject *obj, jsid id, JSBool *foundp)
3552 : {
3553 : JSObject *obj2;
3554 : JSProperty *prop;
3555 : JSBool ok = LookupPropertyById(cx, obj, id, JSRESOLVE_QUALIFIED | JSRESOLVE_DETECTING,
3556 2754 : &obj2, &prop);
3557 2754 : *foundp = (prop != NULL);
3558 2754 : return ok;
3559 : }
3560 :
3561 : JS_PUBLIC_API(JSBool)
3562 0 : JS_HasElement(JSContext *cx, JSObject *obj, uint32_t index, JSBool *foundp)
3563 : {
3564 0 : AssertNoGC(cx);
3565 0 : CHECK_REQUEST(cx);
3566 : jsid id;
3567 0 : if (!IndexToId(cx, index, &id))
3568 0 : return false;
3569 0 : return JS_HasPropertyById(cx, obj, id, foundp);
3570 : }
3571 :
3572 : JS_PUBLIC_API(JSBool)
3573 1012 : JS_HasProperty(JSContext *cx, JSObject *obj, const char *name, JSBool *foundp)
3574 : {
3575 1012 : JSAtom *atom = js_Atomize(cx, name, strlen(name));
3576 1012 : return atom && JS_HasPropertyById(cx, obj, ATOM_TO_JSID(atom), foundp);
3577 : }
3578 :
3579 : JS_PUBLIC_API(JSBool)
3580 82 : JS_HasUCProperty(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen, JSBool *foundp)
3581 : {
3582 82 : JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
3583 82 : return atom && JS_HasPropertyById(cx, obj, ATOM_TO_JSID(atom), foundp);
3584 : }
3585 :
3586 : JS_PUBLIC_API(JSBool)
3587 0 : JS_AlreadyHasOwnPropertyById(JSContext *cx, JSObject *obj, jsid id, JSBool *foundp)
3588 : {
3589 0 : AssertNoGC(cx);
3590 0 : CHECK_REQUEST(cx);
3591 0 : assertSameCompartment(cx, obj, id);
3592 :
3593 0 : if (!obj->isNative()) {
3594 : JSObject *obj2;
3595 : JSProperty *prop;
3596 :
3597 0 : if (!LookupPropertyById(cx, obj, id, JSRESOLVE_QUALIFIED | JSRESOLVE_DETECTING,
3598 0 : &obj2, &prop)) {
3599 0 : return JS_FALSE;
3600 : }
3601 0 : *foundp = (obj == obj2);
3602 0 : return JS_TRUE;
3603 : }
3604 :
3605 0 : *foundp = obj->nativeContains(cx, id);
3606 0 : return JS_TRUE;
3607 : }
3608 :
3609 : JS_PUBLIC_API(JSBool)
3610 0 : JS_AlreadyHasOwnElement(JSContext *cx, JSObject *obj, uint32_t index, JSBool *foundp)
3611 : {
3612 0 : AssertNoGC(cx);
3613 0 : CHECK_REQUEST(cx);
3614 : jsid id;
3615 0 : if (!IndexToId(cx, index, &id))
3616 0 : return false;
3617 0 : return JS_AlreadyHasOwnPropertyById(cx, obj, id, foundp);
3618 : }
3619 :
3620 : JS_PUBLIC_API(JSBool)
3621 0 : JS_AlreadyHasOwnProperty(JSContext *cx, JSObject *obj, const char *name, JSBool *foundp)
3622 : {
3623 0 : JSAtom *atom = js_Atomize(cx, name, strlen(name));
3624 0 : return atom && JS_AlreadyHasOwnPropertyById(cx, obj, ATOM_TO_JSID(atom), foundp);
3625 : }
3626 :
3627 : JS_PUBLIC_API(JSBool)
3628 0 : JS_AlreadyHasOwnUCProperty(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen,
3629 : JSBool *foundp)
3630 : {
3631 0 : JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
3632 0 : return atom && JS_AlreadyHasOwnPropertyById(cx, obj, ATOM_TO_JSID(atom), foundp);
3633 : }
3634 :
3635 : static JSBool
3636 19603944 : DefinePropertyById(JSContext *cx, JSObject *obj, jsid id, const Value &value,
3637 : PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
3638 : unsigned flags, int tinyid)
3639 : {
3640 : /*
3641 : * JSPROP_READONLY has no meaning when accessors are involved. Ideally we'd
3642 : * throw if this happens, but we've accepted it for long enough that it's
3643 : * not worth trying to make callers change their ways. Just flip it off on
3644 : * its way through the API layer so that we can enforce this internally.
3645 : */
3646 19603944 : if (attrs & (JSPROP_GETTER | JSPROP_SETTER))
3647 1755907 : attrs &= ~JSPROP_READONLY;
3648 :
3649 19603944 : AssertNoGC(cx);
3650 39207888 : CHECK_REQUEST(cx);
3651 : assertSameCompartment(cx, obj, id, value,
3652 : (attrs & JSPROP_GETTER)
3653 : ? JS_FUNC_TO_DATA_PTR(JSObject *, getter)
3654 : : NULL,
3655 : (attrs & JSPROP_SETTER)
3656 : ? JS_FUNC_TO_DATA_PTR(JSObject *, setter)
3657 19603944 : : NULL);
3658 :
3659 39207888 : JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_DECLARING);
3660 19603944 : if (flags != 0 && obj->isNative()) {
3661 : return !!DefineNativeProperty(cx, obj, id, value, getter, setter,
3662 11256244 : attrs, flags, tinyid);
3663 : }
3664 8347700 : return obj->defineGeneric(cx, id, value, getter, setter, attrs);
3665 : }
3666 :
3667 : JS_PUBLIC_API(JSBool)
3668 1949911 : JS_DefinePropertyById(JSContext *cx, JSObject *obj, jsid id, jsval value,
3669 : JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
3670 : {
3671 1949911 : return DefinePropertyById(cx, obj, id, value, getter, setter, attrs, 0, 0);
3672 : }
3673 :
3674 : JS_PUBLIC_API(JSBool)
3675 459454 : JS_DefineElement(JSContext *cx, JSObject *obj, uint32_t index, jsval value,
3676 : JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
3677 : {
3678 459454 : AssertNoGC(cx);
3679 918908 : CHECK_REQUEST(cx);
3680 : jsid id;
3681 459454 : if (!IndexToId(cx, index, &id))
3682 0 : return false;
3683 459454 : return DefinePropertyById(cx, obj, id, value, getter, setter, attrs, 0, 0);
3684 : }
3685 :
3686 : static JSBool
3687 17194011 : DefineProperty(JSContext *cx, JSObject *obj, const char *name, const Value &value,
3688 : PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
3689 : unsigned flags, int tinyid)
3690 : {
3691 : jsid id;
3692 : JSAtom *atom;
3693 :
3694 34388022 : RootObject objRoot(cx, &obj);
3695 34388022 : RootValue valueRoot(cx, &value);
3696 :
3697 17194011 : if (attrs & JSPROP_INDEX) {
3698 0 : id = INT_TO_JSID(intptr_t(name));
3699 0 : atom = NULL;
3700 0 : attrs &= ~JSPROP_INDEX;
3701 : } else {
3702 17194011 : atom = js_Atomize(cx, name, strlen(name));
3703 17194011 : if (!atom)
3704 0 : return JS_FALSE;
3705 17194011 : id = ATOM_TO_JSID(atom);
3706 : }
3707 :
3708 17194011 : if (attrs & JSPROP_NATIVE_ACCESSORS) {
3709 1463872 : RootId idRoot(cx, &id);
3710 :
3711 731936 : JS_ASSERT(!(attrs & (JSPROP_GETTER | JSPROP_SETTER)));
3712 731936 : attrs &= ~JSPROP_NATIVE_ACCESSORS;
3713 731936 : if (getter) {
3714 731936 : JSObject *getobj = JS_NewFunction(cx, (Native) getter, 0, 0, &obj->global(), NULL);
3715 731936 : if (!getobj)
3716 0 : return false;
3717 731936 : getter = JS_DATA_TO_FUNC_PTR(PropertyOp, getobj);
3718 731936 : attrs |= JSPROP_GETTER;
3719 : }
3720 731936 : if (setter) {
3721 182984 : JSObject *setobj = JS_NewFunction(cx, (Native) setter, 1, 0, &obj->global(), NULL);
3722 182984 : if (!setobj)
3723 0 : return false;
3724 182984 : setter = JS_DATA_TO_FUNC_PTR(StrictPropertyOp, setobj);
3725 182984 : attrs |= JSPROP_SETTER;
3726 : }
3727 : }
3728 :
3729 17194011 : return DefinePropertyById(cx, obj, id, value, getter, setter, attrs, flags, tinyid);
3730 : }
3731 :
3732 : JS_PUBLIC_API(JSBool)
3733 5776759 : JS_DefineProperty(JSContext *cx, JSObject *obj, const char *name, jsval value,
3734 : PropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
3735 : {
3736 5776759 : return DefineProperty(cx, obj, name, value, getter, setter, attrs, 0, 0);
3737 : }
3738 :
3739 : JS_PUBLIC_API(JSBool)
3740 0 : JS_DefinePropertyWithTinyId(JSContext *cx, JSObject *obj, const char *name, int8_t tinyid,
3741 : jsval value, PropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
3742 : {
3743 0 : return DefineProperty(cx, obj, name, value, getter, setter, attrs, Shape::HAS_SHORTID, tinyid);
3744 : }
3745 :
3746 : static JSBool
3747 568 : DefineUCProperty(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen,
3748 : const Value &value, PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
3749 : unsigned flags, int tinyid)
3750 : {
3751 568 : JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
3752 : return atom && DefinePropertyById(cx, obj, ATOM_TO_JSID(atom), value, getter, setter, attrs,
3753 568 : flags, tinyid);
3754 : }
3755 :
3756 : JS_PUBLIC_API(JSBool)
3757 568 : JS_DefineUCProperty(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen,
3758 : jsval value, JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
3759 : {
3760 568 : return DefineUCProperty(cx, obj, name, namelen, value, getter, setter, attrs, 0, 0);
3761 : }
3762 :
3763 : JS_PUBLIC_API(JSBool)
3764 0 : JS_DefineUCPropertyWithTinyId(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen,
3765 : int8_t tinyid, jsval value,
3766 : JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
3767 : {
3768 : return DefineUCProperty(cx, obj, name, namelen, value, getter, setter, attrs,
3769 0 : Shape::HAS_SHORTID, tinyid);
3770 : }
3771 :
3772 : JS_PUBLIC_API(JSBool)
3773 0 : JS_DefineOwnProperty(JSContext *cx, JSObject *obj, jsid id, jsval descriptor, JSBool *bp)
3774 : {
3775 0 : AssertNoGC(cx);
3776 0 : CHECK_REQUEST(cx);
3777 0 : assertSameCompartment(cx, obj, id, descriptor);
3778 0 : return js_DefineOwnProperty(cx, obj, id, descriptor, bp);
3779 : }
3780 :
3781 : JS_PUBLIC_API(JSObject *)
3782 111913 : JS_DefineObject(JSContext *cx, JSObject *obj, const char *name, JSClass *jsclasp,
3783 : JSObject *proto, unsigned attrs)
3784 : {
3785 111913 : AssertNoGC(cx);
3786 223826 : CHECK_REQUEST(cx);
3787 111913 : assertSameCompartment(cx, obj, proto);
3788 :
3789 111913 : Class *clasp = Valueify(jsclasp);
3790 111913 : if (!clasp)
3791 0 : clasp = &ObjectClass; /* default class is Object */
3792 :
3793 223826 : RootObject root(cx, &obj);
3794 223826 : RootedVarObject nobj(cx);
3795 :
3796 111913 : nobj = NewObjectWithClassProto(cx, clasp, proto, obj);
3797 111913 : if (!nobj)
3798 0 : return NULL;
3799 :
3800 111913 : if (!DefineProperty(cx, obj, name, ObjectValue(*nobj), NULL, NULL, attrs, 0, 0))
3801 0 : return NULL;
3802 :
3803 111913 : return nobj;
3804 : }
3805 :
3806 : JS_PUBLIC_API(JSBool)
3807 7464 : JS_DefineConstDoubles(JSContext *cx, JSObject *obj, JSConstDoubleSpec *cds)
3808 : {
3809 : JSBool ok;
3810 : unsigned attrs;
3811 :
3812 7464 : AssertNoGC(cx);
3813 14928 : CHECK_REQUEST(cx);
3814 56559 : for (ok = JS_TRUE; cds->name; cds++) {
3815 49095 : Value value = DoubleValue(cds->dval);
3816 49095 : attrs = cds->flags;
3817 49095 : if (!attrs)
3818 49095 : attrs = JSPROP_READONLY | JSPROP_PERMANENT;
3819 49095 : ok = DefineProperty(cx, obj, cds->name, value, NULL, NULL, attrs, 0, 0);
3820 49095 : if (!ok)
3821 0 : break;
3822 : }
3823 7464 : return ok;
3824 : }
3825 :
3826 : JS_PUBLIC_API(JSBool)
3827 5136801 : JS_DefineProperties(JSContext *cx, JSObject *obj, JSPropertySpec *ps)
3828 : {
3829 : JSBool ok;
3830 10273602 : RootObject root(cx, &obj);
3831 :
3832 16393045 : for (ok = true; ps->name; ps++) {
3833 : ok = DefineProperty(cx, obj, ps->name, UndefinedValue(), ps->getter, ps->setter,
3834 11256244 : ps->flags, Shape::HAS_SHORTID, ps->tinyid);
3835 11256244 : if (!ok)
3836 0 : break;
3837 : }
3838 5136801 : return ok;
3839 : }
3840 :
3841 : static JSBool
3842 18898 : GetPropertyDescriptorById(JSContext *cx, JSObject *obj, jsid id, unsigned flags,
3843 : JSBool own, PropertyDescriptor *desc)
3844 : {
3845 : JSObject *obj2;
3846 : JSProperty *prop;
3847 :
3848 18898 : if (!LookupPropertyById(cx, obj, id, flags, &obj2, &prop))
3849 0 : return JS_FALSE;
3850 :
3851 18898 : if (!prop || (own && obj != obj2)) {
3852 3 : desc->obj = NULL;
3853 3 : desc->attrs = 0;
3854 3 : desc->getter = NULL;
3855 3 : desc->setter = NULL;
3856 3 : desc->value.setUndefined();
3857 3 : return JS_TRUE;
3858 : }
3859 :
3860 18895 : desc->obj = obj2;
3861 18895 : if (obj2->isNative()) {
3862 18895 : Shape *shape = (Shape *) prop;
3863 18895 : desc->attrs = shape->attributes();
3864 :
3865 18895 : if (shape->isMethod()) {
3866 0 : desc->getter = JS_PropertyStub;
3867 0 : desc->setter = JS_StrictPropertyStub;
3868 0 : desc->value.setObject(*obj2->nativeGetMethod(shape));
3869 : } else {
3870 18895 : desc->getter = shape->getter();
3871 18895 : desc->setter = shape->setter();
3872 18895 : if (shape->hasSlot())
3873 10858 : desc->value = obj2->nativeGetSlot(shape->slot());
3874 : else
3875 8037 : desc->value.setUndefined();
3876 : }
3877 : } else {
3878 0 : if (obj2->isProxy()) {
3879 0 : JSAutoResolveFlags rf(cx, flags);
3880 : return own
3881 0 : ? Proxy::getOwnPropertyDescriptor(cx, obj2, id, false, desc)
3882 0 : : Proxy::getPropertyDescriptor(cx, obj2, id, false, desc);
3883 : }
3884 0 : if (!obj2->getGenericAttributes(cx, id, &desc->attrs))
3885 0 : return false;
3886 0 : desc->getter = NULL;
3887 0 : desc->setter = NULL;
3888 0 : desc->value.setUndefined();
3889 : }
3890 18895 : return true;
3891 : }
3892 :
3893 : JS_PUBLIC_API(JSBool)
3894 18890 : JS_GetPropertyDescriptorById(JSContext *cx, JSObject *obj, jsid id, unsigned flags,
3895 : JSPropertyDescriptor *desc)
3896 : {
3897 18890 : return GetPropertyDescriptorById(cx, obj, id, flags, JS_FALSE, desc);
3898 : }
3899 :
3900 : JS_PUBLIC_API(JSBool)
3901 8 : JS_GetPropertyAttrsGetterAndSetterById(JSContext *cx, JSObject *obj, jsid id,
3902 : unsigned *attrsp, JSBool *foundp,
3903 : JSPropertyOp *getterp, JSStrictPropertyOp *setterp)
3904 : {
3905 : PropertyDescriptor desc;
3906 8 : if (!GetPropertyDescriptorById(cx, obj, id, JSRESOLVE_QUALIFIED, JS_FALSE, &desc))
3907 0 : return false;
3908 :
3909 8 : *attrsp = desc.attrs;
3910 8 : *foundp = (desc.obj != NULL);
3911 8 : if (getterp)
3912 0 : *getterp = desc.getter;
3913 8 : if (setterp)
3914 0 : *setterp = desc.setter;
3915 8 : return true;
3916 : }
3917 :
3918 : JS_PUBLIC_API(JSBool)
3919 8 : JS_GetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name,
3920 : unsigned *attrsp, JSBool *foundp)
3921 : {
3922 8 : JSAtom *atom = js_Atomize(cx, name, strlen(name));
3923 : return atom && JS_GetPropertyAttrsGetterAndSetterById(cx, obj, ATOM_TO_JSID(atom),
3924 8 : attrsp, foundp, NULL, NULL);
3925 : }
3926 :
3927 : JS_PUBLIC_API(JSBool)
3928 0 : JS_GetUCPropertyAttributes(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen,
3929 : unsigned *attrsp, JSBool *foundp)
3930 : {
3931 0 : JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
3932 : return atom && JS_GetPropertyAttrsGetterAndSetterById(cx, obj, ATOM_TO_JSID(atom),
3933 0 : attrsp, foundp, NULL, NULL);
3934 : }
3935 :
3936 : JS_PUBLIC_API(JSBool)
3937 0 : JS_GetPropertyAttrsGetterAndSetter(JSContext *cx, JSObject *obj, const char *name,
3938 : unsigned *attrsp, JSBool *foundp,
3939 : JSPropertyOp *getterp, JSStrictPropertyOp *setterp)
3940 : {
3941 0 : JSAtom *atom = js_Atomize(cx, name, strlen(name));
3942 : return atom && JS_GetPropertyAttrsGetterAndSetterById(cx, obj, ATOM_TO_JSID(atom),
3943 0 : attrsp, foundp, getterp, setterp);
3944 : }
3945 :
3946 : JS_PUBLIC_API(JSBool)
3947 0 : JS_GetUCPropertyAttrsGetterAndSetter(JSContext *cx, JSObject *obj,
3948 : const jschar *name, size_t namelen,
3949 : unsigned *attrsp, JSBool *foundp,
3950 : JSPropertyOp *getterp, JSStrictPropertyOp *setterp)
3951 : {
3952 0 : JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
3953 : return atom && JS_GetPropertyAttrsGetterAndSetterById(cx, obj, ATOM_TO_JSID(atom),
3954 0 : attrsp, foundp, getterp, setterp);
3955 : }
3956 :
3957 : JS_PUBLIC_API(JSBool)
3958 0 : JS_GetOwnPropertyDescriptor(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
3959 : {
3960 0 : AssertNoGC(cx);
3961 0 : CHECK_REQUEST(cx);
3962 0 : return GetOwnPropertyDescriptor(cx, obj, id, vp);
3963 : }
3964 :
3965 : static JSBool
3966 0 : SetPropertyAttributesById(JSContext *cx, JSObject *obj, jsid id, unsigned attrs, JSBool *foundp)
3967 : {
3968 : JSObject *obj2;
3969 : JSProperty *prop;
3970 :
3971 0 : if (!LookupPropertyById(cx, obj, id, JSRESOLVE_QUALIFIED, &obj2, &prop))
3972 0 : return false;
3973 0 : if (!prop || obj != obj2) {
3974 0 : *foundp = false;
3975 0 : return true;
3976 : }
3977 0 : JSBool ok = obj->isNative()
3978 0 : ? js_SetNativeAttributes(cx, obj, (Shape *) prop, attrs)
3979 0 : : obj->setGenericAttributes(cx, id, &attrs);
3980 0 : if (ok)
3981 0 : *foundp = true;
3982 0 : return ok;
3983 : }
3984 :
3985 : JS_PUBLIC_API(JSBool)
3986 0 : JS_SetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name,
3987 : unsigned attrs, JSBool *foundp)
3988 : {
3989 0 : JSAtom *atom = js_Atomize(cx, name, strlen(name));
3990 0 : return atom && SetPropertyAttributesById(cx, obj, ATOM_TO_JSID(atom), attrs, foundp);
3991 : }
3992 :
3993 : JS_PUBLIC_API(JSBool)
3994 0 : JS_SetUCPropertyAttributes(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen,
3995 : unsigned attrs, JSBool *foundp)
3996 : {
3997 0 : JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
3998 0 : return atom && SetPropertyAttributesById(cx, obj, ATOM_TO_JSID(atom), attrs, foundp);
3999 : }
4000 :
4001 : JS_PUBLIC_API(JSBool)
4002 1397633 : JS_GetPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
4003 : {
4004 1397633 : return JS_ForwardGetPropertyTo(cx, obj, id, obj, vp);
4005 : }
4006 :
4007 : JS_PUBLIC_API(JSBool)
4008 1397641 : JS_ForwardGetPropertyTo(JSContext *cx, JSObject *obj, jsid id, JSObject *onBehalfOf, jsval *vp)
4009 : {
4010 1397641 : AssertNoGC(cx);
4011 2795282 : CHECK_REQUEST(cx);
4012 1397641 : assertSameCompartment(cx, obj, id);
4013 1397641 : assertSameCompartment(cx, onBehalfOf);
4014 2795282 : JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
4015 1397641 : return obj->getGeneric(cx, onBehalfOf, id, vp);
4016 : }
4017 :
4018 : JS_PUBLIC_API(JSBool)
4019 4 : JS_GetPropertyByIdDefault(JSContext *cx, JSObject *obj, jsid id, jsval def, jsval *vp)
4020 : {
4021 4 : return GetPropertyDefault(cx, obj, id, def, vp);
4022 : }
4023 :
4024 : JS_PUBLIC_API(JSBool)
4025 4678115 : JS_GetElement(JSContext *cx, JSObject *obj, uint32_t index, jsval *vp)
4026 : {
4027 4678115 : return JS_ForwardGetElementTo(cx, obj, index, obj, vp);
4028 : }
4029 :
4030 : JS_PUBLIC_API(JSBool)
4031 4678115 : JS_ForwardGetElementTo(JSContext *cx, JSObject *obj, uint32_t index, JSObject *onBehalfOf, jsval *vp)
4032 : {
4033 4678115 : AssertNoGC(cx);
4034 9356230 : CHECK_REQUEST(cx);
4035 4678115 : assertSameCompartment(cx, obj);
4036 9356230 : JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
4037 4678115 : return obj->getElement(cx, onBehalfOf, index, vp);
4038 : }
4039 :
4040 : JS_PUBLIC_API(JSBool)
4041 0 : JS_GetElementIfPresent(JSContext *cx, JSObject *obj, uint32_t index, JSObject *onBehalfOf, jsval *vp, JSBool* present)
4042 : {
4043 0 : AssertNoGC(cx);
4044 0 : CHECK_REQUEST(cx);
4045 0 : assertSameCompartment(cx, obj);
4046 0 : JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
4047 : bool isPresent;
4048 0 : if (!obj->getElementIfPresent(cx, onBehalfOf, index, vp, &isPresent))
4049 0 : return false;
4050 0 : *present = isPresent;
4051 0 : return true;
4052 : }
4053 :
4054 : JS_PUBLIC_API(JSBool)
4055 848736 : JS_GetProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp)
4056 : {
4057 848736 : JSAtom *atom = js_Atomize(cx, name, strlen(name));
4058 848736 : return atom && JS_GetPropertyById(cx, obj, ATOM_TO_JSID(atom), vp);
4059 : }
4060 :
4061 : JS_PUBLIC_API(JSBool)
4062 2 : JS_GetPropertyDefault(JSContext *cx, JSObject *obj, const char *name, jsval def, jsval *vp)
4063 : {
4064 2 : JSAtom *atom = js_Atomize(cx, name, strlen(name));
4065 2 : return atom && JS_GetPropertyByIdDefault(cx, obj, ATOM_TO_JSID(atom), def, vp);
4066 : }
4067 :
4068 : JS_PUBLIC_API(JSBool)
4069 703 : JS_GetUCProperty(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen, jsval *vp)
4070 : {
4071 703 : JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
4072 703 : return atom && JS_GetPropertyById(cx, obj, ATOM_TO_JSID(atom), vp);
4073 : }
4074 :
4075 : JS_PUBLIC_API(JSBool)
4076 429369 : JS_GetMethodById(JSContext *cx, JSObject *obj, jsid id, JSObject **objp, jsval *vp)
4077 : {
4078 429369 : AssertNoGC(cx);
4079 858738 : CHECK_REQUEST(cx);
4080 429369 : assertSameCompartment(cx, obj, id);
4081 429369 : if (!js_GetMethod(cx, obj, id, JSGET_METHOD_BARRIER, vp))
4082 1 : return JS_FALSE;
4083 429368 : if (objp)
4084 429321 : *objp = obj;
4085 429368 : return JS_TRUE;
4086 : }
4087 :
4088 : JS_PUBLIC_API(JSBool)
4089 429369 : JS_GetMethod(JSContext *cx, JSObject *obj, const char *name, JSObject **objp, jsval *vp)
4090 : {
4091 429369 : JSAtom *atom = js_Atomize(cx, name, strlen(name));
4092 429369 : return atom && JS_GetMethodById(cx, obj, ATOM_TO_JSID(atom), objp, vp);
4093 : }
4094 :
4095 : JS_PUBLIC_API(JSBool)
4096 281309 : JS_SetPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
4097 : {
4098 281309 : AssertNoGC(cx);
4099 562618 : CHECK_REQUEST(cx);
4100 281309 : assertSameCompartment(cx, obj, id);
4101 562618 : JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_ASSIGNING);
4102 281309 : return obj->setGeneric(cx, id, vp, false);
4103 : }
4104 :
4105 : JS_PUBLIC_API(JSBool)
4106 13531376 : JS_SetElement(JSContext *cx, JSObject *obj, uint32_t index, jsval *vp)
4107 : {
4108 13531376 : AssertNoGC(cx);
4109 27062752 : CHECK_REQUEST(cx);
4110 13531376 : assertSameCompartment(cx, obj);
4111 27062752 : JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_ASSIGNING);
4112 13531376 : return obj->setElement(cx, index, vp, false);
4113 : }
4114 :
4115 : JS_PUBLIC_API(JSBool)
4116 34088 : JS_SetProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp)
4117 : {
4118 34088 : JSAtom *atom = js_Atomize(cx, name, strlen(name));
4119 34088 : return atom && JS_SetPropertyById(cx, obj, ATOM_TO_JSID(atom), vp);
4120 : }
4121 :
4122 : JS_PUBLIC_API(JSBool)
4123 0 : JS_SetUCProperty(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen, jsval *vp)
4124 : {
4125 0 : JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
4126 0 : return atom && JS_SetPropertyById(cx, obj, ATOM_TO_JSID(atom), vp);
4127 : }
4128 :
4129 : JS_PUBLIC_API(JSBool)
4130 9 : JS_DeletePropertyById2(JSContext *cx, JSObject *obj, jsid id, jsval *rval)
4131 : {
4132 9 : AssertNoGC(cx);
4133 18 : CHECK_REQUEST(cx);
4134 9 : assertSameCompartment(cx, obj, id);
4135 18 : JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
4136 :
4137 9 : if (JSID_IS_SPECIAL(id))
4138 0 : return obj->deleteSpecial(cx, JSID_TO_SPECIALID(id), rval, false);
4139 :
4140 9 : return obj->deleteByValue(cx, IdToValue(id), rval, false);
4141 : }
4142 :
4143 : JS_PUBLIC_API(JSBool)
4144 0 : JS_DeleteElement2(JSContext *cx, JSObject *obj, uint32_t index, jsval *rval)
4145 : {
4146 0 : AssertNoGC(cx);
4147 0 : CHECK_REQUEST(cx);
4148 0 : assertSameCompartment(cx, obj);
4149 0 : JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
4150 0 : return obj->deleteElement(cx, index, rval, false);
4151 : }
4152 :
4153 : JS_PUBLIC_API(JSBool)
4154 0 : JS_DeleteProperty2(JSContext *cx, JSObject *obj, const char *name, jsval *rval)
4155 : {
4156 0 : CHECK_REQUEST(cx);
4157 0 : assertSameCompartment(cx, obj);
4158 0 : JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
4159 :
4160 0 : JSAtom *atom = js_Atomize(cx, name, strlen(name));
4161 0 : if (!atom)
4162 0 : return false;
4163 :
4164 0 : return obj->deleteByValue(cx, StringValue(atom), rval, false);
4165 : }
4166 :
4167 : JS_PUBLIC_API(JSBool)
4168 16 : JS_DeleteUCProperty2(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen, jsval *rval)
4169 : {
4170 32 : CHECK_REQUEST(cx);
4171 16 : assertSameCompartment(cx, obj);
4172 32 : JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
4173 :
4174 16 : JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
4175 16 : if (!atom)
4176 0 : return false;
4177 :
4178 16 : return obj->deleteByValue(cx, StringValue(atom), rval, false);
4179 : }
4180 :
4181 : JS_PUBLIC_API(JSBool)
4182 0 : JS_DeletePropertyById(JSContext *cx, JSObject *obj, jsid id)
4183 : {
4184 : jsval junk;
4185 0 : return JS_DeletePropertyById2(cx, obj, id, &junk);
4186 : }
4187 :
4188 : JS_PUBLIC_API(JSBool)
4189 0 : JS_DeleteElement(JSContext *cx, JSObject *obj, uint32_t index)
4190 : {
4191 : jsval junk;
4192 0 : return JS_DeleteElement2(cx, obj, index, &junk);
4193 : }
4194 :
4195 : JS_PUBLIC_API(JSBool)
4196 0 : JS_DeleteProperty(JSContext *cx, JSObject *obj, const char *name)
4197 : {
4198 : jsval junk;
4199 0 : return JS_DeleteProperty2(cx, obj, name, &junk);
4200 : }
4201 :
4202 : JS_PUBLIC_API(void)
4203 13218 : JS_ClearScope(JSContext *cx, JSObject *obj)
4204 : {
4205 13218 : AssertNoGC(cx);
4206 26436 : CHECK_REQUEST(cx);
4207 13218 : assertSameCompartment(cx, obj);
4208 :
4209 13218 : JSFinalizeOp clearOp = obj->getOps()->clear;
4210 13218 : if (clearOp)
4211 13218 : clearOp(cx, obj);
4212 :
4213 13218 : if (obj->isNative())
4214 13218 : js_ClearNative(cx, obj);
4215 :
4216 : /* Clear cached class objects on the global object. */
4217 13218 : if (obj->isGlobal())
4218 13212 : obj->asGlobal().clear(cx);
4219 :
4220 13218 : js_InitRandom(cx);
4221 13218 : }
4222 :
4223 : JS_PUBLIC_API(JSIdArray *)
4224 2449 : JS_Enumerate(JSContext *cx, JSObject *obj)
4225 : {
4226 2449 : AssertNoGC(cx);
4227 4898 : CHECK_REQUEST(cx);
4228 2449 : assertSameCompartment(cx, obj);
4229 :
4230 4898 : AutoIdVector props(cx);
4231 : JSIdArray *ida;
4232 2449 : if (!GetPropertyNames(cx, obj, JSITER_OWNONLY, &props) || !VectorToIdArray(cx, props, &ida))
4233 0 : return NULL;
4234 5339 : for (size_t n = 0; n < size_t(ida->length); ++n)
4235 2890 : JS_ASSERT(js_CheckForStringIndex(ida->vector[n]) == ida->vector[n]);
4236 2449 : return ida;
4237 : }
4238 :
4239 : /*
4240 : * XXX reverse iterator for properties, unreverse and meld with jsinterp.c's
4241 : * prop_iterator_class somehow...
4242 : * + preserve the obj->enumerate API while optimizing the native object case
4243 : * + native case here uses a Shape *, but that iterates in reverse!
4244 : * + so we make non-native match, by reverse-iterating after JS_Enumerating
4245 : */
4246 : const uint32_t JSSLOT_ITER_INDEX = 0;
4247 :
4248 : static void
4249 583 : prop_iter_finalize(JSContext *cx, JSObject *obj)
4250 : {
4251 583 : void *pdata = obj->getPrivate();
4252 583 : if (!pdata)
4253 0 : return;
4254 :
4255 583 : if (obj->getSlot(JSSLOT_ITER_INDEX).toInt32() >= 0) {
4256 : /* Non-native case: destroy the ida enumerated when obj was created. */
4257 2 : JSIdArray *ida = (JSIdArray *) pdata;
4258 2 : JS_DestroyIdArray(cx, ida);
4259 : }
4260 : }
4261 :
4262 : static void
4263 0 : prop_iter_trace(JSTracer *trc, JSObject *obj)
4264 : {
4265 0 : void *pdata = obj->getPrivate();
4266 0 : if (!pdata)
4267 0 : return;
4268 :
4269 0 : if (obj->getSlot(JSSLOT_ITER_INDEX).toInt32() < 0) {
4270 : /*
4271 : * Native case: just mark the next property to visit. We don't need a
4272 : * barrier here because the pointer is updated via setPrivate, which
4273 : * always takes a barrier.
4274 : */
4275 0 : Shape *tmp = (Shape *)pdata;
4276 0 : MarkShapeUnbarriered(trc, &tmp, "prop iter shape");
4277 0 : obj->setPrivateUnbarriered(tmp);
4278 : } else {
4279 : /* Non-native case: mark each id in the JSIdArray private. */
4280 0 : JSIdArray *ida = (JSIdArray *) pdata;
4281 0 : MarkIdRange(trc, ida->length, ida->vector, "prop iter");
4282 : }
4283 : }
4284 :
4285 : static Class prop_iter_class = {
4286 : "PropertyIterator",
4287 : JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS | JSCLASS_HAS_RESERVED_SLOTS(1),
4288 : JS_PropertyStub, /* addProperty */
4289 : JS_PropertyStub, /* delProperty */
4290 : JS_PropertyStub, /* getProperty */
4291 : JS_StrictPropertyStub, /* setProperty */
4292 : JS_EnumerateStub,
4293 : JS_ResolveStub,
4294 : JS_ConvertStub,
4295 : prop_iter_finalize,
4296 : NULL, /* checkAccess */
4297 : NULL, /* call */
4298 : NULL, /* construct */
4299 : NULL, /* hasInstance */
4300 : prop_iter_trace
4301 : };
4302 :
4303 : JS_PUBLIC_API(JSObject *)
4304 583 : JS_NewPropertyIterator(JSContext *cx, JSObject *obj)
4305 : {
4306 : JSObject *iterobj;
4307 : void *pdata;
4308 : int index;
4309 : JSIdArray *ida;
4310 :
4311 583 : AssertNoGC(cx);
4312 1166 : CHECK_REQUEST(cx);
4313 583 : assertSameCompartment(cx, obj);
4314 583 : iterobj = NewObjectWithClassProto(cx, &prop_iter_class, NULL, obj);
4315 583 : if (!iterobj)
4316 0 : return NULL;
4317 :
4318 583 : if (obj->isNative()) {
4319 : /* Native case: start with the last property in obj. */
4320 581 : pdata = (void *)obj->lastProperty();
4321 581 : index = -1;
4322 : } else {
4323 : /*
4324 : * Non-native case: enumerate a JSIdArray and keep it via private.
4325 : *
4326 : * Note: we have to make sure that we root obj around the call to
4327 : * JS_Enumerate to protect against multiple allocations under it.
4328 : */
4329 2 : ida = JS_Enumerate(cx, obj);
4330 2 : if (!ida)
4331 0 : return NULL;
4332 2 : pdata = ida;
4333 2 : index = ida->length;
4334 : }
4335 :
4336 : /* iterobj cannot escape to other threads here. */
4337 583 : iterobj->setPrivate(pdata);
4338 583 : iterobj->setSlot(JSSLOT_ITER_INDEX, Int32Value(index));
4339 583 : return iterobj;
4340 : }
4341 :
4342 : JS_PUBLIC_API(JSBool)
4343 1166 : JS_NextProperty(JSContext *cx, JSObject *iterobj, jsid *idp)
4344 : {
4345 : int32_t i;
4346 : const Shape *shape;
4347 : JSIdArray *ida;
4348 :
4349 1166 : AssertNoGC(cx);
4350 2332 : CHECK_REQUEST(cx);
4351 1166 : assertSameCompartment(cx, iterobj);
4352 1166 : i = iterobj->getSlot(JSSLOT_ITER_INDEX).toInt32();
4353 1166 : if (i < 0) {
4354 : /* Native case: private data is a property tree node pointer. */
4355 1164 : JS_ASSERT(iterobj->getParent()->isNative());
4356 1164 : shape = (Shape *) iterobj->getPrivate();
4357 :
4358 2328 : while (shape->previous() && !shape->enumerable())
4359 0 : shape = shape->previous();
4360 :
4361 1164 : if (!shape->previous()) {
4362 572 : JS_ASSERT(shape->isEmptyShape());
4363 572 : *idp = JSID_VOID;
4364 : } else {
4365 592 : iterobj->setPrivate(const_cast<Shape *>(shape->previous().get()));
4366 592 : *idp = shape->propid();
4367 : }
4368 : } else {
4369 : /* Non-native case: use the ida enumerated when iterobj was created. */
4370 2 : ida = (JSIdArray *) iterobj->getPrivate();
4371 2 : JS_ASSERT(i <= ida->length);
4372 : STATIC_ASSUME(i <= ida->length);
4373 2 : if (i == 0) {
4374 0 : *idp = JSID_VOID;
4375 : } else {
4376 2 : *idp = ida->vector[--i];
4377 2 : iterobj->setSlot(JSSLOT_ITER_INDEX, Int32Value(i));
4378 : }
4379 : }
4380 1166 : return JS_TRUE;
4381 : }
4382 :
4383 : JS_PUBLIC_API(JSObject *)
4384 927 : JS_NewElementIterator(JSContext *cx, JSObject *obj)
4385 : {
4386 927 : AssertNoGC(cx);
4387 1854 : CHECK_REQUEST(cx);
4388 927 : assertSameCompartment(cx, obj);
4389 927 : return ElementIteratorObject::create(cx, obj);
4390 : }
4391 :
4392 : JS_PUBLIC_API(JSObject *)
4393 927 : JS_ElementIteratorStub(JSContext *cx, JSObject *obj, JSBool keysonly)
4394 : {
4395 927 : JS_ASSERT(!keysonly);
4396 927 : return JS_NewElementIterator(cx, obj);
4397 : }
4398 :
4399 : JS_PUBLIC_API(jsval)
4400 4737978 : JS_GetReservedSlot(JSObject *obj, uint32_t index)
4401 : {
4402 4737978 : return obj->getReservedSlot(index);
4403 : }
4404 :
4405 : JS_PUBLIC_API(void)
4406 5904473 : JS_SetReservedSlot(JSObject *obj, uint32_t index, jsval v)
4407 : {
4408 5904473 : obj->setReservedSlot(index, v);
4409 5904473 : }
4410 :
4411 : JS_PUBLIC_API(JSObject *)
4412 72003 : JS_NewArrayObject(JSContext *cx, int length, jsval *vector)
4413 : {
4414 72003 : JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
4415 72003 : AssertNoGC(cx);
4416 144006 : CHECK_REQUEST(cx);
4417 :
4418 72003 : assertSameCompartment(cx, JSValueArray(vector, vector ? (uint32_t)length : 0));
4419 72003 : return NewDenseCopiedArray(cx, (uint32_t)length, vector);
4420 : }
4421 :
4422 : JS_PUBLIC_API(JSBool)
4423 86170 : JS_IsArrayObject(JSContext *cx, JSObject *obj)
4424 : {
4425 86170 : assertSameCompartment(cx, obj);
4426 86170 : return ObjectClassIs(*obj, ESClass_Array, cx);
4427 : }
4428 :
4429 : JS_PUBLIC_API(JSBool)
4430 81587 : JS_GetArrayLength(JSContext *cx, JSObject *obj, uint32_t *lengthp)
4431 : {
4432 81587 : AssertNoGC(cx);
4433 163174 : CHECK_REQUEST(cx);
4434 81587 : assertSameCompartment(cx, obj);
4435 81587 : return js_GetLengthProperty(cx, obj, lengthp);
4436 : }
4437 :
4438 : JS_PUBLIC_API(JSBool)
4439 40 : JS_SetArrayLength(JSContext *cx, JSObject *obj, uint32_t length)
4440 : {
4441 40 : AssertNoGC(cx);
4442 80 : CHECK_REQUEST(cx);
4443 40 : assertSameCompartment(cx, obj);
4444 40 : return js_SetLengthProperty(cx, obj, length);
4445 : }
4446 :
4447 : JS_PUBLIC_API(JSBool)
4448 0 : JS_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
4449 : jsval *vp, unsigned *attrsp)
4450 : {
4451 0 : AssertNoGC(cx);
4452 0 : CHECK_REQUEST(cx);
4453 0 : assertSameCompartment(cx, obj, id);
4454 0 : return CheckAccess(cx, obj, id, mode, vp, attrsp);
4455 : }
4456 :
4457 : JS_PUBLIC_API(void)
4458 2193853 : JS_HoldPrincipals(JSPrincipals *principals)
4459 : {
4460 2193853 : JS_ATOMIC_INCREMENT(&principals->refcount);
4461 2193853 : }
4462 :
4463 : JS_PUBLIC_API(void)
4464 2192889 : JS_DropPrincipals(JSRuntime *rt, JSPrincipals *principals)
4465 : {
4466 2192889 : int rc = JS_ATOMIC_DECREMENT(&principals->refcount);
4467 2192889 : if (rc == 0)
4468 1415 : rt->destroyPrincipals(principals);
4469 2192889 : }
4470 :
4471 : JS_PUBLIC_API(void)
4472 22602 : JS_SetSecurityCallbacks(JSRuntime *rt, const JSSecurityCallbacks *scb)
4473 : {
4474 22602 : JS_ASSERT(scb != &NullSecurityCallbacks);
4475 22602 : rt->securityCallbacks = scb ? scb : &NullSecurityCallbacks;
4476 22602 : }
4477 :
4478 : JS_PUBLIC_API(const JSSecurityCallbacks *)
4479 10832 : JS_GetSecurityCallbacks(JSRuntime *rt)
4480 : {
4481 10832 : return (rt->securityCallbacks != &NullSecurityCallbacks) ? rt->securityCallbacks : NULL;
4482 : }
4483 :
4484 : JS_PUBLIC_API(void)
4485 21214 : JS_SetTrustedPrincipals(JSRuntime *rt, JSPrincipals *prin)
4486 : {
4487 21214 : rt->setTrustedPrincipals(prin);
4488 21214 : }
4489 :
4490 : extern JS_PUBLIC_API(void)
4491 1405 : JS_InitDestroyPrincipalsCallback(JSRuntime *rt, JSDestroyPrincipalsOp destroyPrincipals)
4492 : {
4493 1405 : JS_ASSERT(destroyPrincipals);
4494 1405 : JS_ASSERT(!rt->destroyPrincipals);
4495 1405 : rt->destroyPrincipals = destroyPrincipals;
4496 1405 : }
4497 :
4498 : JS_PUBLIC_API(JSFunction *)
4499 916812 : JS_NewFunction(JSContext *cx, JSNative native, unsigned nargs, unsigned flags,
4500 : JSObject *parent, const char *name)
4501 : {
4502 916812 : JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
4503 : JSAtom *atom;
4504 :
4505 916812 : AssertNoGC(cx);
4506 1833624 : CHECK_REQUEST(cx);
4507 916812 : assertSameCompartment(cx, parent);
4508 :
4509 916812 : if (!name) {
4510 914920 : atom = NULL;
4511 : } else {
4512 1892 : atom = js_Atomize(cx, name, strlen(name));
4513 1892 : if (!atom)
4514 0 : return NULL;
4515 : }
4516 :
4517 1833624 : RootObject parentRoot(cx, &parent);
4518 916812 : return js_NewFunction(cx, NULL, native, nargs, flags, parentRoot, atom);
4519 : }
4520 :
4521 : JS_PUBLIC_API(JSFunction *)
4522 304 : JS_NewFunctionById(JSContext *cx, JSNative native, unsigned nargs, unsigned flags, JSObject *parent,
4523 : jsid id)
4524 : {
4525 304 : JS_ASSERT(JSID_IS_STRING(id));
4526 304 : JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
4527 304 : AssertNoGC(cx);
4528 608 : CHECK_REQUEST(cx);
4529 304 : assertSameCompartment(cx, parent);
4530 :
4531 608 : RootObject parentRoot(cx, &parent);
4532 304 : return js_NewFunction(cx, NULL, native, nargs, flags, parentRoot, JSID_TO_ATOM(id));
4533 : }
4534 :
4535 : JS_PUBLIC_API(JSObject *)
4536 2279 : JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent)
4537 : {
4538 2279 : AssertNoGC(cx);
4539 4558 : CHECK_REQUEST(cx);
4540 2279 : assertSameCompartment(cx, parent); // XXX no funobj for now
4541 2279 : if (!parent) {
4542 0 : if (cx->hasfp())
4543 0 : parent = &cx->fp()->scopeChain();
4544 0 : if (!parent)
4545 0 : parent = cx->globalObject;
4546 0 : JS_ASSERT(parent);
4547 : }
4548 :
4549 2279 : if (!funobj->isFunction()) {
4550 : /*
4551 : * We cannot clone this object, so fail (we used to return funobj, bad
4552 : * idea, but we changed incompatibly to teach any abusers a lesson!).
4553 : */
4554 0 : Value v = ObjectValue(*funobj);
4555 0 : js_ReportIsNotFunction(cx, &v, 0);
4556 0 : return NULL;
4557 : }
4558 :
4559 2279 : JSFunction *fun = funobj->toFunction();
4560 2279 : if (!fun->isInterpreted())
4561 0 : return CloneFunctionObject(cx, fun, parent, fun->getAllocKind());
4562 :
4563 2279 : if (fun->script()->compileAndGo) {
4564 : JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
4565 0 : JSMSG_BAD_CLONE_FUNOBJ_SCOPE);
4566 0 : return NULL;
4567 : }
4568 :
4569 2279 : if (!fun->isFlatClosure())
4570 2279 : return CloneFunctionObject(cx, fun, parent, fun->getAllocKind());
4571 :
4572 : /*
4573 : * A flat closure carries its own environment, so why clone it? In case
4574 : * someone wants to mutate its fixed slots or add ad-hoc properties. API
4575 : * compatibility suggests we not return funobj and let callers mutate the
4576 : * returned object at will.
4577 : *
4578 : * But it's worse than that: API compatibility according to the test for
4579 : * bug 300079 requires we get "upvars" from parent and its ancestors! So
4580 : * we do that (grudgingly!). The scope chain ancestors are searched as if
4581 : * they were activations, respecting the skip field in each upvar's cookie
4582 : * but looking up the property by name instead of frame slot.
4583 : */
4584 0 : JSObject *clone = js_AllocFlatClosure(cx, fun, parent);
4585 0 : if (!clone)
4586 0 : return NULL;
4587 :
4588 0 : JSUpvarArray *uva = fun->script()->upvars();
4589 0 : uint32_t i = uva->length;
4590 0 : JS_ASSERT(i != 0);
4591 :
4592 0 : for (Shape::Range r(fun->script()->bindings.lastUpvar()); i-- != 0; r.popFront()) {
4593 0 : JSObject *obj = parent;
4594 0 : int skip = uva->vector[i].level();
4595 0 : while (--skip > 0) {
4596 0 : if (!obj) {
4597 : JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
4598 0 : JSMSG_BAD_CLONE_FUNOBJ_SCOPE);
4599 0 : return NULL;
4600 : }
4601 0 : obj = obj->enclosingScope();
4602 : }
4603 :
4604 : Value v;
4605 0 : if (!obj->getGeneric(cx, r.front().propid(), &v))
4606 0 : return NULL;
4607 0 : clone->toFunction()->setFlatClosureUpvar(i, v);
4608 : }
4609 :
4610 0 : return clone;
4611 : }
4612 :
4613 : JS_PUBLIC_API(JSObject *)
4614 1867183 : JS_GetFunctionObject(JSFunction *fun)
4615 : {
4616 1867183 : return fun;
4617 : }
4618 :
4619 : JS_PUBLIC_API(JSString *)
4620 1346602 : JS_GetFunctionId(JSFunction *fun)
4621 : {
4622 1346602 : return fun->atom;
4623 : }
4624 :
4625 : JS_PUBLIC_API(unsigned)
4626 0 : JS_GetFunctionFlags(JSFunction *fun)
4627 : {
4628 0 : return fun->flags;
4629 : }
4630 :
4631 : JS_PUBLIC_API(uint16_t)
4632 0 : JS_GetFunctionArity(JSFunction *fun)
4633 : {
4634 0 : return fun->nargs;
4635 : }
4636 :
4637 : JS_PUBLIC_API(JSBool)
4638 260315424 : JS_ObjectIsFunction(JSContext *cx, JSObject *obj)
4639 : {
4640 260315424 : return obj->isFunction();
4641 : }
4642 :
4643 : JS_PUBLIC_API(JSBool)
4644 18 : JS_ObjectIsCallable(JSContext *cx, JSObject *obj)
4645 : {
4646 18 : return obj->isCallable();
4647 : }
4648 :
4649 : JS_PUBLIC_API(JSBool)
4650 14531 : JS_IsNativeFunction(JSObject *funobj, JSNative call)
4651 : {
4652 14531 : if (!funobj->isFunction())
4653 0 : return false;
4654 14531 : JSFunction *fun = funobj->toFunction();
4655 14531 : return fun->isNative() && fun->native() == call;
4656 : }
4657 :
4658 : JSBool
4659 33227 : js_generic_native_method_dispatcher(JSContext *cx, unsigned argc, Value *vp)
4660 : {
4661 : JSFunctionSpec *fs = (JSFunctionSpec *)
4662 33227 : vp->toObject().toFunction()->getExtendedSlot(0).toPrivate();
4663 33227 : JS_ASSERT((fs->flags & JSFUN_GENERIC_NATIVE) != 0);
4664 :
4665 33227 : if (argc < 1) {
4666 0 : js_ReportMissingArg(cx, *vp, 0);
4667 0 : return JS_FALSE;
4668 : }
4669 :
4670 : /*
4671 : * Copy all actual (argc) arguments down over our |this| parameter, vp[1],
4672 : * which is almost always the class constructor object, e.g. Array. Then
4673 : * call the corresponding prototype native method with our first argument
4674 : * passed as |this|.
4675 : */
4676 33227 : memmove(vp + 1, vp + 2, argc * sizeof(jsval));
4677 :
4678 : /* Clear the last parameter in case too few arguments were passed. */
4679 33227 : vp[2 + --argc].setUndefined();
4680 :
4681 33227 : return fs->call(cx, argc, vp);
4682 : }
4683 :
4684 : JS_PUBLIC_API(JSBool)
4685 711593 : JS_DefineFunctions(JSContext *cx, JSObject *obj, JSFunctionSpec *fs)
4686 : {
4687 1423186 : RootObject objRoot(cx, &obj);
4688 :
4689 711593 : JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
4690 : unsigned flags;
4691 1423186 : RootedVarObject ctor(cx);
4692 : JSFunction *fun;
4693 :
4694 711593 : AssertNoGC(cx);
4695 1423186 : CHECK_REQUEST(cx);
4696 711593 : assertSameCompartment(cx, obj);
4697 5055698 : for (; fs->name; fs++) {
4698 4344105 : flags = fs->flags;
4699 :
4700 4344105 : JSAtom *atom = js_Atomize(cx, fs->name, strlen(fs->name));
4701 4344105 : if (!atom)
4702 0 : return JS_FALSE;
4703 :
4704 : /*
4705 : * Define a generic arity N+1 static method for the arity N prototype
4706 : * method if flags contains JSFUN_GENERIC_NATIVE.
4707 : */
4708 4344105 : if (flags & JSFUN_GENERIC_NATIVE) {
4709 1580996 : RootAtom root(cx, &atom);
4710 :
4711 790498 : if (!ctor) {
4712 52323 : ctor = JS_GetConstructor(cx, obj);
4713 52323 : if (!ctor)
4714 0 : return JS_FALSE;
4715 : }
4716 :
4717 790498 : flags &= ~JSFUN_GENERIC_NATIVE;
4718 790498 : fun = js_DefineFunction(cx, ctor, ATOM_TO_JSID(atom),
4719 : js_generic_native_method_dispatcher,
4720 : fs->nargs + 1,
4721 : flags,
4722 1580996 : JSFunction::ExtendedFinalizeKind);
4723 790498 : if (!fun)
4724 0 : return JS_FALSE;
4725 :
4726 : /*
4727 : * As jsapi.h notes, fs must point to storage that lives as long
4728 : * as fun->object lives.
4729 : */
4730 1580996 : fun->setExtendedSlot(0, PrivateValue(fs));
4731 : }
4732 :
4733 : fun = js_DefineFunction(cx, objRoot,
4734 4344105 : ATOM_TO_JSID(atom), fs->call, fs->nargs, flags);
4735 4344105 : if (!fun)
4736 0 : return JS_FALSE;
4737 : }
4738 711593 : return JS_TRUE;
4739 : }
4740 :
4741 : JS_PUBLIC_API(JSFunction *)
4742 156170 : JS_DefineFunction(JSContext *cx, JSObject *obj, const char *name, JSNative call,
4743 : unsigned nargs, unsigned attrs)
4744 : {
4745 312340 : RootObject objRoot(cx, &obj);
4746 :
4747 156170 : JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
4748 156170 : AssertNoGC(cx);
4749 312340 : CHECK_REQUEST(cx);
4750 156170 : assertSameCompartment(cx, obj);
4751 156170 : JSAtom *atom = js_Atomize(cx, name, strlen(name));
4752 156170 : if (!atom)
4753 0 : return NULL;
4754 156170 : return js_DefineFunction(cx, objRoot, ATOM_TO_JSID(atom), call, nargs, attrs);
4755 : }
4756 :
4757 : JS_PUBLIC_API(JSFunction *)
4758 0 : JS_DefineUCFunction(JSContext *cx, JSObject *obj,
4759 : const jschar *name, size_t namelen, JSNative call,
4760 : unsigned nargs, unsigned attrs)
4761 : {
4762 0 : RootObject objRoot(cx, &obj);
4763 :
4764 0 : JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
4765 0 : AssertNoGC(cx);
4766 0 : CHECK_REQUEST(cx);
4767 0 : assertSameCompartment(cx, obj);
4768 0 : JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
4769 0 : if (!atom)
4770 0 : return NULL;
4771 0 : return js_DefineFunction(cx, objRoot, ATOM_TO_JSID(atom), call, nargs, attrs);
4772 : }
4773 :
4774 : extern JS_PUBLIC_API(JSFunction *)
4775 0 : JS_DefineFunctionById(JSContext *cx, JSObject *obj, jsid id, JSNative call,
4776 : unsigned nargs, unsigned attrs)
4777 : {
4778 0 : RootObject objRoot(cx, &obj);
4779 :
4780 0 : JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
4781 0 : AssertNoGC(cx);
4782 0 : CHECK_REQUEST(cx);
4783 0 : assertSameCompartment(cx, obj);
4784 0 : return js_DefineFunction(cx, objRoot, id, call, nargs, attrs);
4785 : }
4786 :
4787 : struct AutoLastFrameCheck {
4788 793641 : AutoLastFrameCheck(JSContext *cx JS_GUARD_OBJECT_NOTIFIER_PARAM)
4789 793641 : : cx(cx) {
4790 793641 : JS_ASSERT(cx);
4791 793641 : JS_GUARD_OBJECT_NOTIFIER_INIT;
4792 793641 : }
4793 :
4794 1587282 : ~AutoLastFrameCheck() {
4795 857919 : if (cx->isExceptionPending() &&
4796 58524 : !JS_IsRunning(cx) &&
4797 5754 : !cx->hasRunOption(JSOPTION_DONT_REPORT_UNCAUGHT)) {
4798 810 : js_ReportUncaughtException(cx);
4799 : }
4800 793641 : }
4801 :
4802 : private:
4803 : JSContext *cx;
4804 : JS_DECL_USE_GUARD_OBJECT_NOTIFIER
4805 : };
4806 :
4807 : inline static uint32_t
4808 54335 : JS_OPTIONS_TO_TCFLAGS(JSContext *cx)
4809 : {
4810 54335 : return (cx->hasRunOption(JSOPTION_COMPILE_N_GO) ? TCF_COMPILE_N_GO : 0) |
4811 54335 : (cx->hasRunOption(JSOPTION_NO_SCRIPT_RVAL) ? TCF_NO_SCRIPT_RVAL : 0);
4812 : }
4813 :
4814 : static JSScript *
4815 11844 : CompileUCScriptForPrincipalsCommon(JSContext *cx, JSObject *obj,
4816 : JSPrincipals *principals, JSPrincipals *originPrincipals,
4817 : const jschar *chars, size_t length,
4818 : const char *filename, unsigned lineno, JSVersion version)
4819 : {
4820 11844 : JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
4821 11844 : AssertNoGC(cx);
4822 23688 : CHECK_REQUEST(cx);
4823 11844 : assertSameCompartment(cx, obj, principals);
4824 23688 : AutoLastFrameCheck lfc(cx);
4825 :
4826 11844 : uint32_t tcflags = JS_OPTIONS_TO_TCFLAGS(cx) | TCF_NEED_SCRIPT_GLOBAL;
4827 : return frontend::CompileScript(cx, obj, NULL, principals, originPrincipals, tcflags,
4828 11844 : chars, length, filename, lineno, version);
4829 : }
4830 :
4831 : extern JS_PUBLIC_API(JSScript *)
4832 0 : JS_CompileUCScriptForPrincipalsVersion(JSContext *cx, JSObject *obj,
4833 : JSPrincipals *principals,
4834 : const jschar *chars, size_t length,
4835 : const char *filename, unsigned lineno,
4836 : JSVersion version)
4837 : {
4838 0 : AutoVersionAPI avi(cx, version);
4839 : return CompileUCScriptForPrincipalsCommon(cx, obj, principals, NULL, chars, length,
4840 0 : filename, lineno, avi.version());
4841 : }
4842 :
4843 : extern JS_PUBLIC_API(JSScript *)
4844 18 : JS_CompileUCScriptForPrincipalsVersionOrigin(JSContext *cx, JSObject *obj,
4845 : JSPrincipals *principals,
4846 : JSPrincipals *originPrincipals,
4847 : const jschar *chars, size_t length,
4848 : const char *filename, unsigned lineno,
4849 : JSVersion version)
4850 : {
4851 36 : AutoVersionAPI avi(cx, version);
4852 : return CompileUCScriptForPrincipalsCommon(cx, obj, principals, originPrincipals,
4853 18 : chars, length, filename, lineno, avi.version());
4854 : }
4855 :
4856 : JS_PUBLIC_API(JSScript *)
4857 11826 : JS_CompileUCScriptForPrincipals(JSContext *cx, JSObject *obj, JSPrincipals *principals,
4858 : const jschar *chars, size_t length,
4859 : const char *filename, unsigned lineno)
4860 : {
4861 : return CompileUCScriptForPrincipalsCommon(cx, obj, principals, NULL, chars, length,
4862 11826 : filename, lineno, cx->findVersion());
4863 : }
4864 :
4865 : JS_PUBLIC_API(JSScript *)
4866 2 : JS_CompileUCScript(JSContext *cx, JSObject *obj, const jschar *chars, size_t length,
4867 : const char *filename, unsigned lineno)
4868 : {
4869 2 : JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
4870 2 : return JS_CompileUCScriptForPrincipals(cx, obj, NULL, chars, length, filename, lineno);
4871 : }
4872 :
4873 : JS_PUBLIC_API(JSScript *)
4874 11288 : JS_CompileScriptForPrincipalsVersion(JSContext *cx, JSObject *obj,
4875 : JSPrincipals *principals,
4876 : const char *bytes, size_t length,
4877 : const char *filename, unsigned lineno,
4878 : JSVersion version)
4879 : {
4880 22576 : AutoVersionAPI ava(cx, version);
4881 11288 : return JS_CompileScriptForPrincipals(cx, obj, principals, bytes, length, filename, lineno);
4882 : }
4883 :
4884 : JS_PUBLIC_API(JSScript *)
4885 11823 : JS_CompileScriptForPrincipals(JSContext *cx, JSObject *obj,
4886 : JSPrincipals *principals,
4887 : const char *bytes, size_t length,
4888 : const char *filename, unsigned lineno)
4889 : {
4890 11823 : JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
4891 11823 : AssertNoGC(cx);
4892 23646 : CHECK_REQUEST(cx);
4893 :
4894 11823 : jschar *chars = InflateString(cx, bytes, &length);
4895 11823 : if (!chars)
4896 0 : return NULL;
4897 : JSScript *script =
4898 11823 : JS_CompileUCScriptForPrincipals(cx, obj, principals, chars, length, filename, lineno);
4899 11823 : cx->free_(chars);
4900 11823 : return script;
4901 : }
4902 :
4903 : JS_PUBLIC_API(JSScript *)
4904 9 : JS_CompileScript(JSContext *cx, JSObject *obj, const char *bytes, size_t length,
4905 : const char *filename, unsigned lineno)
4906 : {
4907 9 : JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
4908 9 : return JS_CompileScriptForPrincipals(cx, obj, NULL, bytes, length, filename, lineno);
4909 : }
4910 :
4911 : JS_PUBLIC_API(JSBool)
4912 0 : JS_BufferIsCompilableUnit(JSContext *cx, JSBool bytes_are_utf8, JSObject *obj, const char *bytes, size_t length)
4913 : {
4914 : jschar *chars;
4915 : JSBool result;
4916 : JSExceptionState *exnState;
4917 : JSErrorReporter older;
4918 :
4919 0 : AssertNoGC(cx);
4920 0 : CHECK_REQUEST(cx);
4921 0 : assertSameCompartment(cx, obj);
4922 0 : if (bytes_are_utf8)
4923 0 : chars = InflateString(cx, bytes, &length, CESU8Encoding);
4924 : else
4925 0 : chars = InflateString(cx, bytes, &length);
4926 0 : if (!chars)
4927 0 : return JS_TRUE;
4928 :
4929 : /*
4930 : * Return true on any out-of-memory error, so our caller doesn't try to
4931 : * collect more buffered source.
4932 : */
4933 0 : result = JS_TRUE;
4934 0 : exnState = JS_SaveExceptionState(cx);
4935 : {
4936 0 : Parser parser(cx);
4937 0 : if (parser.init(chars, length, NULL, 1, cx->findVersion())) {
4938 0 : older = JS_SetErrorReporter(cx, NULL);
4939 0 : if (!parser.parse(obj) &&
4940 0 : parser.tokenStream.isUnexpectedEOF()) {
4941 : /*
4942 : * We ran into an error. If it was because we ran out of
4943 : * source, we return false so our caller knows to try to
4944 : * collect more buffered source.
4945 : */
4946 0 : result = JS_FALSE;
4947 : }
4948 0 : JS_SetErrorReporter(cx, older);
4949 : }
4950 : }
4951 0 : cx->free_(chars);
4952 0 : JS_RestoreExceptionState(cx, exnState);
4953 0 : return result;
4954 : }
4955 :
4956 : /* Use the fastest available getc. */
4957 : #if defined(HAVE_GETC_UNLOCKED)
4958 : # define fast_getc getc_unlocked
4959 : #elif defined(HAVE__GETC_NOLOCK)
4960 : # define fast_getc _getc_nolock
4961 : #else
4962 : # define fast_getc getc
4963 : #endif
4964 :
4965 : static JSScript *
4966 42491 : CompileUTF8FileHelper(JSContext *cx, JSObject *obj, JSPrincipals *principals,
4967 : const char* filename, FILE *fp)
4968 : {
4969 : struct stat st;
4970 42491 : int ok = fstat(fileno(fp), &st);
4971 42491 : if (ok != 0)
4972 0 : return NULL;
4973 :
4974 42491 : char *buf = NULL;
4975 42491 : size_t len = st.st_size;
4976 42491 : size_t i = 0;
4977 : JSScript *script;
4978 :
4979 : /* Read in the whole file, then compile it. */
4980 42491 : if (fp == stdin) {
4981 0 : if (len == 0)
4982 0 : len = 8; /* start with a small buffer, expand as necessary */
4983 :
4984 : int c;
4985 0 : bool hitEOF = false;
4986 0 : while (!hitEOF) {
4987 0 : len *= 2;
4988 0 : char* tmpbuf = (char *) cx->realloc_(buf, len * sizeof(char));
4989 0 : if (!tmpbuf) {
4990 0 : cx->free_(buf);
4991 0 : return NULL;
4992 : }
4993 0 : buf = tmpbuf;
4994 :
4995 0 : while (i < len) {
4996 0 : c = fast_getc(fp);
4997 0 : if (c == EOF) {
4998 0 : hitEOF = true;
4999 0 : break;
5000 : }
5001 0 : buf[i++] = c;
5002 : }
5003 : }
5004 : } else {
5005 42491 : buf = (char *) cx->malloc_(len * sizeof(char));
5006 42491 : if (!buf)
5007 0 : return NULL;
5008 :
5009 : int c;
5010 : // The |i < len| is necessary for files that lie about their length,
5011 : // e.g. /dev/zero and /dev/random. See bug 669434.
5012 340270733 : while (i < len && (c = fast_getc(fp)) != EOF)
5013 340185751 : buf[i++] = c;
5014 : }
5015 :
5016 42491 : JS_ASSERT(i <= len);
5017 42491 : len = i;
5018 42491 : size_t decodelen = len;
5019 42491 : jschar *decodebuf = (jschar *)cx->malloc_(decodelen * sizeof(jschar));
5020 42491 : if (JS_DecodeUTF8(cx, buf, len, decodebuf, &decodelen)) {
5021 42491 : uint32_t tcflags = JS_OPTIONS_TO_TCFLAGS(cx) | TCF_NEED_SCRIPT_GLOBAL;
5022 : script = frontend::CompileScript(cx, obj, NULL, principals, NULL,
5023 : tcflags, decodebuf, decodelen,
5024 42491 : filename, 1, cx->findVersion());
5025 : } else {
5026 0 : script = NULL;
5027 : }
5028 42491 : cx->free_(buf);
5029 42491 : cx->free_(decodebuf);
5030 42491 : return script;
5031 : }
5032 :
5033 : JS_PUBLIC_API(JSScript *)
5034 875 : JS_CompileUTF8File(JSContext *cx, JSObject *obj, const char *filename)
5035 : {
5036 875 : JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
5037 875 : AssertNoGC(cx);
5038 1750 : CHECK_REQUEST(cx);
5039 875 : assertSameCompartment(cx, obj);
5040 1750 : AutoLastFrameCheck lfc(cx);
5041 :
5042 : FILE *fp;
5043 875 : if (!filename || strcmp(filename, "-") == 0) {
5044 0 : fp = stdin;
5045 : } else {
5046 875 : fp = fopen(filename, "r");
5047 875 : if (!fp) {
5048 : JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_OPEN,
5049 0 : filename, "No such file or directory");
5050 0 : return NULL;
5051 : }
5052 : }
5053 :
5054 875 : JSScript *script = CompileUTF8FileHelper(cx, obj, NULL, filename, fp);
5055 875 : if (fp != stdin)
5056 875 : fclose(fp);
5057 875 : return script;
5058 : }
5059 :
5060 : JS_PUBLIC_API(JSScript *)
5061 41616 : JS_CompileUTF8FileHandleForPrincipals(JSContext *cx, JSObject *obj, const char *filename,
5062 : FILE *file, JSPrincipals *principals)
5063 : {
5064 41616 : JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
5065 41616 : AssertNoGC(cx);
5066 83232 : CHECK_REQUEST(cx);
5067 41616 : assertSameCompartment(cx, obj, principals);
5068 83232 : AutoLastFrameCheck lfc(cx);
5069 :
5070 41616 : return CompileUTF8FileHelper(cx, obj, principals, filename, file);
5071 : }
5072 :
5073 : JS_PUBLIC_API(JSScript *)
5074 0 : JS_CompileUTF8FileHandleForPrincipalsVersion(JSContext *cx, JSObject *obj, const char *filename,
5075 : FILE *file, JSPrincipals *principals, JSVersion version)
5076 : {
5077 0 : AutoVersionAPI ava(cx, version);
5078 0 : return JS_CompileUTF8FileHandleForPrincipals(cx, obj, filename, file, principals);
5079 : }
5080 :
5081 : JS_PUBLIC_API(JSScript *)
5082 36812 : JS_CompileUTF8FileHandle(JSContext *cx, JSObject *obj, const char *filename, FILE *file)
5083 : {
5084 36812 : JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
5085 36812 : return JS_CompileUTF8FileHandleForPrincipals(cx, obj, filename, file, NULL);
5086 : }
5087 :
5088 : JS_PUBLIC_API(JSObject *)
5089 0 : JS_GetGlobalFromScript(JSScript *script)
5090 : {
5091 0 : JS_ASSERT(!script->isCachedEval);
5092 0 : JS_ASSERT(script->globalObject);
5093 :
5094 0 : return script->globalObject;
5095 : }
5096 :
5097 : static JSFunction *
5098 8 : CompileUCFunctionForPrincipalsCommon(JSContext *cx, JSObject *obj,
5099 : JSPrincipals *principals, const char *name,
5100 : unsigned nargs, const char **argnames,
5101 : const jschar *chars, size_t length,
5102 : const char *filename, unsigned lineno, JSVersion version)
5103 : {
5104 16 : RootObject objRoot(cx, &obj);
5105 :
5106 8 : JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
5107 8 : AssertNoGC(cx);
5108 16 : CHECK_REQUEST(cx);
5109 8 : assertSameCompartment(cx, obj, principals);
5110 16 : AutoLastFrameCheck lfc(cx);
5111 :
5112 : JSAtom *funAtom;
5113 8 : if (!name) {
5114 0 : funAtom = NULL;
5115 : } else {
5116 8 : funAtom = js_Atomize(cx, name, strlen(name));
5117 8 : if (!funAtom)
5118 0 : return NULL;
5119 : }
5120 :
5121 16 : Bindings bindings(cx);
5122 14 : for (unsigned i = 0; i < nargs; i++) {
5123 : uint16_t dummy;
5124 6 : JSAtom *argAtom = js_Atomize(cx, argnames[i], strlen(argnames[i]));
5125 6 : if (!argAtom || !bindings.addArgument(cx, argAtom, &dummy))
5126 0 : return NULL;
5127 : }
5128 :
5129 8 : JSFunction *fun = js_NewFunction(cx, NULL, NULL, 0, JSFUN_INTERPRETED, objRoot, funAtom);
5130 8 : if (!fun)
5131 0 : return NULL;
5132 :
5133 8 : if (!frontend::CompileFunctionBody(cx, fun, principals, NULL, &bindings,
5134 8 : chars, length, filename, lineno, version))
5135 : {
5136 0 : return NULL;
5137 : }
5138 :
5139 16 : if (obj && funAtom &&
5140 8 : !obj->defineGeneric(cx, ATOM_TO_JSID(funAtom), ObjectValue(*fun), NULL, NULL,
5141 8 : JSPROP_ENUMERATE))
5142 : {
5143 0 : return NULL;
5144 : }
5145 :
5146 8 : return fun;
5147 : }
5148 :
5149 : JS_PUBLIC_API(JSFunction *)
5150 0 : JS_CompileUCFunctionForPrincipalsVersion(JSContext *cx, JSObject *obj,
5151 : JSPrincipals *principals, const char *name,
5152 : unsigned nargs, const char **argnames,
5153 : const jschar *chars, size_t length,
5154 : const char *filename, unsigned lineno,
5155 : JSVersion version)
5156 : {
5157 0 : AutoVersionAPI avi(cx, version);
5158 : return CompileUCFunctionForPrincipalsCommon(cx, obj, principals, name, nargs, argnames, chars,
5159 0 : length, filename, lineno, avi.version());
5160 : }
5161 :
5162 : JS_PUBLIC_API(JSFunction *)
5163 8 : JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *obj,
5164 : JSPrincipals *principals, const char *name,
5165 : unsigned nargs, const char **argnames,
5166 : const jschar *chars, size_t length,
5167 : const char *filename, unsigned lineno)
5168 : {
5169 : return CompileUCFunctionForPrincipalsCommon(cx, obj, principals, name, nargs, argnames, chars,
5170 8 : length, filename, lineno, cx->findVersion());
5171 : }
5172 :
5173 : JS_PUBLIC_API(JSFunction *)
5174 0 : JS_CompileUCFunction(JSContext *cx, JSObject *obj, const char *name,
5175 : unsigned nargs, const char **argnames,
5176 : const jschar *chars, size_t length,
5177 : const char *filename, unsigned lineno)
5178 : {
5179 0 : JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
5180 : return JS_CompileUCFunctionForPrincipals(cx, obj, NULL, name, nargs, argnames,
5181 0 : chars, length, filename, lineno);
5182 : }
5183 :
5184 : JS_PUBLIC_API(JSFunction *)
5185 8 : JS_CompileFunctionForPrincipals(JSContext *cx, JSObject *obj,
5186 : JSPrincipals *principals, const char *name,
5187 : unsigned nargs, const char **argnames,
5188 : const char *bytes, size_t length,
5189 : const char *filename, unsigned lineno)
5190 : {
5191 8 : JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
5192 8 : jschar *chars = InflateString(cx, bytes, &length);
5193 8 : if (!chars)
5194 0 : return NULL;
5195 : JSFunction *fun = JS_CompileUCFunctionForPrincipals(cx, obj, principals, name,
5196 : nargs, argnames, chars, length,
5197 8 : filename, lineno);
5198 8 : cx->free_(chars);
5199 8 : return fun;
5200 : }
5201 :
5202 : JS_PUBLIC_API(JSFunction *)
5203 4 : JS_CompileFunction(JSContext *cx, JSObject *obj, const char *name,
5204 : unsigned nargs, const char **argnames,
5205 : const char *bytes, size_t length,
5206 : const char *filename, unsigned lineno)
5207 : {
5208 4 : JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
5209 : return JS_CompileFunctionForPrincipals(cx, obj, NULL, name, nargs, argnames, bytes, length,
5210 4 : filename, lineno);
5211 : }
5212 :
5213 : JS_PUBLIC_API(JSString *)
5214 0 : JS_DecompileScript(JSContext *cx, JSScript *script, const char *name, unsigned indent)
5215 : {
5216 0 : JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
5217 : JSPrinter *jp;
5218 : JSString *str;
5219 :
5220 0 : AssertNoGC(cx);
5221 0 : CHECK_REQUEST(cx);
5222 : #ifdef DEBUG
5223 0 : if (cx->compartment != script->compartment())
5224 0 : CompartmentChecker::fail(cx->compartment, script->compartment());
5225 : #endif
5226 : jp = js_NewPrinter(cx, name, NULL,
5227 : indent & ~JS_DONT_PRETTY_PRINT,
5228 : !(indent & JS_DONT_PRETTY_PRINT),
5229 0 : false, false);
5230 0 : if (!jp)
5231 0 : return NULL;
5232 0 : if (js_DecompileScript(jp, script))
5233 0 : str = js_GetPrinterOutput(jp);
5234 : else
5235 0 : str = NULL;
5236 0 : js_DestroyPrinter(jp);
5237 0 : return str;
5238 : }
5239 :
5240 : JS_PUBLIC_API(JSString *)
5241 12524 : JS_DecompileFunction(JSContext *cx, JSFunction *fun, unsigned indent)
5242 : {
5243 12524 : JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
5244 12524 : AssertNoGC(cx);
5245 25048 : CHECK_REQUEST(cx);
5246 12524 : assertSameCompartment(cx, fun);
5247 : return js_DecompileToString(cx, "JS_DecompileFunction", fun,
5248 : indent & ~JS_DONT_PRETTY_PRINT,
5249 : !(indent & JS_DONT_PRETTY_PRINT),
5250 12524 : false, false, js_DecompileFunction);
5251 : }
5252 :
5253 : JS_PUBLIC_API(JSString *)
5254 0 : JS_DecompileFunctionBody(JSContext *cx, JSFunction *fun, unsigned indent)
5255 : {
5256 0 : JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
5257 0 : AssertNoGC(cx);
5258 0 : CHECK_REQUEST(cx);
5259 0 : assertSameCompartment(cx, fun);
5260 : return js_DecompileToString(cx, "JS_DecompileFunctionBody", fun,
5261 : indent & ~JS_DONT_PRETTY_PRINT,
5262 : !(indent & JS_DONT_PRETTY_PRINT),
5263 0 : false, false, js_DecompileFunctionBody);
5264 : }
5265 :
5266 : JS_PUBLIC_API(JSBool)
5267 54922 : JS_ExecuteScript(JSContext *cx, JSObject *obj, JSScript *script, jsval *rval)
5268 : {
5269 54922 : JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
5270 54922 : AssertNoGC(cx);
5271 109844 : CHECK_REQUEST(cx);
5272 54922 : assertSameCompartment(cx, obj, script);
5273 109844 : AutoLastFrameCheck lfc(cx);
5274 :
5275 54922 : return Execute(cx, script, *obj, rval);
5276 : }
5277 :
5278 : JS_PUBLIC_API(JSBool)
5279 12452 : JS_ExecuteScriptVersion(JSContext *cx, JSObject *obj, JSScript *script, jsval *rval,
5280 : JSVersion version)
5281 : {
5282 24904 : AutoVersionAPI ava(cx, version);
5283 12452 : return JS_ExecuteScript(cx, obj, script, rval);
5284 : }
5285 :
5286 : bool
5287 29360 : EvaluateUCScriptForPrincipalsCommon(JSContext *cx, JSObject *obj,
5288 : JSPrincipals *principals, JSPrincipals *originPrincipals,
5289 : const jschar *chars, unsigned length,
5290 : const char *filename, unsigned lineno,
5291 : jsval *rval, JSVersion compileVersion)
5292 : {
5293 29360 : JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
5294 :
5295 29360 : uint32_t flags = TCF_COMPILE_N_GO | TCF_NEED_SCRIPT_GLOBAL;
5296 29360 : if (!rval)
5297 0 : flags |= TCF_NO_SCRIPT_RVAL;
5298 :
5299 58720 : CHECK_REQUEST(cx);
5300 58720 : AutoLastFrameCheck lfc(cx);
5301 : JSScript *script = frontend::CompileScript(cx, obj, NULL, principals, originPrincipals,
5302 : flags, chars, length, filename, lineno,
5303 29360 : compileVersion);
5304 29360 : if (!script)
5305 2 : return false;
5306 :
5307 29358 : JS_ASSERT(script->getVersion() == compileVersion);
5308 :
5309 29358 : return Execute(cx, script, *obj, rval);
5310 : }
5311 :
5312 : JS_PUBLIC_API(JSBool)
5313 29332 : JS_EvaluateUCScriptForPrincipals(JSContext *cx, JSObject *obj,
5314 : JSPrincipals *principals,
5315 : const jschar *chars, unsigned length,
5316 : const char *filename, unsigned lineno,
5317 : jsval *rval)
5318 : {
5319 : return EvaluateUCScriptForPrincipalsCommon(cx, obj, principals, NULL, chars, length,
5320 29332 : filename, lineno, rval, cx->findVersion());
5321 : }
5322 :
5323 : JS_PUBLIC_API(JSBool)
5324 2 : JS_EvaluateUCScriptForPrincipalsVersion(JSContext *cx, JSObject *obj,
5325 : JSPrincipals *principals,
5326 : const jschar *chars, unsigned length,
5327 : const char *filename, unsigned lineno,
5328 : jsval *rval, JSVersion version)
5329 : {
5330 4 : AutoVersionAPI avi(cx, version);
5331 : return EvaluateUCScriptForPrincipalsCommon(cx, obj, principals, NULL, chars, length,
5332 2 : filename, lineno, rval, avi.version());
5333 : }
5334 :
5335 : extern JS_PUBLIC_API(JSBool)
5336 26 : JS_EvaluateUCScriptForPrincipalsVersionOrigin(JSContext *cx, JSObject *obj,
5337 : JSPrincipals *principals,
5338 : JSPrincipals *originPrincipals,
5339 : const jschar *chars, unsigned length,
5340 : const char *filename, unsigned lineno,
5341 : jsval *rval, JSVersion version)
5342 : {
5343 52 : AutoVersionAPI avi(cx, version);
5344 : return EvaluateUCScriptForPrincipalsCommon(cx, obj, principals, originPrincipals,
5345 : chars, length, filename, lineno, rval,
5346 26 : avi.version());
5347 : }
5348 :
5349 : JS_PUBLIC_API(JSBool)
5350 459 : JS_EvaluateUCScript(JSContext *cx, JSObject *obj, const jschar *chars, unsigned length,
5351 : const char *filename, unsigned lineno, jsval *rval)
5352 : {
5353 459 : JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
5354 459 : return JS_EvaluateUCScriptForPrincipals(cx, obj, NULL, chars, length, filename, lineno, rval);
5355 : }
5356 :
5357 : /* Ancient unsigned nbytes is part of API/ABI, so use size_t length local. */
5358 : JS_PUBLIC_API(JSBool)
5359 28282 : JS_EvaluateScriptForPrincipals(JSContext *cx, JSObject *obj, JSPrincipals *principals,
5360 : const char *bytes, unsigned nbytes,
5361 : const char *filename, unsigned lineno, jsval *rval)
5362 : {
5363 28282 : JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
5364 28282 : size_t length = nbytes;
5365 28282 : jschar *chars = InflateString(cx, bytes, &length);
5366 28282 : if (!chars)
5367 0 : return JS_FALSE;
5368 : JSBool ok = JS_EvaluateUCScriptForPrincipals(cx, obj, principals, chars, length,
5369 28282 : filename, lineno, rval);
5370 28282 : cx->free_(chars);
5371 28282 : return ok;
5372 : }
5373 :
5374 : JS_PUBLIC_API(JSBool)
5375 0 : JS_EvaluateScriptForPrincipalsVersion(JSContext *cx, JSObject *obj, JSPrincipals *principals,
5376 : const char *bytes, unsigned nbytes,
5377 : const char *filename, unsigned lineno, jsval *rval, JSVersion version)
5378 : {
5379 0 : AutoVersionAPI avi(cx, version);
5380 : return JS_EvaluateScriptForPrincipals(cx, obj, principals, bytes, nbytes, filename, lineno,
5381 0 : rval);
5382 : }
5383 :
5384 : JS_PUBLIC_API(JSBool)
5385 18580 : JS_EvaluateScript(JSContext *cx, JSObject *obj, const char *bytes, unsigned nbytes,
5386 : const char *filename, unsigned lineno, jsval *rval)
5387 : {
5388 18580 : JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
5389 18580 : return JS_EvaluateScriptForPrincipals(cx, obj, NULL, bytes, nbytes, filename, lineno, rval);
5390 : }
5391 :
5392 : JS_PUBLIC_API(JSBool)
5393 5 : JS_CallFunction(JSContext *cx, JSObject *obj, JSFunction *fun, unsigned argc, jsval *argv,
5394 : jsval *rval)
5395 : {
5396 5 : JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
5397 5 : AssertNoGC(cx);
5398 10 : CHECK_REQUEST(cx);
5399 5 : assertSameCompartment(cx, obj, fun, JSValueArray(argv, argc));
5400 10 : AutoLastFrameCheck lfc(cx);
5401 :
5402 5 : return Invoke(cx, ObjectOrNullValue(obj), ObjectValue(*fun), argc, argv, rval);
5403 : }
5404 :
5405 : JS_PUBLIC_API(JSBool)
5406 47171 : JS_CallFunctionName(JSContext *cx, JSObject *obj, const char *name, unsigned argc, jsval *argv,
5407 : jsval *rval)
5408 : {
5409 47171 : JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
5410 47171 : AssertNoGC(cx);
5411 94342 : CHECK_REQUEST(cx);
5412 47171 : assertSameCompartment(cx, obj, JSValueArray(argv, argc));
5413 94342 : AutoLastFrameCheck lfc(cx);
5414 :
5415 : Value v;
5416 47171 : JSAtom *atom = js_Atomize(cx, name, strlen(name));
5417 : return atom &&
5418 47171 : js_GetMethod(cx, obj, ATOM_TO_JSID(atom), JSGET_NO_METHOD_BARRIER, &v) &&
5419 94342 : Invoke(cx, ObjectOrNullValue(obj), v, argc, argv, rval);
5420 : }
5421 :
5422 : JS_PUBLIC_API(JSBool)
5423 607836 : JS_CallFunctionValue(JSContext *cx, JSObject *obj, jsval fval, unsigned argc, jsval *argv,
5424 : jsval *rval)
5425 : {
5426 607836 : JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
5427 607836 : AssertNoGC(cx);
5428 1215672 : CHECK_REQUEST(cx);
5429 607836 : assertSameCompartment(cx, obj, fval, JSValueArray(argv, argc));
5430 1215672 : AutoLastFrameCheck lfc(cx);
5431 :
5432 607836 : return Invoke(cx, ObjectOrNullValue(obj), fval, argc, argv, rval);
5433 : }
5434 :
5435 : namespace JS {
5436 :
5437 : JS_PUBLIC_API(bool)
5438 0 : Call(JSContext *cx, jsval thisv, jsval fval, unsigned argc, jsval *argv, jsval *rval)
5439 : {
5440 0 : AssertNoGC(cx);
5441 0 : CHECK_REQUEST(cx);
5442 0 : assertSameCompartment(cx, thisv, fval, JSValueArray(argv, argc));
5443 0 : AutoLastFrameCheck lfc(cx);
5444 :
5445 0 : return Invoke(cx, thisv, fval, argc, argv, rval);
5446 : }
5447 :
5448 : } // namespace JS
5449 :
5450 : JS_PUBLIC_API(JSObject *)
5451 4 : JS_New(JSContext *cx, JSObject *ctor, unsigned argc, jsval *argv)
5452 : {
5453 4 : AssertNoGC(cx);
5454 8 : CHECK_REQUEST(cx);
5455 4 : assertSameCompartment(cx, ctor, JSValueArray(argv, argc));
5456 8 : AutoLastFrameCheck lfc(cx);
5457 :
5458 : // This is not a simple variation of JS_CallFunctionValue because JSOP_NEW
5459 : // is not a simple variation of JSOP_CALL. We have to determine what class
5460 : // of object to create, create it, and clamp the return value to an object,
5461 : // among other details. InvokeConstructor does the hard work.
5462 8 : InvokeArgsGuard args;
5463 4 : if (!cx->stack.pushInvokeArgs(cx, argc, &args))
5464 0 : return NULL;
5465 :
5466 4 : args.calleev().setObject(*ctor);
5467 4 : args.thisv().setNull();
5468 4 : PodCopy(args.array(), argv, argc);
5469 :
5470 4 : if (!InvokeConstructor(cx, args))
5471 0 : return NULL;
5472 :
5473 4 : if (!args.rval().isObject()) {
5474 : /*
5475 : * Although constructors may return primitives (via proxies), this
5476 : * API is asking for an object, so we report an error.
5477 : */
5478 0 : JSAutoByteString bytes;
5479 0 : if (js_ValueToPrintable(cx, args.rval(), &bytes)) {
5480 : JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_NEW_RESULT,
5481 0 : bytes.ptr());
5482 : }
5483 0 : return NULL;
5484 : }
5485 :
5486 4 : return &args.rval().toObject();
5487 : }
5488 :
5489 : JS_PUBLIC_API(JSOperationCallback)
5490 55806 : JS_SetOperationCallback(JSContext *cx, JSOperationCallback callback)
5491 : {
5492 55806 : JSOperationCallback old = cx->operationCallback;
5493 55806 : cx->operationCallback = callback;
5494 55806 : return old;
5495 : }
5496 :
5497 : JS_PUBLIC_API(JSOperationCallback)
5498 3 : JS_GetOperationCallback(JSContext *cx)
5499 : {
5500 3 : return cx->operationCallback;
5501 : }
5502 :
5503 : JS_PUBLIC_API(void)
5504 3339 : JS_TriggerOperationCallback(JSRuntime *rt)
5505 : {
5506 3339 : rt->triggerOperationCallback();
5507 3339 : }
5508 :
5509 : JS_PUBLIC_API(JSBool)
5510 72145 : JS_IsRunning(JSContext *cx)
5511 : {
5512 72145 : StackFrame *fp = cx->maybefp();
5513 146312 : while (fp && fp->isDummyFrame())
5514 2022 : fp = fp->prev();
5515 72145 : return fp != NULL;
5516 : }
5517 :
5518 : JS_PUBLIC_API(JSBool)
5519 220467 : JS_SaveFrameChain(JSContext *cx)
5520 : {
5521 220467 : AssertNoGC(cx);
5522 440934 : CHECK_REQUEST(cx);
5523 220467 : return cx->stack.saveFrameChain();
5524 : }
5525 :
5526 : JS_PUBLIC_API(void)
5527 220467 : JS_RestoreFrameChain(JSContext *cx)
5528 : {
5529 220467 : AssertNoGC(cx);
5530 440934 : CHECK_REQUEST(cx);
5531 220467 : cx->stack.restoreFrameChain();
5532 220467 : }
5533 :
5534 : #ifdef MOZ_TRACE_JSCALLS
5535 : JS_PUBLIC_API(void)
5536 : JS_SetFunctionCallback(JSContext *cx, JSFunctionCallback fcb)
5537 : {
5538 : cx->functionCallback = fcb;
5539 : }
5540 :
5541 : JS_PUBLIC_API(JSFunctionCallback)
5542 : JS_GetFunctionCallback(JSContext *cx)
5543 : {
5544 : return cx->functionCallback;
5545 : }
5546 : #endif
5547 :
5548 : /************************************************************************/
5549 : JS_PUBLIC_API(JSString *)
5550 20353 : JS_NewStringCopyN(JSContext *cx, const char *s, size_t n)
5551 : {
5552 20353 : AssertNoGC(cx);
5553 40706 : CHECK_REQUEST(cx);
5554 20353 : return js_NewStringCopyN(cx, s, n);
5555 : }
5556 :
5557 : JS_PUBLIC_API(JSString *)
5558 1186610 : JS_NewStringCopyZ(JSContext *cx, const char *s)
5559 : {
5560 : size_t n;
5561 : jschar *js;
5562 : JSString *str;
5563 :
5564 1186610 : AssertNoGC(cx);
5565 2373220 : CHECK_REQUEST(cx);
5566 1186610 : if (!s || !*s)
5567 283 : return cx->runtime->emptyString;
5568 1186327 : n = strlen(s);
5569 1186327 : js = InflateString(cx, s, &n);
5570 1186327 : if (!js)
5571 0 : return NULL;
5572 1186327 : str = js_NewString(cx, js, n);
5573 1186327 : if (!str)
5574 0 : cx->free_(js);
5575 1186327 : return str;
5576 : }
5577 :
5578 : JS_PUBLIC_API(JSBool)
5579 4237985 : JS_StringHasBeenInterned(JSContext *cx, JSString *str)
5580 : {
5581 4237985 : AssertNoGC(cx);
5582 8475970 : CHECK_REQUEST(cx);
5583 :
5584 4237985 : if (!str->isAtom())
5585 0 : return false;
5586 :
5587 4237985 : return AtomIsInterned(cx, &str->asAtom());
5588 : }
5589 :
5590 : JS_PUBLIC_API(JSString *)
5591 1 : JS_InternJSString(JSContext *cx, JSString *str)
5592 : {
5593 1 : AssertNoGC(cx);
5594 2 : CHECK_REQUEST(cx);
5595 1 : JSAtom *atom = js_AtomizeString(cx, str, InternAtom);
5596 1 : JS_ASSERT_IF(atom, JS_StringHasBeenInterned(cx, atom));
5597 1 : return atom;
5598 : }
5599 :
5600 : JS_PUBLIC_API(JSString *)
5601 2134716 : JS_InternString(JSContext *cx, const char *s)
5602 : {
5603 2134716 : AssertNoGC(cx);
5604 4269432 : CHECK_REQUEST(cx);
5605 2134716 : JSAtom *atom = js_Atomize(cx, s, strlen(s), InternAtom);
5606 2134716 : JS_ASSERT_IF(atom, JS_StringHasBeenInterned(cx, atom));
5607 2134716 : return atom;
5608 : }
5609 :
5610 : JS_PUBLIC_API(JSString *)
5611 1261953 : JS_NewUCString(JSContext *cx, jschar *chars, size_t length)
5612 : {
5613 1261953 : AssertNoGC(cx);
5614 2523906 : CHECK_REQUEST(cx);
5615 1261953 : return js_NewString(cx, chars, length);
5616 : }
5617 :
5618 : JS_PUBLIC_API(JSString *)
5619 28124 : JS_NewUCStringCopyN(JSContext *cx, const jschar *s, size_t n)
5620 : {
5621 28124 : AssertNoGC(cx);
5622 56248 : CHECK_REQUEST(cx);
5623 28124 : return js_NewStringCopyN(cx, s, n);
5624 : }
5625 :
5626 : JS_PUBLIC_API(JSString *)
5627 31163 : JS_NewUCStringCopyZ(JSContext *cx, const jschar *s)
5628 : {
5629 31163 : AssertNoGC(cx);
5630 62326 : CHECK_REQUEST(cx);
5631 31163 : if (!s)
5632 0 : return cx->runtime->emptyString;
5633 31163 : return js_NewStringCopyZ(cx, s);
5634 : }
5635 :
5636 : JS_PUBLIC_API(JSString *)
5637 0 : JS_InternUCStringN(JSContext *cx, const jschar *s, size_t length)
5638 : {
5639 0 : AssertNoGC(cx);
5640 0 : CHECK_REQUEST(cx);
5641 0 : JSAtom *atom = js_AtomizeChars(cx, s, length, InternAtom);
5642 0 : JS_ASSERT_IF(atom, JS_StringHasBeenInterned(cx, atom));
5643 0 : return atom;
5644 : }
5645 :
5646 : JS_PUBLIC_API(JSString *)
5647 0 : JS_InternUCString(JSContext *cx, const jschar *s)
5648 : {
5649 0 : return JS_InternUCStringN(cx, s, js_strlen(s));
5650 : }
5651 :
5652 : JS_PUBLIC_API(size_t)
5653 1926149 : JS_GetStringLength(JSString *str)
5654 : {
5655 1926149 : return str->length();
5656 : }
5657 :
5658 : JS_PUBLIC_API(const jschar *)
5659 1920619 : JS_GetStringCharsZ(JSContext *cx, JSString *str)
5660 : {
5661 1920619 : AssertNoGCOrFlatString(cx, str);
5662 3841238 : CHECK_REQUEST(cx);
5663 1920619 : assertSameCompartment(cx, str);
5664 1920619 : return str->getCharsZ(cx);
5665 : }
5666 :
5667 : JS_PUBLIC_API(const jschar *)
5668 319180 : JS_GetStringCharsZAndLength(JSContext *cx, JSString *str, size_t *plength)
5669 : {
5670 319180 : AssertNoGCOrFlatString(cx, str);
5671 638360 : CHECK_REQUEST(cx);
5672 319180 : assertSameCompartment(cx, str);
5673 319180 : *plength = str->length();
5674 319180 : return str->getCharsZ(cx);
5675 : }
5676 :
5677 : JS_PUBLIC_API(const jschar *)
5678 179883 : JS_GetStringCharsAndLength(JSContext *cx, JSString *str, size_t *plength)
5679 : {
5680 179883 : AssertNoGCOrFlatString(cx, str);
5681 359766 : CHECK_REQUEST(cx);
5682 179883 : assertSameCompartment(cx, str);
5683 179883 : *plength = str->length();
5684 179883 : return str->getChars(cx);
5685 : }
5686 :
5687 : JS_PUBLIC_API(const jschar *)
5688 0 : JS_GetInternedStringChars(JSString *str)
5689 : {
5690 0 : return str->asAtom().chars();
5691 : }
5692 :
5693 : JS_PUBLIC_API(const jschar *)
5694 15641 : JS_GetInternedStringCharsAndLength(JSString *str, size_t *plength)
5695 : {
5696 15641 : JSAtom &atom = str->asAtom();
5697 15641 : *plength = atom.length();
5698 15641 : return atom.chars();
5699 : }
5700 :
5701 : extern JS_PUBLIC_API(JSFlatString *)
5702 307 : JS_FlattenString(JSContext *cx, JSString *str)
5703 : {
5704 307 : AssertNoGC(cx);
5705 614 : CHECK_REQUEST(cx);
5706 307 : assertSameCompartment(cx, str);
5707 307 : return str->getCharsZ(cx) ? (JSFlatString *)str : NULL;
5708 : }
5709 :
5710 : extern JS_PUBLIC_API(const jschar *)
5711 8 : JS_GetFlatStringChars(JSFlatString *str)
5712 : {
5713 8 : return str->chars();
5714 : }
5715 :
5716 : JS_PUBLIC_API(JSBool)
5717 0 : JS_CompareStrings(JSContext *cx, JSString *str1, JSString *str2, int32_t *result)
5718 : {
5719 0 : AssertNoGC(cx);
5720 0 : CHECK_REQUEST(cx);
5721 :
5722 0 : return CompareStrings(cx, str1, str2, result);
5723 : }
5724 :
5725 : JS_PUBLIC_API(JSBool)
5726 8865 : JS_StringEqualsAscii(JSContext *cx, JSString *str, const char *asciiBytes, JSBool *match)
5727 : {
5728 8865 : AssertNoGC(cx);
5729 17730 : CHECK_REQUEST(cx);
5730 :
5731 8865 : JSLinearString *linearStr = str->ensureLinear(cx);
5732 8865 : if (!linearStr)
5733 0 : return false;
5734 8865 : *match = StringEqualsAscii(linearStr, asciiBytes);
5735 8865 : return true;
5736 : }
5737 :
5738 : JS_PUBLIC_API(JSBool)
5739 286675 : JS_FlatStringEqualsAscii(JSFlatString *str, const char *asciiBytes)
5740 : {
5741 286675 : return StringEqualsAscii(str, asciiBytes);
5742 : }
5743 :
5744 : JS_PUBLIC_API(size_t)
5745 0 : JS_PutEscapedFlatString(char *buffer, size_t size, JSFlatString *str, char quote)
5746 : {
5747 0 : return PutEscapedString(buffer, size, str, quote);
5748 : }
5749 :
5750 : JS_PUBLIC_API(size_t)
5751 0 : JS_PutEscapedString(JSContext *cx, char *buffer, size_t size, JSString *str, char quote)
5752 : {
5753 0 : AssertNoGC(cx);
5754 0 : JSLinearString *linearStr = str->ensureLinear(cx);
5755 0 : if (!linearStr)
5756 0 : return size_t(-1);
5757 0 : return PutEscapedString(buffer, size, linearStr, quote);
5758 : }
5759 :
5760 : JS_PUBLIC_API(JSBool)
5761 0 : JS_FileEscapedString(FILE *fp, JSString *str, char quote)
5762 : {
5763 0 : JSLinearString *linearStr = str->ensureLinear(NULL);
5764 0 : return linearStr && FileEscapedString(fp, linearStr, quote);
5765 : }
5766 :
5767 : JS_PUBLIC_API(JSString *)
5768 0 : JS_NewGrowableString(JSContext *cx, jschar *chars, size_t length)
5769 : {
5770 0 : AssertNoGC(cx);
5771 0 : CHECK_REQUEST(cx);
5772 0 : return js_NewString(cx, chars, length);
5773 : }
5774 :
5775 : JS_PUBLIC_API(JSString *)
5776 0 : JS_NewDependentString(JSContext *cx, JSString *str, size_t start, size_t length)
5777 : {
5778 0 : AssertNoGC(cx);
5779 0 : CHECK_REQUEST(cx);
5780 0 : return js_NewDependentString(cx, str, start, length);
5781 : }
5782 :
5783 : JS_PUBLIC_API(JSString *)
5784 0 : JS_ConcatStrings(JSContext *cx, JSString *left, JSString *right)
5785 : {
5786 0 : AssertNoGC(cx);
5787 0 : CHECK_REQUEST(cx);
5788 0 : return js_ConcatStrings(cx, left, right);
5789 : }
5790 :
5791 : JS_PUBLIC_API(const jschar *)
5792 0 : JS_UndependString(JSContext *cx, JSString *str)
5793 : {
5794 0 : AssertNoGC(cx);
5795 0 : CHECK_REQUEST(cx);
5796 0 : return str->getCharsZ(cx);
5797 : }
5798 :
5799 : JS_PUBLIC_API(JSBool)
5800 2576 : JS_MakeStringImmutable(JSContext *cx, JSString *str)
5801 : {
5802 2576 : AssertNoGC(cx);
5803 5152 : CHECK_REQUEST(cx);
5804 2576 : return !!str->ensureFixed(cx);
5805 : }
5806 :
5807 : JS_PUBLIC_API(JSBool)
5808 2 : JS_EncodeCharacters(JSContext *cx, const jschar *src, size_t srclen, char *dst, size_t *dstlenp)
5809 : {
5810 2 : AssertNoGC(cx);
5811 4 : CHECK_REQUEST(cx);
5812 :
5813 : size_t n;
5814 2 : if (!dst) {
5815 1 : n = GetDeflatedStringLength(cx, src, srclen);
5816 1 : if (n == (size_t)-1) {
5817 0 : *dstlenp = 0;
5818 0 : return JS_FALSE;
5819 : }
5820 1 : *dstlenp = n;
5821 1 : return JS_TRUE;
5822 : }
5823 :
5824 1 : return DeflateStringToBuffer(cx, src, srclen, dst, dstlenp);
5825 : }
5826 :
5827 : JS_PUBLIC_API(JSBool)
5828 36 : JS_DecodeBytes(JSContext *cx, const char *src, size_t srclen, jschar *dst, size_t *dstlenp)
5829 : {
5830 36 : AssertNoGC(cx);
5831 72 : CHECK_REQUEST(cx);
5832 36 : return InflateStringToBuffer(cx, src, srclen, dst, dstlenp);
5833 : }
5834 :
5835 : JS_PUBLIC_API(JSBool)
5836 42491 : JS_DecodeUTF8(JSContext *cx, const char *src, size_t srclen, jschar *dst,
5837 : size_t *dstlenp)
5838 : {
5839 42491 : AssertNoGC(cx);
5840 84982 : CHECK_REQUEST(cx);
5841 42491 : return InflateUTF8StringToBuffer(cx, src, srclen, dst, dstlenp);
5842 : }
5843 :
5844 : JS_PUBLIC_API(char *)
5845 809664 : JS_EncodeString(JSContext *cx, JSString *str)
5846 : {
5847 809664 : AssertNoGC(cx);
5848 1619328 : CHECK_REQUEST(cx);
5849 :
5850 809664 : const jschar *chars = str->getChars(cx);
5851 809664 : if (!chars)
5852 0 : return NULL;
5853 809664 : return DeflateString(cx, chars, str->length());
5854 : }
5855 :
5856 : JS_PUBLIC_API(size_t)
5857 2434158 : JS_GetStringEncodingLength(JSContext *cx, JSString *str)
5858 : {
5859 : /* jsd calls us with a NULL cx. Ugh. */
5860 2434158 : if (cx) {
5861 2434154 : AssertNoGC(cx);
5862 2434154 : CHECK_REQUEST(cx);
5863 : }
5864 :
5865 2434158 : const jschar *chars = str->getChars(cx);
5866 2434158 : if (!chars)
5867 0 : return size_t(-1);
5868 2434158 : return GetDeflatedStringLength(cx, chars, str->length());
5869 : }
5870 :
5871 : JS_PUBLIC_API(size_t)
5872 2426325 : JS_EncodeStringToBuffer(JSString *str, char *buffer, size_t length)
5873 : {
5874 : /*
5875 : * FIXME bug 612141 - fix DeflateStringToBuffer interface so the result
5876 : * would allow to distinguish between insufficient buffer and encoding
5877 : * error.
5878 : */
5879 2426325 : size_t writtenLength = length;
5880 2426325 : const jschar *chars = str->getChars(NULL);
5881 2426325 : if (!chars)
5882 0 : return size_t(-1);
5883 2426325 : if (DeflateStringToBuffer(NULL, chars, str->length(), buffer, &writtenLength)) {
5884 2426325 : JS_ASSERT(writtenLength <= length);
5885 2426325 : return writtenLength;
5886 : }
5887 0 : JS_ASSERT(writtenLength <= length);
5888 0 : size_t necessaryLength = GetDeflatedStringLength(NULL, chars, str->length());
5889 0 : if (necessaryLength == size_t(-1))
5890 0 : return size_t(-1);
5891 0 : if (writtenLength != length) {
5892 : /* Make sure that the buffer contains only valid UTF-8 sequences. */
5893 0 : JS_ASSERT(js_CStringsAreUTF8);
5894 0 : PodZero(buffer + writtenLength, length - writtenLength);
5895 : }
5896 0 : return necessaryLength;
5897 : }
5898 :
5899 : JS_PUBLIC_API(JSBool)
5900 568 : JS_Stringify(JSContext *cx, jsval *vp, JSObject *replacer, jsval space,
5901 : JSONWriteCallback callback, void *data)
5902 : {
5903 568 : AssertNoGC(cx);
5904 1136 : CHECK_REQUEST(cx);
5905 568 : assertSameCompartment(cx, replacer, space);
5906 1136 : StringBuffer sb(cx);
5907 568 : if (!js_Stringify(cx, vp, replacer, space, sb))
5908 0 : return false;
5909 568 : if (sb.empty()) {
5910 0 : JSAtom *nullAtom = cx->runtime->atomState.nullAtom;
5911 0 : return callback(nullAtom->chars(), nullAtom->length(), data);
5912 : }
5913 568 : return callback(sb.begin(), sb.length(), data);
5914 : }
5915 :
5916 : JS_PUBLIC_API(JSBool)
5917 30 : JS_ParseJSON(JSContext *cx, const jschar *chars, uint32_t len, jsval *vp)
5918 : {
5919 30 : AssertNoGC(cx);
5920 60 : CHECK_REQUEST(cx);
5921 :
5922 30 : return ParseJSONWithReviver(cx, chars, len, NullValue(), vp);
5923 : }
5924 :
5925 : JS_PUBLIC_API(JSBool)
5926 8 : JS_ParseJSONWithReviver(JSContext *cx, const jschar *chars, uint32_t len, jsval reviver, jsval *vp)
5927 : {
5928 8 : AssertNoGC(cx);
5929 16 : CHECK_REQUEST(cx);
5930 :
5931 8 : return ParseJSONWithReviver(cx, chars, len, reviver, vp);
5932 : }
5933 :
5934 : JS_PUBLIC_API(JSBool)
5935 756 : JS_ReadStructuredClone(JSContext *cx, const uint64_t *buf, size_t nbytes,
5936 : uint32_t version, jsval *vp,
5937 : const JSStructuredCloneCallbacks *optionalCallbacks,
5938 : void *closure)
5939 : {
5940 756 : AssertNoGC(cx);
5941 1512 : CHECK_REQUEST(cx);
5942 :
5943 756 : if (version > JS_STRUCTURED_CLONE_VERSION) {
5944 0 : JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_CLONE_VERSION);
5945 0 : return false;
5946 : }
5947 : const JSStructuredCloneCallbacks *callbacks =
5948 : optionalCallbacks ?
5949 : optionalCallbacks :
5950 756 : cx->runtime->structuredCloneCallbacks;
5951 756 : return ReadStructuredClone(cx, buf, nbytes, vp, callbacks, closure);
5952 : }
5953 :
5954 : JS_PUBLIC_API(JSBool)
5955 1891 : JS_WriteStructuredClone(JSContext *cx, jsval v, uint64_t **bufp, size_t *nbytesp,
5956 : const JSStructuredCloneCallbacks *optionalCallbacks,
5957 : void *closure)
5958 : {
5959 1891 : AssertNoGC(cx);
5960 3782 : CHECK_REQUEST(cx);
5961 :
5962 : const JSStructuredCloneCallbacks *callbacks =
5963 : optionalCallbacks ?
5964 : optionalCallbacks :
5965 1891 : cx->runtime->structuredCloneCallbacks;
5966 1891 : return WriteStructuredClone(cx, v, (uint64_t **) bufp, nbytesp, callbacks, closure);
5967 : }
5968 :
5969 : JS_PUBLIC_API(JSBool)
5970 0 : JS_StructuredClone(JSContext *cx, jsval v, jsval *vp,
5971 : const JSStructuredCloneCallbacks *optionalCallbacks,
5972 : void *closure)
5973 : {
5974 0 : AssertNoGC(cx);
5975 0 : CHECK_REQUEST(cx);
5976 :
5977 : const JSStructuredCloneCallbacks *callbacks =
5978 : optionalCallbacks ?
5979 : optionalCallbacks :
5980 0 : cx->runtime->structuredCloneCallbacks;
5981 0 : JSAutoStructuredCloneBuffer buf;
5982 0 : return buf.write(cx, v, callbacks, closure) &&
5983 0 : buf.read(cx, vp, callbacks, closure);
5984 : }
5985 :
5986 : void
5987 14271 : JSAutoStructuredCloneBuffer::clear()
5988 : {
5989 14271 : if (data_) {
5990 3807 : Foreground::free_(data_);
5991 3807 : data_ = NULL;
5992 3807 : nbytes_ = 0;
5993 3807 : version_ = 0;
5994 : }
5995 14271 : }
5996 :
5997 : void
5998 0 : JSAutoStructuredCloneBuffer::adopt(uint64_t *data, size_t nbytes, uint32_t version)
5999 : {
6000 0 : clear();
6001 0 : data_ = data;
6002 0 : nbytes_ = nbytes;
6003 0 : version_ = version;
6004 0 : }
6005 :
6006 : bool
6007 1970 : JSAutoStructuredCloneBuffer::copy(const uint64_t *srcData, size_t nbytes, uint32_t version)
6008 : {
6009 1970 : uint64_t *newData = static_cast<uint64_t *>(OffTheBooks::malloc_(nbytes));
6010 1970 : if (!newData)
6011 0 : return false;
6012 :
6013 1970 : js_memcpy(newData, srcData, nbytes);
6014 :
6015 1970 : clear();
6016 1970 : data_ = newData;
6017 1970 : nbytes_ = nbytes;
6018 1970 : version_ = version;
6019 1970 : return true;
6020 : }
6021 : void
6022 0 : JSAutoStructuredCloneBuffer::steal(uint64_t **datap, size_t *nbytesp, uint32_t *versionp)
6023 : {
6024 0 : *datap = data_;
6025 0 : *nbytesp = nbytes_;
6026 0 : if (versionp)
6027 0 : *versionp = version_;
6028 :
6029 0 : data_ = NULL;
6030 0 : nbytes_ = 0;
6031 0 : version_ = 0;
6032 0 : }
6033 :
6034 : bool
6035 747 : JSAutoStructuredCloneBuffer::read(JSContext *cx, jsval *vp,
6036 : const JSStructuredCloneCallbacks *optionalCallbacks,
6037 : void *closure) const
6038 : {
6039 747 : JS_ASSERT(cx);
6040 747 : JS_ASSERT(data_);
6041 : return !!JS_ReadStructuredClone(cx, data_, nbytes_, version_, vp,
6042 747 : optionalCallbacks, closure);
6043 : }
6044 :
6045 : bool
6046 1837 : JSAutoStructuredCloneBuffer::write(JSContext *cx, jsval v,
6047 : const JSStructuredCloneCallbacks *optionalCallbacks,
6048 : void *closure)
6049 : {
6050 1837 : clear();
6051 : bool ok = !!JS_WriteStructuredClone(cx, v, &data_, &nbytes_,
6052 1837 : optionalCallbacks, closure);
6053 1837 : if (!ok) {
6054 0 : data_ = NULL;
6055 0 : nbytes_ = 0;
6056 0 : version_ = JS_STRUCTURED_CLONE_VERSION;
6057 : }
6058 1837 : return ok;
6059 : }
6060 :
6061 : void
6062 3549 : JSAutoStructuredCloneBuffer::swap(JSAutoStructuredCloneBuffer &other)
6063 : {
6064 3549 : uint64_t *data = other.data_;
6065 3549 : size_t nbytes = other.nbytes_;
6066 3549 : uint32_t version = other.version_;
6067 :
6068 3549 : other.data_ = this->data_;
6069 3549 : other.nbytes_ = this->nbytes_;
6070 3549 : other.version_ = this->version_;
6071 :
6072 3549 : this->data_ = data;
6073 3549 : this->nbytes_ = nbytes;
6074 3549 : this->version_ = version;
6075 3549 : }
6076 :
6077 : JS_PUBLIC_API(void)
6078 50 : JS_SetStructuredCloneCallbacks(JSRuntime *rt, const JSStructuredCloneCallbacks *callbacks)
6079 : {
6080 50 : rt->structuredCloneCallbacks = callbacks;
6081 50 : }
6082 :
6083 : JS_PUBLIC_API(JSBool)
6084 0 : JS_ReadUint32Pair(JSStructuredCloneReader *r, uint32_t *p1, uint32_t *p2)
6085 : {
6086 0 : return r->input().readPair((uint32_t *) p1, (uint32_t *) p2);
6087 : }
6088 :
6089 : JS_PUBLIC_API(JSBool)
6090 0 : JS_ReadBytes(JSStructuredCloneReader *r, void *p, size_t len)
6091 : {
6092 0 : return r->input().readBytes(p, len);
6093 : }
6094 :
6095 : JS_PUBLIC_API(JSBool)
6096 0 : JS_WriteUint32Pair(JSStructuredCloneWriter *w, uint32_t tag, uint32_t data)
6097 : {
6098 0 : return w->output().writePair(tag, data);
6099 : }
6100 :
6101 : JS_PUBLIC_API(JSBool)
6102 16 : JS_WriteBytes(JSStructuredCloneWriter *w, const void *p, size_t len)
6103 : {
6104 16 : return w->output().writeBytes(p, len);
6105 : }
6106 :
6107 : /*
6108 : * The following determines whether C Strings are to be treated as UTF-8
6109 : * or ISO-8859-1. For correct operation, it must be set prior to the
6110 : * first call to JS_NewRuntime.
6111 : */
6112 : #ifndef JS_C_STRINGS_ARE_UTF8
6113 : JSBool js_CStringsAreUTF8 = JS_FALSE;
6114 : #endif
6115 :
6116 : JS_PUBLIC_API(JSBool)
6117 0 : JS_CStringsAreUTF8()
6118 : {
6119 0 : return js_CStringsAreUTF8;
6120 : }
6121 :
6122 : JS_PUBLIC_API(void)
6123 1 : JS_SetCStringsAreUTF8()
6124 : {
6125 1 : JS_ASSERT(!js_NewRuntimeWasCalled);
6126 :
6127 : #ifndef JS_C_STRINGS_ARE_UTF8
6128 1 : js_CStringsAreUTF8 = JS_TRUE;
6129 : #endif
6130 1 : }
6131 :
6132 : /************************************************************************/
6133 :
6134 : JS_PUBLIC_API(void)
6135 287 : JS_ReportError(JSContext *cx, const char *format, ...)
6136 : {
6137 : va_list ap;
6138 :
6139 287 : AssertNoGC(cx);
6140 287 : va_start(ap, format);
6141 287 : js_ReportErrorVA(cx, JSREPORT_ERROR, format, ap);
6142 287 : va_end(ap);
6143 287 : }
6144 :
6145 : JS_PUBLIC_API(void)
6146 6913 : JS_ReportErrorNumber(JSContext *cx, JSErrorCallback errorCallback,
6147 : void *userRef, const unsigned errorNumber, ...)
6148 : {
6149 : va_list ap;
6150 :
6151 6913 : AssertNoGC(cx);
6152 6913 : va_start(ap, errorNumber);
6153 : js_ReportErrorNumberVA(cx, JSREPORT_ERROR, errorCallback, userRef,
6154 6913 : errorNumber, JS_TRUE, ap);
6155 6913 : va_end(ap);
6156 6913 : }
6157 :
6158 : JS_PUBLIC_API(void)
6159 0 : JS_ReportErrorNumberUC(JSContext *cx, JSErrorCallback errorCallback,
6160 : void *userRef, const unsigned errorNumber, ...)
6161 : {
6162 : va_list ap;
6163 :
6164 0 : AssertNoGC(cx);
6165 0 : va_start(ap, errorNumber);
6166 : js_ReportErrorNumberVA(cx, JSREPORT_ERROR, errorCallback, userRef,
6167 0 : errorNumber, JS_FALSE, ap);
6168 0 : va_end(ap);
6169 0 : }
6170 :
6171 : JS_PUBLIC_API(JSBool)
6172 63 : JS_ReportWarning(JSContext *cx, const char *format, ...)
6173 : {
6174 : va_list ap;
6175 : JSBool ok;
6176 :
6177 63 : AssertNoGC(cx);
6178 63 : va_start(ap, format);
6179 63 : ok = js_ReportErrorVA(cx, JSREPORT_WARNING, format, ap);
6180 63 : va_end(ap);
6181 63 : return ok;
6182 : }
6183 :
6184 : JS_PUBLIC_API(JSBool)
6185 7849 : JS_ReportErrorFlagsAndNumber(JSContext *cx, unsigned flags,
6186 : JSErrorCallback errorCallback, void *userRef,
6187 : const unsigned errorNumber, ...)
6188 : {
6189 : va_list ap;
6190 : JSBool ok;
6191 :
6192 7849 : AssertNoGC(cx);
6193 7849 : va_start(ap, errorNumber);
6194 : ok = js_ReportErrorNumberVA(cx, flags, errorCallback, userRef,
6195 7849 : errorNumber, JS_TRUE, ap);
6196 7849 : va_end(ap);
6197 7849 : return ok;
6198 : }
6199 :
6200 : JS_PUBLIC_API(JSBool)
6201 83 : JS_ReportErrorFlagsAndNumberUC(JSContext *cx, unsigned flags,
6202 : JSErrorCallback errorCallback, void *userRef,
6203 : const unsigned errorNumber, ...)
6204 : {
6205 : va_list ap;
6206 : JSBool ok;
6207 :
6208 83 : AssertNoGC(cx);
6209 83 : va_start(ap, errorNumber);
6210 : ok = js_ReportErrorNumberVA(cx, flags, errorCallback, userRef,
6211 83 : errorNumber, JS_FALSE, ap);
6212 83 : va_end(ap);
6213 83 : return ok;
6214 : }
6215 :
6216 : JS_PUBLIC_API(void)
6217 0 : JS_ReportOutOfMemory(JSContext *cx)
6218 : {
6219 0 : js_ReportOutOfMemory(cx);
6220 0 : }
6221 :
6222 : JS_PUBLIC_API(void)
6223 0 : JS_ReportAllocationOverflow(JSContext *cx)
6224 : {
6225 0 : js_ReportAllocationOverflow(cx);
6226 0 : }
6227 :
6228 : JS_PUBLIC_API(JSErrorReporter)
6229 1521579 : JS_GetErrorReporter(JSContext *cx)
6230 : {
6231 1521579 : return cx->errorReporter;
6232 : }
6233 :
6234 : JS_PUBLIC_API(JSErrorReporter)
6235 81168 : JS_SetErrorReporter(JSContext *cx, JSErrorReporter er)
6236 : {
6237 : JSErrorReporter older;
6238 :
6239 81168 : older = cx->errorReporter;
6240 81168 : cx->errorReporter = er;
6241 81168 : return older;
6242 : }
6243 :
6244 : /************************************************************************/
6245 :
6246 : /*
6247 : * Dates.
6248 : */
6249 : JS_PUBLIC_API(JSObject *)
6250 0 : JS_NewDateObject(JSContext *cx, int year, int mon, int mday, int hour, int min, int sec)
6251 : {
6252 0 : AssertNoGC(cx);
6253 0 : CHECK_REQUEST(cx);
6254 0 : return js_NewDateObject(cx, year, mon, mday, hour, min, sec);
6255 : }
6256 :
6257 : JS_PUBLIC_API(JSObject *)
6258 58 : JS_NewDateObjectMsec(JSContext *cx, double msec)
6259 : {
6260 58 : AssertNoGC(cx);
6261 116 : CHECK_REQUEST(cx);
6262 58 : return js_NewDateObjectMsec(cx, msec);
6263 : }
6264 :
6265 : JS_PUBLIC_API(JSBool)
6266 1065 : JS_ObjectIsDate(JSContext *cx, JSObject *obj)
6267 : {
6268 1065 : AssertNoGC(cx);
6269 1065 : JS_ASSERT(obj);
6270 1065 : return obj->isDate();
6271 : }
6272 :
6273 : /************************************************************************/
6274 :
6275 : /*
6276 : * Regular Expressions.
6277 : */
6278 : JS_PUBLIC_API(JSObject *)
6279 0 : JS_NewRegExpObject(JSContext *cx, JSObject *obj, char *bytes, size_t length, unsigned flags)
6280 : {
6281 0 : AssertNoGC(cx);
6282 0 : CHECK_REQUEST(cx);
6283 0 : jschar *chars = InflateString(cx, bytes, &length);
6284 0 : if (!chars)
6285 0 : return NULL;
6286 :
6287 0 : RegExpStatics *res = obj->asGlobal().getRegExpStatics();
6288 0 : RegExpObject *reobj = RegExpObject::create(cx, res, chars, length, RegExpFlag(flags), NULL);
6289 0 : cx->free_(chars);
6290 0 : return reobj;
6291 : }
6292 :
6293 : JS_PUBLIC_API(JSObject *)
6294 0 : JS_NewUCRegExpObject(JSContext *cx, JSObject *obj, jschar *chars, size_t length, unsigned flags)
6295 : {
6296 0 : AssertNoGC(cx);
6297 0 : CHECK_REQUEST(cx);
6298 0 : RegExpStatics *res = obj->asGlobal().getRegExpStatics();
6299 0 : return RegExpObject::create(cx, res, chars, length, RegExpFlag(flags), NULL);
6300 : }
6301 :
6302 : JS_PUBLIC_API(void)
6303 0 : JS_SetRegExpInput(JSContext *cx, JSObject *obj, JSString *input, JSBool multiline)
6304 : {
6305 0 : AssertNoGC(cx);
6306 0 : CHECK_REQUEST(cx);
6307 0 : assertSameCompartment(cx, input);
6308 :
6309 0 : obj->asGlobal().getRegExpStatics()->reset(cx, input, !!multiline);
6310 0 : }
6311 :
6312 : JS_PUBLIC_API(void)
6313 0 : JS_ClearRegExpStatics(JSContext *cx, JSObject *obj)
6314 : {
6315 0 : AssertNoGC(cx);
6316 0 : CHECK_REQUEST(cx);
6317 0 : JS_ASSERT(obj);
6318 :
6319 0 : obj->asGlobal().getRegExpStatics()->clear();
6320 0 : }
6321 :
6322 : JS_PUBLIC_API(JSBool)
6323 0 : JS_ExecuteRegExp(JSContext *cx, JSObject *obj, JSObject *reobj, jschar *chars, size_t length,
6324 : size_t *indexp, JSBool test, jsval *rval)
6325 : {
6326 0 : AssertNoGC(cx);
6327 0 : CHECK_REQUEST(cx);
6328 :
6329 0 : RegExpStatics *res = obj->asGlobal().getRegExpStatics();
6330 0 : return ExecuteRegExp(cx, res, reobj->asRegExp(), NULL, chars, length,
6331 0 : indexp, test ? RegExpTest : RegExpExec, rval);
6332 : }
6333 :
6334 : JS_PUBLIC_API(JSObject *)
6335 0 : JS_NewRegExpObjectNoStatics(JSContext *cx, char *bytes, size_t length, unsigned flags)
6336 : {
6337 0 : AssertNoGC(cx);
6338 0 : CHECK_REQUEST(cx);
6339 0 : jschar *chars = InflateString(cx, bytes, &length);
6340 0 : if (!chars)
6341 0 : return NULL;
6342 0 : RegExpObject *reobj = RegExpObject::createNoStatics(cx, chars, length, RegExpFlag(flags), NULL);
6343 0 : cx->free_(chars);
6344 0 : return reobj;
6345 : }
6346 :
6347 : JS_PUBLIC_API(JSObject *)
6348 0 : JS_NewUCRegExpObjectNoStatics(JSContext *cx, jschar *chars, size_t length, unsigned flags)
6349 : {
6350 0 : AssertNoGC(cx);
6351 0 : CHECK_REQUEST(cx);
6352 0 : return RegExpObject::createNoStatics(cx, chars, length, RegExpFlag(flags), NULL);
6353 : }
6354 :
6355 : JS_PUBLIC_API(JSBool)
6356 0 : JS_ExecuteRegExpNoStatics(JSContext *cx, JSObject *obj, jschar *chars, size_t length,
6357 : size_t *indexp, JSBool test, jsval *rval)
6358 : {
6359 0 : AssertNoGC(cx);
6360 0 : CHECK_REQUEST(cx);
6361 :
6362 0 : return ExecuteRegExp(cx, NULL, obj->asRegExp(), NULL, chars, length, indexp,
6363 0 : test ? RegExpTest : RegExpExec, rval);
6364 : }
6365 :
6366 : JS_PUBLIC_API(JSBool)
6367 2 : JS_ObjectIsRegExp(JSContext *cx, JSObject *obj)
6368 : {
6369 2 : AssertNoGC(cx);
6370 2 : JS_ASSERT(obj);
6371 2 : return obj->isRegExp();
6372 : }
6373 :
6374 : JS_PUBLIC_API(unsigned)
6375 3 : JS_GetRegExpFlags(JSContext *cx, JSObject *obj)
6376 : {
6377 3 : AssertNoGC(cx);
6378 6 : CHECK_REQUEST(cx);
6379 :
6380 3 : return obj->asRegExp().getFlags();
6381 : }
6382 :
6383 : JS_PUBLIC_API(JSString *)
6384 1 : JS_GetRegExpSource(JSContext *cx, JSObject *obj)
6385 : {
6386 1 : AssertNoGC(cx);
6387 2 : CHECK_REQUEST(cx);
6388 :
6389 1 : return obj->asRegExp().getSource();
6390 : }
6391 :
6392 : /************************************************************************/
6393 :
6394 : JS_PUBLIC_API(void)
6395 4704 : JS_SetLocaleCallbacks(JSContext *cx, JSLocaleCallbacks *callbacks)
6396 : {
6397 4704 : AssertNoGC(cx);
6398 4704 : cx->localeCallbacks = callbacks;
6399 4704 : }
6400 :
6401 : JS_PUBLIC_API(JSLocaleCallbacks *)
6402 10473 : JS_GetLocaleCallbacks(JSContext *cx)
6403 : {
6404 : /* This function can be called by a finalizer. */
6405 10473 : return cx->localeCallbacks;
6406 : }
6407 :
6408 : /************************************************************************/
6409 :
6410 : JS_PUBLIC_API(JSBool)
6411 8229777 : JS_IsExceptionPending(JSContext *cx)
6412 : {
6413 : /* This function can be called by a finalizer. */
6414 8229777 : return (JSBool) cx->isExceptionPending();
6415 : }
6416 :
6417 : JS_PUBLIC_API(JSBool)
6418 72337 : JS_GetPendingException(JSContext *cx, jsval *vp)
6419 : {
6420 72337 : AssertNoGC(cx);
6421 144674 : CHECK_REQUEST(cx);
6422 72337 : if (!cx->isExceptionPending())
6423 13146 : return JS_FALSE;
6424 59191 : *vp = cx->getPendingException();
6425 59191 : assertSameCompartment(cx, *vp);
6426 59191 : return JS_TRUE;
6427 : }
6428 :
6429 : JS_PUBLIC_API(void)
6430 57892 : JS_SetPendingException(JSContext *cx, jsval v)
6431 : {
6432 57892 : AssertNoGC(cx);
6433 115784 : CHECK_REQUEST(cx);
6434 57892 : assertSameCompartment(cx, v);
6435 57892 : cx->setPendingException(v);
6436 57892 : }
6437 :
6438 : JS_PUBLIC_API(void)
6439 2826294 : JS_ClearPendingException(JSContext *cx)
6440 : {
6441 2826294 : AssertNoGC(cx);
6442 2826294 : cx->clearPendingException();
6443 2826294 : }
6444 :
6445 : JS_PUBLIC_API(JSBool)
6446 12161 : JS_ReportPendingException(JSContext *cx)
6447 : {
6448 : JSBool ok;
6449 : bool save;
6450 :
6451 12161 : AssertNoGC(cx);
6452 24322 : CHECK_REQUEST(cx);
6453 :
6454 : /*
6455 : * Set cx->generatingError to suppress the standard error-to-exception
6456 : * conversion done by all {js,JS}_Report* functions except for OOM. The
6457 : * cx->generatingError flag was added to suppress recursive divergence
6458 : * under js_ErrorToException, but it serves for our purposes here too.
6459 : */
6460 12161 : save = cx->generatingError;
6461 12161 : cx->generatingError = JS_TRUE;
6462 12161 : ok = js_ReportUncaughtException(cx);
6463 12161 : cx->generatingError = save;
6464 12161 : return ok;
6465 : }
6466 :
6467 : struct JSExceptionState {
6468 : JSBool throwing;
6469 : jsval exception;
6470 : };
6471 :
6472 : JS_PUBLIC_API(JSExceptionState *)
6473 13079 : JS_SaveExceptionState(JSContext *cx)
6474 : {
6475 : JSExceptionState *state;
6476 :
6477 13079 : AssertNoGC(cx);
6478 26158 : CHECK_REQUEST(cx);
6479 13079 : state = (JSExceptionState *) cx->malloc_(sizeof(JSExceptionState));
6480 13079 : if (state) {
6481 13079 : state->throwing = JS_GetPendingException(cx, &state->exception);
6482 13079 : if (state->throwing && JSVAL_IS_GCTHING(state->exception))
6483 1 : js_AddRoot(cx, &state->exception, "JSExceptionState.exception");
6484 : }
6485 13079 : return state;
6486 : }
6487 :
6488 : JS_PUBLIC_API(void)
6489 13079 : JS_RestoreExceptionState(JSContext *cx, JSExceptionState *state)
6490 : {
6491 13079 : AssertNoGC(cx);
6492 26158 : CHECK_REQUEST(cx);
6493 13079 : if (state) {
6494 13079 : if (state->throwing)
6495 21 : JS_SetPendingException(cx, state->exception);
6496 : else
6497 13058 : JS_ClearPendingException(cx);
6498 13079 : JS_DropExceptionState(cx, state);
6499 : }
6500 13079 : }
6501 :
6502 : JS_PUBLIC_API(void)
6503 13079 : JS_DropExceptionState(JSContext *cx, JSExceptionState *state)
6504 : {
6505 13079 : AssertNoGC(cx);
6506 26158 : CHECK_REQUEST(cx);
6507 13079 : if (state) {
6508 13079 : if (state->throwing && JSVAL_IS_GCTHING(state->exception)) {
6509 1 : assertSameCompartment(cx, state->exception);
6510 1 : JS_RemoveValueRoot(cx, &state->exception);
6511 : }
6512 13079 : cx->free_(state);
6513 : }
6514 13079 : }
6515 :
6516 : JS_PUBLIC_API(JSErrorReport *)
6517 305 : JS_ErrorFromException(JSContext *cx, jsval v)
6518 : {
6519 305 : AssertNoGC(cx);
6520 610 : CHECK_REQUEST(cx);
6521 305 : assertSameCompartment(cx, v);
6522 305 : return js_ErrorFromException(cx, v);
6523 : }
6524 :
6525 : JS_PUBLIC_API(JSBool)
6526 0 : JS_ThrowReportedError(JSContext *cx, const char *message,
6527 : JSErrorReport *reportp)
6528 : {
6529 0 : AssertNoGC(cx);
6530 0 : return JS_IsRunning(cx) &&
6531 0 : js_ErrorToException(cx, message, reportp, NULL, NULL);
6532 : }
6533 :
6534 : JS_PUBLIC_API(JSBool)
6535 1 : JS_ThrowStopIteration(JSContext *cx)
6536 : {
6537 1 : AssertNoGC(cx);
6538 1 : return js_ThrowStopIteration(cx);
6539 : }
6540 :
6541 : JS_PUBLIC_API(intptr_t)
6542 0 : JS_GetCurrentThread()
6543 : {
6544 : #ifdef JS_THREADSAFE
6545 0 : return reinterpret_cast<intptr_t>(PR_GetCurrentThread());
6546 : #else
6547 : return 0;
6548 : #endif
6549 : }
6550 :
6551 : extern JS_PUBLIC_API(void)
6552 6 : JS_ClearRuntimeThread(JSRuntime *rt)
6553 : {
6554 6 : AssertNoGC(rt);
6555 : #ifdef JS_THREADSAFE
6556 6 : rt->clearOwnerThread();
6557 : #endif
6558 6 : }
6559 :
6560 : extern JS_PUBLIC_API(void)
6561 6 : JS_SetRuntimeThread(JSRuntime *rt)
6562 : {
6563 6 : AssertNoGC(rt);
6564 : #ifdef JS_THREADSAFE
6565 6 : rt->setOwnerThread();
6566 : #endif
6567 6 : }
6568 :
6569 : extern JS_NEVER_INLINE JS_PUBLIC_API(void)
6570 239718 : JS_AbortIfWrongThread(JSRuntime *rt)
6571 : {
6572 : #ifdef JS_THREADSAFE
6573 239718 : if (!rt->onOwnerThread())
6574 0 : MOZ_Assert("rt->onOwnerThread()", __FILE__, __LINE__);
6575 : #endif
6576 239718 : }
6577 :
6578 : #ifdef JS_GC_ZEAL
6579 : JS_PUBLIC_API(void)
6580 1637 : JS_SetGCZeal(JSContext *cx, uint8_t zeal, uint32_t frequency, JSBool compartment)
6581 : {
6582 : #ifdef JS_GC_ZEAL
6583 1637 : const char *env = getenv("JS_GC_ZEAL");
6584 1637 : if (env) {
6585 0 : zeal = atoi(env);
6586 0 : frequency = 1;
6587 0 : compartment = false;
6588 : }
6589 : #endif
6590 :
6591 1637 : bool schedule = zeal >= js::gc::ZealAllocValue;
6592 1637 : cx->runtime->gcZeal_ = zeal;
6593 1637 : cx->runtime->gcZealFrequency = frequency;
6594 1637 : cx->runtime->gcNextScheduled = schedule ? frequency : 0;
6595 1637 : cx->runtime->gcDebugCompartmentGC = !!compartment;
6596 1637 : }
6597 :
6598 : JS_PUBLIC_API(void)
6599 27 : JS_ScheduleGC(JSContext *cx, uint32_t count, JSBool compartment)
6600 : {
6601 27 : cx->runtime->gcNextScheduled = count;
6602 27 : cx->runtime->gcDebugCompartmentGC = !!compartment;
6603 27 : }
6604 : #endif
6605 :
6606 : /************************************************************************/
6607 :
6608 : #if !defined(STATIC_EXPORTABLE_JS_API) && !defined(STATIC_JS_API) && defined(XP_WIN)
6609 :
6610 : #include "jswin.h"
6611 :
6612 : /*
6613 : * Initialization routine for the JS DLL.
6614 : */
6615 : BOOL WINAPI DllMain (HINSTANCE hDLL, DWORD dwReason, LPVOID lpReserved)
6616 : {
6617 : return TRUE;
6618 : }
6619 :
6620 : #endif
6621 :
6622 : JS_PUBLIC_API(JSBool)
6623 0 : JS_IndexToId(JSContext *cx, uint32_t index, jsid *id)
6624 : {
6625 0 : return IndexToId(cx, index, id);
6626 : }
6627 :
6628 : JS_PUBLIC_API(JSBool)
6629 837 : JS_IsIdentifier(JSContext *cx, JSString *str, JSBool *isIdentifier)
6630 : {
6631 837 : assertSameCompartment(cx, str);
6632 :
6633 837 : JSLinearString* linearStr = str->ensureLinear(cx);
6634 837 : if (!linearStr)
6635 0 : return false;
6636 :
6637 837 : *isIdentifier = js::IsIdentifier(linearStr);
6638 837 : return true;
6639 : }
6640 :
6641 : JS_PUBLIC_API(JSBool)
6642 553 : JS_DescribeScriptedCaller(JSContext *cx, JSScript **script, unsigned *lineno)
6643 : {
6644 553 : if (script)
6645 553 : *script = NULL;
6646 553 : if (lineno)
6647 126 : *lineno = 0;
6648 :
6649 553 : FrameRegsIter i(cx);
6650 553 : if (i.done())
6651 0 : return JS_FALSE;
6652 :
6653 553 : if (script)
6654 553 : *script = i.script();
6655 553 : if (lineno)
6656 126 : *lineno = js::PCToLineNumber(i.script(), i.pc());
6657 553 : return JS_TRUE;
6658 : }
6659 :
6660 : #ifdef JS_THREADSAFE
6661 : static PRStatus
6662 19811 : CallOnce(void *func)
6663 : {
6664 19811 : JSInitCallback init = JS_DATA_TO_FUNC_PTR(JSInitCallback, func);
6665 19811 : return init() ? PR_SUCCESS : PR_FAILURE;
6666 : }
6667 : #endif
6668 :
6669 : JS_PUBLIC_API(JSBool)
6670 19910 : JS_CallOnce(JSCallOnceType *once, JSInitCallback func)
6671 : {
6672 : #ifdef JS_THREADSAFE
6673 19910 : return PR_CallOnceWithArg(once, CallOnce, JS_FUNC_TO_DATA_PTR(void *, func)) == PR_SUCCESS;
6674 : #else
6675 : if (!*once) {
6676 : *once = true;
6677 : return func();
6678 : } else {
6679 : return JS_TRUE;
6680 : }
6681 : #endif
6682 : }
6683 :
6684 : namespace JS {
6685 :
6686 28983989 : AutoGCRooter::AutoGCRooter(JSContext *cx, ptrdiff_t tag)
6687 28983989 : : down(cx->runtime->autoGCRooters), tag(tag), stackTop(&cx->runtime->autoGCRooters)
6688 : {
6689 28983989 : JS_ASSERT(this != *stackTop);
6690 28983989 : *stackTop = this;
6691 28983989 : }
6692 :
6693 0 : AutoEnumStateRooter::~AutoEnumStateRooter()
6694 : {
6695 0 : if (!stateValue.isNull())
6696 0 : MOZ_ALWAYS_TRUE(obj->enumerate(context, JSENUMERATE_DESTROY, &stateValue, 0));
6697 0 : }
6698 :
6699 59610 : } // namespace JS
|