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