@ugo-studio/jspp 0.2.5 → 0.2.6

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,145 +1,145 @@
1
- #pragma once
2
- #include <deque>
3
- #include <functional>
4
- #include <chrono>
5
- #include <queue>
6
- #include <unordered_set>
7
- #include <vector>
8
- #include <thread>
9
- #include <iostream>
10
-
11
- namespace jspp {
12
- class Scheduler {
13
- public:
14
- using Task = std::function<void()>;
15
- using TimePoint = std::chrono::steady_clock::time_point;
16
-
17
- struct Timer {
18
- size_t id;
19
- TimePoint next_run;
20
- std::chrono::milliseconds interval; // 0 if not repeating
21
- Task task;
22
-
23
- // Min-heap priority queue (smallest time at top)
24
- bool operator>(const Timer& other) const {
25
- return next_run > other.next_run;
26
- }
27
- };
28
-
29
- static Scheduler& instance() {
30
- static Scheduler s;
31
- return s;
32
- }
33
-
34
- void enqueue(Task task) {
35
- tasks.push_back(std::move(task));
36
- }
37
-
38
- size_t set_timeout(Task task, size_t delay_ms) {
39
- return schedule_timer(std::move(task), delay_ms, false);
40
- }
41
-
42
- size_t set_interval(Task task, size_t delay_ms) {
43
- return schedule_timer(std::move(task), delay_ms, true);
44
- }
45
-
46
- void clear_timer(size_t id) {
47
- cancelled_timers.insert(id);
48
- }
49
-
50
- void run() {
51
- while (true) {
52
- bool has_work = false;
53
-
54
- // 1. Process all immediate tasks (microtask/task queue)
55
- while (!tasks.empty()) {
56
- Task task = tasks.front();
57
- tasks.pop_front();
58
- task();
59
- has_work = true;
60
- }
61
-
62
- // 2. Process timers
63
- auto now = std::chrono::steady_clock::now();
64
- while (!timers.empty()) {
65
- // Peek top
66
- const auto& top = timers.top();
67
-
68
- // Cleanup cancelled timers lazily
69
- if (cancelled_timers.count(top.id)) {
70
- cancelled_timers.erase(top.id);
71
- timers.pop();
72
- continue;
73
- }
74
-
75
- if (top.next_run <= now) {
76
- // Timer is ready
77
- Timer t = top;
78
- timers.pop();
79
-
80
- // Execute task
81
- t.task();
82
- has_work = true;
83
-
84
- // Reschedule if interval and not cancelled during execution
85
- if (t.interval.count() > 0 && cancelled_timers.find(t.id) == cancelled_timers.end()) {
86
- // Drift-safe(ish) scheduling: run next interval relative to now
87
- // Note: JS allows drift.
88
- t.next_run = std::chrono::steady_clock::now() + t.interval;
89
- timers.push(t);
90
- }
91
- } else {
92
- break; // Next timer is in the future
93
- }
94
- }
95
-
96
- // 3. Exit or Wait
97
- if (!has_work) {
98
- if (tasks.empty() && timers.empty()) {
99
- break; // No pending work, exit event loop
100
- }
101
-
102
- if (!timers.empty()) {
103
- auto next_time = timers.top().next_run;
104
- std::this_thread::sleep_until(next_time);
105
- }
106
- }
107
- }
108
- }
109
-
110
- bool has_tasks() const {
111
- return !tasks.empty() || !timers.empty();
112
- }
113
-
114
- private:
115
- std::deque<Task> tasks;
116
- std::priority_queue<Timer, std::vector<Timer>, std::greater<Timer>> timers;
117
- std::unordered_set<size_t> cancelled_timers;
118
- size_t next_timer_id = 1;
119
- const size_t MAX_TIMER_ID = 2147483647; // 2^31 - 1
120
-
121
- size_t schedule_timer(Task task, size_t delay_ms, bool repeat) {
122
- size_t id = next_timer_id++;
123
- if (next_timer_id > MAX_TIMER_ID) {
124
- next_timer_id = 1;
125
- }
126
-
127
- // If we wrap around, ensure we don't accidentally treat this new ID as cancelled
128
- // (in case an old timer with this ID is still lingering in the 'cancelled' set)
129
- if (cancelled_timers.count(id)) {
130
- cancelled_timers.erase(id);
131
- }
132
-
133
- auto now = std::chrono::steady_clock::now();
134
-
135
- Timer t;
136
- t.id = id;
137
- t.next_run = now + std::chrono::milliseconds(delay_ms);
138
- t.interval = repeat ? std::chrono::milliseconds(delay_ms) : std::chrono::milliseconds(0);
139
- t.task = std::move(task);
140
-
141
- timers.push(t);
142
- return id;
143
- }
144
- };
1
+ #pragma once
2
+ #include <deque>
3
+ #include <functional>
4
+ #include <chrono>
5
+ #include <queue>
6
+ #include <unordered_set>
7
+ #include <vector>
8
+ #include <thread>
9
+ #include <iostream>
10
+
11
+ namespace jspp {
12
+ class Scheduler {
13
+ public:
14
+ using Task = std::function<void()>;
15
+ using TimePoint = std::chrono::steady_clock::time_point;
16
+
17
+ struct Timer {
18
+ size_t id;
19
+ TimePoint next_run;
20
+ std::chrono::milliseconds interval; // 0 if not repeating
21
+ Task task;
22
+
23
+ // Min-heap priority queue (smallest time at top)
24
+ bool operator>(const Timer& other) const {
25
+ return next_run > other.next_run;
26
+ }
27
+ };
28
+
29
+ static Scheduler& instance() {
30
+ static Scheduler s;
31
+ return s;
32
+ }
33
+
34
+ void enqueue(Task task) {
35
+ tasks.push_back(std::move(task));
36
+ }
37
+
38
+ size_t set_timeout(Task task, size_t delay_ms) {
39
+ return schedule_timer(std::move(task), delay_ms, false);
40
+ }
41
+
42
+ size_t set_interval(Task task, size_t delay_ms) {
43
+ return schedule_timer(std::move(task), delay_ms, true);
44
+ }
45
+
46
+ void clear_timer(size_t id) {
47
+ cancelled_timers.insert(id);
48
+ }
49
+
50
+ void run() {
51
+ while (true) {
52
+ bool has_work = false;
53
+
54
+ // 1. Process all immediate tasks (microtask/task queue)
55
+ while (!tasks.empty()) {
56
+ Task task = tasks.front();
57
+ tasks.pop_front();
58
+ task();
59
+ has_work = true;
60
+ }
61
+
62
+ // 2. Process timers
63
+ auto now = std::chrono::steady_clock::now();
64
+ while (!timers.empty()) {
65
+ // Peek top
66
+ const auto& top = timers.top();
67
+
68
+ // Cleanup cancelled timers lazily
69
+ if (cancelled_timers.count(top.id)) {
70
+ cancelled_timers.erase(top.id);
71
+ timers.pop();
72
+ continue;
73
+ }
74
+
75
+ if (top.next_run <= now) {
76
+ // Timer is ready
77
+ Timer t = top;
78
+ timers.pop();
79
+
80
+ // Execute task
81
+ t.task();
82
+ has_work = true;
83
+
84
+ // Reschedule if interval and not cancelled during execution
85
+ if (t.interval.count() > 0 && cancelled_timers.find(t.id) == cancelled_timers.end()) {
86
+ // Drift-safe(ish) scheduling: run next interval relative to now
87
+ // Note: JS allows drift.
88
+ t.next_run = std::chrono::steady_clock::now() + t.interval;
89
+ timers.push(t);
90
+ }
91
+ } else {
92
+ break; // Next timer is in the future
93
+ }
94
+ }
95
+
96
+ // 3. Exit or Wait
97
+ if (!has_work) {
98
+ if (tasks.empty() && timers.empty()) {
99
+ break; // No pending work, exit event loop
100
+ }
101
+
102
+ if (!timers.empty()) {
103
+ auto next_time = timers.top().next_run;
104
+ std::this_thread::sleep_until(next_time);
105
+ }
106
+ }
107
+ }
108
+ }
109
+
110
+ bool has_tasks() const {
111
+ return !tasks.empty() || !timers.empty();
112
+ }
113
+
114
+ private:
115
+ std::deque<Task> tasks;
116
+ std::priority_queue<Timer, std::vector<Timer>, std::greater<Timer>> timers;
117
+ std::unordered_set<size_t> cancelled_timers;
118
+ size_t next_timer_id = 1;
119
+ const size_t MAX_TIMER_ID = 2147483647; // 2^31 - 1
120
+
121
+ size_t schedule_timer(Task task, size_t delay_ms, bool repeat) {
122
+ size_t id = next_timer_id++;
123
+ if (next_timer_id > MAX_TIMER_ID) {
124
+ next_timer_id = 1;
125
+ }
126
+
127
+ // If we wrap around, ensure we don't accidentally treat this new ID as cancelled
128
+ // (in case an old timer with this ID is still lingering in the 'cancelled' set)
129
+ if (cancelled_timers.count(id)) {
130
+ cancelled_timers.erase(id);
131
+ }
132
+
133
+ auto now = std::chrono::steady_clock::now();
134
+
135
+ Timer t;
136
+ t.id = id;
137
+ t.next_run = now + std::chrono::milliseconds(delay_ms);
138
+ t.interval = repeat ? std::chrono::milliseconds(delay_ms) : std::chrono::milliseconds(0);
139
+ t.task = std::move(task);
140
+
141
+ timers.push(t);
142
+ return id;
143
+ }
144
+ };
145
145
  }
@@ -22,7 +22,7 @@ namespace jspp
22
22
 
23
23
  for (size_t i = 0; i < obj->storage.size(); ++i)
24
24
  {
25
- const auto& prop_val = obj->storage[i];
25
+ const auto &prop_val = obj->storage[i];
26
26
  if (!is_enumerable_property(prop_val))
27
27
  {
28
28
  prop_count--;
@@ -69,8 +69,8 @@ namespace jspp
69
69
  size_t current_prop = 0;
70
70
  for (size_t i = 0; i < obj->shape->property_names.size(); ++i)
71
71
  {
72
- const auto& key = obj->shape->property_names[i];
73
- const auto& prop_val = obj->storage[i];
72
+ const auto &key = obj->shape->property_names[i];
73
+ const auto &prop_val = obj->storage[i];
74
74
 
75
75
  if (!is_enumerable_property(prop_val))
76
76
  continue;
@@ -81,9 +81,10 @@ namespace jspp
81
81
  }
82
82
  else
83
83
  {
84
- ss << "\"" << key << "\"";
84
+ ss << Color::GREEN << "\"" << key << "\"" << Color::RESET;
85
85
  }
86
- ss << ": " << to_log_string(prop_val, visited, depth + 1);
86
+ ss << Color::BRIGHT_BLACK << ": " << Color::RESET;
87
+ ss << to_log_string(prop_val, visited, depth + 1);
87
88
  if (++current_prop < prop_count)
88
89
  ss << Color::BRIGHT_BLACK << ", " << Color::RESET;
89
90
  }
@@ -98,12 +99,12 @@ namespace jspp
98
99
  size_t props_shown = 0;
99
100
  for (size_t i = 0; i < obj->shape->property_names.size(); ++i)
100
101
  {
101
- const auto& key = obj->shape->property_names[i];
102
- const auto& prop_val = obj->storage[i];
102
+ const auto &key = obj->shape->property_names[i];
103
+ const auto &prop_val = obj->storage[i];
103
104
 
104
105
  if (props_shown >= MAX_OBJECT_PROPS)
105
106
  break;
106
-
107
+
107
108
  if (!is_enumerable_property(prop_val))
108
109
  continue;
109
110
 
@@ -117,9 +118,10 @@ namespace jspp
117
118
  }
118
119
  else
119
120
  {
120
- ss << "\"" << key << "\"";
121
+ ss << Color::GREEN << "\"" << key << "\"" << Color::RESET;
121
122
  }
122
- ss << ": " << to_log_string(prop_val, visited, depth + 1);
123
+ ss << Color::BRIGHT_BLACK << ": " << Color::RESET;
124
+ ss << to_log_string(prop_val, visited, depth + 1);
123
125
  props_shown++;
124
126
  }
125
127
  if (prop_count > MAX_OBJECT_PROPS)