Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,7 @@ v8_build
/project-template-ios/.build_env_vars.sh
/project-template-ios/__PROJECT_NAME__.xcodeproj/project.xcworkspace/xcshareddata/
/project-template-vision/.build_env_vars.sh
/project-template-vision/__PROJECT_NAME__.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
/project-template-vision/__PROJECT_NAME__.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist

# test262
dist-test/
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@
path = libffi
url = https://github.com/NativeScript/libffi.git
branch = darind/v8-ios
[submodule "TestRunner/app/tests/vendor/test262"]
path = TestRunner/app/tests/vendor/test262
url = https://github.com/tc39/test262.git
16 changes: 10 additions & 6 deletions NativeScript/inspector/JsV8InspectorClient.mm
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@

namespace v8_inspector {

namespace {
StringView Make8BitStringView(const std::string& value) {
return StringView(reinterpret_cast<const uint8_t*>(value.data()),
value.size());
}
} // namespace

#define NOTIFICATION(name) \
[[NSString stringWithFormat:@"%@:NativeScript.Debug.%s", \
[[NSBundle mainBundle] bundleIdentifier], name] UTF8String]
Expand Down Expand Up @@ -257,8 +264,7 @@
}

void JsV8InspectorClient::dispatchMessage(const std::string& message) {
std::vector<uint16_t> vector = tns::ToVector(message);
StringView messageView(vector.data(), vector.size());
StringView messageView = Make8BitStringView(message);
Isolate* isolate = isolate_;
v8::Locker locker(isolate);
Isolate::Scope isolate_scope(isolate);
Expand Down Expand Up @@ -343,8 +349,7 @@
auto returnString = GetReturnMessageFromDomainHandlerResult(result, requestId);

if (returnString.size() > 0) {
std::vector<uint16_t> vector = tns::ToVector(returnString);
StringView messageView(vector.data(), vector.size());
StringView messageView = Make8BitStringView(returnString);
auto msg = StringBuffer::create(messageView);
this->sendNotification(std::move(msg));
}
Expand Down Expand Up @@ -486,8 +491,7 @@
Local<v8::String> arg = args[0].As<v8::String>();
std::string message = tns::ToString(isolate, arg);

std::vector<uint16_t> vector = tns::ToVector(message);
StringView messageView(vector.data(), vector.size());
StringView messageView = Make8BitStringView(message);
auto msg = StringBuffer::create(messageView);
client->sendNotification(std::move(msg));
}
Expand Down
2 changes: 1 addition & 1 deletion NativeScript/inspector/src/inspector/string-16.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

namespace v8_inspector {

using UChar = uint16_t;
using UChar = char16_t;

class String16 {
public:
Expand Down
4 changes: 2 additions & 2 deletions NativeScript/inspector/src/inspector/string-util.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@ class StringUtil {
}

static String fromUTF16LE(const uint16_t* data, size_t length) {
return String16::fromUTF16LE(data, length);
return String16::fromUTF16LE(reinterpret_cast<const UChar*>(data), length);
}

static const uint8_t* CharactersLatin1(const String& s) { return nullptr; }
static const uint8_t* CharactersUTF8(const String& s) { return nullptr; }
static const uint16_t* CharactersUTF16(const String& s) {
return s.characters16();
return reinterpret_cast<const uint16_t*>(s.characters16());
}
static size_t CharacterCount(const String& s) { return s.length(); }
};
Expand Down
9 changes: 4 additions & 5 deletions NativeScript/inspector/utils.mm
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,16 @@
}

