js/src/jsfriendapi.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
michael@0 2 * vim: set ts=8 sts=4 et sw=4 tw=99:
michael@0 3 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #include "jsfriendapi.h"
michael@0 8
michael@0 9 #include "mozilla/PodOperations.h"
michael@0 10
michael@0 11 #include <stdint.h>
michael@0 12
michael@0 13 #include "jscntxt.h"
michael@0 14 #include "jscompartment.h"
michael@0 15 #include "jsgc.h"
michael@0 16 #include "jsobj.h"
michael@0 17 #include "jsproxy.h"
michael@0 18 #include "jswatchpoint.h"
michael@0 19 #include "jsweakmap.h"
michael@0 20 #include "jswrapper.h"
michael@0 21 #include "prmjtime.h"
michael@0 22
michael@0 23 #include "builtin/TestingFunctions.h"
michael@0 24 #include "vm/WrapperObject.h"
michael@0 25
michael@0 26 #include "jsobjinlines.h"
michael@0 27
michael@0 28 #include "vm/ScopeObject-inl.h"
michael@0 29
michael@0 30 using namespace js;
michael@0 31 using namespace JS;
michael@0 32
michael@0 33 using mozilla::PodArrayZero;
michael@0 34
michael@0 35 // Required by PerThreadDataFriendFields::getMainThread()
michael@0 36 JS_STATIC_ASSERT(offsetof(JSRuntime, mainThread) ==
michael@0 37 PerThreadDataFriendFields::RuntimeMainThreadOffset);
michael@0 38
michael@0 39 PerThreadDataFriendFields::PerThreadDataFriendFields()
michael@0 40 {
michael@0 41 PodArrayZero(nativeStackLimit);
michael@0 42 #if JS_STACK_GROWTH_DIRECTION > 0
michael@0 43 for (int i=0; i<StackKindCount; i++)
michael@0 44 nativeStackLimit[i] = UINTPTR_MAX;
michael@0 45 #endif
michael@0 46 #if defined(JSGC_USE_EXACT_ROOTING)
michael@0 47 PodArrayZero(thingGCRooters);
michael@0 48 #endif
michael@0 49 }
michael@0 50
michael@0 51 JS_FRIEND_API(void)
michael@0 52 js::SetSourceHook(JSRuntime *rt, SourceHook *hook)
michael@0 53 {
michael@0 54 rt->sourceHook = hook;
michael@0 55 }
michael@0 56
michael@0 57 JS_FRIEND_API(SourceHook *)
michael@0 58 js::ForgetSourceHook(JSRuntime *rt)
michael@0 59 {
michael@0 60 return rt->sourceHook.forget();
michael@0 61 }
michael@0 62
michael@0 63 JS_FRIEND_API(void)
michael@0 64 JS_SetGrayGCRootsTracer(JSRuntime *rt, JSTraceDataOp traceOp, void *data)
michael@0 65 {
michael@0 66 rt->gcGrayRootTracer.op = traceOp;
michael@0 67 rt->gcGrayRootTracer.data = data;
michael@0 68 }
michael@0 69
michael@0 70 JS_FRIEND_API(JSString *)
michael@0 71 JS_GetAnonymousString(JSRuntime *rt)
michael@0 72 {
michael@0 73 JS_ASSERT(rt->hasContexts());
michael@0 74 return rt->commonNames->anonymous;
michael@0 75 }
michael@0 76
michael@0 77 JS_FRIEND_API(void)
michael@0 78 JS_SetIsWorkerRuntime(JSRuntime *rt)
michael@0 79 {
michael@0 80 rt->setIsWorkerRuntime();
michael@0 81 }
michael@0 82
michael@0 83 JS_FRIEND_API(JSObject *)
michael@0 84 JS_FindCompilationScope(JSContext *cx, HandleObject objArg)
michael@0 85 {
michael@0 86 RootedObject obj(cx, objArg);
michael@0 87
michael@0 88 /*
michael@0 89 * We unwrap wrappers here. This is a little weird, but it's what's being
michael@0 90 * asked of us.
michael@0 91 */
michael@0 92 if (obj->is<WrapperObject>())
michael@0 93 obj = UncheckedUnwrap(obj);
michael@0 94
michael@0 95 /*
michael@0 96 * Innerize the target_obj so that we compile in the correct (inner)
michael@0 97 * scope.
michael@0 98 */
michael@0 99 if (JSObjectOp op = obj->getClass()->ext.innerObject)
michael@0 100 obj = op(cx, obj);
michael@0 101 return obj;
michael@0 102 }
michael@0 103
michael@0 104 JS_FRIEND_API(JSFunction *)
michael@0 105 JS_GetObjectFunction(JSObject *obj)
michael@0 106 {
michael@0 107 if (obj->is<JSFunction>())
michael@0 108 return &obj->as<JSFunction>();
michael@0 109 return nullptr;
michael@0 110 }
michael@0 111
michael@0 112 JS_FRIEND_API(bool)
michael@0 113 JS_SplicePrototype(JSContext *cx, HandleObject obj, HandleObject proto)
michael@0 114 {
michael@0 115 /*
michael@0 116 * Change the prototype of an object which hasn't been used anywhere
michael@0 117 * and does not share its type with another object. Unlike JS_SetPrototype,
michael@0 118 * does not nuke type information for the object.
michael@0 119 */
michael@0 120 CHECK_REQUEST(cx);
michael@0 121
michael@0 122 if (!obj->hasSingletonType()) {
michael@0 123 /*
michael@0 124 * We can see non-singleton objects when trying to splice prototypes
michael@0 125 * due to mutable __proto__ (ugh).
michael@0 126 */
michael@0 127 return JS_SetPrototype(cx, obj, proto);
michael@0 128 }
michael@0 129
michael@0 130 Rooted<TaggedProto> tagged(cx, TaggedProto(proto));
michael@0 131 return obj->splicePrototype(cx, obj->getClass(), tagged);
michael@0 132 }
michael@0 133
michael@0 134 JS_FRIEND_API(JSObject *)
michael@0 135 JS_NewObjectWithUniqueType(JSContext *cx, const JSClass *clasp, HandleObject proto,
michael@0 136 HandleObject parent)
michael@0 137 {
michael@0 138 /*
michael@0 139 * Create our object with a null proto and then splice in the correct proto
michael@0 140 * after we setSingletonType, so that we don't pollute the default
michael@0 141 * TypeObject attached to our proto with information about our object, since
michael@0 142 * we're not going to be using that TypeObject anyway.
michael@0 143 */
michael@0 144 RootedObject obj(cx, NewObjectWithGivenProto(cx, (const js::Class *)clasp, nullptr,
michael@0 145 parent, SingletonObject));
michael@0 146 if (!obj)
michael@0 147 return nullptr;
michael@0 148 if (!JS_SplicePrototype(cx, obj, proto))
michael@0 149 return nullptr;
michael@0 150 return obj;
michael@0 151 }
michael@0 152
michael@0 153 JS_FRIEND_API(void)
michael@0 154 JS::PrepareZoneForGC(Zone *zone)
michael@0 155 {
michael@0 156 zone->scheduleGC();
michael@0 157 }
michael@0 158
michael@0 159 JS_FRIEND_API(void)
michael@0 160 JS::PrepareForFullGC(JSRuntime *rt)
michael@0 161 {
michael@0 162 for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next())
michael@0 163 zone->scheduleGC();
michael@0 164 }
michael@0 165
michael@0 166 JS_FRIEND_API(void)
michael@0 167 JS::PrepareForIncrementalGC(JSRuntime *rt)
michael@0 168 {
michael@0 169 if (!JS::IsIncrementalGCInProgress(rt))
michael@0 170 return;
michael@0 171
michael@0 172 for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) {
michael@0 173 if (zone->wasGCStarted())
michael@0 174 PrepareZoneForGC(zone);
michael@0 175 }
michael@0 176 }
michael@0 177
michael@0 178 JS_FRIEND_API(bool)
michael@0 179 JS::IsGCScheduled(JSRuntime *rt)
michael@0 180 {
michael@0 181 for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) {
michael@0 182 if (zone->isGCScheduled())
michael@0 183 return true;
michael@0 184 }
michael@0 185
michael@0 186 return false;
michael@0 187 }
michael@0 188
michael@0 189 JS_FRIEND_API(void)
michael@0 190 JS::SkipZoneForGC(Zone *zone)
michael@0 191 {
michael@0 192 zone->unscheduleGC();
michael@0 193 }
michael@0 194
michael@0 195 JS_FRIEND_API(void)
michael@0 196 JS::GCForReason(JSRuntime *rt, gcreason::Reason reason)
michael@0 197 {
michael@0 198 GC(rt, GC_NORMAL, reason);
michael@0 199 }
michael@0 200
michael@0 201 JS_FRIEND_API(void)
michael@0 202 JS::ShrinkingGC(JSRuntime *rt, gcreason::Reason reason)
michael@0 203 {
michael@0 204 GC(rt, GC_SHRINK, reason);
michael@0 205 }
michael@0 206
michael@0 207 JS_FRIEND_API(void)
michael@0 208 JS::IncrementalGC(JSRuntime *rt, gcreason::Reason reason, int64_t millis)
michael@0 209 {
michael@0 210 GCSlice(rt, GC_NORMAL, reason, millis);
michael@0 211 }
michael@0 212
michael@0 213 JS_FRIEND_API(void)
michael@0 214 JS::FinishIncrementalGC(JSRuntime *rt, gcreason::Reason reason)
michael@0 215 {
michael@0 216 GCFinalSlice(rt, GC_NORMAL, reason);
michael@0 217 }
michael@0 218
michael@0 219 JS_FRIEND_API(JSPrincipals *)
michael@0 220 JS_GetCompartmentPrincipals(JSCompartment *compartment)
michael@0 221 {
michael@0 222 return compartment->principals;
michael@0 223 }
michael@0 224
michael@0 225 JS_FRIEND_API(void)
michael@0 226 JS_SetCompartmentPrincipals(JSCompartment *compartment, JSPrincipals *principals)
michael@0 227 {
michael@0 228 // Short circuit if there's no change.
michael@0 229 if (principals == compartment->principals)
michael@0 230 return;
michael@0 231
michael@0 232 // Any compartment with the trusted principals -- and there can be
michael@0 233 // multiple -- is a system compartment.
michael@0 234 const JSPrincipals *trusted = compartment->runtimeFromMainThread()->trustedPrincipals();
michael@0 235 bool isSystem = principals && principals == trusted;
michael@0 236
michael@0 237 // Clear out the old principals, if any.
michael@0 238 if (compartment->principals) {
michael@0 239 JS_DropPrincipals(compartment->runtimeFromMainThread(), compartment->principals);
michael@0 240 compartment->principals = nullptr;
michael@0 241 // We'd like to assert that our new principals is always same-origin
michael@0 242 // with the old one, but JSPrincipals doesn't give us a way to do that.
michael@0 243 // But we can at least assert that we're not switching between system
michael@0 244 // and non-system.
michael@0 245 JS_ASSERT(compartment->isSystem == isSystem);
michael@0 246 }
michael@0 247
michael@0 248 // Set up the new principals.
michael@0 249 if (principals) {
michael@0 250 JS_HoldPrincipals(principals);
michael@0 251 compartment->principals = principals;
michael@0 252 }
michael@0 253
michael@0 254 // Update the system flag.
michael@0 255 compartment->isSystem = isSystem;
michael@0 256 }
michael@0 257
michael@0 258 JS_FRIEND_API(bool)
michael@0 259 JS_WrapPropertyDescriptor(JSContext *cx, JS::MutableHandle<js::PropertyDescriptor> desc)
michael@0 260 {
michael@0 261 return cx->compartment()->wrap(cx, desc);
michael@0 262 }
michael@0 263
michael@0 264 JS_FRIEND_API(bool)
michael@0 265 JS_WrapAutoIdVector(JSContext *cx, js::AutoIdVector &props)
michael@0 266 {
michael@0 267 return cx->compartment()->wrap(cx, props);
michael@0 268 }
michael@0 269
michael@0 270 JS_FRIEND_API(void)
michael@0 271 JS_TraceShapeCycleCollectorChildren(JSTracer *trc, void *shape)
michael@0 272 {
michael@0 273 MarkCycleCollectorChildren(trc, static_cast<Shape *>(shape));
michael@0 274 }
michael@0 275
michael@0 276 static bool
michael@0 277 DefineHelpProperty(JSContext *cx, HandleObject obj, const char *prop, const char *value)
michael@0 278 {
michael@0 279 RootedAtom atom(cx, Atomize(cx, value, strlen(value)));
michael@0 280 if (!atom)
michael@0 281 return false;
michael@0 282 return JS_DefineProperty(cx, obj, prop, atom, JSPROP_READONLY | JSPROP_PERMANENT,
michael@0 283 JS_PropertyStub, JS_StrictPropertyStub);
michael@0 284 }
michael@0 285
michael@0 286 JS_FRIEND_API(bool)
michael@0 287 JS_DefineFunctionsWithHelp(JSContext *cx, HandleObject obj, const JSFunctionSpecWithHelp *fs)
michael@0 288 {
michael@0 289 JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
michael@0 290
michael@0 291 CHECK_REQUEST(cx);
michael@0 292 assertSameCompartment(cx, obj);
michael@0 293 for (; fs->name; fs++) {
michael@0 294 JSAtom *atom = Atomize(cx, fs->name, strlen(fs->name));
michael@0 295 if (!atom)
michael@0 296 return false;
michael@0 297
michael@0 298 Rooted<jsid> id(cx, AtomToId(atom));
michael@0 299 RootedFunction fun(cx, DefineFunction(cx, obj, id, fs->call, fs->nargs, fs->flags));
michael@0 300 if (!fun)
michael@0 301 return false;
michael@0 302
michael@0 303 if (fs->usage) {
michael@0 304 if (!DefineHelpProperty(cx, fun, "usage", fs->usage))
michael@0 305 return false;
michael@0 306 }
michael@0 307
michael@0 308 if (fs->help) {
michael@0 309 if (!DefineHelpProperty(cx, fun, "help", fs->help))
michael@0 310 return false;
michael@0 311 }
michael@0 312 }
michael@0 313
michael@0 314 return true;
michael@0 315 }
michael@0 316
michael@0 317 JS_FRIEND_API(bool)
michael@0 318 js_ObjectClassIs(JSContext *cx, HandleObject obj, ESClassValue classValue)
michael@0 319 {
michael@0 320 return ObjectClassIs(obj, classValue, cx);
michael@0 321 }
michael@0 322
michael@0 323 JS_FRIEND_API(const char *)
michael@0 324 js_ObjectClassName(JSContext *cx, HandleObject obj)
michael@0 325 {
michael@0 326 return JSObject::className(cx, obj);
michael@0 327 }
michael@0 328
michael@0 329 JS_FRIEND_API(JS::Zone *)
michael@0 330 js::GetCompartmentZone(JSCompartment *comp)
michael@0 331 {
michael@0 332 return comp->zone();
michael@0 333 }
michael@0 334
michael@0 335 JS_FRIEND_API(bool)
michael@0 336 js::IsSystemCompartment(JSCompartment *comp)
michael@0 337 {
michael@0 338 return comp->isSystem;
michael@0 339 }
michael@0 340
michael@0 341 JS_FRIEND_API(bool)
michael@0 342 js::IsSystemZone(Zone *zone)
michael@0 343 {
michael@0 344 return zone->isSystem;
michael@0 345 }
michael@0 346
michael@0 347 JS_FRIEND_API(bool)
michael@0 348 js::IsAtomsCompartment(JSCompartment *comp)
michael@0 349 {
michael@0 350 return comp->runtimeFromAnyThread()->isAtomsCompartment(comp);
michael@0 351 }
michael@0 352
michael@0 353 JS_FRIEND_API(bool)
michael@0 354 js::IsInNonStrictPropertySet(JSContext *cx)
michael@0 355 {
michael@0 356 jsbytecode *pc;
michael@0 357 JSScript *script = cx->currentScript(&pc, JSContext::ALLOW_CROSS_COMPARTMENT);
michael@0 358 return script && !script->strict() && (js_CodeSpec[*pc].format & JOF_SET);
michael@0 359 }
michael@0 360
michael@0 361 JS_FRIEND_API(bool)
michael@0 362 js::IsFunctionObject(JSObject *obj)
michael@0 363 {
michael@0 364 return obj->is<JSFunction>();
michael@0 365 }
michael@0 366
michael@0 367 JS_FRIEND_API(bool)
michael@0 368 js::IsScopeObject(JSObject *obj)
michael@0 369 {
michael@0 370 return obj->is<ScopeObject>();
michael@0 371 }
michael@0 372
michael@0 373 JS_FRIEND_API(bool)
michael@0 374 js::IsCallObject(JSObject *obj)
michael@0 375 {
michael@0 376 return obj->is<CallObject>();
michael@0 377 }
michael@0 378
michael@0 379 JS_FRIEND_API(JSObject *)
michael@0 380 js::GetObjectParentMaybeScope(JSObject *obj)
michael@0 381 {
michael@0 382 return obj->enclosingScope();
michael@0 383 }
michael@0 384
michael@0 385 JS_FRIEND_API(JSObject *)
michael@0 386 js::GetGlobalForObjectCrossCompartment(JSObject *obj)
michael@0 387 {
michael@0 388 return &obj->global();
michael@0 389 }
michael@0 390
michael@0 391 JS_FRIEND_API(void)
michael@0 392 js::SetPendingExceptionCrossContext(JSContext *cx, JS::HandleValue v)
michael@0 393 {
michael@0 394 cx->setPendingException(v);
michael@0 395 }
michael@0 396
michael@0 397 JS_FRIEND_API(void)
michael@0 398 js::AssertSameCompartment(JSContext *cx, JSObject *obj)
michael@0 399 {
michael@0 400 assertSameCompartment(cx, obj);
michael@0 401 }
michael@0 402
michael@0 403 #ifdef DEBUG
michael@0 404 JS_FRIEND_API(void)
michael@0 405 js::AssertSameCompartment(JSObject *objA, JSObject *objB)
michael@0 406 {
michael@0 407 JS_ASSERT(objA->compartment() == objB->compartment());
michael@0 408 }
michael@0 409 #endif
michael@0 410
michael@0 411 JS_FRIEND_API(JSObject *)
michael@0 412 js::DefaultObjectForContextOrNull(JSContext *cx)
michael@0 413 {
michael@0 414 if (cx->options().noDefaultCompartmentObject())
michael@0 415 return nullptr;
michael@0 416 return cx->maybeDefaultCompartmentObject();
michael@0 417 }
michael@0 418
michael@0 419 JS_FRIEND_API(void)
michael@0 420 js::SetDefaultObjectForContext(JSContext *cx, JSObject *obj)
michael@0 421 {
michael@0 422 cx->setDefaultCompartmentObject(obj);
michael@0 423 }
michael@0 424
michael@0 425 JS_FRIEND_API(void)
michael@0 426 js::NotifyAnimationActivity(JSObject *obj)
michael@0 427 {
michael@0 428 obj->compartment()->lastAnimationTime = PRMJ_Now();
michael@0 429 }
michael@0 430
michael@0 431 JS_FRIEND_API(uint32_t)
michael@0 432 js::GetObjectSlotSpan(JSObject *obj)
michael@0 433 {
michael@0 434 return obj->slotSpan();
michael@0 435 }
michael@0 436
michael@0 437 JS_FRIEND_API(bool)
michael@0 438 js::IsObjectInContextCompartment(JSObject *obj, const JSContext *cx)
michael@0 439 {
michael@0 440 return obj->compartment() == cx->compartment();
michael@0 441 }
michael@0 442
michael@0 443 JS_FRIEND_API(bool)
michael@0 444 js::RunningWithTrustedPrincipals(JSContext *cx)
michael@0 445 {
michael@0 446 return cx->runningWithTrustedPrincipals();
michael@0 447 }
michael@0 448
michael@0 449 JS_FRIEND_API(JSScript *)
michael@0 450 js::GetOutermostEnclosingFunctionOfScriptedCaller(JSContext *cx)
michael@0 451 {
michael@0 452 ScriptFrameIter iter(cx);
michael@0 453 if (iter.done())
michael@0 454 return nullptr;
michael@0 455
michael@0 456 if (!iter.isFunctionFrame())
michael@0 457 return nullptr;
michael@0 458
michael@0 459 RootedFunction scriptedCaller(cx, iter.callee());
michael@0 460 RootedScript outermost(cx, scriptedCaller->nonLazyScript());
michael@0 461 for (StaticScopeIter<NoGC> i(scriptedCaller); !i.done(); i++) {
michael@0 462 if (i.type() == StaticScopeIter<NoGC>::FUNCTION)
michael@0 463 outermost = i.funScript();
michael@0 464 }
michael@0 465 return outermost;
michael@0 466 }
michael@0 467
michael@0 468 JS_FRIEND_API(JSFunction *)
michael@0 469 js::DefineFunctionWithReserved(JSContext *cx, JSObject *objArg, const char *name, JSNative call,
michael@0 470 unsigned nargs, unsigned attrs)
michael@0 471 {
michael@0 472 RootedObject obj(cx, objArg);
michael@0 473 JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
michael@0 474 CHECK_REQUEST(cx);
michael@0 475 assertSameCompartment(cx, obj);
michael@0 476 JSAtom *atom = Atomize(cx, name, strlen(name));
michael@0 477 if (!atom)
michael@0 478 return nullptr;
michael@0 479 Rooted<jsid> id(cx, AtomToId(atom));
michael@0 480 return DefineFunction(cx, obj, id, call, nargs, attrs, JSFunction::ExtendedFinalizeKind);
michael@0 481 }
michael@0 482
michael@0 483 JS_FRIEND_API(JSFunction *)
michael@0 484 js::NewFunctionWithReserved(JSContext *cx, JSNative native, unsigned nargs, unsigned flags,
michael@0 485 JSObject *parentArg, const char *name)
michael@0 486 {
michael@0 487 RootedObject parent(cx, parentArg);
michael@0 488 JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
michael@0 489
michael@0 490 CHECK_REQUEST(cx);
michael@0 491 assertSameCompartment(cx, parent);
michael@0 492
michael@0 493 RootedAtom atom(cx);
michael@0 494 if (name) {
michael@0 495 atom = Atomize(cx, name, strlen(name));
michael@0 496 if (!atom)
michael@0 497 return nullptr;
michael@0 498 }
michael@0 499
michael@0 500 JSFunction::Flags funFlags = JSAPIToJSFunctionFlags(flags);
michael@0 501 return NewFunction(cx, NullPtr(), native, nargs, funFlags, parent, atom,
michael@0 502 JSFunction::ExtendedFinalizeKind);
michael@0 503 }
michael@0 504
michael@0 505 JS_FRIEND_API(JSFunction *)
michael@0 506 js::NewFunctionByIdWithReserved(JSContext *cx, JSNative native, unsigned nargs, unsigned flags, JSObject *parentArg,
michael@0 507 jsid id)
michael@0 508 {
michael@0 509 RootedObject parent(cx, parentArg);
michael@0 510 JS_ASSERT(JSID_IS_STRING(id));
michael@0 511 JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
michael@0 512 CHECK_REQUEST(cx);
michael@0 513 assertSameCompartment(cx, parent);
michael@0 514
michael@0 515 RootedAtom atom(cx, JSID_TO_ATOM(id));
michael@0 516 JSFunction::Flags funFlags = JSAPIToJSFunctionFlags(flags);
michael@0 517 return NewFunction(cx, NullPtr(), native, nargs, funFlags, parent, atom,
michael@0 518 JSFunction::ExtendedFinalizeKind);
michael@0 519 }
michael@0 520
michael@0 521 JS_FRIEND_API(JSObject *)
michael@0 522 js::InitClassWithReserved(JSContext *cx, JSObject *objArg, JSObject *parent_protoArg,
michael@0 523 const JSClass *clasp, JSNative constructor, unsigned nargs,
michael@0 524 const JSPropertySpec *ps, const JSFunctionSpec *fs,
michael@0 525 const JSPropertySpec *static_ps, const JSFunctionSpec *static_fs)
michael@0 526 {
michael@0 527 RootedObject obj(cx, objArg);
michael@0 528 RootedObject parent_proto(cx, parent_protoArg);
michael@0 529 CHECK_REQUEST(cx);
michael@0 530 assertSameCompartment(cx, obj, parent_proto);
michael@0 531 return js_InitClass(cx, obj, parent_proto, Valueify(clasp), constructor,
michael@0 532 nargs, ps, fs, static_ps, static_fs, nullptr,
michael@0 533 JSFunction::ExtendedFinalizeKind);
michael@0 534 }
michael@0 535
michael@0 536 JS_FRIEND_API(const Value &)
michael@0 537 js::GetFunctionNativeReserved(JSObject *fun, size_t which)
michael@0 538 {
michael@0 539 JS_ASSERT(fun->as<JSFunction>().isNative());
michael@0 540 return fun->as<JSFunction>().getExtendedSlot(which);
michael@0 541 }
michael@0 542
michael@0 543 JS_FRIEND_API(void)
michael@0 544 js::SetFunctionNativeReserved(JSObject *fun, size_t which, const Value &val)
michael@0 545 {
michael@0 546 JS_ASSERT(fun->as<JSFunction>().isNative());
michael@0 547 MOZ_ASSERT_IF(val.isObject(), val.toObject().compartment() == fun->compartment());
michael@0 548 fun->as<JSFunction>().setExtendedSlot(which, val);
michael@0 549 }
michael@0 550
michael@0 551 JS_FRIEND_API(bool)
michael@0 552 js::GetObjectProto(JSContext *cx, JS::Handle<JSObject*> obj, JS::MutableHandle<JSObject*> proto)
michael@0 553 {
michael@0 554 if (IsProxy(obj))
michael@0 555 return JS_GetPrototype(cx, obj, proto);
michael@0 556
michael@0 557 proto.set(reinterpret_cast<const shadow::Object*>(obj.get())->type->proto);
michael@0 558 return true;
michael@0 559 }
michael@0 560
michael@0 561 JS_FRIEND_API(bool)
michael@0 562 js::GetOriginalEval(JSContext *cx, HandleObject scope, MutableHandleObject eval)
michael@0 563 {
michael@0 564 assertSameCompartment(cx, scope);
michael@0 565 Rooted<GlobalObject *> global(cx, &scope->global());
michael@0 566 return GlobalObject::getOrCreateEval(cx, global, eval);
michael@0 567 }
michael@0 568
michael@0 569 JS_FRIEND_API(void)
michael@0 570 js::SetReservedSlotWithBarrier(JSObject *obj, size_t slot, const js::Value &value)
michael@0 571 {
michael@0 572 obj->setSlot(slot, value);
michael@0 573 }
michael@0 574
michael@0 575 JS_FRIEND_API(bool)
michael@0 576 js::GetGeneric(JSContext *cx, JSObject *objArg, JSObject *receiverArg, jsid idArg,
michael@0 577 Value *vp)
michael@0 578 {
michael@0 579 RootedObject obj(cx, objArg), receiver(cx, receiverArg);
michael@0 580 RootedId id(cx, idArg);
michael@0 581 RootedValue value(cx);
michael@0 582 if (!JSObject::getGeneric(cx, obj, receiver, id, &value))
michael@0 583 return false;
michael@0 584 *vp = value;
michael@0 585 return true;
michael@0 586 }
michael@0 587
michael@0 588 void
michael@0 589 js::SetPreserveWrapperCallback(JSRuntime *rt, PreserveWrapperCallback callback)
michael@0 590 {
michael@0 591 rt->preserveWrapperCallback = callback;
michael@0 592 }
michael@0 593
michael@0 594 /*
michael@0 595 * The below code is for temporary telemetry use. It can be removed when
michael@0 596 * sufficient data has been harvested.
michael@0 597 */
michael@0 598
michael@0 599 namespace js {
michael@0 600 // Defined in vm/GlobalObject.cpp.
michael@0 601 extern size_t sSetProtoCalled;
michael@0 602 }
michael@0 603
michael@0 604 JS_FRIEND_API(size_t)
michael@0 605 JS_SetProtoCalled(JSContext *)
michael@0 606 {
michael@0 607 return sSetProtoCalled;
michael@0 608 }
michael@0 609
michael@0 610 // Defined in jsiter.cpp.
michael@0 611 extern size_t sCustomIteratorCount;
michael@0 612
michael@0 613 JS_FRIEND_API(size_t)
michael@0 614 JS_GetCustomIteratorCount(JSContext *cx)
michael@0 615 {
michael@0 616 return sCustomIteratorCount;
michael@0 617 }
michael@0 618
michael@0 619 JS_FRIEND_API(bool)
michael@0 620 JS_IsDeadWrapper(JSObject *obj)
michael@0 621 {
michael@0 622 if (!obj->is<ProxyObject>()) {
michael@0 623 return false;
michael@0 624 }
michael@0 625
michael@0 626 return obj->as<ProxyObject>().handler()->family() == &DeadObjectProxy::sDeadObjectFamily;
michael@0 627 }
michael@0 628
michael@0 629 void
michael@0 630 js::TraceWeakMaps(WeakMapTracer *trc)
michael@0 631 {
michael@0 632 WeakMapBase::traceAllMappings(trc);
michael@0 633 WatchpointMap::traceAll(trc);
michael@0 634 }
michael@0 635
michael@0 636 extern JS_FRIEND_API(bool)
michael@0 637 js::AreGCGrayBitsValid(JSRuntime *rt)
michael@0 638 {
michael@0 639 return rt->gcGrayBitsValid;
michael@0 640 }
michael@0 641
michael@0 642 JS_FRIEND_API(bool)
michael@0 643 js::ZoneGlobalsAreAllGray(JS::Zone *zone)
michael@0 644 {
michael@0 645 for (CompartmentsInZoneIter comp(zone); !comp.done(); comp.next()) {
michael@0 646 JSObject *obj = comp->maybeGlobal();
michael@0 647 if (!obj || !JS::GCThingIsMarkedGray(obj))
michael@0 648 return false;
michael@0 649 }
michael@0 650 return true;
michael@0 651 }
michael@0 652
michael@0 653 JS_FRIEND_API(JSGCTraceKind)
michael@0 654 js::GCThingTraceKind(void *thing)
michael@0 655 {
michael@0 656 JS_ASSERT(thing);
michael@0 657 return gc::GetGCThingTraceKind(thing);
michael@0 658 }
michael@0 659
michael@0 660 JS_FRIEND_API(void)
michael@0 661 js::VisitGrayWrapperTargets(Zone *zone, GCThingCallback callback, void *closure)
michael@0 662 {
michael@0 663 JSRuntime *rt = zone->runtimeFromMainThread();
michael@0 664 for (CompartmentsInZoneIter comp(zone); !comp.done(); comp.next()) {
michael@0 665 for (JSCompartment::WrapperEnum e(comp); !e.empty(); e.popFront()) {
michael@0 666 gc::Cell *thing = e.front().key().wrapped;
michael@0 667 if (!IsInsideNursery(rt, thing) && thing->isMarked(gc::GRAY))
michael@0 668 callback(closure, thing);
michael@0 669 }
michael@0 670 }
michael@0 671 }
michael@0 672
michael@0 673 JS_FRIEND_API(JSObject *)
michael@0 674 js::GetWeakmapKeyDelegate(JSObject *key)
michael@0 675 {
michael@0 676 if (JSWeakmapKeyDelegateOp op = key->getClass()->ext.weakmapKeyDelegateOp)
michael@0 677 return op(key);
michael@0 678 return nullptr;
michael@0 679 }
michael@0 680
michael@0 681 JS_FRIEND_API(void)
michael@0 682 JS_SetAccumulateTelemetryCallback(JSRuntime *rt, JSAccumulateTelemetryDataCallback callback)
michael@0 683 {
michael@0 684 rt->telemetryCallback = callback;
michael@0 685 }
michael@0 686
michael@0 687 JS_FRIEND_API(JSObject *)
michael@0 688 JS_CloneObject(JSContext *cx, HandleObject obj, HandleObject protoArg, HandleObject parent)
michael@0 689 {
michael@0 690 Rooted<js::TaggedProto> proto(cx, protoArg.get());
michael@0 691 return CloneObject(cx, obj, proto, parent);
michael@0 692 }
michael@0 693
michael@0 694 #ifdef DEBUG
michael@0 695 JS_FRIEND_API(void)
michael@0 696 js_DumpString(JSString *str)
michael@0 697 {
michael@0 698 str->dump();
michael@0 699 }
michael@0 700
michael@0 701 JS_FRIEND_API(void)
michael@0 702 js_DumpAtom(JSAtom *atom)
michael@0 703 {
michael@0 704 atom->dump();
michael@0 705 }
michael@0 706
michael@0 707 JS_FRIEND_API(void)
michael@0 708 js_DumpChars(const jschar *s, size_t n)
michael@0 709 {
michael@0 710 fprintf(stderr, "jschar * (%p) = ", (void *) s);
michael@0 711 JSString::dumpChars(s, n);
michael@0 712 fputc('\n', stderr);
michael@0 713 }
michael@0 714
michael@0 715 JS_FRIEND_API(void)
michael@0 716 js_DumpObject(JSObject *obj)
michael@0 717 {
michael@0 718 if (!obj) {
michael@0 719 fprintf(stderr, "NULL\n");
michael@0 720 return;
michael@0 721 }
michael@0 722 obj->dump();
michael@0 723 }
michael@0 724
michael@0 725 #endif
michael@0 726
michael@0 727 struct DumpHeapTracer : public JSTracer
michael@0 728 {
michael@0 729 FILE *output;
michael@0 730
michael@0 731 DumpHeapTracer(FILE *fp, JSRuntime *rt, JSTraceCallback callback,
michael@0 732 WeakMapTraceKind weakTraceKind)
michael@0 733 : JSTracer(rt, callback, weakTraceKind), output(fp)
michael@0 734 {}
michael@0 735 };
michael@0 736
michael@0 737 static char
michael@0 738 MarkDescriptor(void *thing)
michael@0 739 {
michael@0 740 gc::Cell *cell = static_cast<gc::Cell*>(thing);
michael@0 741 if (cell->isMarked(gc::BLACK))
michael@0 742 return cell->isMarked(gc::GRAY) ? 'G' : 'B';
michael@0 743 else
michael@0 744 return cell->isMarked(gc::GRAY) ? 'X' : 'W';
michael@0 745 }
michael@0 746
michael@0 747 static void
michael@0 748 DumpHeapVisitZone(JSRuntime *rt, void *data, Zone *zone)
michael@0 749 {
michael@0 750 DumpHeapTracer *dtrc = static_cast<DumpHeapTracer *>(data);
michael@0 751 fprintf(dtrc->output, "# zone %p\n", (void *)zone);
michael@0 752 }
michael@0 753
michael@0 754 static void
michael@0 755 DumpHeapVisitCompartment(JSRuntime *rt, void *data, JSCompartment *comp)
michael@0 756 {
michael@0 757 char name[1024];
michael@0 758 if (rt->compartmentNameCallback)
michael@0 759 (*rt->compartmentNameCallback)(rt, comp, name, sizeof(name));
michael@0 760 else
michael@0 761 strcpy(name, "<unknown>");
michael@0 762
michael@0 763 DumpHeapTracer *dtrc = static_cast<DumpHeapTracer *>(data);
michael@0 764 fprintf(dtrc->output, "# compartment %s [in zone %p]\n", name, (void *)comp->zone());
michael@0 765 }
michael@0 766
michael@0 767 static void
michael@0 768 DumpHeapVisitArena(JSRuntime *rt, void *data, gc::Arena *arena,
michael@0 769 JSGCTraceKind traceKind, size_t thingSize)
michael@0 770 {
michael@0 771 DumpHeapTracer *dtrc = static_cast<DumpHeapTracer *>(data);
michael@0 772 fprintf(dtrc->output, "# arena allockind=%u size=%u\n",
michael@0 773 unsigned(arena->aheader.getAllocKind()), unsigned(thingSize));
michael@0 774 }
michael@0 775
michael@0 776 static void
michael@0 777 DumpHeapVisitCell(JSRuntime *rt, void *data, void *thing,
michael@0 778 JSGCTraceKind traceKind, size_t thingSize)
michael@0 779 {
michael@0 780 DumpHeapTracer *dtrc = static_cast<DumpHeapTracer *>(data);
michael@0 781 char cellDesc[1024 * 32];
michael@0 782 JS_GetTraceThingInfo(cellDesc, sizeof(cellDesc), dtrc, thing, traceKind, true);
michael@0 783 fprintf(dtrc->output, "%p %c %s\n", thing, MarkDescriptor(thing), cellDesc);
michael@0 784 JS_TraceChildren(dtrc, thing, traceKind);
michael@0 785 }
michael@0 786
michael@0 787 static void
michael@0 788 DumpHeapVisitChild(JSTracer *trc, void **thingp, JSGCTraceKind kind)
michael@0 789 {
michael@0 790 if (gc::IsInsideNursery(trc->runtime(), *thingp))
michael@0 791 return;
michael@0 792
michael@0 793 DumpHeapTracer *dtrc = static_cast<DumpHeapTracer *>(trc);
michael@0 794 char buffer[1024];
michael@0 795 fprintf(dtrc->output, "> %p %c %s\n", *thingp, MarkDescriptor(*thingp),
michael@0 796 dtrc->getTracingEdgeName(buffer, sizeof(buffer)));
michael@0 797 }
michael@0 798
michael@0 799 static void
michael@0 800 DumpHeapVisitRoot(JSTracer *trc, void **thingp, JSGCTraceKind kind)
michael@0 801 {
michael@0 802 if (gc::IsInsideNursery(trc->runtime(), *thingp))
michael@0 803 return;
michael@0 804
michael@0 805 DumpHeapTracer *dtrc = static_cast<DumpHeapTracer *>(trc);
michael@0 806 char buffer[1024];
michael@0 807 fprintf(dtrc->output, "%p %c %s\n", *thingp, MarkDescriptor(*thingp),
michael@0 808 dtrc->getTracingEdgeName(buffer, sizeof(buffer)));
michael@0 809 }
michael@0 810
michael@0 811 void
michael@0 812 js::DumpHeapComplete(JSRuntime *rt, FILE *fp, js::DumpHeapNurseryBehaviour nurseryBehaviour)
michael@0 813 {
michael@0 814 #ifdef JSGC_GENERATIONAL
michael@0 815 if (nurseryBehaviour == js::CollectNurseryBeforeDump)
michael@0 816 MinorGC(rt, JS::gcreason::API);
michael@0 817 #endif
michael@0 818
michael@0 819 DumpHeapTracer dtrc(fp, rt, DumpHeapVisitRoot, TraceWeakMapKeysValues);
michael@0 820 TraceRuntime(&dtrc);
michael@0 821
michael@0 822 fprintf(dtrc.output, "==========\n");
michael@0 823
michael@0 824 dtrc.setTraceCallback(DumpHeapVisitChild);
michael@0 825 IterateZonesCompartmentsArenasCells(rt, &dtrc,
michael@0 826 DumpHeapVisitZone,
michael@0 827 DumpHeapVisitCompartment,
michael@0 828 DumpHeapVisitArena,
michael@0 829 DumpHeapVisitCell);
michael@0 830
michael@0 831 fflush(dtrc.output);
michael@0 832 }
michael@0 833
michael@0 834 JS_FRIEND_API(const JSStructuredCloneCallbacks *)
michael@0 835 js::GetContextStructuredCloneCallbacks(JSContext *cx)
michael@0 836 {
michael@0 837 return cx->runtime()->structuredCloneCallbacks;
michael@0 838 }
michael@0 839
michael@0 840 #ifdef JS_THREADSAFE
michael@0 841 JS_FRIEND_API(bool)
michael@0 842 js::ContextHasOutstandingRequests(const JSContext *cx)
michael@0 843 {
michael@0 844 return cx->outstandingRequests > 0;
michael@0 845 }
michael@0 846 #endif
michael@0 847
michael@0 848 JS_FRIEND_API(void)
michael@0 849 js::SetActivityCallback(JSRuntime *rt, ActivityCallback cb, void *arg)
michael@0 850 {
michael@0 851 rt->activityCallback = cb;
michael@0 852 rt->activityCallbackArg = arg;
michael@0 853 }
michael@0 854
michael@0 855 JS_FRIEND_API(bool)
michael@0 856 js::IsContextRunningJS(JSContext *cx)
michael@0 857 {
michael@0 858 return cx->currentlyRunning();
michael@0 859 }
michael@0 860
michael@0 861 JS_FRIEND_API(JS::GCSliceCallback)
michael@0 862 JS::SetGCSliceCallback(JSRuntime *rt, GCSliceCallback callback)
michael@0 863 {
michael@0 864 JS::GCSliceCallback old = rt->gcSliceCallback;
michael@0 865 rt->gcSliceCallback = callback;
michael@0 866 return old;
michael@0 867 }
michael@0 868
michael@0 869 JS_FRIEND_API(bool)
michael@0 870 JS::WasIncrementalGC(JSRuntime *rt)
michael@0 871 {
michael@0 872 return rt->gcIsIncremental;
michael@0 873 }
michael@0 874
michael@0 875 jschar *
michael@0 876 GCDescription::formatMessage(JSRuntime *rt) const
michael@0 877 {
michael@0 878 return rt->gcStats.formatMessage();
michael@0 879 }
michael@0 880
michael@0 881 jschar *
michael@0 882 GCDescription::formatJSON(JSRuntime *rt, uint64_t timestamp) const
michael@0 883 {
michael@0 884 return rt->gcStats.formatJSON(timestamp);
michael@0 885 }
michael@0 886
michael@0 887 JS_FRIEND_API(void)
michael@0 888 JS::NotifyDidPaint(JSRuntime *rt)
michael@0 889 {
michael@0 890 if (rt->gcZeal() == gc::ZealFrameVerifierPreValue) {
michael@0 891 gc::VerifyBarriers(rt, gc::PreBarrierVerifier);
michael@0 892 return;
michael@0 893 }
michael@0 894
michael@0 895 if (rt->gcZeal() == gc::ZealFrameVerifierPostValue) {
michael@0 896 gc::VerifyBarriers(rt, gc::PostBarrierVerifier);
michael@0 897 return;
michael@0 898 }
michael@0 899
michael@0 900 if (rt->gcZeal() == gc::ZealFrameGCValue) {
michael@0 901 PrepareForFullGC(rt);
michael@0 902 GCSlice(rt, GC_NORMAL, gcreason::REFRESH_FRAME);
michael@0 903 return;
michael@0 904 }
michael@0 905
michael@0 906 if (JS::IsIncrementalGCInProgress(rt) && !rt->gcInterFrameGC) {
michael@0 907 JS::PrepareForIncrementalGC(rt);
michael@0 908 GCSlice(rt, GC_NORMAL, gcreason::REFRESH_FRAME);
michael@0 909 }
michael@0 910
michael@0 911 rt->gcInterFrameGC = false;
michael@0 912 }
michael@0 913
michael@0 914 JS_FRIEND_API(bool)
michael@0 915 JS::IsIncrementalGCEnabled(JSRuntime *rt)
michael@0 916 {
michael@0 917 return rt->gcIncrementalEnabled && rt->gcMode() == JSGC_MODE_INCREMENTAL;
michael@0 918 }
michael@0 919
michael@0 920 JS_FRIEND_API(bool)
michael@0 921 JS::IsIncrementalGCInProgress(JSRuntime *rt)
michael@0 922 {
michael@0 923 return rt->gcIncrementalState != gc::NO_INCREMENTAL && !rt->gcVerifyPreData;
michael@0 924 }
michael@0 925
michael@0 926 JS_FRIEND_API(void)
michael@0 927 JS::DisableIncrementalGC(JSRuntime *rt)
michael@0 928 {
michael@0 929 rt->gcIncrementalEnabled = false;
michael@0 930 }
michael@0 931
michael@0 932 JS::AutoDisableGenerationalGC::AutoDisableGenerationalGC(JSRuntime *rt)
michael@0 933 : runtime(rt)
michael@0 934 #if defined(JSGC_GENERATIONAL) && defined(JS_GC_ZEAL)
michael@0 935 , restartVerifier(rt->gcVerifyPostData)
michael@0 936 #endif
michael@0 937 {
michael@0 938 #ifdef JSGC_GENERATIONAL
michael@0 939 if (IsGenerationalGCEnabled(rt)) {
michael@0 940 #ifdef JS_GC_ZEAL
michael@0 941 if (restartVerifier)
michael@0 942 gc::EndVerifyPostBarriers(rt);
michael@0 943 #endif
michael@0 944 MinorGC(rt, JS::gcreason::API);
michael@0 945 rt->gcNursery.disable();
michael@0 946 rt->gcStoreBuffer.disable();
michael@0 947 }
michael@0 948 #endif
michael@0 949 ++rt->gcGenerationalDisabled;
michael@0 950 }
michael@0 951
michael@0 952 JS::AutoDisableGenerationalGC::~AutoDisableGenerationalGC()
michael@0 953 {
michael@0 954 JS_ASSERT(runtime->gcGenerationalDisabled > 0);
michael@0 955 --runtime->gcGenerationalDisabled;
michael@0 956 #ifdef JSGC_GENERATIONAL
michael@0 957 if (runtime->gcGenerationalDisabled == 0) {
michael@0 958 runtime->gcNursery.enable();
michael@0 959 runtime->gcStoreBuffer.enable();
michael@0 960 #ifdef JS_GC_ZEAL
michael@0 961 if (restartVerifier)
michael@0 962 gc::StartVerifyPostBarriers(runtime);
michael@0 963 #endif
michael@0 964 }
michael@0 965 #endif
michael@0 966 }
michael@0 967
michael@0 968 extern JS_FRIEND_API(bool)
michael@0 969 JS::IsGenerationalGCEnabled(JSRuntime *rt)
michael@0 970 {
michael@0 971 return rt->gcGenerationalDisabled == 0;
michael@0 972 }
michael@0 973
michael@0 974 JS_FRIEND_API(bool)
michael@0 975 JS::IsIncrementalBarrierNeeded(JSRuntime *rt)
michael@0 976 {
michael@0 977 return rt->gcIncrementalState == gc::MARK && !rt->isHeapBusy();
michael@0 978 }
michael@0 979
michael@0 980 JS_FRIEND_API(bool)
michael@0 981 JS::IsIncrementalBarrierNeeded(JSContext *cx)
michael@0 982 {
michael@0 983 return IsIncrementalBarrierNeeded(cx->runtime());
michael@0 984 }
michael@0 985
michael@0 986 JS_FRIEND_API(void)
michael@0 987 JS::IncrementalObjectBarrier(JSObject *obj)
michael@0 988 {
michael@0 989 if (!obj)
michael@0 990 return;
michael@0 991
michael@0 992 JS_ASSERT(!obj->zone()->runtimeFromMainThread()->isHeapMajorCollecting());
michael@0 993
michael@0 994 AutoMarkInDeadZone amn(obj->zone());
michael@0 995
michael@0 996 JSObject::writeBarrierPre(obj);
michael@0 997 }
michael@0 998
michael@0 999 JS_FRIEND_API(void)
michael@0 1000 JS::IncrementalReferenceBarrier(void *ptr, JSGCTraceKind kind)
michael@0 1001 {
michael@0 1002 if (!ptr)
michael@0 1003 return;
michael@0 1004
michael@0 1005 if (kind == JSTRACE_STRING && StringIsPermanentAtom(static_cast<JSString *>(ptr)))
michael@0 1006 return;
michael@0 1007
michael@0 1008 gc::Cell *cell = static_cast<gc::Cell *>(ptr);
michael@0 1009 Zone *zone = kind == JSTRACE_OBJECT
michael@0 1010 ? static_cast<JSObject *>(cell)->zone()
michael@0 1011 : cell->tenuredZone();
michael@0 1012
michael@0 1013 JS_ASSERT(!zone->runtimeFromMainThread()->isHeapMajorCollecting());
michael@0 1014
michael@0 1015 AutoMarkInDeadZone amn(zone);
michael@0 1016
michael@0 1017 if (kind == JSTRACE_OBJECT)
michael@0 1018 JSObject::writeBarrierPre(static_cast<JSObject*>(cell));
michael@0 1019 else if (kind == JSTRACE_STRING)
michael@0 1020 JSString::writeBarrierPre(static_cast<JSString*>(cell));
michael@0 1021 else if (kind == JSTRACE_SCRIPT)
michael@0 1022 JSScript::writeBarrierPre(static_cast<JSScript*>(cell));
michael@0 1023 else if (kind == JSTRACE_LAZY_SCRIPT)
michael@0 1024 LazyScript::writeBarrierPre(static_cast<LazyScript*>(cell));
michael@0 1025 else if (kind == JSTRACE_SHAPE)
michael@0 1026 Shape::writeBarrierPre(static_cast<Shape*>(cell));
michael@0 1027 else if (kind == JSTRACE_BASE_SHAPE)
michael@0 1028 BaseShape::writeBarrierPre(static_cast<BaseShape*>(cell));
michael@0 1029 else if (kind == JSTRACE_TYPE_OBJECT)
michael@0 1030 types::TypeObject::writeBarrierPre((types::TypeObject *) ptr);
michael@0 1031 else
michael@0 1032 MOZ_ASSUME_UNREACHABLE("invalid trace kind");
michael@0 1033 }
michael@0 1034
michael@0 1035 JS_FRIEND_API(void)
michael@0 1036 JS::IncrementalValueBarrier(const Value &v)
michael@0 1037 {
michael@0 1038 js::HeapValue::writeBarrierPre(v);
michael@0 1039 }
michael@0 1040
michael@0 1041 JS_FRIEND_API(void)
michael@0 1042 JS::PokeGC(JSRuntime *rt)
michael@0 1043 {
michael@0 1044 rt->gcPoke = true;
michael@0 1045 }
michael@0 1046
michael@0 1047 JS_FRIEND_API(JSCompartment *)
michael@0 1048 js::GetAnyCompartmentInZone(JS::Zone *zone)
michael@0 1049 {
michael@0 1050 CompartmentsInZoneIter comp(zone);
michael@0 1051 JS_ASSERT(!comp.done());
michael@0 1052 return comp.get();
michael@0 1053 }
michael@0 1054
michael@0 1055 bool
michael@0 1056 JS::ObjectPtr::isAboutToBeFinalized()
michael@0 1057 {
michael@0 1058 return JS_IsAboutToBeFinalized(&value);
michael@0 1059 }
michael@0 1060
michael@0 1061 void
michael@0 1062 JS::ObjectPtr::trace(JSTracer *trc, const char *name)
michael@0 1063 {
michael@0 1064 JS_CallHeapObjectTracer(trc, &value, name);
michael@0 1065 }
michael@0 1066
michael@0 1067 JS_FRIEND_API(JSObject *)
michael@0 1068 js::GetTestingFunctions(JSContext *cx)
michael@0 1069 {
michael@0 1070 RootedObject obj(cx, JS_NewObject(cx, nullptr, NullPtr(), NullPtr()));
michael@0 1071 if (!obj)
michael@0 1072 return nullptr;
michael@0 1073
michael@0 1074 if (!DefineTestingFunctions(cx, obj, false))
michael@0 1075 return nullptr;
michael@0 1076
michael@0 1077 return obj;
michael@0 1078 }
michael@0 1079
michael@0 1080 #ifdef DEBUG
michael@0 1081 JS_FRIEND_API(unsigned)
michael@0 1082 js::GetEnterCompartmentDepth(JSContext *cx)
michael@0 1083 {
michael@0 1084 return cx->getEnterCompartmentDepth();
michael@0 1085 }
michael@0 1086 #endif
michael@0 1087
michael@0 1088 JS_FRIEND_API(void)
michael@0 1089 js::SetDOMCallbacks(JSRuntime *rt, const DOMCallbacks *callbacks)
michael@0 1090 {
michael@0 1091 rt->DOMcallbacks = callbacks;
michael@0 1092 }
michael@0 1093
michael@0 1094 JS_FRIEND_API(const DOMCallbacks *)
michael@0 1095 js::GetDOMCallbacks(JSRuntime *rt)
michael@0 1096 {
michael@0 1097 return rt->DOMcallbacks;
michael@0 1098 }
michael@0 1099
michael@0 1100 static const void *gDOMProxyHandlerFamily = nullptr;
michael@0 1101 static uint32_t gDOMProxyExpandoSlot = 0;
michael@0 1102 static DOMProxyShadowsCheck gDOMProxyShadowsCheck;
michael@0 1103
michael@0 1104 JS_FRIEND_API(void)
michael@0 1105 js::SetDOMProxyInformation(const void *domProxyHandlerFamily, uint32_t domProxyExpandoSlot,
michael@0 1106 DOMProxyShadowsCheck domProxyShadowsCheck)
michael@0 1107 {
michael@0 1108 gDOMProxyHandlerFamily = domProxyHandlerFamily;
michael@0 1109 gDOMProxyExpandoSlot = domProxyExpandoSlot;
michael@0 1110 gDOMProxyShadowsCheck = domProxyShadowsCheck;
michael@0 1111 }
michael@0 1112
michael@0 1113 const void *
michael@0 1114 js::GetDOMProxyHandlerFamily()
michael@0 1115 {
michael@0 1116 return gDOMProxyHandlerFamily;
michael@0 1117 }
michael@0 1118
michael@0 1119 uint32_t
michael@0 1120 js::GetDOMProxyExpandoSlot()
michael@0 1121 {
michael@0 1122 return gDOMProxyExpandoSlot;
michael@0 1123 }
michael@0 1124
michael@0 1125 DOMProxyShadowsCheck
michael@0 1126 js::GetDOMProxyShadowsCheck()
michael@0 1127 {
michael@0 1128 return gDOMProxyShadowsCheck;
michael@0 1129 }
michael@0 1130
michael@0 1131 bool
michael@0 1132 js::detail::IdMatchesAtom(jsid id, JSAtom *atom)
michael@0 1133 {
michael@0 1134 return id == INTERNED_STRING_TO_JSID(nullptr, atom);
michael@0 1135 }
michael@0 1136
michael@0 1137 JS_FRIEND_API(JSContext *)
michael@0 1138 js::DefaultJSContext(JSRuntime *rt)
michael@0 1139 {
michael@0 1140 if (rt->defaultJSContextCallback) {
michael@0 1141 JSContext *cx = rt->defaultJSContextCallback(rt);
michael@0 1142 JS_ASSERT(cx);
michael@0 1143 return cx;
michael@0 1144 }
michael@0 1145 JS_ASSERT(rt->contextList.getFirst() == rt->contextList.getLast());
michael@0 1146 return rt->contextList.getFirst();
michael@0 1147 }
michael@0 1148
michael@0 1149 JS_FRIEND_API(void)
michael@0 1150 js::SetDefaultJSContextCallback(JSRuntime *rt, DefaultJSContextCallback cb)
michael@0 1151 {
michael@0 1152 rt->defaultJSContextCallback = cb;
michael@0 1153 }
michael@0 1154
michael@0 1155 #ifdef DEBUG
michael@0 1156 JS_FRIEND_API(void)
michael@0 1157 js::Debug_SetActiveJSContext(JSRuntime *rt, JSContext *cx)
michael@0 1158 {
michael@0 1159 rt->activeContext = cx;
michael@0 1160 }
michael@0 1161 #endif
michael@0 1162
michael@0 1163 JS_FRIEND_API(void)
michael@0 1164 js::SetCTypesActivityCallback(JSRuntime *rt, CTypesActivityCallback cb)
michael@0 1165 {
michael@0 1166 rt->ctypesActivityCallback = cb;
michael@0 1167 }
michael@0 1168
michael@0 1169 js::AutoCTypesActivityCallback::AutoCTypesActivityCallback(JSContext *cx,
michael@0 1170 js::CTypesActivityType beginType,
michael@0 1171 js::CTypesActivityType endType
michael@0 1172 MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
michael@0 1173 : cx(cx), callback(cx->runtime()->ctypesActivityCallback), endType(endType)
michael@0 1174 {
michael@0 1175 MOZ_GUARD_OBJECT_NOTIFIER_INIT;
michael@0 1176
michael@0 1177 if (callback)
michael@0 1178 callback(cx, beginType);
michael@0 1179 }
michael@0 1180
michael@0 1181 JS_FRIEND_API(void)
michael@0 1182 js::SetObjectMetadataCallback(JSContext *cx, ObjectMetadataCallback callback)
michael@0 1183 {
michael@0 1184 cx->compartment()->setObjectMetadataCallback(callback);
michael@0 1185 }
michael@0 1186
michael@0 1187 JS_FRIEND_API(bool)
michael@0 1188 js::SetObjectMetadata(JSContext *cx, HandleObject obj, HandleObject metadata)
michael@0 1189 {
michael@0 1190 return JSObject::setMetadata(cx, obj, metadata);
michael@0 1191 }
michael@0 1192
michael@0 1193 JS_FRIEND_API(JSObject *)
michael@0 1194 js::GetObjectMetadata(JSObject *obj)
michael@0 1195 {
michael@0 1196 return obj->getMetadata();
michael@0 1197 }
michael@0 1198
michael@0 1199 JS_FRIEND_API(void)
michael@0 1200 js::UnsafeDefineElement(JSContext *cx, JS::HandleObject obj, uint32_t index, JS::HandleValue value)
michael@0 1201 {
michael@0 1202 JS_ASSERT(obj->isNative());
michael@0 1203 JS_ASSERT(index < obj->getDenseInitializedLength());
michael@0 1204 obj->setDenseElementWithType(cx, index, value);
michael@0 1205 }
michael@0 1206
michael@0 1207 JS_FRIEND_API(bool)
michael@0 1208 js_DefineOwnProperty(JSContext *cx, JSObject *objArg, jsid idArg,
michael@0 1209 JS::Handle<js::PropertyDescriptor> descriptor, bool *bp)
michael@0 1210 {
michael@0 1211 RootedObject obj(cx, objArg);
michael@0 1212 RootedId id(cx, idArg);
michael@0 1213 JS_ASSERT(cx->runtime()->heapState == js::Idle);
michael@0 1214 CHECK_REQUEST(cx);
michael@0 1215 assertSameCompartment(cx, obj, id, descriptor.value());
michael@0 1216 if (descriptor.hasGetterObject())
michael@0 1217 assertSameCompartment(cx, descriptor.getterObject());
michael@0 1218 if (descriptor.hasSetterObject())
michael@0 1219 assertSameCompartment(cx, descriptor.setterObject());
michael@0 1220
michael@0 1221 return DefineOwnProperty(cx, HandleObject(obj), id, descriptor, bp);
michael@0 1222 }
michael@0 1223
michael@0 1224 JS_FRIEND_API(bool)
michael@0 1225 js_ReportIsNotFunction(JSContext *cx, JS::HandleValue v)
michael@0 1226 {
michael@0 1227 return ReportIsNotFunction(cx, v);
michael@0 1228 }
michael@0 1229
michael@0 1230 #ifdef DEBUG
michael@0 1231 JS_PUBLIC_API(bool)
michael@0 1232 js::IsInRequest(JSContext *cx)
michael@0 1233 {
michael@0 1234 #ifdef JS_THREADSAFE
michael@0 1235 return !!cx->runtime()->requestDepth;
michael@0 1236 #else
michael@0 1237 return true;
michael@0 1238 #endif
michael@0 1239 }
michael@0 1240 #endif
michael@0 1241
michael@0 1242 #ifdef JSGC_GENERATIONAL
michael@0 1243 JS_FRIEND_API(void)
michael@0 1244 JS_StoreObjectPostBarrierCallback(JSContext* cx,
michael@0 1245 void (*callback)(JSTracer *trc, JSObject *key, void *data),
michael@0 1246 JSObject *key, void *data)
michael@0 1247 {
michael@0 1248 JSRuntime *rt = cx->runtime();
michael@0 1249 if (IsInsideNursery(rt, key))
michael@0 1250 rt->gcStoreBuffer.putCallback(callback, key, data);
michael@0 1251 }
michael@0 1252
michael@0 1253 extern JS_FRIEND_API(void)
michael@0 1254 JS_StoreStringPostBarrierCallback(JSContext* cx,
michael@0 1255 void (*callback)(JSTracer *trc, JSString *key, void *data),
michael@0 1256 JSString *key, void *data)
michael@0 1257 {
michael@0 1258 JSRuntime *rt = cx->runtime();
michael@0 1259 if (IsInsideNursery(rt, key))
michael@0 1260 rt->gcStoreBuffer.putCallback(callback, key, data);
michael@0 1261 }
michael@0 1262 #endif /* JSGC_GENERATIONAL */

mercurial