@flamework-experimental/core 2.0.0-alpha.0 → 2.0.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,29 +1,48 @@
1
1
  -- Compiled with roblox-ts v3.0.0
2
2
  local inactiveThread
3
- local function reusableThread(func)
3
+ local function reusableThread(func, a, b, c, d, e)
4
4
  local thread = coroutine.running()
5
5
  while true do
6
6
  if inactiveThread == thread then
7
7
  inactiveThread = nil
8
8
  end
9
- func()
9
+ func(a, b, c, d, e)
10
10
  -- If there's a different idle thread, we should end the current thread.
11
11
  if inactiveThread ~= nil then
12
12
  break
13
13
  end
14
14
  inactiveThread = thread
15
- -- Let go of the callback while idle: it closes over whatever it was run for -- a lifecycle
16
- -- listener, a component -- which would otherwise stay reachable from this thread until the
17
- -- next callback comes through, and for good when none does.
15
+ -- Let go of the callback and its arguments while idle: they are whatever it was run for -- a
16
+ -- lifecycle listener, a component -- which would otherwise stay reachable from this thread
17
+ -- until the next callback comes through, and for good when none does.
18
18
  func = nil
19
- func = coroutine.yield()
19
+ a = nil
20
+ b = nil
21
+ c = nil
22
+ d = nil
23
+ e = nil
24
+ func, a, b, c, d, e = coroutine.yield()
20
25
  end
21
26
  end
22
- local function recycleThread(func)
23
- if inactiveThread then
24
- task.spawn(inactiveThread, func)
27
+ --[[
28
+ *
29
+ * Runs `func` with the arguments given, on a thread that is kept for the next call once it returns:
30
+ * one that yields keeps its thread, and the next call gets a new one.
31
+ *
32
+ * The arguments are passed through rather than closed over, so that a caller running many callbacks
33
+ * -- the per-frame events, once per listener every frame -- creates nothing per call.
34
+
35
+ ]]
36
+ local function recycleThread(func, a, b, c, d, e)
37
+ -- Only while it is parked: a callback that kept `coroutine.running()` and cancelled it later left
38
+ -- a dead thread here, and every later call, of every module, raised trying to resume it. One that
39
+ -- is not is dropped, and a new thread takes its place.
40
+ local idle = inactiveThread
41
+ if idle ~= nil and coroutine.status(idle) == "suspended" then
42
+ task.spawn(idle, func, a, b, c, d, e)
25
43
  else
26
- task.spawn(reusableThread, func)
44
+ inactiveThread = nil
45
+ task.spawn(reusableThread, func, a, b, c, d, e)
27
46
  end
28
47
  end
