Skip to content

Commit 6e6adc8

Browse files
committed
fix(module): build the optional-module placeholder without string interpolation
1 parent 380b915 commit 6e6adc8

1 file changed

Lines changed: 49 additions & 31 deletions

File tree

NativeScript/runtime/ModuleInternal.mm

Lines changed: 49 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1648,44 +1648,62 @@ throw NativeScriptException(
16481648
// Create a module object with exports that throws when accessed
16491649
Local<Object> moduleObj = Object::New(isolate);
16501650

1651-
// Create a Proxy that throws an error when any property is accessed
1651+
// Create a Proxy that throws an error when any property is accessed.
1652+
//
1653+
// The message is passed to a constant factory script as a real V8 string
1654+
// (never interpolated into the script source). Interpolation is a JS
1655+
// injection hazard: the message itself contains single quotes
1656+
// ("Module 'zip' is not available...") which terminated the string literal
1657+
// early and made the generated script a guaranteed SyntaxError
1658+
// ("missing ) after argument list") that propagated out of require() with
1659+
// no hint of its origin.
16521660
std::string errorMessage =
16531661
"Module '" + moduleName + "' is not available. This is an optional module.";
1654-
std::string proxyCode = "(function() {"
1655-
" const error = new Error('" +
1656-
errorMessage +
1657-
"');"
1658-
" return new Proxy({}, {"
1659-
" get: function(target, prop) {"
1660-
" throw error;"
1661-
" },"
1662-
" set: function(target, prop, value) {"
1663-
" throw error;"
1664-
" },"
1665-
" has: function(target, prop) {"
1666-
" return false;"
1667-
" },"
1668-
" ownKeys: function(target) {"
1669-
" return [];"
1670-
" },"
1671-
" getPrototypeOf: function(target) {"
1672-
" return null;"
1673-
" }"
1674-
" });"
1675-
"})()";
1662+
static const char* kProxyFactorySource = "(function(msg) {"
1663+
" const error = new Error(msg);"
1664+
" return new Proxy({}, {"
1665+
" get: function(target, prop) {"
1666+
" throw error;"
1667+
" },"
1668+
" set: function(target, prop, value) {"
1669+
" throw error;"
1670+
" },"
1671+
" has: function(target, prop) {"
1672+
" return false;"
1673+
" },"
1674+
" ownKeys: function(target) {"
1675+
" return [];"
1676+
" },"
1677+
" getPrototypeOf: function(target) {"
1678+
" return null;"
1679+
" }"
1680+
" });"
1681+
"})";
16761682

1683+
TryCatch tc(isolate);
16771684
Local<Script> proxyScript;
1678-
if (Script::Compile(context, tns::ToV8String(isolate, proxyCode.c_str())).ToLocal(&proxyScript)) {
1679-
Local<Value> proxyObject;
1680-
if (proxyScript->Run(context).ToLocal(&proxyObject)) {
1681-
// Set the exports to the proxy object
1682-
bool success = moduleObj->Set(context, tns::ToV8String(isolate, "exports"), proxyObject)
1683-
.FromMaybe(false);
1684-
if (!success) {
1685-
Log(@"Warning: Failed to set exports property on proxy module object");
1685+
if (Script::Compile(context, tns::ToV8String(isolate, kProxyFactorySource)).ToLocal(&proxyScript)) {
1686+
Local<Value> factoryValue;
1687+
if (proxyScript->Run(context).ToLocal(&factoryValue) && factoryValue->IsFunction()) {
1688+
Local<Value> args[]{tns::ToV8String(isolate, errorMessage.c_str())};
1689+
Local<Value> proxyObject;
1690+
if (factoryValue.As<v8::Function>()
1691+
->Call(context, v8::Undefined(isolate), 1, args)
1692+
.ToLocal(&proxyObject)) {
1693+
// Set the exports to the proxy object
1694+
bool success = moduleObj->Set(context, tns::ToV8String(isolate, "exports"), proxyObject)
1695+
.FromMaybe(false);
1696+
if (!success) {
1697+
Log(@"Warning: Failed to set exports property on proxy module object");
1698+
}
16861699
}
16871700
}
16881701
}
1702+
if (tc.HasCaught()) {
1703+
// The placeholder is best-effort. Never let its construction machinery
1704+
// leak an exception that masks the real "module not found" condition.
1705+
Log(@"Warning: placeholder module construction failed for %s", moduleName.c_str());
1706+
}
16891707

16901708
// Set up the module object
16911709
bool success = moduleObj

0 commit comments

Comments
 (0)