Exemple #1
0
JSObject *newDelegate()
{
    static const JSClass delegateClass = {
        "delegate",
        JSCLASS_GLOBAL_FLAGS | JSCLASS_HAS_RESERVED_SLOTS(1),
        JS_PropertyStub,
        JS_DeletePropertyStub,
        JS_PropertyStub,
        JS_StrictPropertyStub,
        JS_EnumerateStub,
        JS_ResolveStub,
        JS_ConvertStub,
        nullptr,
        nullptr,
        nullptr,
        nullptr,
        JS_GlobalObjectTraceHook
    };

    /* Create the global object. */
    JS::CompartmentOptions options;
    options.setVersion(JSVERSION_LATEST);
    JS::RootedObject global(cx);
    global = JS_NewGlobalObject(cx, &delegateClass, nullptr, JS::FireOnNewGlobalHook, options);
    JS_SetReservedSlot(global, 0, JS::Int32Value(42));

    /*
     * Ensure the delegate is not in the nursery because for the purpose of this
     * test we're going to put it in a private slot where it won't get updated.
     */
    JS_GC(rt);

    return global;
}
Exemple #2
0
void
InitGlobalObjectOptions(JS::CompartmentOptions& aOptions,
                        nsIPrincipal* aPrincipal)
{
    bool shouldDiscardSystemSource = ShouldDiscardSystemSource();
    bool extraWarningsForSystemJS = ExtraWarningsForSystemJS();

    bool isSystem = nsContentUtils::IsSystemPrincipal(aPrincipal);

    if (isSystem) {
        // Make sure [SecureContext] APIs are visible:
        aOptions.creationOptions().setSecureContext(true);

#if 0 // TODO: Reenable in Bug 1288653
        // Enable the ECMA-402 experimental formatToParts in any chrome page
        aOptions.creationOptions()
                .setExperimentalDateTimeFormatFormatToPartsEnabled(true);
#endif
    }

    if (shouldDiscardSystemSource) {
        bool discardSource = isSystem;

        aOptions.behaviors().setDiscardSource(discardSource);
    }

    if (extraWarningsForSystemJS) {
        if (isSystem)
            aOptions.behaviors().extraWarningsOverride().set(true);
    }
}
Exemple #3
0
bool
DedicatedWorkerGlobalScope::WrapGlobalObject(JSContext* aCx,
                                             JS::MutableHandle<JSObject*> aReflector)
{
  mWorkerPrivate->AssertIsOnWorkerThread();
  MOZ_ASSERT(!mWorkerPrivate->IsSharedWorker());

  JS::CompartmentOptions options;
  mWorkerPrivate->CopyJSCompartmentOptions(options);

  const bool usesSystemPrincipal = mWorkerPrivate->UsesSystemPrincipal();

  // Note that xpc::ShouldDiscardSystemSource() and
  // xpc::ExtraWarningsForSystemJS() read prefs that are cached on the main
  // thread. This is benignly racey.
  const bool discardSource = (usesSystemPrincipal ||
                              mWorkerPrivate->IsInPrivilegedApp()) &&
                             xpc::ShouldDiscardSystemSource();
  const bool extraWarnings = usesSystemPrincipal &&
                             xpc::ExtraWarningsForSystemJS();

  options.setDiscardSource(discardSource)
         .extraWarningsOverride().set(extraWarnings);

  return DedicatedWorkerGlobalScopeBinding_workers::Wrap(aCx, this, this,
                                                         options,
                                                         GetWorkerPrincipal(),
                                                         true, aReflector);
}
JSObject*
createTestGlobal(bool preserveJitCode)
{
    JS::CompartmentOptions options;
    options.creationOptions().setPreserveJitCode(preserveJitCode);
    return JS_NewGlobalObject(cx, getGlobalClass(), nullptr, JS::FireOnNewGlobalHook, options);
}
Exemple #5
0
bool
DedicatedWorkerGlobalScope::WrapGlobalObject(JSContext* aCx,
                                             JS::MutableHandle<JSObject*> aReflector)
{
  mWorkerPrivate->AssertIsOnWorkerThread();
  MOZ_ASSERT(!mWorkerPrivate->IsSharedWorker());

  JS::CompartmentOptions options;
  mWorkerPrivate->CopyJSCompartmentOptions(options);

  const bool usesSystemPrincipal = mWorkerPrivate->UsesSystemPrincipal();

  // Note that xpc::ShouldDiscardSystemSource() and
  // xpc::ExtraWarningsForSystemJS() read prefs that are cached on the main
  // thread. This is benignly racey.
  const bool discardSource = usesSystemPrincipal &&
                             xpc::ShouldDiscardSystemSource();
  const bool extraWarnings = usesSystemPrincipal &&
                             xpc::ExtraWarningsForSystemJS();

  JS::CompartmentBehaviors& behaviors = options.behaviors();
  behaviors.setDiscardSource(discardSource)
           .extraWarningsOverride().set(extraWarnings);

  const bool sharedMemoryEnabled = xpc::SharedMemoryEnabled();

  JS::CompartmentCreationOptions& creationOptions = options.creationOptions();
  creationOptions.setSharedMemoryAndAtomicsEnabled(sharedMemoryEnabled);

  return DedicatedWorkerGlobalScopeBinding::Wrap(aCx, this, this,
                                                 options,
                                                 GetWorkerPrincipal(),
                                                 true, aReflector);
}
void
InitGlobalObjectOptions(JS::CompartmentOptions& aOptions,
                        nsIPrincipal* aPrincipal)
{
    bool shouldDiscardSystemSource = ShouldDiscardSystemSource();
    bool extraWarningsForSystemJS = ExtraWarningsForSystemJS();

    bool isSystem = nsContentUtils::IsSystemPrincipal(aPrincipal);

    if (isSystem) {
        // Make sure [SecureContext] APIs are visible:
        aOptions.creationOptions().setSecureContext(true);
    }

    short status = aPrincipal->GetAppStatus();

    // Enable the ECMA-402 experimental formatToParts in certified apps.
    if (status == nsIPrincipal::APP_STATUS_CERTIFIED) {
        aOptions.creationOptions()
                .setExperimentalDateTimeFormatFormatToPartsEnabled(true);
    }

    if (shouldDiscardSystemSource) {
        bool discardSource = isSystem ||
                             (status == nsIPrincipal::APP_STATUS_PRIVILEGED ||
                              status == nsIPrincipal::APP_STATUS_CERTIFIED);

        aOptions.behaviors().setDiscardSource(discardSource);
    }

    if (extraWarningsForSystemJS) {
        if (isSystem)
            aOptions.behaviors().extraWarningsOverride().set(true);
    }
}
Exemple #7
0
ScriptInterface_impl::ScriptInterface_impl(const char* nativeScopeName, const shared_ptr<ScriptRuntime>& runtime) :
	m_runtime(runtime), m_glob(runtime->m_rt), m_nativeScope(runtime->m_rt)
{
	bool ok;

	m_cx = JS_NewContext(m_runtime->m_rt, STACK_CHUNK_SIZE);
	ENSURE(m_cx);

	JS_SetParallelIonCompilationEnabled(m_runtime->m_rt, true);

	// For GC debugging:
	// JS_SetGCZeal(m_cx, 2);

	JS_SetContextPrivate(m_cx, NULL);

	JS_SetErrorReporter(m_cx, ErrorReporter);

	JS_SetGlobalJitCompilerOption(m_runtime->m_rt, JSJITCOMPILER_ION_ENABLE, 1);
	JS_SetGlobalJitCompilerOption(m_runtime->m_rt, JSJITCOMPILER_BASELINE_ENABLE, 1);

	JS::ContextOptionsRef(m_cx).setExtraWarnings(1)
		.setWerror(0)
		.setVarObjFix(1)
		.setStrictMode(1);

	JS::CompartmentOptions opt;
	opt.setVersion(JSVERSION_LATEST);

	JSAutoRequest rq(m_cx);
	JS::RootedObject globalRootedVal(m_cx, JS_NewGlobalObject(m_cx, &global_class, NULL, JS::OnNewGlobalHookOption::FireOnNewGlobalHook, opt));
	m_comp = JS_EnterCompartment(m_cx, globalRootedVal);
	ok = JS_InitStandardClasses(m_cx, globalRootedVal);
	ENSURE(ok);
	m_glob = globalRootedVal.get();

	// Use the testing functions to globally enable gcPreserveCode. This brings quite a 
	// big performance improvement. In future SpiderMonkey versions, we should probably 
	// use the functions implemented here: https://bugzilla.mozilla.org/show_bug.cgi?id=1068697
	JS::RootedObject testingFunctionsObj(m_cx, js::GetTestingFunctions(m_cx));
	ENSURE(testingFunctionsObj);
	JS::RootedValue ret(m_cx);
	JS_CallFunctionName(m_cx, testingFunctionsObj, "gcPreserveCode", JS::HandleValueArray::empty(), &ret);

	JS_DefineProperty(m_cx, m_glob, "global", globalRootedVal, JSPROP_ENUMERATE | JSPROP_READONLY
			| JSPROP_PERMANENT);

	m_nativeScope = JS_DefineObject(m_cx, m_glob, nativeScopeName, NULL, NULL, JSPROP_ENUMERATE | JSPROP_READONLY
			| JSPROP_PERMANENT);

	JS_DefineFunction(m_cx, globalRootedVal, "print", ::print,        0, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);
	JS_DefineFunction(m_cx, globalRootedVal, "log",   ::logmsg,       1, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);
	JS_DefineFunction(m_cx, globalRootedVal, "warn",  ::warn,         1, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);
	JS_DefineFunction(m_cx, globalRootedVal, "error", ::error,        1, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);
	JS_DefineFunction(m_cx, globalRootedVal, "deepcopy", ::deepcopy,  1, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);

	Register("ProfileStart", ::ProfileStart, 1);
	Register("ProfileStop", ::ProfileStop, 0);

	runtime->RegisterContext(m_cx);
}
Exemple #8
0
static void
CreateGlobalAndRunTest(JSRuntime* rt, JSContext* cx)
{
  static const JSClass GlobalClass = {
    "global", JSCLASS_GLOBAL_FLAGS,
    JS_PropertyStub, JS_DeletePropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub,
    nullptr, nullptr, nullptr, nullptr,
    JS_GlobalObjectTraceHook
  };

  JS::CompartmentOptions options;
  options.setVersion(JSVERSION_LATEST);
  JS::RootedObject global(cx);
  global = JS_NewGlobalObject(cx, &GlobalClass, nullptr, JS::FireOnNewGlobalHook, options);
  ASSERT_TRUE(global != nullptr);

  JS_AddNamedObjectRoot(cx, global.address(), "test-global");
  JSCompartment *oldCompartment = JS_EnterCompartment(cx, global);

  RunTest(rt, cx);

  JS_LeaveCompartment(cx, oldCompartment);
  JS_RemoveObjectRoot(cx, global.address());
}
Exemple #9
0
JSCompartment::JSCompartment(Zone* zone, const JS::CompartmentOptions& options = JS::CompartmentOptions())
  : creationOptions_(options.creationOptions()),
    behaviors_(options.behaviors()),
    zone_(zone),
    runtime_(zone->runtimeFromAnyThread()),
    principals_(nullptr),
    isSystem_(false),
    isAtomsCompartment_(false),
    isSelfHosting(false),
    marked(true),
    warnedAboutExprClosure(false),
    warnedAboutStringGenericsMethods(0),
