Commit e47c56be authored by Tooru Fujisawa's avatar Tooru Fujisawa
Browse files

Bug 1744176 - Part 1: Support debug metadata in evalStencil and evalStencilXDR. r=nbp

To replace JSScript-based off-thread testing functions with stencil-based
testing functions, support "elements" and "elementAttributeName" options in
`evalStencil` and `evalStencilXDR`.

Differential Revision: https://phabricator.services.mozilla.com/D132873
parent 32695720
Loading
Loading
Loading
Loading
+31 −3
Original line number Diff line number Diff line
@@ -51,7 +51,7 @@
#endif
#include "builtin/Promise.h"
#include "builtin/SelfHostingDefines.h"
#include "builtin/TestingUtility.h"        // js::ParseCompileOptions
#include "builtin/TestingUtility.h"  // js::ParseCompileOptions, js::ParseDebugMetadata
#include "frontend/BytecodeCompilation.h"  // frontend::CanLazilyParse,
// frontend::CompileGlobalScriptToExtensibleStencil,
// frontend::DelazifyCanonicalScriptedFunction
@@ -6259,6 +6259,8 @@ static bool EvalStencil(JSContext* cx, uint32_t argc, Value* vp) {

  CompileOptions options(cx);
  UniqueChars fileNameBytes;
  Rooted<JS::Value> privateValue(cx);
  Rooted<JSString*> elementAttributeName(cx);
  if (args.length() == 2) {
    if (!args[1].isObject()) {
      JS_ReportErrorASCII(cx,
@@ -6271,6 +6273,10 @@ static bool EvalStencil(JSContext* cx, uint32_t argc, Value* vp) {
    if (!js::ParseCompileOptions(cx, options, opts, &fileNameBytes)) {
      return false;
    }
    if (!js::ParseDebugMetadata(cx, opts, &privateValue,
                                &elementAttributeName)) {
      return false;
    }
  }

  if (stencilObj->stencil()->canLazilyParse !=
@@ -6294,8 +6300,16 @@ static bool EvalStencil(JSContext* cx, uint32_t argc, Value* vp) {
    return false;
  }

  /* Obtain the JSScript and evaluate it. */
  RootedScript script(cx, output.get().script);

  if (!privateValue.isUndefined() || elementAttributeName) {
    JS::InstantiateOptions instantiateOptions(options);
    if (!JS::UpdateDebugMetadata(cx, script, instantiateOptions, privateValue,
                                 elementAttributeName, nullptr, nullptr)) {
      return false;
    }
  }

  RootedValue retVal(cx);
  if (!JS_ExecuteScript(cx, script, &retVal)) {
    return false;
@@ -6409,6 +6423,8 @@ static bool EvalStencilXDR(JSContext* cx, uint32_t argc, Value* vp) {

  CompileOptions options(cx);
  UniqueChars fileNameBytes;
  Rooted<JS::Value> privateValue(cx);
  Rooted<JSString*> elementAttributeName(cx);
  if (args.length() == 2) {
    if (!args[1].isObject()) {
      JS_ReportErrorASCII(cx,
@@ -6421,6 +6437,10 @@ static bool EvalStencilXDR(JSContext* cx, uint32_t argc, Value* vp) {
    if (!js::ParseCompileOptions(cx, options, opts, &fileNameBytes)) {
      return false;
    }
    if (!js::ParseDebugMetadata(cx, opts, &privateValue,
                                &elementAttributeName)) {
      return false;
    }
  }

  /* Prepare the CompilationStencil for decoding. */
@@ -6456,8 +6476,16 @@ static bool EvalStencilXDR(JSContext* cx, uint32_t argc, Value* vp) {
    return false;
  }

  /* Obtain the JSScript and evaluate it. */
  RootedScript script(cx, output.get().script);

  if (!privateValue.isUndefined() || elementAttributeName) {
    JS::InstantiateOptions instantiateOptions(options);
    if (!JS::UpdateDebugMetadata(cx, script, instantiateOptions, privateValue,
                                 elementAttributeName, nullptr, nullptr)) {
      return false;
    }
  }

  RootedValue retVal(cx, UndefinedValue());
  if (!JS_ExecuteScript(cx, script, &retVal)) {
    return false;
+59 −2
Original line number Diff line number Diff line
@@ -8,13 +8,15 @@

#include <stdint.h>  // uint32_t

#include "jsapi.h"                 // JS_NewPlainObject, JS_WrapValue
#include "js/CharacterEncoding.h"  // JS_EncodeStringToLatin1
#include "js/CompileOptions.h"     // JS::CompileOptions
#include "js/Conversions.h"  // JS::ToBoolean, JS::ToString, JS::ToUint32, JS::ToInt32
#include "js/PropertyAndElement.h"  // JS_GetProperty
#include "js/PropertyAndElement.h"  // JS_GetProperty, JS_DefineProperty
#include "js/PropertyDescriptor.h"  // JSPROP_ENUMERATE
#include "js/RootingAPI.h"          // JS::Rooted, JS::Handle
#include "js/Utility.h"             // JS::UniqueChars
#include "js/Value.h"               // JS::Value
#include "js/Value.h"               // JS::Value, JS::StringValue
#include "vm/JSContext.h"           // JSContext
#include "vm/JSObject.h"            // JSObject
#include "vm/StringType.h"          // JSString
@@ -156,3 +158,58 @@ bool js::SetSourceOptions(JSContext* cx, ScriptSource* source,

  return true;
}

JSObject* js::CreateScriptPrivate(JSContext* cx,
                                  JS::Handle<JSString*> path /* = nullptr */) {
  JS::Rooted<JSObject*> info(cx, JS_NewPlainObject(cx));
  if (!info) {
    return nullptr;
  }

  if (path) {
    JS::Rooted<JS::Value> pathValue(cx, JS::StringValue(path));
    if (!JS_DefineProperty(cx, info, "path", pathValue, JSPROP_ENUMERATE)) {
      return nullptr;
    }
  }

  return info;
}

bool js::ParseDebugMetadata(JSContext* cx, JS::Handle<JSObject*> opts,
                            JS::MutableHandle<JS::Value> privateValue,
                            JS::MutableHandle<JSString*> elementAttributeName) {
  JS::Rooted<JS::Value> v(cx);
  JS::Rooted<JSString*> s(cx);

  if (!JS_GetProperty(cx, opts, "element", &v)) {
    return false;
  }
  if (v.isObject()) {
    JS::Rooted<JSObject*> infoObject(cx, CreateScriptPrivate(cx));
    if (!infoObject) {
      return false;
    }
    JS::Rooted<JS::Value> elementValue(cx, v);
    if (!JS_WrapValue(cx, &elementValue)) {
      return false;
    }
    if (!JS_DefineProperty(cx, infoObject, "element", elementValue, 0)) {
      return false;
    }
    privateValue.set(ObjectValue(*infoObject));
  }

  if (!JS_GetProperty(cx, opts, "elementAttributeName", &v)) {
    return false;
  }
  if (!v.isUndefined()) {
    s = ToString(cx, v);
    if (!s) {
      return false;
    }
    elementAttributeName.set(s);
  }

  return true;
}
+8 −0
Original line number Diff line number Diff line
@@ -46,6 +46,14 @@ class ScriptSource;
                                    JS::Handle<JSString*> displayURL,
                                    JS::Handle<JSString*> sourceMapURL);

JSObject* CreateScriptPrivate(JSContext* cx,
                              JS::Handle<JSString*> path = nullptr);

[[nodiscard]] bool ParseDebugMetadata(
    JSContext* cx, JS::Handle<JSObject*> opts,
    JS::MutableHandle<JS::Value> privateValue,
    JS::MutableHandle<JSString*> elementAttributeName);

} /* namespace js */

#endif /* builtin_TestingUtility_h */
+2 −1
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@
#include "jsapi.h"
#include "NamespaceImports.h"

#include "builtin/TestingUtility.h"  // js::CreateScriptPrivate
#include "js/MapAndSet.h"
#include "js/Modules.h"
#include "js/PropertyAndElement.h"  // JS_DefineProperty, JS_GetProperty
@@ -406,7 +407,7 @@ JSObject* ModuleLoader::loadAndParse(JSContext* cx, HandleString pathArg) {
    return nullptr;
  }

  RootedObject info(cx, CreateScriptPrivate(cx, path));
  RootedObject info(cx, js::CreateScriptPrivate(cx, path));
  if (!info) {
    return nullptr;
  }
+2 −56
Original line number Diff line number Diff line
@@ -73,7 +73,7 @@
#include "builtin/ModuleObject.h"
#include "builtin/RegExp.h"
#include "builtin/TestingFunctions.h"
#include "builtin/TestingUtility.h"  // js::ParseCompileOptions
#include "builtin/TestingUtility.h"  // js::ParseCompileOptions, js::ParseDebugMetadata, js::CreateScriptPrivate
#include "debugger/DebugAPI.h"
#include "frontend/BytecodeCompilation.h"
#include "frontend/BytecodeCompiler.h"
@@ -972,22 +972,6 @@ void EnvironmentPreparer::invoke(HandleObject global, Closure& closure) {
  }
}

JSObject* js::shell::CreateScriptPrivate(JSContext* cx, HandleString path) {
  RootedObject info(cx, JS_NewPlainObject(cx));
  if (!info) {
    return nullptr;
  }

  if (path) {
    RootedValue pathValue(cx, StringValue(path));
    if (!JS_DefineProperty(cx, info, "path", pathValue, JSPROP_ENUMERATE)) {
      return nullptr;
    }
  }

  return info;
}

static bool RegisterScriptPathWithModuleLoader(JSContext* cx,
                                               HandleScript script,
                                               const char* filename) {
@@ -1001,7 +985,7 @@ static bool RegisterScriptPathWithModuleLoader(JSContext* cx,
  }

  MOZ_ASSERT(JS::GetScriptPrivate(script).isUndefined());
  RootedObject infoObject(cx, CreateScriptPrivate(cx, path));
  RootedObject infoObject(cx, js::CreateScriptPrivate(cx, path));
  if (!infoObject) {
    return false;
  }
@@ -2000,44 +1984,6 @@ static bool LoadScriptRelativeToScript(JSContext* cx, unsigned argc,
  return LoadScript(cx, argc, vp, true);
}

static bool ParseDebugMetadata(JSContext* cx, HandleObject opts,
                               MutableHandleValue privateValue,
                               MutableHandleString elementAttributeName) {
  RootedValue v(cx);
  RootedString s(cx);

  if (!JS_GetProperty(cx, opts, "element", &v)) {
    return false;
  }
  if (v.isObject()) {
    RootedObject infoObject(cx, CreateScriptPrivate(cx));
    if (!infoObject) {
      return false;
    }
    RootedValue elementValue(cx, v);
    if (!JS_WrapValue(cx, &elementValue)) {
      return false;
    }
    if (!JS_DefineProperty(cx, infoObject, "element", elementValue, 0)) {
      return false;
    }
    privateValue.set(ObjectValue(*infoObject));
  }

  if (!JS_GetProperty(cx, opts, "elementAttributeName", &v)) {
    return false;
  }
  if (!v.isUndefined()) {
    s = ToString(cx, v);
    if (!s) {
      return false;
    }
    elementAttributeName.set(s);
  }

  return true;
}

static void my_LargeAllocFailCallback() {
  JSContext* cx = TlsContext.get();
  if (!cx || cx->isHelperThreadContext()) {
Loading