std::string v8_inspector::ToStdString(const StringView& value) {
std::vector<uint16_t> buffer(value.length());
std::u16string value16;
value16.resize(value.length());
for (size_t i = 0; i < value.length(); i++) {
if (value.is8Bit()) {
buffer[i] = value.characters8()[i];
value16[i] = static_cast<char16_t>(value.characters8()[i]);
} else {
buffer[i] = value.characters16()[i];
value16[i] = static_cast<char16_t>(value.characters16()[i]);
}
}

std::u16string value16(buffer.begin(), buffer.end());

#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
// FIXME: std::codecvt_utf8_utf16 is deprecated
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
Expand Down
5 changes: 5 additions & 0 deletions NativeScript/runtime/ModuleInternal.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ class ModuleInternal {
void RunScript(v8::Isolate* isolate, std::string script);
static v8::Local<v8::Value> LoadScript(v8::Isolate* isolate,
const std::string& path);
static v8::Local<v8::Value> LoadSourceTextModule(v8::Isolate* isolate,
const std::string& path);

private:
static void RequireCallback(const v8::FunctionCallbackInfo<v8::Value>& info);
Expand All @@ -28,6 +30,9 @@ class ModuleInternal {
// Compile/link/evaluate an ES module; returns its namespace object.
static v8::Local<v8::Value> LoadESModule(v8::Isolate* isolate,
const std::string& path);
static v8::Local<v8::Value> LoadESModule(v8::Isolate* isolate,
const std::string& path,
bool suppressInDebug);
static v8::Local<v8::String> WrapModuleContent(v8::Isolate* isolate,
const std::string& path);
v8::Local<v8::Object> LoadModule(v8::Isolate* isolate,
Expand Down
56 changes: 49 additions & 7 deletions NativeScript/runtime/ModuleInternal.mm
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,36 @@ bool IsESModule(const std::string& path) {
return std::string([standardized UTF8String]);
}

static bool ShouldTreatAsForcedSourceTextModule(v8::Isolate* isolate,
const std::string& path) {
v8::Local<v8::Context> context = isolate->GetCurrentContext();
v8::Local<v8::Object> global = context->Global();

v8::Local<v8::Value> enabledValue;
if (!global->Get(context, tns::ToV8String(isolate, "__test262ForceModule"))
.ToLocal(&enabledValue) ||
!enabledValue->BooleanValue(isolate)) {
return false;
}

v8::Local<v8::Value> rootValue;
if (!global->Get(context, tns::ToV8String(isolate, "__test262ModuleRoot"))
.ToLocal(&rootValue) ||
rootValue.IsEmpty() || !rootValue->IsString()) {
return false;
}

std::string root = NormalizePath(tns::ToString(isolate, rootValue));
std::string normalizedPath = NormalizePath(path);
if (root.empty() || normalizedPath.size() < root.size() ||
normalizedPath.compare(0, root.size(), root) != 0) {
return false;
}

return normalizedPath.size() >= 3 &&
normalizedPath.compare(normalizedPath.size() - 3, 3, ".js") == 0;
}

// Helper function to resolve main entry from package.json with proper extension handling
std::string ResolveMainEntryFromPackageJson(const std::string& baseDir) {
// Get the main value from package.json
Expand Down Expand Up @@ -708,7 +738,7 @@ throw NativeScriptException(isolate,

if (IsESModule(canonicalPath)) {
// Treat all .mjs files as standard ES modules.
return ModuleInternal::LoadESModule(isolate, canonicalPath);
return ModuleInternal::LoadESModule(isolate, canonicalPath, true);
}

Local<Script> script = ModuleInternal::LoadClassicScript(isolate, canonicalPath);
Expand Down Expand Up @@ -778,6 +808,11 @@ throw NativeScriptException(isolate,
return result;
}

Local<Value> ModuleInternal::LoadSourceTextModule(Isolate* isolate,
const std::string& path) {
return ModuleInternal::LoadESModule(isolate, NormalizePath(path), false);
}

Local<Script> ModuleInternal::LoadClassicScript(Isolate* isolate, const std::string& path) {
std::string canonicalPath = NormalizePath(path);

Expand Down Expand Up @@ -848,6 +883,11 @@ ScriptOrigin origin(isolate, urlString,
}

Local<Value> ModuleInternal::LoadESModule(Isolate* isolate, const std::string& path) {
return ModuleInternal::LoadESModule(isolate, path, true);
}

Local<Value> ModuleInternal::LoadESModule(Isolate* isolate, const std::string& path,
bool suppressInDebug) {
std::string canonicalPath = NormalizePath(path);
auto context = isolate->GetCurrentContext();

Expand Down Expand Up @@ -910,7 +950,7 @@ ScriptOrigin origin(isolate, urlString, 0, 0, false, -1, Local<Value>(), false,
}
logPhase("compile", "fail", classification);
// V8 threw a syntax error or similar
if (RuntimeConfig.IsDebug) {
if (RuntimeConfig.IsDebug && suppressInDebug) {
// Log the detailed JavaScript error with full stack trace
Log(@"***** JavaScript exception occurred *****");
Log(@"Error compiling ES module: %s", canonicalPath.c_str());
Expand Down Expand Up @@ -969,7 +1009,7 @@ ScriptOrigin origin(isolate, urlString, 0, 0, false, -1, Local<Value>(), false,
}
}
logPhase("instantiate", "fail", classification);
if (RuntimeConfig.IsDebug) {
if (RuntimeConfig.IsDebug && suppressInDebug) {
// Log the detailed JavaScript error with full stack trace
Log(@"***** JavaScript exception occurred *****");
Log(@"Error instantiating module: %s", canonicalPath.c_str());
Expand Down Expand Up @@ -1013,7 +1053,7 @@ ScriptOrigin origin(isolate, urlString, 0, 0, false, -1, Local<Value>(), false,
}
}
logPhase("evaluate", "fail", classification);
if (RuntimeConfig.IsDebug) {
if (RuntimeConfig.IsDebug && suppressInDebug) {
// Log the detailed JavaScript error with full stack trace
Log(@"***** JavaScript exception occurred *****");
Log(@"Error evaluating ES module: %s", canonicalPath.c_str());
Expand Down Expand Up @@ -1204,14 +1244,16 @@ ScriptOrigin origin(isolate, urlString, 0, 0, false, -1, Local<Value>(), false,
std::shared_ptr<Caches> cache = Caches::Get(isolate);
bool isWorkerContext = cache && cache->isWorker;

// Check if this is an .mjs file but NOT a .mjs.map file
if (IsESModule(path)) {
bool isForcedSourceTextModule = ShouldTreatAsForcedSourceTextModule(isolate, path);

// Check if this is an ES module path or a forced source-text module path.
if (IsESModule(path) || isForcedSourceTextModule) {
// Read raw text without wrapping.
std::string sourceText = tns::ReadText(path);

// For ES modules in worker context, we need to provide access to global objects
// since ES modules run in their own scope
if (isWorkerContext) {
if (isWorkerContext && !isForcedSourceTextModule) {
// Prepend global declarations to make worker globals available in ES module scope
std::string globalDeclarations = "const self = globalThis.self || globalThis;\n"
"const postMessage = globalThis.postMessage;\n"
Expand Down
Loading
Loading