#ifdef DEBUG
    firedOnNewGlobalObject(false),
#endif
    global_(nullptr),
    enterCompartmentDepth(0),
    globalHolds(0),
    performanceMonitoring(runtime_),
    data(nullptr),
    realmData(nullptr),
    allocationMetadataBuilder(nullptr),
    lastAnimationTime(0),
    regExps(),
    arraySpeciesLookup(),
    globalWriteBarriered(0),
    detachedTypedObjects(0),
    objectMetadataState(ImmediateMetadata()),
    selfHostingScriptSource(nullptr),
    objectMetadataTable(nullptr),
    innerViews(zone),
    lazyArrayBuffers(nullptr),
    wasm(zone),
    nonSyntacticLexicalEnvironments_(nullptr),
    gcIncomingGrayPointers(nullptr),
    debugModeBits(0),
    validAccessPtr(nullptr),
    randomKeyGenerator_(runtime_->forkRandomKeyGenerator()),
    scriptCountsMap(nullptr),
    scriptNameMap(nullptr),
    debugScriptMap(nullptr),
    debugEnvs(nullptr),
    enumerators(nullptr),
    compartmentStats_(nullptr),
    scheduledForDestruction(false),
    maybeAlive(true),
    jitCompartment_(nullptr),
    mappedArgumentsTemplate_(nullptr),
    unmappedArgumentsTemplate_(nullptr),
    iterResultTemplate_(nullptr),
    lcovOutput()
{
    PodArrayZero(sawDeprecatedLanguageExtension);
    runtime_->numCompartments++;
    MOZ_ASSERT_IF(creationOptions_.mergeable(),
                  creationOptions_.invisibleToDebugger());
}
Exemple #10
0
JSContext*
XPCJSContextStack::GetSafeJSContext()
{
    if (mSafeJSContext)
        return mSafeJSContext;

    // Start by getting the principal holder and principal for this
    // context.  If we can't manage that, don't bother with the rest.
    nsRefPtr<nsNullPrincipal> principal = new nsNullPrincipal();
    nsresult rv = principal->Init();
    if (NS_FAILED(rv))
        MOZ_CRASH();

    nsXPConnect* xpc = nsXPConnect::XPConnect();
    JSRuntime *rt = xpc->GetRuntime()->Runtime();
    if (!rt)
        MOZ_CRASH();

    mSafeJSContext = JS_NewContext(rt, 8192);
    if (!mSafeJSContext)
        MOZ_CRASH();
    JSAutoRequest req(mSafeJSContext);

    JS::RootedObject glob(mSafeJSContext);
    JS_SetErrorReporter(mSafeJSContext, xpc::SystemErrorReporter);

    JS::CompartmentOptions options;
    options.setZone(JS::SystemZone);
    glob = xpc::CreateGlobalObject(mSafeJSContext, &SafeJSContextGlobalClass, principal, options);
    if (!glob)
        MOZ_CRASH();

    // Make sure the context is associated with a proper compartment
    // and not the default compartment.
    js::SetDefaultObjectForContext(mSafeJSContext, glob);

    // Note: make sure to set the private before calling
    // InitClasses
    nsCOMPtr<nsIScriptObjectPrincipal> sop = new SandboxPrivate(principal, glob);
    JS_SetPrivate(glob, sop.forget().get());

    // After this point either glob is null and the
    // nsIScriptObjectPrincipal ownership is either handled by the
    // nsCOMPtr or dealt with, or we'll release in the finalize
    // hook.
    if (NS_FAILED(xpc->InitClasses(mSafeJSContext, glob)))
        MOZ_CRASH();

    JS_FireOnNewGlobalObject(mSafeJSContext, glob);

    // Save it off so we can destroy it later.
    mOwnSafeJSContext = mSafeJSContext;

    return mSafeJSContext;
}
Exemple #11
0
bool JSAudioContext::createContext()
{
    if (m_JsRt != NULL) return false;

    if ((m_JsRt = JS_NewRuntime(JS::DefaultHeapMaxBytes, JS::DefaultNurseryBytes))
        == NULL) {
        fprintf(stderr, "Failed to init JS runtime");
        return false;
    }

    NidiumJS::SetJSRuntimeOptions(m_JsRt);

    JS_SetGCParameter(m_JsRt, JSGC_MAX_BYTES, 0xffffffff);
    JS_SetGCParameter(m_JsRt, JSGC_SLICE_TIME_BUDGET, 15);

    if ((m_JsTcx = JS_NewContext(m_JsRt, 8192)) == NULL) {
        fprintf(stderr, "Failed to init JS context");
        return false;
    }

    NidiumLocalContext::InitJSThread(m_JsRt, m_JsTcx);

    JSAutoRequest ar(m_JsTcx);

    // JS_SetGCParameterForThread(this->tcx, JSGC_MAX_CODE_CACHE_BYTES, 16 *
    // 1024 * 1024);
    JS::CompartmentOptions options;
    options.setVersion(JSVERSION_LATEST);

    JS::RootedObject global(
        m_JsTcx, JS_NewGlobalObject(m_JsTcx, &Global_AudioThread_class, nullptr,
                                    JS::DontFireOnNewGlobalHook, options));

    JSAutoCompartment ac(m_JsTcx, global);

    m_JsGlobalObj = global;

    // We don't actually needs to root a global object, but we
    // need to store a reference to the global object in a
    // JS::Heap and this reference needs to be traced.
    NidiumLocalContext::RootObjectUntilShutdown(m_JsGlobalObj);

    if (!JS_InitStandardClasses(m_JsTcx, global)) {
        fprintf(stderr, "Failed to init std class");
        return false;
    }
    JS_SetErrorReporter(m_JsRt, reportError);
    JS_FireOnNewGlobalObject(m_JsTcx, global);
    JSConsole::RegisterObject(m_JsTcx);
    JSAudioNodeThreaded::RegisterObject(m_JsTcx);

    return true;
}
void JavaScriptInterpreter::ReadEvalPrintLoop()
{
	JSAutoRequest ar(cx);
	JS::CompartmentOptions compartmentOptions;
	compartmentOptions.setVersion(JSVERSION_DEFAULT);
	JS::RootedObject global(cx, JS_NewGlobalObject(cx, &global_class, nullptr, JS::FireOnNewGlobalHook, compartmentOptions));
	if (!global)
		return;

	JS::RootedValue rval(cx);

	JSAutoCompartment ac(cx, global);

	if (!JS_InitStandardClasses(cx, global))
		return;

	v = JS_GetVersion(cx);
	actionJSVersion->setDisabled(false);

	/////////////////////////////////////////////////////////////

	int lineno = 1;
	int startline = lineno;
	errno = 1;

	u16string source = TextEdit_input->toPlainText().toStdU16String();
	
	if (source.empty()) {
		if (errno) {
			char buffer[80];
			strerror_s(buffer, 80, errno);
			JS_ReportError(cx, buffer);
			return;
		}
		return;
	}
	
	lineno++;

	QString output = EvalAndPrint(source.c_str(), source.length(), startline);
	if (output.isEmpty())
	{
		JS_ReportPendingException(cx);
	}
	
	if (checkBox->isChecked()) {
		TextEdit_output->setPlainText(output);
	}
	else {
		TextEdit_output->insertPlainText(output + "\n");
	}
	
}
Exemple #13
0
ScriptInterface_impl::ScriptInterface_impl(const char* nativeScopeName, const shared_ptr<ScriptRuntime>& runtime) :
	m_runtime(runtime), m_glob(runtime->m_rt), m_nativeScope(runtime->m_rt)
{
	bool ok;

	m_cx = JS_NewContext(m_runtime->m_rt, STACK_CHUNK_SIZE);
	ENSURE(m_cx);

	JS_SetOffthreadIonCompilationEnabled(m_runtime->m_rt, true);

	// For GC debugging:
	// JS_SetGCZeal(m_cx, 2, JS_DEFAULT_ZEAL_FREQ);

	JS_SetContextPrivate(m_cx, NULL);

	JS_SetErrorReporter(m_runtime->m_rt, ErrorReporter);

	JS_SetGlobalJitCompilerOption(m_runtime->m_rt, JSJITCOMPILER_ION_ENABLE, 1);
	JS_SetGlobalJitCompilerOption(m_runtime->m_rt, JSJITCOMPILER_BASELINE_ENABLE, 1);

	JS::RuntimeOptionsRef(m_cx).setExtraWarnings(1)
		.setWerror(0)
		.setVarObjFix(1)
		.setStrictMode(1);

	JS::CompartmentOptions opt;
	opt.setVersion(JSVERSION_LATEST);
	// Keep JIT code during non-shrinking GCs. This brings a quite big performance improvement.
	opt.setPreserveJitCode(true);

	JSAutoRequest rq(m_cx);
	JS::RootedObject globalRootedVal(m_cx, JS_NewGlobalObject(m_cx, &global_class, NULL, JS::OnNewGlobalHookOption::FireOnNewGlobalHook, opt));
	m_comp = JS_EnterCompartment(m_cx, globalRootedVal);
	ok = JS_InitStandardClasses(m_cx, globalRootedVal);
	ENSURE(ok);
	m_glob = globalRootedVal.get();

	JS_DefineProperty(m_cx, m_glob, "global", globalRootedVal, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);

	m_nativeScope = JS_DefineObject(m_cx, m_glob, nativeScopeName, nullptr, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);

	JS_DefineFunction(m_cx, globalRootedVal, "print", ::print,        0, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);
	JS_DefineFunction(m_cx, globalRootedVal, "log",   ::logmsg,       1, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);
	JS_DefineFunction(m_cx, globalRootedVal, "warn",  ::warn,         1, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);
	JS_DefineFunction(m_cx, globalRootedVal, "error", ::error,        1, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);
	JS_DefineFunction(m_cx, globalRootedVal, "deepcopy", ::deepcopy,  1, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);

	Register("ProfileStart", ::ProfileStart, 1);
	Register("ProfileStop", ::ProfileStop, 0);
	Register("ProfileAttribute", ::ProfileAttribute, 1);

	runtime->RegisterContext(m_cx);
}
Exemple #14
0
JSContext*
XPCJSContextStack::InitSafeJSContext()
{
    MOZ_ASSERT(!mSafeJSContext);

    // Start by getting the principal holder and principal for this
    // context.  If we can't manage that, don't bother with the rest.
    nsRefPtr<nsNullPrincipal> principal = new nsNullPrincipal();
    nsresult rv = principal->Init();
    if (NS_FAILED(rv))
        MOZ_CRASH();

    nsXPConnect* xpc = nsXPConnect::XPConnect();
    JSRuntime *rt = xpc->GetRuntime()->Runtime();
    if (!rt)
        MOZ_CRASH();

    mSafeJSContext = JS_NewContext(rt, 8192);
    if (!mSafeJSContext)
        MOZ_CRASH();
    JSAutoRequest req(mSafeJSContext);
    ContextOptionsRef(mSafeJSContext).setNoDefaultCompartmentObject(true);

    JS_SetErrorReporter(mSafeJSContext, xpc::SystemErrorReporter);

    JS::CompartmentOptions options;
    options.setZone(JS::SystemZone)
           .setTrace(TraceXPCGlobal);
    mSafeJSContextGlobal = CreateGlobalObject(mSafeJSContext,
                                              &SafeJSContextGlobalClass,
                                              principal, options);
    if (!mSafeJSContextGlobal)
        MOZ_CRASH();
    JS_AddNamedObjectRoot(mSafeJSContext, &mSafeJSContextGlobal, "SafeJSContext global");

    // Note: make sure to set the private before calling
    // InitClasses
    nsRefPtr<SandboxPrivate> sp = new SandboxPrivate(principal, mSafeJSContextGlobal);
    JS_SetPrivate(mSafeJSContextGlobal, sp.forget().take());

    // After this point either glob is null and the
    // nsIScriptObjectPrincipal ownership is either handled by the
    // nsCOMPtr or dealt with, or we'll release in the finalize
    // hook.
    if (NS_FAILED(xpc->InitClasses(mSafeJSContext, mSafeJSContextGlobal)))
        MOZ_CRASH();

    JS::RootedObject glob(mSafeJSContext, mSafeJSContextGlobal);
    JS_FireOnNewGlobalObject(mSafeJSContext, glob);

    return mSafeJSContext;
}
JSCompartment::JSCompartment(Zone* zone, const JS::CompartmentOptions& options = JS::CompartmentOptions())
  : creationOptions_(options.creationOptions()),
    behaviors_(options.behaviors()),
    zone_(zone),
    runtime_(zone->runtimeFromMainThread()),
    principals_(nullptr),
    isSystem_(false),
    isSelfHosting(false),
    marked(true),
    warnedAboutExprClosure(false),
