diff --git a/NativeScript/runtime/MetadataBuilder.mm b/NativeScript/runtime/MetadataBuilder.mm index fd4728560..d75d97aa6 100644 --- a/NativeScript/runtime/MetadataBuilder.mm +++ b/NativeScript/runtime/MetadataBuilder.mm @@ -117,9 +117,12 @@ NamedPropertyHandlerConfiguration config(MetadataBuilder::GlobalPropertyGetter, const FunctionMeta* funcMeta = static_cast(meta); void* functionPointer = SymbolLoader::instance().loadFunctionSymbol(meta->topLevelModule(), meta->name()); + // Metadata can list functions the running OS or linked binary doesn't export + // (newer SDK, weak-linked or stripped symbol); expose those as undefined so + // `typeof fn === "undefined"` works as feature detection. if (functionPointer == nullptr) { Log(@"Unable to load \"%s\" function", meta->name()); - tns::Assert(false, isolate); + return v8::Intercepted::kNo; } CacheItem* item = diff --git a/TestFixtures/Functions/TNSFunctions.h b/TestFixtures/Functions/TNSFunctions.h index 72d483d2c..dba6339d8 100644 --- a/TestFixtures/Functions/TNSFunctions.h +++ b/TestFixtures/Functions/TNSFunctions.h @@ -1 +1,5 @@ CFArrayRef CFArrayCreateWithString(CFStringRef string); + +// Declared for the metadata generator but intentionally left undefined, so the +// symbol is listed in metadata yet absent at runtime. +void TNSFunctionMissingAtRuntime(void); diff --git a/TestRunner/app/tests/ApiTests.js b/TestRunner/app/tests/ApiTests.js index d862b8554..ddd27494d 100644 --- a/TestRunner/app/tests/ApiTests.js +++ b/TestRunner/app/tests/ApiTests.js @@ -12,6 +12,13 @@ describe(module.id, function () { expect(object.hash).toBe(3); }); + it("exposes a C function listed in metadata but missing at runtime as undefined", function () { + expect(typeof TNSFunctionMissingAtRuntime).toBe("undefined"); + expect(global.TNSFunctionMissingAtRuntime).toBeUndefined(); + expect("TNSFunctionMissingAtRuntime" in global).toBe(false); + expect(function () { TNSFunctionMissingAtRuntime(); }).toThrowError(ReferenceError); + }); + it("preserves a lone high surrogate when bridging a JS string to NSString", function () { // A lone high surrogate (U+D834, range U+D800-U+DBFF) is a valid JS string // code unit but has no UTF-8 encoding. The old UTF-8 round-trip replaced it