29
48
  return {
@@ -13,6 +13,8 @@ export interface ComponentsRuntimeConfig {
13
13
  attributeWarningTimeout?: number;
14
14
  /** Default `streamingMode` for components that do not set one. */
15
15
  streamingMode?: "Disabled" | "Watching" | "Contextual";
16
+ /** Default `watchRenames` for components that do not set one. */
17
+ watchRenames?: boolean;
16
18
  }
17
19
  export interface ScopesRuntimeConfig {
18
20
  /**
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Every thread waiting for another to finish something, to the thread it waits for: an extinguish
3
+ * waiting in `awaitExtinguished` for one running on another thread, and an ignition waiting for an
4
+ * `onInit` the lifecycle plugin runs on a thread of its own. Shared by every module, since a chain
5
+ * of waits runs through several: `awaitExtinguished` follows it to refuse the wait that would close
6
+ * a circle.
7
+ *
8
+ * Or to the Promise it waits for: an ignition waiting for the Promise an `onInit` returned, whose
9
+ * work runs on a thread nothing can name -- an `async` method's body runs on one of its own, not the
10
+ * `onInit` thread. A chain that ends at one may end at any thread, the waiting one included.
11
+ *
12
+ * An entry is removed by whatever ends the wait -- what is waited for, as it finishes, or the poll
13
+ * that sees the waiting thread die -- and not by the waiting thread once it resumes: one that is
14
+ * cancelled never resumes.
15
+ */
16
+ export declare const threadWaits: Map<thread, thread | Promise<unknown>>;
17
+ /**
18
+ * How many extinguishes have begun, in any module, counted from the first line of `extinguish()`.
19
+ * The lifecycle plugin's per-frame walks read it after every callback and ask their module whether
20
+ * it has begun to extinguish only when it has changed, so that a callback that extinguishes the
21
+ * module -- itself, on a thread it starts, through a signal it fires -- stops the walk without a
22
+ * call per listener.
23
+ */
24
+ export declare const extinguishesBegun: {
25
+ count: number;
26
+ };
27
+ /**
28
+ * Whether a thread does Promise work: whether its outermost function -- what it was started with --
29
+ * is the Promise library's or the one an `async` function's body runs in.
30
+ *
31
+ * The lifecycle plugin takes such a thread to be doing the work of the Promise an `onInit` returned
32
+ * while it waits on one, since nothing records which threads that is: an `async` body that has
33
+ * yielded, an executor, a chained callback. An unrelated Promise's thread passes too, and a thread
34
+ * an executor starts itself with `task.spawn` or `task.delay` does not.
35
+ */
36
+ export declare function runsPromiseWork(thread: thread): boolean;
@@ -0,0 +1,81 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ local TS = _G[script]
3
+ --[[
4
+ *
5
+ * Every thread waiting for another to finish something, to the thread it waits for: an extinguish
6
+ * waiting in `awaitExtinguished` for one running on another thread, and an ignition waiting for an
7
+ * `onInit` the lifecycle plugin runs on a thread of its own. Shared by every module, since a chain
8
+ * of waits runs through several: `awaitExtinguished` follows it to refuse the wait that would close
9
+ * a circle.
10
+ *
11
+ * Or to the Promise it waits for: an ignition waiting for the Promise an `onInit` returned, whose
12
+ * work runs on a thread nothing can name -- an `async` method's body runs on one of its own, not the
13
+ * `onInit` thread. A chain that ends at one may end at any thread, the waiting one included.
14
+ *
15
+ * An entry is removed by whatever ends the wait -- what is waited for, as it finishes, or the poll
16
+ * that sees the waiting thread die -- and not by the waiting thread once it resumes: one that is
17
+ * cancelled never resumes.
18
+
19
+ ]]
20
+ local threadWaits = {}
21
+ --[[
22
+ *
23
+ * How many extinguishes have begun, in any module, counted from the first line of `extinguish()`.
24
+ * The lifecycle plugin's per-frame walks read it after every callback and ask their module whether
25
+ * it has begun to extinguish only when it has changed, so that a callback that extinguishes the
26
+ * module -- itself, on a thread it starts, through a signal it fires -- stops the walk without a
27
+ * call per listener.
28
+
29
+ ]]
30
+ local extinguishesBegun = {
31
+ count = 0,
32
+ }
33
+ local asyncFunction = TS.async(function() end)
34
+ --[[
35
+ *
36
+ * The scripts a thread doing Promise work starts in: the Promise library, which runs executors and
37
+ * chained callbacks on threads of their own, and the runtime library, which runs an `async`
38
+ * function's body on one of its own.
39
+
40
+ ]]
41
+ local promiseSources = {
42
+ [(debug.info(TS.Promise.is, "s"))] = true,
43
+ [(debug.info(asyncFunction, "s"))] = true,
44
+ }
45
+ --[[
46
+ *
47
+ * Whether a thread does Promise work: whether its outermost function -- what it was started with --
48
+ * is the Promise library's or the one an `async` function's body runs in.
49
+ *
50
+ * The lifecycle plugin takes such a thread to be doing the work of the Promise an `onInit` returned
51
+ * while it waits on one, since nothing records which threads that is: an `async` body that has
52
+ * yielded, an executor, a chained callback. An unrelated Promise's thread passes too, and a thread
53
+ * an executor starts itself with `task.spawn` or `task.delay` does not.
54
+
55
+ ]]
56
+ local function runsPromiseWork(thread)
57
+ local outermost
58
+ local level = 1
59
+ while true do
60
+ local source = (debug.info(thread, level, "s"))
61
+ if source == nil then
62
+ break
63
+ end
64
+ -- A C function (`pcall`, the scheduler's resume) is not where the thread's work comes from.
65
+ if source ~= "[C]" then
66
+ outermost = source
67
+ end
68
+ level += 1
69
+ end
70
+ local _condition = outermost ~= nil
71
+ if _condition then
72
+ local _outermost = outermost
73
+ _condition = promiseSources[_outermost] ~= nil
74
+ end
75
+ return _condition
76
+ end
77
+ return {
78
+ runsPromiseWork = runsPromiseWork,
79
+ threadWaits = threadWaits,
80
+ extinguishesBegun = extinguishesBegun,
81
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flamework-experimental/core",
3
- "version": "2.0.0-alpha.0",
3
+ "version": "2.0.0-alpha.2",
4
4
  "main": "out/init.luau",
5
5
  "types": "out/index.d.ts",
6
6
  "scripts": {