#ifdef DEBUG
    firedOnNewGlobalObject(false),
#endif
    global_(nullptr),
    enterCompartmentDepth(0),
    performanceMonitoring(runtime_),
    data(nullptr),
    allocationMetadataBuilder(nullptr),
    lastAnimationTime(0),
    regExps(runtime_),
    globalWriteBarriered(0),
    detachedTypedObjects(0),
    objectMetadataState(ImmediateMetadata()),
    propertyTree(thisForCtor()),
    baseShapes(zone, BaseShapeSet()),
    initialShapes(zone, InitialShapeSet()),
    selfHostingScriptSource(nullptr),
    objectMetadataTable(nullptr),
    lazyArrayBuffers(nullptr),
    wasmInstances(zone, WasmInstanceObjectSet()),
    nonSyntacticLexicalScopes_(nullptr),
    gcIncomingGrayPointers(nullptr),
    debugModeBits(0),
    watchpointMap(nullptr),
    scriptCountsMap(nullptr),
    debugScriptMap(nullptr),
    debugScopes(nullptr),
    enumerators(nullptr),
    compartmentStats_(nullptr),
    scheduledForDestruction(false),
    maybeAlive(true),
    jitCompartment_(nullptr),
    mappedArgumentsTemplate_(nullptr),
    unmappedArgumentsTemplate_(nullptr),
    lcovOutput()
{
    PodArrayZero(sawDeprecatedLanguageExtension);
    runtime_->numCompartments++;
    MOZ_ASSERT_IF(creationOptions_.mergeable(),
                  creationOptions_.invisibleToDebugger());
}
JSCompartment::JSCompartment(Zone* zone, const JS::CompartmentOptions& options = JS::CompartmentOptions())
  : options_(options),
    zone_(zone),
    runtime_(zone->runtimeFromMainThread()),
    principals_(nullptr),
    isSystem_(false),
    isSelfHosting(false),
    marked(true),
    warnedAboutNoSuchMethod(false),
    warnedAboutFlagsArgument(false),
    addonId(options.addonIdOrNull()),
