Repository navigation
@lucent-lang/lucent@0.1.0
Minor Changes
-
#13
9031f4eThanks @Fausto95! - Give Android code the app's Activities.lucent:androidaddscurrentActivity()(the Activity in front, or null; Lucent holds Activities weakly),startActivityForResult(intent, signal?)andrequestPermissions(permissions, signal?)(promises settled once with the answer; aborting forgets the request, and a late answer is dropped), andonActivityEvent(event, handler)for the Activities' lifecycle and new intents. Requests go through a translucent Activity of Lucent's, so they work with any app Activity and survive it being recreated meanwhile. The native package's manifest declares it and a provider that starts tracking Activities with the process. Package manifest components may now set an activity'sthemeandconfigChanges. -
#13
9031f4eThanks @Fausto95! - Supportbigint: literals, every operator JavaScript has for it,BigInt(),BigInt.asIntNandasUintN,Number()andString()of a bigint, and bigints in collections, objects, classes, unions and async code. Values of any size cross the JavaScript boundary exactly, and loose==between a bigint and a number or string, which converts in JavaScript, is reported as LUCENT1002. -
#13
9031f4eThanks @Fausto95! - Turn callback APIs, such as a native listener, into promises and subscriptions withfromCallbackandsubscribefromlucent:core: each settles once, whichever callback or abort comes first, and runs the cleanup you return exactly once. -
#13
9031f4eThanks @Fausto95! - Say exactly what the app needs after a build.lucent buildlistsactions(also in--jsonand the build record): recompile native code, reload JavaScript, repackage resources, relink native dependencies or reinstall the app, each with its platforms and the files behind it. They come from what the build changed: a body edit recompiles, new exports also reload JavaScript, a package's resources are repackaged.lucent devnow watches Lucent packages outside the app (workspace or linked) whole, including theirlucent.jsonand native files, never rebuilds for what builds write, and stops a build a newer change made stale before it writes anything. Generated files are replaced whole, so Metro never reads half a proxy. Package files are hashed once while their size and times hold, and lucent build no longer starts a second Gradle run while another one resolves the classpath. -
#13
9031f4eThanks @Fausto95! - Run heavy work on worker threads withcompute(task, input, { signal })fromlucent:core. The task is a function declared at the top level of a module, taking one parameter, and runs on a bounded pool of workers without a second JavaScript runtime; the promise settles on the calling thread. The compiler checks everything the task runs (no module state, no main-thread or unknown native code, no function values it cannot follow, nothing asynchronous: LUCENT3011) and that its input and result are data (LUCENT3012), naming the path to what breaks the rule. The input is copied whencomputeis called, keeping aliases and cycles; aborting the signal rejects the promise at once, and a running task stops at the next iteration of a loop in the task or in a module function it calls (loops in closures, methods and generic functions, and native calls, run to their end first). The JavaScript version in@lucent-lang/lucent/corebehaves the same on the calling thread, for tests. -
#13
9031f4eThanks @Fausto95! - Recognize components: an exported function of a.lucent.tsxmodule that returns a platform view (a UIKitUIView, an AndroidView, or a subclass). React can't render them yet. Lucent now checks them and leaves them out of the module's JavaScript. It checks that the view comes back on every path, from one props object of plain data, with callback props namedon…that return nothing, and that setup code can run on the main thread. The new diagnostics areLUCENT3020toLUCENT3023.compile()lists each component undercomponents, identified by package, module path and export name. -
#13
9031f4eThanks @Fausto95! - Check iOS availability as Android's is checked: an Objective-C or Swift API newer than iOS 15.1 must be used underavailable("ios", major, minor?)(in anif, after an early exit, or in?:/&&), or the build fails with LUCENT3007 instead of crashing on older devices. Swift shims are marked@availablefrom what they call, so they compile against the deployment target. -
#13
9031f4eThanks @Fausto95! - Lucent classes can extend Objective-C classes on iOS, as they extend SDK classes on Android:class Greeting extends UIViewControlleris made with the base initializersuper(…)names, its methods override the base's (UIKit callingviewDidLoadruns the Lucent one),super.viewDidLoad()calls UIKit's, and inherited members such asthis.viewwork on the instance, which passes wherever the base type is taken. A generated Objective-C subclass stands for each instance; it and the Lucent object keep each other alive while either side uses them, without a cycle. Subclasses of main-thread classes are used on the main thread. -
#13
9031f4eThanks @Fausto95! - Native 64-bit integers are bigints: Java'slong(long[]asbigint[]),int64_t,uint64_t,NSInteger,NSUIntegerand Swift'sInt,Int64andUInt64, in arguments, results, properties, struct fields,Outs, callbacks and constants. Every native value is exact,NSNotFoundandLong.MAX_VALUEincluded, and a bigint the native type cannot hold throwsRangeErrornaming the parameter or field. Enums, option sets and@IntDef/@LongDefgroups stay numbers. Code that passes numbers to these APIs must pass bigints now (1000n,BigInt(n)), andNumber(list.count)turns a count or index back into a number. -
#13
9031f4eThanks @Fausto95! - Hand bytes between Lucent, compute tasks and JavaScript without copying them, withNativeBufferfromlucent:core.NativeBuffer.allocate(size)andNativeBuffer.from(bytes)make one;withRead(read)andwithWrite(write)lend a callback the bytes for one call as a span with aUint8Array's element semantics (reads share the buffer, a write needs it to itself, a conflicting borrow throws anInvalidStateError);transfer(), or passing the buffer tocompute, moves the bytes to a new owner and leaves every reference to the old buffer refusing them;toUint8Array()andfromare the only copies, andNativeBuffer.stats()counts them. The compiler keeps a span inside its callback (LUCENT3030: not returned, stored, captured by a closure that outlives the call, kept by a callee or held acrossawait) and reports a buffer used after it certainly moved (LUCENT3031). JavaScript receives a buffer as an opaque handle with the same methods, whose borrows lend it a copy, so it never holds memory a worker may be writing.Uint8Arraykeeps its copy semantics. -
#13
9031f4eThanks @Fausto95! - Add typed native extensions. A Lucent package declares one inlucent.json(extensions.<name>): a C header in native sources both platforms build, the opaque structs Lucent code holds as handles (their create, destroy, methods and thread), what pointer parameters are (bytes with their length, a UTF-8 string, an error struct) and how results report failure.lucent buildreads the header with clang, checks every name and shape against it, and fails naming the package and the field when they disagree. Lucent code, shared code included, imports the handles as classes and the functions by their C names fromlucent:ext/<name>: handles close once (close(),using, or their last reference), throwInvalidStateErrorafter, and cannot cross to JavaScript; a reported failure throws an Error with C's message and code; 64-bit integers are bigints; an exception escaping C ends the process at the call instead of unwinding through Lucent. The header must declare its functions inextern "C"for C++; a function taking a handle is bound only when the declaration names it; aclose()from another thread waits for the calls using the handle. Editors get the declarations from.lucent/native/types/ext/. -
#13
9031f4eThanks @Fausto95! - Bind the prebuilt frameworks and libraries Lucent packages ship.lucent:ios/<Module>now finds the module of a framework listed inios.vendoredFrameworks(an.xcframeworkthrough its iOS simulator slice), andlucent:android/<package>the classes of a jar or AAR listed inandroid.libraries, before the app's Gradle build has resolved its classpath.lucent sdk show,search,prefetchandcoveragesee them too. -
#13
9031f4eThanks @Fausto95! - Check and merge Lucent packages'lucent.jsonwith clear rules. An unknown field or a value of the wrong type fails the build, naming the package and the field. Every package's requirement on a pod goes to CocoaPods, and every version of a Gradle artifact goes to Gradle, instead of failing when two packages write different versions; requirements no version can meet, and a strict Gradle version another package's excludes, still fail naming both packages.ios.frameworkslists Apple frameworks to link.Info.plistvalues can be booleans and arrays of strings; arrays from several packages join, and the Expo config plugin adds the values an app's array lacks. The merged result, with the package each need came from, is written to.lucent/native/resolved.json. -
#13
9031f4eThanks @Fausto95! - Let Lucent packages ship native files through typedlucent.jsonfields:ios.nativeSources,resources,resourceBundlesandvendoredFrameworks, andandroid.nativeSources,resources,assets,librariesandnativeLibraries. Paths are relative to the package.lucent buildcopies the files into.lucent/native/packages/<package>/and adds them to the podspec, the Android library'sbuild.gradleand, for C and C++ sources, the runtime's CMake target, so apps need no manual changes to their native projects. Two files that would land in the same place in the app fail the build, naming both packages. The resolved manifest and the build record list each input with its package and a content hash. -
#13
9031f4eThanks @Fausto95! - Let Lucent packages declare entitlements, Swift packages, Android manifest components and minimum platform versions inlucent.json:ios.entitlements(merged likeInfo.plistentries and added by the Expo config plugin; bare apps are told what their.entitlementsfile lacks),ios.swiftPackages(one requirement per package URL, products joined, added with React Native'sspm_dependency),ios.deploymentTargetandandroid.minSdk(the highest any package needs), andandroid.components(services, receivers, activities and providers, declared once in the native package's manifest; packages that declare one differently fail the build, naming both). -
#13
9031f4eThanks @Fausto95! - Judge every SDK call by one set of binding rules: a refused call says why and which native declaration it comes from, declarations document what cannot be used, andlucent sdk coveragecounts it. Native 64-bit integers (Java'slong,NSInteger,Int64) no longer round: they are bigints, and enums, option sets and@IntDefgroups stay numbers that cross exactly or throwRangeError; option sets take0; Java arrays of any element copy; functions can be assigned to block properties; and a local named like a reserved word (id) no longer breaks Android glue. -
#13
9031f4eThanks @Fausto95! - Pin the SDKs and see what an update changes for your code.lucent sdk lockrecords the SDKs and dependencies each module was read from, and every SDK member the code uses, inlucent-sdk.lock.json; it needs the SDK of every platform the project has code for, unless--platformsleaves one out.lucent build --frozenandlucent check --frozenthen fail when an SDK or dependency differs from the lock, when the code uses a member the lock does not record, or when a platform the lock lists has no SDK installed or would be left to the Gradle build, instead of skipping that platform.lucent sdk diffcompares the lock with the installed SDKs, member by member, by native identity: removed members, and changed signatures, availability, deprecation and TypeScript names, before you rebuild the app (--alladds the members your code does not use).lucent sdk coveragenow shows how far members get: discovered, representable, generated by the last build, and exercised (from an--exercisedfile), with--membersfor every member's stage and reason. Each build and check writes what it used to.lucent/sdk-usage.json. -
#13
9031f4eThanks @Fausto95! - Swift async methods take anAbortSignallast, as Kotlin suspend functions do: aborting it, or the calling context going away (a reload), rejects the promise at once withAbortErrorand cancels the Swift task, and a result that arrives afterwards is released instead of delivered. -
#13
9031f4eThanks @Fausto95! - Lucent classes implement every kind of Swift protocol requirement an object can: properties (read, and set when the requirement allows it), throwing methods (a Lucent error becomes theNSErrorSwift catches), async methods (Swift awaits the Lucent promise), andmutatingones. Protocols with associated types are generic in their declarations (Store<Item>), and a class fixes them withimplements Store<string>;Selfin a requirement is the implementing class. Such protocols' values pass as arguments that name their associated types (some Store<String>, from iOS 16). Initializer and static requirements are refused with a diagnostic. -
#13
9031f4eThanks @Fausto95! - Trace why a call or a build was slow:LUCENT_TRACE=trace.jsonrecords, off the hot path, how long each call waited for its thread, for the Lucent lock or for a compute worker, how long it ran and how many bytes it copied, each call at its.lucent.tsline;lucent trace --runtime trace.jsonmerges that with the last build's steps into one trace for Perfetto and prints how long each cause took. On devices,LUCENT_TRACE=platform(iOS, Instruments) anddebug.lucent.trace(Android, Perfetto) send the same spans to the platform's tools.
Patch Changes
-
#13
9031f4eThanks @Fausto95! - Report errors thrown by anabortlistener in the device log, like other uncaught errors, and keep running the remaining listeners whatever was thrown. -
#13
9031f4eThanks @Fausto95! - Run calls whose result isundefinedornullwhen that result is passed on, stored or compared, likeshow(reset())orreset() ?? fallback, instead of leaving the call out; a function that always throws now throws there too. -
#13
46e09c1Thanks @Fausto95! - Check and build an Expo app beforeexpo prebuildwhen it imports Android libraries from its dependencies: those modules stay untyped, named in a warning, and Android is checked once the app has its Android project, instead of failing with LUCENT3004. -
#13
46e09c1Thanks @Fausto95! - Build Android on a machine without Xcode when a platform module's declaration file names iOS types: they are untyped there, as in shared code. -
#13
9031f4eThanks @Fausto95! - Android constant groups: annotation types holding constants (Play services'Priority) are enums, results annotated@IntDefor@StringDef(from the SDK'sannotations.zipand each AAR's own) are the union of their constants, and passing a literal or constant outside a parameter's group is the new warning LUCENT3008. Warnings don't fail the build:lucent buildandlucent checkprint them, their--jsonoutput lists them underwarnings, and the editor shows them as warnings. AARs'@RequiresPermissionannotations are read too. -
#13
9031f4eThanks @Fausto95! - Android declarations TypeScript accepts: anActivitygoes where aContextis taken (an override keeps the non-null result of the method it overrides, whatever package declares it), and abstract SDK classes such asBiometricPrompt.AuthenticationCallbackkeep their constructors, protected ones as protected, so Lucent classes extend them. Every class extendsjava.lang.Object, imports named like a local type are aliased, and a few members TypeScript cannot relate to what they override are left out with their reason (anObjectresult narrowed to an interface or a type variable,EditText.getText()underTextView's string,Stack.empty()besideisEmpty()). A class whose superclass and interface give one property two ways (ViewGroup'slayoutDirection, typed byView's constants and as a number byViewParent) declares the superclass's, the one it calls. The Android declaration audit drops from 81 errors to none. -
#13
9031f4eThanks @Fausto95! - Members of generic Java classes are bound:List<String>.get(0)reads a string, and a function implementsConsumer<Location>. Classes declare their type parameters and references keep their type arguments; values of a type parameter cross as SDK objects, strings, numbers or booleans, as the type argument says. -
#13
9031f4eThanks @Fausto95! - Android thread annotations are followed:@UiThreadand@MainThreadclasses and methods (aView, and every member of it but those marked@AnyThread) must be used insidemain(() => …)(LUCENT3006), and calling a@WorkerThreadmember there warns with the new LUCENT3009, since it blocks. The SDK declarations document both on each member. iOS@MainActorproperties of classes that aren't main-only are now checked too. -
#13
9031f4eThanks @Fausto95! - Call a Java or Kotlin interface's default method on Android as TypeScript declares it, asserted present:manager.getCredential!(context, request)no longer fails with LUCENT1001. -
#13
9031f4eThanks @Fausto95! - Async functions whose body only throws, likeasync function load(): Promise<string> { return fail(); }, return a rejected promise instead of throwing at the call. Generators without ayieldrun their body on the firstnext()instead of when called, and no longer give invalid C++ when empty. -
#13
9031f4eThanks @Fausto95! -awaiton a platform SDK object, such as a Play servicesTaskor a Java future, is a compile error (LUCENT1010) instead of giving the object back: it is not a promise. Wait for it through its completion listener withfromCallbackfromlucent:core, as for any callback API. No library class is recognized by name, so a package's own listener-based types work the same way. -
#13
9031f4eThanks @Fausto95! - Convert and compare values that are a bigint or a number (an SDK constant or a 64-bit value), possibly absent, as JavaScript does:Number(x),BigInt(x),<and the other relational operators, unary-and~, and++/--.Number()andBigInt()of such unions were refused, and comparisons and unary minus threw at run time. -
#13
9031f4eThanks @Fausto95! - Blocks the iOS SDK passes to Lucent code become functions: a completion handler given to a Lucent function (coordinator.prepare(…, (done) => done())) or to a Lucent class's protocol method (URLSessionTaskDelegate'scompletionHandler) can be called like any function. Blocks taking CoreFoundation values (CFArrayRef,CFErrorRef) are supported too. Protocol requirements are declared in their completion-handler form only, so Lucent classes can implement them; before, the promise form merged in as an overload made that a type error. -
#13
46e09c1Thanks @Fausto95! - Keeplucent buildfrom running small machines and CI runners out of memory: it reads the SDK bindings ahead in one background process per spare core, for the platforms it builds, instead of one process per imported module. -
#13
9031f4eThanks @Fausto95! - Record each build's steps in.lucent/build-record.json: what every step read and wrote, with content hashes, whether it ran, was cached or failed, and what the app needs next, so a slow or surprising build can be inspected afterwards. -
#13
9031f4eThanks @Fausto95! - Stop refusing a function passed tocomputebecause another module's code that the platform calls back (a kept callback, an override of a platform class's method, a protocol method) uses module state: that code runs on the module's thread, holding its lock, not in the task. -
#13
9031f4eThanks @Fausto95! - Print alucentcommand's whole output when it goes to a pipe: a large--jsonreport (lucent sdk coverage --json) was cut after 64 kB on macOS. -
#13
9031f4eThanks @Fausto95! - Assignments follow JavaScript's order:log += next()readslogbeforenext()runs,box.n = next()writes the objectboxnamed beforenext()ran, an element or field target's object and key run once, andxs[i]! += 1is accepted as a target. -
#13
9031f4eThanks @Fausto95! - Compute tasks read module constants safely across a JavaScript reload. A reload runs each module's initialization again, which assigned constants while a task could still read them (a string or function constant could be freed under the task). Code now reads number, string, boolean and bigint literal constants, and static readonly fields holding one, as their literals; a task that reads any other module constant is refused with LUCENT3011, with the path to it: make it a literal or pass its value in the task's input. -
#13
9031f4eThanks @Fausto95! - Let compute tasks callBigInt(),BigInt.asIntN,BigInt.asUintN, a bigint'stoStringandvalueOf, a number's or boolean'svalueOf, andtoStringon arrays, byte arrays, objects and functions. They were refused with LUCENT3011, although none of them touches module state. -
#13
9031f4eThanks @Fausto95! - Build the object literals in a conditional's branches as the type the conditional is used as, soconst o: Options = big ? { name, size } : { name }no longer throws aTypeErrorat run time. -
#13
9031f4eThanks @Fausto95! - Refuse loose==and!=where JavaScript converts before comparing, asLUCENT1002: a number, string, boolean or bigint against another of them (1 == "1",true == 1), or an object against a primitive ([1] == 1). Lucent used to compare these like===and answer false where JavaScript answers true. Generics are checked once instantiated;==between values of one kind, or withnullorundefined, is unchanged. -
#13
9031f4eThanks @Fausto95! - Letexpo prebuildaccept areact-native.config.jswhoselucententry is written without quotes, as formatters write it, instead of failing and asking for an entry that is already there. -
#13
9031f4eThanks @Fausto95! - Let JavaScript call into Lucent while a long async Lucent function yields withawait delay(0): threads now take the Lucent lock in the order they asked, so timers, callbacks and aborts no longer wait seconds behind a loop that keeps retaking it. -
#13
9031f4eThanks @Fausto95! - Report comparing two functions asLUCENT1002(LUCENT2002for aMapkey orSetelement), where it used to fail with a C++ error:===and!==between functions,indexOf,lastIndexOfandincludeson arrays of functions, and generics that compare a type parameter instantiated with a function type. Lucent does not keep a function value's identity, so it cannot compare functions as JavaScript does. -
#13
9031f4eThanks @Fausto95! - Whenlucent build, run by the app's Gradle build, changes the Lucent Android library'sbuild.gradle(its first Kotlin shim, a package's Android dependency), it now fails and asks for another build instead of letting Gradle build the library as it was configured, which left new Kotlin shims out of the app. -
#13
9031f4eThanks @Fausto95! -BOOL *parameters are bound: in calls as anOut<boolean>, and where a block or protocol method receives one (stopin enumeration blocks such ascalendar.enumerateDates(…, (date, exact, stop) => { stop.value = true; })), as anOutwhose value goes back to the platform when the function returns. A class whose only initializer a protocol synthesizes keepsnew C()(new NSDateComponents()). -
#13
9031f4eThanks @Fausto95! - iOS methods that write through pointers to numbers, enums, structs, strings, dates and objects are bound: pass anOut<T>fromlucent:iosand read itsvalueafter the call (color.getRed(red, green, blue, alpha),calendar.range(.day, start, interval, date), aPropertyListSerializationformat, anNSRangeeffective range).valueis writable, for pointers the method also reads. Throwing methods that returnidno longer fail to compile in-Werrorbuilds. -
#13
9031f4eThanks @Fausto95! - A Java SDK call whose result is an array other thanbyte[],int[],long[]orString[](such asfloat[]) reports LUCENT2002 instead of crashing the compiler. -
#13
9031f4eThanks @Fausto95! - Android release builds with R8 (Expo's default) no longer fail SDK calls with "Java method not found" when a method's parameters name a library class the code never uses directly (Play services'getCurrentLocation(priority, null)and itsCancellationToken): the consumer rules now keep every class in the descriptors the glue looks up. -
#13
9031f4eThanks @Fausto95! - A Kotlin parameter with a default followed by one without (create(scope = …, produceFile)) now takesundefinedon Android, which leaves Kotlin's default in place:PreferenceDataStoreFactory.INSTANCE.create(undefined, undefined, undefined, () => file). -
#13
9031f4eThanks @Fausto95! - Collect Kotlin flows on Android:await flow.collect((value) => …, signal)runs the Lucent function for each value, resolves when the flow completes, rejects with the flow's error or with what the function throws, and cancels the flow when the signal aborts. Lucent functions can be passed where a Kotlin library takes a suspend function (DataStore'sedit), running while Kotlin waits, and generic Kotlin members (Flow.collect,FlowKt.first) are called through shims unless their type parameters have bounds other thanAny. -
#13
9031f4eThanks @Fausto95! - Declare Kotlin libraries on Android as Kotlin declares them, from their Kotlin metadata: parameter names, Kotlin's nullability, properties with their accessors, suspend functions as promises (without theirContinuation), extensions as functions taking their receiver first, top-level declarations as statics of their facade, and value, sealed, data and object classes. Internal members,$DefaultImplsand other compiler plumbing are no longer declared. Calling a suspend function, or passing a value class the JVM unboxes, is refused with a clear error until Lucent generates Kotlin shims; a class whose metadata comes from a newer Kotlin is declared as Java sees it, andlucent sdk coverage --jsonlists why among its reasons. -
#13
9031f4eThanks @Fausto95! - Kotlin's read-onlyList<E>is now an array on Android: a list a Kotlin library returns is copied into anE[], and an array passed where it takes aList<E>is copied into a new list, soawait client.search(prefix)gives an array withmapandlength. Numbers Kotlin boxes (List<Int>,Flow<Double>) are numbers, andLongs bigints (List<Long>isbigint[]), and elements may benullwhere Kotlin's type allows it. AMutableList, aList<*>and lists Java declarations name stay the Java object, whose changes and identity Lucent code shares; code that calledsize()andget(i)on a read-only Kotlin list useslengthand[i]instead. -
#13
9031f4eThanks @Fausto95! - A Kotlin suspend function completing with aLongresolves to a bigint, as every native 64-bit integer does, instead of generating C++ that does not compile. -
#13
9031f4eThanks @Fausto95! - Call Kotlin libraries' suspend functions, default arguments and value classes on Android through Kotlin shims Lucent generates for what the program uses. A suspend function is a promise, cancelled by theAbortSignalit takes last, with thrown exceptions as errors and late results released; leaving out an argument with a Kotlin default lets Kotlin's default apply, and passingnullpasses null. Value classes cross boxed, Kotlin properties with setters can be assigned, andinstanceofmatches Java objects against Android SDK classes, so the cases of a sealed class and their payloads are read as their classes'. -
#13
9031f4eThanks @Fausto95! - Link the native module in an Android app's first build after a fresh checkout:lucent buildwrites.lucent/nativebefore it runs Gradle, and has Gradle read the app's autolinking config again once the package exists. A Gradle build that read that config before the package existed now fails with "build again" instead of shipping an APK without Lucent. -
#13
9031f4eThanks @Fausto95! - Metro can bundle a native package thatlucent build --out <dir>wrote: setLUCENT_OUT=<dir>(relative to the project, as--outis) and each*.lucent.tsfile is bundled as that package's proxy, with its loader and build identity, instead of.lucent/native's. -
#13
9031f4eThanks @Fausto95! - Compile===,!==,==, switch cases,indexOf,includesandMapandSetkeys between values of different types, as TypeScript allows them: an optional against another optional (number | undefinedagainststring | undefined), overlapping unions, and a generic's value againstundefined,nullor a literal whatever type it is instantiated with. Values that can't be the same JavaScript value are never equal, and unions compare the member they hold. Loosex == nullin a generic, andundefined == nullbetween two optionals, are now true as in JavaScript, andincludes,MapandSetfindNaNinside a union. -
#13
9031f4eThanks @Fausto95! - Report two Lucent modules with the same name under their own code, LUCENT3010, whose fix says to rename one of the files. They were reported as LUCENT3002, a top-level statement, with an unrelated fix. -
#13
9031f4eThanks @Fausto95! - Compile names that the C library or a platform SDK defines as macros, likeHUGE,DOMAIN,MINorpascal, as the ordinary TypeScript names they are, instead of failing to build the generated C++. -
#13
9031f4eThanks @Fausto95! - Read optional values the checker narrows toundefinedornull, likesinconst s: string | undefined = undefined; show(s)or afterif (s === undefined), instead of reporting LUCENT2002. -
#13
9031f4eThanks @Fausto95! - The native codelucent buildgenerates now carries a build identity: a hash of each target's program, a hash of each module's API (its exports and their signatures), and the runtime ABI they need, which JavaScript can read as__lucentIdentityon the Lucent module. -
#13
9031f4eThanks @Fausto95! - Compile??,||,&&,??=and conditional expressions whose other operand always throws, likevalue ?? fail("missing"), and run the throwing operand for??=instead of assigningundefined. -
#13
9031f4eThanks @Fausto95! - Compile calls that always throw wherever a value is expected, liketake(fail()),s = fail(),{ size: fail() },[fail()],1 + fail()orif (fail()), instead of reporting LUCENT2002, and exhaustive switches that pass the value they narrowed away toassertNever(value: never). Templates and calls with several parts no longer give invalid C++ when a part is a call that returns nothing. -
#13
9031f4eThanks @Fausto95! - Compilereturn fail(), arrows like(): string => fail(), and declarations likeconst name: string = fail(), wherefailalways throws, instead of reporting LUCENT2002. -
#13
9031f4eThanks @Fausto95! - Objective-C generic classes are bound:new NSCache<string, UIImage>(),NSHashTable,NSMapTableandNSLayoutAnchor<AnchorType>declare their type parameters, and their members pass and return values as the type arguments say (strings, numbers, booleans, data and dates are bridged; objects stay objects). -
#13
9031f4eThanks @Fausto95! - CompileString(x), template literals,+with a string,toString()andconsole.logon arrays, maps, sets, records,Uint8Arrays and promises, which used to fail with a C++ error.AbortSignalandAbortControllernow print as[object AbortSignal]and[object AbortController], as in JavaScript. -
#13
9031f4eThanks @Fausto95! - Compile optional calls of methods and functions that return nothing, likesignal?.addEventListener("abort", …)orcallback?.(), instead of generating C++ that does not build. -
#13
9031f4eThanks @Fausto95! - Bind the jars and AARs Lucent packages ship inandroid.libraries:lucent:android/<package>now finds their classes, as it finds the app's Gradle dependencies'. -
be7d600Thanks @Fausto95! - Add a README to the npm package: what Lucent does, how to install it, what the package contains and where the docs are. -
#13
9031f4eThanks @Fausto95! - A constructor body can read and assign its parameter properties' parameters (constructor(readonly name: string) { log(name); }), which reported "unsupported reference" before. -
#13
9031f4eThanks @Fausto95! - Guard clauses are platform branches: afterif (PLATFORM === "ios") return …;the rest of the block is Android code, as TypeScript narrows it (#12). -
#13
9031f4eThanks @Fausto95! - Build apps that useuse_frameworks!: Lucent's pod now depends on the pods whose modules your iOS code imports, so their headers are found. -
#13
9031f4eThanks @Fausto95! -expo prebuildof a fresh checkout no longer stops at LUCENT3004 when a module's Android branch imports a library from the app's dependencies (Play services, AndroidX): until the Gradle build resolves them, those imports are untyped in the iOS build, and the Gradle build'slucentBuildtask builds and checks Android, reporting an import that is still missing. The first Gradle build after prebuild no longer stops to ask for another build when Android turns out to need Kotlin shims. -
#13
9031f4eThanks @Fausto95! - Present view controllers and system sheets from iOS code and await their result withpresent()fromlucent:ios: it shows the view controller from the scene in use, settles once, dismisses it however it ends, and rejects with anAbortErrorwhen a signal aborts, the person swipes it away or its scene goes. Follow the app's and its scenes' lifecycle withonAppEvent()andonSceneEvent(), without replacing the app's delegates. -
#13
9031f4eThanks @Fausto95! - Stop refusing a function passed tocomputebecause another module keeps a callback that the platform delivers later (a monitor's handler, a delegate method that returns nothing): such a callback never runs during the task's native calls. -
#13
9031f4eThanks @Fausto95! - Say in the editor why Lucent cannot use an iOS C function or constant yet: its declaration inlucent:ios/<module>now carries the reason, as methods and properties already did. -
#13
9031f4eThanks @Fausto95! - End Lucent's work for a JavaScript runtime when it reloads: async calls that have not started are dropped, Lucent code awaiting a JavaScript promise or callback resumes with anAbortErrorinstead of never, results the old runtime can no longer receive are released, and platform objects are released on the thread they require (the main thread for UIKit objects) whichever thread drops them. A second Lucent host for the same runtime no longer leaves JavaScript calls failing with "Lucent is not initialized for this runtime". -
#13
9031f4eThanks @Fausto95! - Extract SDK bindings again only when a library or SDK they were read from changes, not when another dependency is added, the same pods are installed again or the project moves, and bind pods of apps usinguse_frameworks!before their first Xcode build. The first build after upgrading extracts once more. -
#13
9031f4eThanks @Fausto95! - An SDK call, property read or construction whose receiver or argument awaits ((await file()).getName(),Uri.parse(await text())) compiles: the awaiting operand, and those before it, are evaluated first. It used to emit C++ the compiler refused. -
#13
9031f4eThanks @Fausto95! - Type SDK classes as their platforms do: a subclass keeps the overloads it inherits (ByteBuffer.limit()besidelimit(int)), an override keeps the non-null result and constants of the method it overrides, and iOS classes no longer repeat their superclass's protocols, so the generated declarations type-check with far fewer errors. -
#13
9031f4eThanks @Fausto95! - Declare again, in an SDK class, the superclass methods that an interface it inherits through another interface also declares (ArrayBlockingQueue.addAll, fromCollectionthroughBlockingQueue): TypeScript rejected the class for merging two different declarations of one method. -
#13
9031f4eThanks @Fausto95! - Give each SDK member name one kind per class hierarchy: a method named like an inherited property now takes its Swift labels, as it already did beside the class's own property (NSCountedSet.countFor(_:)instead ofcount(_:)), and a class is not declared as conforming to a protocol whose requirement it declares as a property. -
#13
9031f4eThanks @Fausto95! - Declare Java buffers as their superclass:java.nio.Bufferno longer declaresarray(), whoseObjectresultByteBuffer,IntBufferand the others narrow to typed arrays. TypeScript rejected those overrides, and with them each buffer as aBuffer. Coverage lists the left-out member with its reason. -
#13
9031f4eThanks @Fausto95! - An object type with a field holding an SDK object compiles: it stringifies as{}(a host object), and a type only one platform's code uses stays out of the other platform's output (#11). -
#13
9031f4eThanks @Fausto95! - Generate the same iOS declarations on every run: the protocols a class adopts are listed in a stable order, not in the varying order Xcode's symbol graph tool writes them. -
#13
9031f4eThanks @Fausto95! - Numbers print exactly as JavaScript prints them.String(x), template literals,console.logandtoExponential()gave one digit too many for some doubles, such as2 ** 89(6.1897001964269014e+26where JavaScript prints6.189700196426902e+26);toFixeddropped the sign of a negative number that rounds to zero (-0.000); andtoString(radix)of a very large number crashed. -
#13
9031f4eThanks @Fausto95! - Spread maps into array literals ([...map],new Map([...a, ...b])), andUint8Arrays, like the other iterables; spreading a collection into an array of a wider element type (["start", ...numbers]) now keeps its elements. -
#13
9031f4eThanks @Fausto95! - Proxies check the app's native code before a module loads. An app built before this check, with another runtime ABI, without the module, or with another API for it, throws an error that names what to do: rebuild and reinstall the app (compile-native), or reload JavaScript built for the installed app (reload-js). When only function bodies differ, a warning says the installed implementation runs, once per reload. JavaScript-only edits change nothing. -
#13
9031f4eThanks @Fausto95! - Compile===and!==between arrays, maps, sets, records,Uint8Arrays and promises, which compare references as in JavaScript, and between bigints in generic functions. They used to fail with a C++ error. -
#13
9031f4eThanks @Fausto95! - Store a subclass instance in a union that holds its base class (const s: Shape | string = new Circle()), which was rejected withLUCENT2002. -
#13
9031f4eThanks @Fausto95! - Keep the parentheses of a comparison compared again in a SwiftUI body (a === b === false): the view's Swift compiles instead of failing on Swift's non-associative comparisons. -
#13
9031f4eThanks @Fausto95! -lucent sdk coveragecounts Swift-only members (StoreKit 2, CryptoKit, Swift overlays) as unrepresentable, with the reason "Swift-only", instead of leaving them out. -
#13
9031f4eThanks @Fausto95! - Swift-only iOS APIs can be called: initializers, methods, static members, properties (read and written) and top-level functions of Swift types, through a generated@_cdeclshim per member the program uses. Swift structs are objects Lucent holds (boxed), changed in place bymutatingmembers and setters; enums without payloads are numbers, and enums with payloads are unions discriminated bykind({ kind: "circle"; center: Point; radius: number } | …);throwsbecomes a Lucent error;asyncmembers and getters return promises, and async@MainActormembers can be awaited from any thread; strings, data, dates, arrays, dictionaries and optionals convert as for Objective-C. Default arguments can be left out, members that protocol extensions give a type are callable (CryptoKit'sSHA256.hash(data:), AVFoundation'sload(_:)), and C structs cross by value. Swift modules on the include paths and Swift-only SDK frameworks (CryptoKit) bind. Generic members get a shim per combination of type arguments the program uses. Protocol values cross as objects, and Lucent classes can implement Swift protocols (method requirements; not protocols with associated types yet). -
#13
9031f4eThanks @Fausto95! - Compile generics whose signatures put a type parameter in a union (A | B,T | null) whatever order the type arguments sort in, where the call used to pass the union's members in another order than the generic expects. A type argument that would merge into such a union (an optional,nullorundefined, and inA | Ba union or a type the union already holds) is now refused withLUCENT2002instead of failing to build.null | undefinedis accepted as a type. -
#13
9031f4eThanks @Fausto95! - Reject converting a union of object types to another object type (LUCENT2003) when compiling, instead of compiling code that always throws aTypeError; each member of a union is now converted on its own, as a subclass to its base class. -
#13
9031f4eThanks @Fausto95! - AndroidAutoCloseableobjects (aCloseable, aCursor, anything that implements either) are disposable:using cursor = resolver.query(…)closes the cursor however the block is left, andcursor[Symbol.dispose]()closes it too. -
#13
9031f4eThanks @Fausto95! -usingdeclarations:using file = open(path)disposes the value with its class's[Symbol.dispose]()however the block is left (return, throw, break, continue or the end), in reverse order, skippingnull. A disposal that throws while another error is pending throws aSuppressedError. Classes can define[Symbol.dispose](), the one symbol-keyed member they support; JavaScript doesn't see it.await using, andusingdirectly in acaseclause, report LUCENT1001. The editor needsesnext.disposablein tsconfig'slib(React Native's base config lacks it). -
#13
9031f4eThanks @Fausto95! - Compile values typedvoid | undefined, like an unannotated() => item?.update()or a function declared to returnvoid | undefined, and let the result of a call that returns nothing be printed, compared or passed totypeof. -
#13
9031f4eThanks @Fausto95! - Stop reporting every call to a@WorkerThreadmethod of a@UiThreadAndroid class: the method's own annotation now overrides its class's, so it is callable outsidemain()without LUCENT3006.