-
-
Notifications
You must be signed in to change notification settings - Fork 31
feat(core,methods): add react-native framework adapter (#117) #137
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,131 @@ | ||
| import type { Signal } from '../types/signal/index.ts'; | ||
| import type { Framework } from './index.ts'; | ||
|
|
||
| /** | ||
| * The current framework being used. | ||
| */ | ||
| export const framework: Framework = 'react-native'; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If this file is fully identically to
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll check it, nevertheless take into account that the development teams at react and react-native don't sync on their releases, and this could create issues in the future. For instance, the React team announced the v19 release in Dec. 2024 and it took the React Native team until Feb. 2025 to ship it. That's 3 months worth of potential bugs (now with AI-assisted development it'd be much less of course, but it still implies some risk) |
||
|
|
||
| /** | ||
| * Creates a unique identifier string. | ||
| * | ||
| * @returns The unique identifier. | ||
| */ | ||
| // @__NO_SIDE_EFFECTS__ | ||
| export function createId(): string { | ||
| return Math.random().toString(36).slice(2); | ||
| } | ||
|
|
||
| /** | ||
| * Listener tuple. | ||
| * | ||
| * Hint: The first element is the execute function, which notifies the listener | ||
| * about updates. The second element is the subscription set, which keeps track | ||
| * of where the listener is subscribed and is used to clean up subscriptions if | ||
| * they are no longer needed. | ||
| */ | ||
| export type Listener = [() => void, Set<Set<Listener>>]; | ||
|
|
||
| /** | ||
| * The current listener being tracked. | ||
| */ | ||
| let listener: Listener | undefined; | ||
|
|
||
| /** | ||
| * Sets the current listener being tracked. | ||
| * | ||
| * @param newListener The new listener to set. | ||
| */ | ||
| export function setListener(newListener: Listener | undefined): void { | ||
| listener = newListener; | ||
| } | ||
|
|
||
| /** | ||
| * Subscribers collected during a batch. | ||
| */ | ||
| let batchSubscribers: Set<Listener> | undefined; | ||
|
|
||
| /** | ||
| * Creates a reactive signal with an initial value. | ||
| * | ||
| * @param value The initial value. | ||
| * | ||
| * @returns The created signal. | ||
| */ | ||
| // @__NO_SIDE_EFFECTS__ | ||
| export function createSignal<T>(value: T): Signal<T> { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Verify createSignal signature consistency across framework entrypoints and call sites.
fd -i 'index*.ts' packages/core/src/framework
rg -nP --type=ts '^export function createSignal<.*>\(\): Signal<.*>;' packages/core/src/framework -C2
rg -nP --type=ts '^export function createSignal<.*>\(value: .*' packages/core/src/framework -C2
rg -nP --type=ts '\bcreateSignal\s*(<[^>]+>)?\s*\(\s*\)' packages -C2Repository: open-circle/formisch Length of output: 2059
The base contract in Suggested fix // `@__NO_SIDE_EFFECTS__`
+export function createSignal<T>(): Signal<T | undefined>;
export function createSignal<T>(value: T): Signal<T>;
-export function createSignal<T>(value: T): Signal<T | undefined> {
+export function createSignal<T>(value?: T): Signal<T | undefined> {
const subscribers = new Set<Listener>();
return {
get value() {🤖 Prompt for AI Agents |
||
| const subscribers = new Set<Listener>(); | ||
| return { | ||
| get value() { | ||
| if (listener) { | ||
| subscribers.add(listener); | ||
| listener[1].add(subscribers); | ||
| } | ||
| return value; | ||
| }, | ||
| set value(newValue: T) { | ||
| if (newValue !== value) { | ||
| value = newValue; | ||
| const localSubscribers: Listener[] = []; | ||
| for (const subscriber of subscribers) { | ||
| if (batchSubscribers) { | ||
| batchSubscribers.add(subscriber); | ||
| } else { | ||
| localSubscribers.push(subscriber); | ||
| } | ||
| subscriber[1].delete(subscribers); | ||
| } | ||
| subscribers.clear(); | ||
| for (const subscriber of localSubscribers) { | ||
| subscriber[0](); | ||
| } | ||
| } | ||
| }, | ||
| }; | ||
| } | ||
|
|
||
| // Global batch depth counter | ||
| let batchDepth = 0; | ||
|
|
||
| /** | ||
| * Batches multiple signal updates into a single update cycle. | ||
| * | ||
| * @param fn The function to execute in batch. | ||
| * | ||
| * @returns The return value of the function. | ||
| */ | ||
| export function batch<T>(fn: () => T): T { | ||
| batchDepth++; | ||
| if (!batchSubscribers) { | ||
| batchSubscribers = new Set(); | ||
| } | ||
| try { | ||
| return fn(); | ||
| } finally { | ||
| batchDepth--; | ||
| if (batchDepth === 0) { | ||
| const subscribers = batchSubscribers; | ||
| batchSubscribers = undefined; | ||
| for (const subscriber of subscribers) { | ||
| subscriber[0](); | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Executes a function without tracking reactive dependencies. | ||
| * | ||
| * @param fn The function to execute without tracking. | ||
| * | ||
| * @returns The return value of the function. | ||
| */ | ||
| export function untrack<T>(fn: () => T): T { | ||
| const prev = listener; | ||
| listener = undefined; | ||
| try { | ||
| return fn(); | ||
| } finally { | ||
| listener = prev; | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P2: React Native adapter duplicates the entire React adapter signal implementation. The two files differ only by the
frameworkconstant, creating a maintenance burden and drift risk for any future signal-layer changes.Prompt for AI agents