#ifdef DEBUG
    firedOnNewGlobalObject(false),
#endif
    global_(nullptr),
    enterCompartmentDepth(0),
    performanceMonitoring(runtime_),
    data(nullptr),
    objectMetadataCallback(nullptr),
    lastAnimationTime(0),
    regExps(runtime_),
    globalWriteBarriered(false),
    neuteredTypedObjects(0),
    objectMetadataState(ImmediateMetadata()),
    propertyTree(thisForCtor()),
    selfHostingScriptSource(nullptr),
    objectMetadataTable(nullptr),
    lazyArrayBuffers(nullptr),
    nonSyntacticLexicalScopes_(nullptr),
    gcIncomingGrayPointers(nullptr),
    gcPreserveJitCode(options.preserveJitCode()),
    debugModeBits(0),
    rngState(0),
    watchpointMap(nullptr),
    scriptCountsMap(nullptr),
    debugScriptMap(nullptr),
    debugScopes(nullptr),
    enumerators(nullptr),
    compartmentStats(nullptr),
    scheduledForDestruction(false),
    maybeAlive(true),
    jitCompartment_(nullptr),
    mappedArgumentsTemplate_(nullptr),
    unmappedArgumentsTemplate_(nullptr),
    lcovOutput()
{
    PodArrayZero(sawDeprecatedLanguageExtension);
    runtime_->numCompartments++;
    MOZ_ASSERT_IF(options.mergeable(), options.invisibleToDebugger());
}
Exemple #17
0
JSContext*
XPCJSContextStack::InitSafeJSContext()
{
    MOZ_ASSERT(!mSafeJSContext);

    // Start by getting the principal holder and principal for this
    // context.  If we can't manage that, don't bother with the rest.
    nsRefPtr<nsNullPrincipal> principal = new nsNullPrincipal();
    nsresult rv = principal->Init();
    if (NS_FAILED(rv))
        MOZ_CRASH();

    nsXPConnect* xpc = nsXPConnect::XPConnect();
    JSRuntime *rt = xpc->GetRuntime()->Runtime();
    if (!rt)
        MOZ_CRASH();

    mSafeJSContext = JS_NewContext(rt, 8192);
    if (!mSafeJSContext)
        MOZ_CRASH();
    JSAutoRequest req(mSafeJSContext);
    ContextOptionsRef(mSafeJSContext).setNoDefaultCompartmentObject(true);

    JS_SetErrorReporter(mSafeJSContext, xpc::SystemErrorReporter);

    // Note - We intentionally avoid firing OnNewGlobalObject while
    // simultaneously skipping the call to setInvisibleToDebugger(true) here.
    // This lets us piggy-back on the assertions in the JS engine (which make
    // sure that, for non-invisible globals, we always fire onNewGlobalObject
    // before creating scripts), to assert that we never create scripts with
    // the SafeJSContextGlobal. This is all happening way before anyone could be
    // listening for debugger notifications anyway.
    JS::CompartmentOptions options;
    options.setZone(JS::SystemZone)
           .setTrace(TraceXPCGlobal);
    mSafeJSContextGlobal = CreateGlobalObject(mSafeJSContext,
                                              &SafeJSContextGlobalClass,
                                              principal, options);
    if (!mSafeJSContextGlobal)
        MOZ_CRASH();

    nsRefPtr<SandboxPrivate> sp = new SandboxPrivate(principal, mSafeJSContextGlobal);
    JS_SetPrivate(mSafeJSContextGlobal, sp.forget().take());
    return mSafeJSContext;
}
static void
CreateGlobalAndRunTest(JSRuntime* rt, JSContext* cx)
{
  static const JSClass GlobalClass = {
    "global", JSCLASS_GLOBAL_FLAGS,
    nullptr, nullptr, nullptr, nullptr,
    nullptr, nullptr, nullptr, nullptr,
    nullptr, nullptr, nullptr,
    JS_GlobalObjectTraceHook
  };

  JS::CompartmentOptions options;
  options.setVersion(JSVERSION_LATEST);
  JS::PersistentRootedObject global(cx);
  global = JS_NewGlobalObject(cx, &GlobalClass, nullptr, JS::FireOnNewGlobalHook, options);
  ASSERT_TRUE(global != nullptr);

  JSCompartment *oldCompartment = JS_EnterCompartment(cx, global);

  typedef Heap<JSObject*> ElementT;

  {
    nsTArray<ElementT>* array = new nsTArray<ElementT>(InitialElements);
    RunTest(rt, cx, array);
    delete array;
  }

  {
    FallibleTArray<ElementT>* array = new FallibleTArray<ElementT>(InitialElements);
    RunTest(rt, cx, array);
    delete array;
  }

  {
    nsAutoTArray<ElementT, InitialElements> array;
    RunTest(rt, cx, &array);
  }

  {
    AutoFallibleTArray<ElementT, InitialElements> array;
    RunTest(rt, cx, &array);
  }

  JS_LeaveCompartment(cx, oldCompartment);
}
Exemple #19
0
int
main(int argc, const char** argv)
{
    if (!JS_Init()) return 1;
    JSContext* cx = checkPtr(JS_NewContext(1024 * 1024));

    JS_SetGCParameter(cx, JSGC_MAX_BYTES, 0xffffffff);
    JS_SetNativeStackQuota(cx, 5000000);

    checkBool(JS::InitSelfHostedCode(cx));
    JS::SetWarningReporter(cx, reportWarning);

    JSAutoRequest ar(cx);

    /* Create the global object. */
    JS::CompartmentOptions options;
    options.behaviors().setVersion(JSVERSION_LATEST);

    RootedObject global(cx, checkPtr(JS_NewGlobalObject(cx, &global_class,
                        nullptr, JS::FireOnNewGlobalHook, options)));
    JSAutoCompartment ac(cx, global);

    /* Populate the global object with the standard globals,
       like Object and Array. */
    checkBool(JS_InitStandardClasses(cx, global));

    argv++;
    while (*argv) {
        const char* name = *argv++;
        GDBFragment* fragment;
        for (fragment = GDBFragment::allFragments; fragment; fragment = fragment->next) {
            if (strcmp(fragment->name(), name) == 0) {
                fragment->run(cx, argv);
                break;
            }
        }
        if (!fragment) {
            fprintf(stderr, "Unrecognized fragment name: %s\n", name);
            exit(1);
        }
    }

    return 0;
}
int
main (int argc, const char **argv)
{
    JSRuntime *runtime = checkPtr(JS_NewRuntime(1024 * 1024, JS_USE_HELPER_THREADS));
    JS_SetGCParameter(runtime, JSGC_MAX_BYTES, 0xffffffff);
    JS_SetNativeStackQuota(runtime, 5000000);

    JSContext *cx = checkPtr(JS_NewContext(runtime, 8192));
    JS_SetErrorReporter(cx, reportError);

    JSAutoRequest ar(cx);

    /* Create the global object. */
    JS::CompartmentOptions options;
    options.setVersion(JSVERSION_LATEST);
    RootedObject global(cx, checkPtr(JS_NewGlobalObject(cx, &global_class, NULL,
                        JS::FireOnNewGlobalHook, options)));
    js::SetDefaultObjectForContext(cx, global);

    JSAutoCompartment ac(cx, global);

    /* Populate the global object with the standard globals,
       like Object and Array. */
    checkBool(JS_InitStandardClasses(cx, global));

    argv++;
    while (*argv) {
        const char *name = *argv++;
        GDBFragment *fragment;
        for (fragment = GDBFragment::allFragments; fragment; fragment = fragment->next) {
            if (strcmp(fragment->name(), name) == 0) {
                fragment->run(cx, argv);
                break;
            }
        }
        if (!fragment) {
            fprintf(stderr, "Unrecognized fragment name: %s\n", name);
            exit(1);
        }
    }

    return 0;
}
Exemple #21
0
JSObject * JSAPITest::createGlobal(JSPrincipals *principals)
{
    /* Create the global object. */
    JS::CompartmentOptions options;
    options.setVersion(JSVERSION_LATEST);
    global = JS_NewGlobalObject(cx, getGlobalClass(), principals, options);
    if (!global)
        return NULL;
    JS_AddNamedObjectRoot(cx, &global, "test-global");
    JS::HandleObject globalHandle = JS::HandleObject::fromMarkedLocation(&global);

    JSAutoCompartment ac(cx, globalHandle);

    /* Populate the global object with the standard globals, like Object and
       Array. */
    if (!JS_InitStandardClasses(cx, globalHandle))
        return NULL;
    return global;
}
Exemple #22
0
JSCompartment::JSCompartment(Zone *zone, const JS::CompartmentOptions &options = JS::CompartmentOptions())
  : options_(options),
    zone_(zone),
    runtime_(zone->runtimeFromMainThread()),
    principals(nullptr),
    isSystem(false),
    isSelfHosting(false),
    marked(true),
#ifdef DEBUG
    firedOnNewGlobalObject(false),
#endif
    global_(nullptr),
    enterCompartmentDepth(0),
    data(nullptr),
    objectMetadataCallback(nullptr),
    lastAnimationTime(0),
    regExps(runtime_),
    typeReprs(runtime_),
    globalWriteBarriered(false),
    propertyTree(thisForCtor()),
    selfHostingScriptSource(nullptr),
    gcIncomingGrayPointers(nullptr),
    gcLiveArrayBuffers(nullptr),
    gcWeakMapList(nullptr),
    debugModeBits(runtime_->debugMode ? DebugFromC : 0),
    rngState(0),
    watchpointMap(nullptr),
    scriptCountsMap(nullptr),
    debugScriptMap(nullptr),
    debugScopes(nullptr),
    enumerators(nullptr),
    compartmentStats(nullptr)
#ifdef JS_ION
    , jitCompartment_(nullptr)
#endif
{
    runtime_->numCompartments++;
    JS_ASSERT_IF(options.mergeable(), options.invisibleToDebugger());
}
Exemple #23
0
JSObject* newDelegate()
{
    static const js::Class delegateClass = {
        "delegate",
        JSCLASS_GLOBAL_FLAGS | JSCLASS_HAS_RESERVED_SLOTS(1),
        nullptr, /* addProperty */
        nullptr, /* delProperty */
        nullptr, /* getProperty */
        nullptr, /* setProperty */
        nullptr, /* enumerate */
        nullptr, /* resolve */
        nullptr, /* mayResolve */
        nullptr, /* convert */
        nullptr, /* finalize */
        nullptr, /* call */
        nullptr, /* hasInstance */
        nullptr, /* construct */
        JS_GlobalObjectTraceHook,
        JS_NULL_CLASS_SPEC,
        {
            nullptr,
            nullptr,
            false,
            nullptr,
            DelegateObjectMoved
        },
        JS_NULL_OBJECT_OPS
    };

    /* Create the global object. */
    JS::CompartmentOptions options;
    options.setVersion(JSVERSION_LATEST);
    JS::RootedObject global(cx);
    global = JS_NewGlobalObject(cx, Jsvalify(&delegateClass), nullptr, JS::FireOnNewGlobalHook,
                                options);
    JS_SetReservedSlot(global, 0, JS::Int32Value(42));

    return global;
}
Exemple #24
0
GlobalObject *
JSRuntime::createSelfHostingGlobal(JSContext *cx)
{
    MOZ_ASSERT(!cx->isExceptionPending());
    MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));

    JS::CompartmentOptions options;
    options.setDiscardSource(true);
    options.setZone(JS::FreshZone);

    JSCompartment *compartment = NewCompartment(cx, nullptr, nullptr, options);
    if (!compartment)
        return nullptr;

    static const Class shgClass = {
        "self-hosting-global", JSCLASS_GLOBAL_FLAGS,
        nullptr, nullptr, nullptr, nullptr,
        nullptr, nullptr, nullptr, nullptr,
        nullptr, nullptr, nullptr,
        JS_GlobalObjectTraceHook
    };

    AutoCompartment ac(cx, compartment);
    Rooted<GlobalObject*> shg(cx, GlobalObject::createInternal(cx, &shgClass));
    if (!shg)
        return nullptr;

    cx->runtime()->selfHostingGlobal_ = shg;
    compartment->isSelfHosting = true;
    compartment->isSystem = true;

    if (!GlobalObject::initSelfHostingBuiltins(cx, shg, intrinsic_functions))
        return nullptr;

    JS_FireOnNewGlobalObject(cx, shg);

    return shg;
}
Exemple #25
0
  nsresult Init()
  {
    mRuntime = JS_NewRuntime(sRuntimeHeapSize, JS_NO_HELPER_THREADS);
    NS_ENSURE_TRUE(mRuntime, NS_ERROR_OUT_OF_MEMORY);

    /*
     * Not setting this will cause JS_CHECK_RECURSION to report false
     * positives
     */
    JS_SetNativeStackQuota(mRuntime, 128 * sizeof(size_t) * 1024); 

    mContext = JS_NewContext(mRuntime, 0);
    NS_ENSURE_TRUE(mContext, NS_ERROR_OUT_OF_MEMORY);

    JSAutoRequest ar(mContext);

    JS::CompartmentOptions options;
    options.setZone(JS::SystemZone)
           .setVersion(JSVERSION_LATEST);
    mGlobal = JS_NewGlobalObject(mContext, &sGlobalClass, nullptr,
                                 JS::DontFireOnNewGlobalHook, options);
    NS_ENSURE_TRUE(mGlobal, NS_ERROR_OUT_OF_MEMORY);
    JS::Rooted<JSObject*> global(mContext, mGlobal);

    JSAutoCompartment ac(mContext, global);
    js::SetDefaultObjectForContext(mContext, global);
    JS_InitStandardClasses(mContext, global);

    JS_SetErrorReporter(mContext, PACErrorReporter);

    if (!JS_DefineFunctions(mContext, global, PACGlobalFunctions))
      return NS_ERROR_FAILURE;

    JS_FireOnNewGlobalObject(mContext, global);

    return NS_OK;
  }
Exemple #26
0
bool
XPCShellEnvironment::Init()
{
    nsresult rv;

    // unbuffer stdout so that output is in the correct order; note that stderr
    // is unbuffered by default
    setbuf(stdout, 0);

    nsCOMPtr<nsIJSRuntimeService> rtsvc =
        do_GetService("@mozilla.org/js/xpc/RuntimeService;1");
    if (!rtsvc) {
        NS_ERROR("failed to get nsJSRuntimeService!");
        return false;
    }

    JSRuntime *rt;
    if (NS_FAILED(rtsvc->GetRuntime(&rt)) || !rt) {
        NS_ERROR("failed to get JSRuntime from nsJSRuntimeService!");
        return false;
    }

    if (!mGlobalHolder.Hold(rt)) {
        NS_ERROR("Can't protect global object!");
        return false;
    }

    AutoSafeJSContext cx;

    JS_SetContextPrivate(cx, this);

    nsCOMPtr<nsIXPConnect> xpc =
      do_GetService(nsIXPConnect::GetCID());
    if (!xpc) {
        NS_ERROR("failed to get nsXPConnect service!");
        return false;
    }

    nsCOMPtr<nsIPrincipal> principal;
    nsCOMPtr<nsIScriptSecurityManager> securityManager =
        do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
    if (NS_SUCCEEDED(rv) && securityManager) {
        rv = securityManager->GetSystemPrincipal(getter_AddRefs(principal));
        if (NS_FAILED(rv)) {
            fprintf(stderr, "+++ Failed to obtain SystemPrincipal from ScriptSecurityManager service.\n");
        }
    } else {
        fprintf(stderr, "+++ Failed to get ScriptSecurityManager service, running without principals");
    }

    nsRefPtr<BackstagePass> backstagePass;
    rv = NS_NewBackstagePass(getter_AddRefs(backstagePass));
    if (NS_FAILED(rv)) {
        NS_ERROR("Failed to create backstage pass!");
        return false;
    }

    JS::CompartmentOptions options;
    options.setZone(JS::SystemZone)
           .setVersion(JSVERSION_LATEST);
    nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
    rv = xpc->InitClassesWithNewWrappedGlobal(cx,
                                              static_cast<nsIGlobalObject *>(backstagePass),
                                              principal, 0,
                                              options,
                                              getter_AddRefs(holder));
    if (NS_FAILED(rv)) {
        NS_ERROR("InitClassesWithNewWrappedGlobal failed!");
        return false;
    }

    JS::Rooted<JSObject*> globalObj(cx, holder->GetJSObject());
    if (!globalObj) {
        NS_ERROR("Failed to get global JSObject!");
        return false;
    }
    JSAutoCompartment ac(cx, globalObj);

    backstagePass->SetGlobalObject(globalObj);

    if (!JS_DefineProperty(cx, globalObj, "__XPCShellEnvironment",
                           PRIVATE_TO_JSVAL(this), JS_PropertyStub,
                           JS_StrictPropertyStub,
                           JSPROP_READONLY | JSPROP_PERMANENT) ||
        !JS_DefineFunctions(cx, globalObj, gGlobalFunctions) ||
        !JS_DefineProfilingFunctions(cx, globalObj))
    {
        NS_ERROR("JS_DefineFunctions failed!");
        return false;
    }

    mGlobalHolder = globalObj;

    FILE* runtimeScriptFile = fopen(kDefaultRuntimeScriptFilename, "r");
    if (runtimeScriptFile) {
        fprintf(stdout, "[loading '%s'...]\n", kDefaultRuntimeScriptFilename);
        ProcessFile(cx, globalObj, kDefaultRuntimeScriptFilename,
                    runtimeScriptFile, false);
        fclose(runtimeScriptFile);
    }

    return true;
}
Exemple #27
0
bool CompileFile(const std::string &inputFilePath, const std::string &outputFilePath) {
    bool result = false;
    std::string ofp;
    if (!outputFilePath.empty()) {
        ofp = outputFilePath;
    }
    else {
        ofp = RemoveFileExt(inputFilePath) + BYTE_CODE_FILE_EXT;
    }
    
    if (!JS_Init())
        return false;
    
    std::cout << "Input file: " << inputFilePath << std::endl;
    JSRuntime * runtime = JS_NewRuntime(10 * 1024 * 1024, JS_NO_HELPER_THREADS);

    JSContext *cx = JS_NewContext(runtime, 10240);
    JS_SetOptions(cx, JSOPTION_TYPE_INFERENCE);
    
    JS::CompartmentOptions options;
    options.setVersion(JSVERSION_LATEST);
    
    JS::RootedObject global(cx, JS_NewGlobalObject(cx, &GlobalClass, NULL, JS::DontFireOnNewGlobalHook, options));
    
    JS_SetErrorReporter(cx, &ReportError);
    
    {
        JSAutoCompartment ac(cx, global);
    
        if (JS_InitStandardClasses(cx, global)) {
            
            JS_InitReflect(cx, global);
            
            JS_FireOnNewGlobalObject(cx, global);
            
            JS::CompileOptions options(cx);
            options.setUTF8(true);
            options.setSourcePolicy(JS::CompileOptions::NO_SOURCE);
            std::cout << "Compiling ..." << std::endl;
            
            JS::RootedScript script(cx, JS::Compile(cx, global, options, inputFilePath.c_str()));
            
            if (script) {
                void *data = NULL;
                uint32_t length = 0;
                std::cout << "Encoding ..." << std::endl;
                data = JS_EncodeScript(cx, script, &length);
                
                if (data) {
                    if (WriteFile(ofp, data, length)) {
                        std::cout << "Done! " << "Output file: " << ofp << std::endl;
                        result = true;
                    }
                }
            }
            else
            {
                std::cout << "Compiled " << inputFilePath << " fails!" << std::endl;
            }
        }
        else
        {
            std::cout << "JS_InitStandardClasses failed! " << std::endl;
        }
    }
    if (cx) {
        JS_DestroyContext(cx);
        cx = NULL;
    }
    if (runtime) {
        JS_DestroyRuntime(runtime);
        runtime = NULL;
    }
    
    JS_ShutDown();
    
    return result;
}
Exemple #28
0
bool
JSRuntime::initSelfHosting(JSContext *cx)
{
    JS_ASSERT(!selfHostingGlobal_);

    if (cx->runtime()->parentRuntime) {
        selfHostingGlobal_ = cx->runtime()->parentRuntime->selfHostingGlobal_;
        return true;
    }

    /*
     * Self hosted state can be accessed from threads for other runtimes
     * parented to this one, so cannot include state in the nursery.
     */
    JS::AutoDisableGenerationalGC disable(cx->runtime());

    JS::CompartmentOptions compartmentOptions;
    compartmentOptions.setDiscardSource(true);
    if (!(selfHostingGlobal_ = JS_NewGlobalObject(cx, &self_hosting_global_class,
                                                  nullptr, JS::DontFireOnNewGlobalHook,
                                                  compartmentOptions)))
        return false;
    JSAutoCompartment ac(cx, selfHostingGlobal_);
    Rooted<GlobalObject*> shg(cx, &selfHostingGlobal_->as<GlobalObject>());
    selfHostingGlobal_->compartment()->isSelfHosting = true;
    selfHostingGlobal_->compartment()->isSystem = true;
    /*
     * During initialization of standard classes for the self-hosting global,
     * all self-hosted functions are ignored. Thus, we don't create cyclic
     * dependencies in the order of initialization.
     */
    if (!GlobalObject::initStandardClasses(cx, shg))
        return false;

    if (!JS_DefineFunctions(cx, shg, intrinsic_functions))
        return false;

    JS_FireOnNewGlobalObject(cx, shg);

    CompileOptions options(cx);
    FillSelfHostingCompileOptions(options);

    /*
     * Set a temporary error reporter printing to stderr because it is too
     * early in the startup process for any other reporter to be registered
     * and we don't want errors in self-hosted code to be silently swallowed.
     */
    JSErrorReporter oldReporter = JS_SetErrorReporter(cx->runtime(), selfHosting_ErrorReporter);
    RootedValue rv(cx);
    bool ok = false;

    char *filename = getenv("MOZ_SELFHOSTEDJS");
    if (filename) {
        RootedScript script(cx);
        if (Compile(cx, shg, options, filename, &script))
            ok = Execute(cx, script, *shg.get(), rv.address());
    } else {
        uint32_t srcLen = GetRawScriptsSize();

        const unsigned char *compressed = compressedSources;
        uint32_t compressedLen = GetCompressedSize();
        ScopedJSFreePtr<char> src(selfHostingGlobal_->zone()->pod_malloc<char>(srcLen));
        if (!src || !DecompressString(compressed, compressedLen,
                                      reinterpret_cast<unsigned char *>(src.get()), srcLen))
        {
            return false;
        }

        ok = Evaluate(cx, shg, options, src, srcLen, &rv);
    }
    JS_SetErrorReporter(cx->runtime(), oldReporter);
    return ok;
}
JSObject *createTestGlobal()
{
    JS::CompartmentOptions options;
    options.setVersion(JSVERSION_LATEST);
    return JS_NewGlobalObject(cx, getGlobalClass(), nullptr, JS::FireOnNewGlobalHook, options);
}
bool
XPCShellEnvironment::Init()
{
    nsresult rv;

    // unbuffer stdout so that output is in the correct order; note that stderr
    // is unbuffered by default
    setbuf(stdout, 0);

    AutoSafeJSContext cx;

    mGlobalHolder.init(cx);

    nsCOMPtr<nsIXPConnect> xpc =
      do_GetService(nsIXPConnect::GetCID());
    if (!xpc) {
        NS_ERROR("failed to get nsXPConnect service!");
        return false;
    }

    nsCOMPtr<nsIPrincipal> principal;
    nsCOMPtr<nsIScriptSecurityManager> securityManager =
        do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
    if (NS_SUCCEEDED(rv) && securityManager) {
        rv = securityManager->GetSystemPrincipal(getter_AddRefs(principal));
        if (NS_FAILED(rv)) {
            fprintf(stderr, "+++ Failed to obtain SystemPrincipal from ScriptSecurityManager service.\n");
        }
    } else {
        fprintf(stderr, "+++ Failed to get ScriptSecurityManager service, running without principals");
    }

    RefPtr<BackstagePass> backstagePass;
    rv = NS_NewBackstagePass(getter_AddRefs(backstagePass));
    if (NS_FAILED(rv)) {
        NS_ERROR("Failed to create backstage pass!");
        return false;
    }

    JS::CompartmentOptions options;
    options.creationOptions().setSystemZone();
    options.behaviors().setVersion(JSVERSION_LATEST);
    if (xpc::SharedMemoryEnabled())
        options.creationOptions().setSharedMemoryAndAtomicsEnabled(true);

    nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
    rv = xpc->InitClassesWithNewWrappedGlobal(cx,
                                              static_cast<nsIGlobalObject *>(backstagePass),
                                              principal, 0,
                                              options,
                                              getter_AddRefs(holder));
    if (NS_FAILED(rv)) {
        NS_ERROR("InitClassesWithNewWrappedGlobal failed!");
        return false;
    }

    JS::Rooted<JSObject*> globalObj(cx, holder->GetJSObject());
    if (!globalObj) {
        NS_ERROR("Failed to get global JSObject!");
        return false;
    }
    JSAutoCompartment ac(cx, globalObj);

    backstagePass->SetGlobalObject(globalObj);

    JS::Rooted<Value> privateVal(cx, PrivateValue(this));
    if (!JS_DefineProperty(cx, globalObj, "__XPCShellEnvironment",
                           privateVal,
                           JSPROP_READONLY | JSPROP_PERMANENT,
                           JS_STUBGETTER, JS_STUBSETTER) ||
        !JS_DefineFunctions(cx, globalObj, gGlobalFunctions) ||
        !JS_DefineProfilingFunctions(cx, globalObj))
    {
        NS_ERROR("JS_DefineFunctions failed!");
        return false;
    }

    mGlobalHolder = globalObj;

    FILE* runtimeScriptFile = fopen(kDefaultRuntimeScriptFilename, "r");
    if (runtimeScriptFile) {
        fprintf(stdout, "[loading '%s'...]\n", kDefaultRuntimeScriptFilename);
        ProcessFile(cx, kDefaultRuntimeScriptFilename,
                    runtimeScriptFile, false);
        fclose(runtimeScriptFile);
    }

    return true;
}