@ugo-studio/jspp 0.3.0 → 0.3.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.
Files changed (127) hide show
  1. package/LICENSE +25 -25
  2. package/README.md +20 -12
  3. package/dist/cli/args.js +22 -0
  4. package/dist/cli/compiler.js +53 -0
  5. package/dist/cli/index.js +43 -107
  6. package/dist/cli/pch.js +71 -0
  7. package/dist/cli/runner.js +23 -0
  8. package/dist/cli/spinner.js +27 -11
  9. package/dist/cli/transpiler.js +20 -0
  10. package/dist/cli/utils.js +59 -0
  11. package/dist/cli/wasm.js +70 -0
  12. package/dist/index.js +17 -6
  13. package/dist/{analysis → interpreter/analysis}/scope.js +38 -3
  14. package/dist/{analysis → interpreter/analysis}/typeAnalyzer.js +563 -28
  15. package/dist/{core → interpreter/core}/codegen/class-handlers.js +1 -1
  16. package/dist/{core → interpreter/core}/codegen/control-flow-handlers.js +12 -11
  17. package/dist/{core → interpreter/core}/codegen/declaration-handlers.js +28 -9
  18. package/dist/{core → interpreter/core}/codegen/destructuring-handlers.js +9 -4
  19. package/dist/{core → interpreter/core}/codegen/expression-handlers.js +82 -88
  20. package/dist/{core → interpreter/core}/codegen/function-handlers.js +159 -46
  21. package/dist/{core → interpreter/core}/codegen/helpers.js +170 -25
  22. package/dist/interpreter/core/codegen/index.js +156 -0
  23. package/dist/{core → interpreter/core}/codegen/literal-handlers.js +9 -0
  24. package/dist/{core → interpreter/core}/codegen/statement-handlers.js +47 -7
  25. package/package.json +6 -4
  26. package/scripts/precompile-headers.ts +293 -50
  27. package/scripts/setup-compiler.ts +63 -63
  28. package/scripts/setup-emsdk.ts +114 -0
  29. package/src/prelude/any_value.cpp +888 -0
  30. package/src/prelude/any_value.hpp +29 -24
  31. package/src/prelude/{exception_helpers.hpp → exception.cpp} +53 -53
  32. package/src/prelude/exception.hpp +27 -27
  33. package/src/prelude/iterator_instantiations.hpp +10 -0
  34. package/src/prelude/{index.hpp → jspp.hpp} +13 -17
  35. package/src/prelude/library/array.cpp +191 -0
  36. package/src/prelude/library/array.hpp +5 -178
  37. package/src/prelude/library/boolean.cpp +30 -0
  38. package/src/prelude/library/boolean.hpp +14 -0
  39. package/src/prelude/library/console.cpp +125 -0
  40. package/src/prelude/library/console.hpp +9 -97
  41. package/src/prelude/library/error.cpp +100 -0
  42. package/src/prelude/library/error.hpp +8 -108
  43. package/src/prelude/library/function.cpp +69 -0
  44. package/src/prelude/library/function.hpp +6 -5
  45. package/src/prelude/library/global.cpp +98 -0
  46. package/src/prelude/library/global.hpp +12 -28
  47. package/src/prelude/library/global_usings.hpp +15 -0
  48. package/src/prelude/library/math.cpp +261 -0
  49. package/src/prelude/library/math.hpp +8 -288
  50. package/src/prelude/library/object.cpp +379 -0
  51. package/src/prelude/library/object.hpp +5 -267
  52. package/src/prelude/library/performance.cpp +21 -0
  53. package/src/prelude/library/performance.hpp +5 -20
  54. package/src/prelude/library/process.cpp +38 -0
  55. package/src/prelude/library/process.hpp +3 -31
  56. package/src/prelude/library/promise.cpp +131 -0
  57. package/src/prelude/library/promise.hpp +5 -116
  58. package/src/prelude/library/symbol.cpp +56 -0
  59. package/src/prelude/library/symbol.hpp +5 -46
  60. package/src/prelude/library/timer.cpp +88 -0
  61. package/src/prelude/library/timer.hpp +11 -87
  62. package/src/prelude/runtime.cpp +19 -0
  63. package/src/prelude/types.hpp +26 -20
  64. package/src/prelude/utils/access.hpp +123 -32
  65. package/src/prelude/utils/assignment_operators.hpp +119 -99
  66. package/src/prelude/utils/log_any_value/array.hpp +61 -40
  67. package/src/prelude/utils/log_any_value/function.hpp +39 -39
  68. package/src/prelude/utils/log_any_value/log_any_value.hpp +1 -1
  69. package/src/prelude/utils/log_any_value/object.hpp +60 -3
  70. package/src/prelude/utils/log_any_value/primitives.hpp +1 -1
  71. package/src/prelude/utils/operators.hpp +109 -94
  72. package/src/prelude/utils/operators_native.hpp +349 -0
  73. package/src/prelude/utils/well_known_symbols.hpp +24 -24
  74. package/src/prelude/values/array.cpp +1399 -0
  75. package/src/prelude/values/array.hpp +4 -0
  76. package/src/prelude/values/async_iterator.cpp +251 -0
  77. package/src/prelude/values/async_iterator.hpp +60 -32
  78. package/src/prelude/values/boolean.cpp +64 -0
  79. package/src/prelude/values/function.cpp +262 -0
  80. package/src/prelude/values/function.hpp +10 -30
  81. package/src/prelude/values/iterator.cpp +309 -0
  82. package/src/prelude/values/iterator.hpp +33 -64
  83. package/src/prelude/values/number.cpp +221 -0
  84. package/src/prelude/values/object.cpp +200 -0
  85. package/src/prelude/values/object.hpp +4 -0
  86. package/src/prelude/values/promise.cpp +479 -0
  87. package/src/prelude/values/promise.hpp +9 -2
  88. package/src/prelude/values/prototypes/array.hpp +46 -1348
  89. package/src/prelude/values/prototypes/async_iterator.hpp +19 -61
  90. package/src/prelude/values/prototypes/boolean.hpp +24 -0
  91. package/src/prelude/values/prototypes/function.hpp +7 -46
  92. package/src/prelude/values/prototypes/iterator.hpp +15 -191
  93. package/src/prelude/values/prototypes/number.hpp +30 -210
  94. package/src/prelude/values/prototypes/object.hpp +7 -23
  95. package/src/prelude/values/prototypes/promise.hpp +8 -186
  96. package/src/prelude/values/prototypes/string.hpp +28 -553
  97. package/src/prelude/values/prototypes/symbol.hpp +9 -70
  98. package/src/prelude/values/shape.hpp +52 -52
  99. package/src/prelude/values/string.cpp +485 -0
  100. package/src/prelude/values/symbol.cpp +89 -0
  101. package/src/prelude/values/symbol.hpp +101 -101
  102. package/dist/cli/file-utils.js +0 -20
  103. package/dist/cli-utils/args.js +0 -59
  104. package/dist/cli-utils/colors.js +0 -9
  105. package/dist/cli-utils/file-utils.js +0 -20
  106. package/dist/cli-utils/spinner.js +0 -55
  107. package/dist/cli.js +0 -153
  108. package/dist/core/codegen/index.js +0 -86
  109. package/src/prelude/any_value_access.hpp +0 -170
  110. package/src/prelude/any_value_defines.hpp +0 -190
  111. package/src/prelude/any_value_helpers.hpp +0 -374
  112. package/src/prelude/utils/operators_primitive.hpp +0 -337
  113. package/src/prelude/values/helpers/array.hpp +0 -199
  114. package/src/prelude/values/helpers/async_iterator.hpp +0 -275
  115. package/src/prelude/values/helpers/function.hpp +0 -109
  116. package/src/prelude/values/helpers/iterator.hpp +0 -145
  117. package/src/prelude/values/helpers/object.hpp +0 -104
  118. package/src/prelude/values/helpers/promise.hpp +0 -254
  119. package/src/prelude/values/helpers/string.hpp +0 -37
  120. package/src/prelude/values/helpers/symbol.hpp +0 -21
  121. /package/dist/{ast → interpreter/ast}/symbols.js +0 -0
  122. /package/dist/{ast → interpreter/ast}/types.js +0 -0
  123. /package/dist/{core → interpreter/core}/codegen/visitor.js +0 -0
  124. /package/dist/{core → interpreter/core}/constants.js +0 -0
  125. /package/dist/{core → interpreter/core}/error.js +0 -0
  126. /package/dist/{core → interpreter/core}/parser.js +0 -0
  127. /package/dist/{core → interpreter/core}/traverser.js +0 -0
@@ -5,182 +5,9 @@
5
5
  #include "utils/operators.hpp"
6
6
  #include "utils/access.hpp"
7
7
 
8
- inline auto Array = jspp::AnyValue::make_class([](jspp::AnyValue thisVal, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
9
- {
10
- if (args.size() == 1 && args[0].is_number()) {
11
- double len = args[0].as_double();
12
- if (len < 0 || len > 4294967295.0) { // Max uint32
13
- throw jspp::Exception::make_exception("Invalid array length", "RangeError");
14
- }
15
- auto arr = jspp::AnyValue::make_array(std::vector<jspp::AnyValue>());
16
- auto arr_ptr = arr.as_array();
17
- arr_ptr->length = static_cast<uint64_t>(len);
18
- arr_ptr->dense.resize(static_cast<size_t>(len), jspp::Constants::UNINITIALIZED);
19
- return arr;
20
- }
21
- std::vector<jspp::AnyValue> elements;
22
- for(const auto& arg : args) {
23
- elements.push_back(arg);
24
- }
25
- return jspp::AnyValue::make_array(std::move(elements)); }, "Array");
8
+ namespace jspp {
9
+ extern AnyValue Array;
10
+ void init_array();
11
+ }
26
12
 
27
- struct ArrayInit
28
- {
29
- ArrayInit()
30
- {
31
- // Array.isArray(value)
32
- Array.define_data_property("isArray", jspp::AnyValue::make_function([](jspp::AnyValue, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
33
- {
34
- if (args.empty()) return jspp::Constants::FALSE;
35
- return jspp::AnyValue::make_boolean(args[0].is_array()); }, "isArray"));
36
-
37
- // Array.of(...elements)
38
- Array.define_data_property("of", jspp::AnyValue::make_function([](jspp::AnyValue, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
39
- {
40
- std::vector<jspp::AnyValue> elements;
41
- for(const auto& arg : args) {
42
- elements.push_back(arg);
43
- }
44
- return jspp::AnyValue::make_array(std::move(elements)); }, "of"));
45
-
46
- // Array.from(arrayLike, mapFn?, thisArg?)
47
- Array.define_data_property("from", jspp::AnyValue::make_function([](jspp::AnyValue, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
48
- {
49
- if (args.empty() || args[0].is_null() || args[0].is_undefined()) {
50
- throw jspp::Exception::make_exception("Array.from requires an array-like object", "TypeError");
51
- }
52
-
53
- const auto& items = args[0];
54
- const auto& mapFn = (args.size() > 1 && args[1].is_function()) ? args[1] : jspp::Constants::UNDEFINED;
55
- const auto& thisArg = (args.size() > 2) ? args[2] : jspp::Constants::UNDEFINED;
56
-
57
- std::vector<jspp::AnyValue> result;
58
-
59
- auto iteratorSym = jspp::WellKnownSymbols::iterator;
60
- if (items.has_property(iteratorSym->key)) {
61
- auto iter = jspp::Access::get_object_iterator(items, "Array.from source");
62
- auto nextFn = iter.get_own_property("next");
63
-
64
- size_t k = 0;
65
- while (true) {
66
- auto nextRes = nextFn.call(iter, std::span<const jspp::AnyValue>{}, "next");
67
- if (jspp::is_truthy(nextRes.get_own_property("done"))) break;
68
-
69
- auto val = nextRes.get_own_property("value");
70
- if (mapFn.is_function()) {
71
- jspp::AnyValue kVal = jspp::AnyValue::make_number(k);
72
- const jspp::AnyValue mapArgs[] = {val, kVal};
73
- val = mapFn.call(thisArg, std::span<const jspp::AnyValue>(mapArgs, 2));
74
- }
75
- result.push_back(val);
76
- k++;
77
- }
78
- } else {
79
- // Array-like (length property)
80
- auto lenVal = items.get_property_with_receiver("length", items);
81
- size_t len = static_cast<size_t>(jspp::Operators_Private::ToUint32(lenVal));
82
-
83
- for (size_t k = 0; k < len; ++k) {
84
- auto kVal = items.get_property_with_receiver(std::to_string(k), items);
85
- if (mapFn.is_function()) {
86
- jspp::AnyValue kNum = jspp::AnyValue::make_number(k);
87
- const jspp::AnyValue mapArgs[] = {kVal, kNum};
88
- kVal = mapFn.call(thisArg, std::span<const jspp::AnyValue>(mapArgs, 2));
89
- }
90
- result.push_back(kVal);
91
- }
92
- }
93
-
94
- return jspp::AnyValue::make_array(std::move(result)); }, "from"));
95
-
96
- // Array.fromAsync(iterableOrArrayLike, mapFn?, thisArg?)
97
- Array.define_data_property("fromAsync", jspp::AnyValue::make_async_function([](jspp::AnyValue, std::vector<jspp::AnyValue> args) -> jspp::JsPromise
98
- {
99
- if (args.empty() || args[0].is_null() || args[0].is_undefined()) {
100
- throw jspp::Exception::make_exception("Array.fromAsync requires an iterable or array-like object", "TypeError");
101
- }
102
-
103
- const auto& items = args[0];
104
- const auto& mapFn = (args.size() > 1 && args[1].is_function()) ? args[1] : jspp::Constants::UNDEFINED;
105
- const auto& thisArg = (args.size() > 2) ? args[2] : jspp::Constants::UNDEFINED;
106
-
107
- std::vector<jspp::AnyValue> result;
108
-
109
- bool isAsync = false;
110
- jspp::AnyValue iter = jspp::Constants::UNDEFINED;
111
- jspp::AnyValue nextFn = jspp::Constants::UNDEFINED;
112
-
113
- if (items.has_property(jspp::WellKnownSymbols::asyncIterator->key)) {
114
- auto method = items.get_property_with_receiver(jspp::WellKnownSymbols::asyncIterator->key, items);
115
- if (method.is_function()) {
116
- iter = method.call(items, {});
117
- nextFn = iter.get_own_property("next");
118
- isAsync = true;
119
- }
120
- }
121
-
122
- if (!isAsync && items.has_property(jspp::WellKnownSymbols::iterator->key)) {
123
- auto method = items.get_property_with_receiver(jspp::WellKnownSymbols::iterator->key, items);
124
- if (method.is_function()) {
125
- iter = method.call(items, {});
126
- nextFn = iter.get_own_property("next");
127
- }
128
- }
129
-
130
- if (!iter.is_undefined()) {
131
- size_t k = 0;
132
- while (true) {
133
- auto nextRes = nextFn.call(iter, {});
134
-
135
- if (nextRes.is_promise()) {
136
- nextRes = co_await nextRes;
137
- }
138
-
139
- if (jspp::is_truthy(nextRes.get_own_property("done"))) break;
140
-
141
- auto val = nextRes.get_own_property("value");
142
-
143
- if (mapFn.is_function()) {
144
- jspp::AnyValue kVal = jspp::AnyValue::make_number(k);
145
- const jspp::AnyValue mapArgs[] = {val, kVal};
146
- auto mapRes = mapFn.call(thisArg, std::span<const jspp::AnyValue>(mapArgs, 2));
147
- if (mapRes.is_promise()) {
148
- val = co_await mapRes;
149
- } else {
150
- val = mapRes;
151
- }
152
- }
153
- result.push_back(val);
154
- k++;
155
- }
156
- } else {
157
- auto lenVal = items.get_property_with_receiver("length", items);
158
- size_t len = static_cast<size_t>(jspp::Operators_Private::ToUint32(lenVal));
159
-
160
- for (size_t k = 0; k < len; ++k) {
161
- auto kVal = items.get_property_with_receiver(std::to_string(k), items);
162
- if (kVal.is_promise()) {
163
- kVal = co_await kVal;
164
- }
165
-
166
- if (mapFn.is_function()) {
167
- jspp::AnyValue kNum = jspp::AnyValue::make_number(k);
168
- const jspp::AnyValue mapArgs[] = {kVal, kNum};
169
- auto mapRes = mapFn.call(thisArg, std::span<const jspp::AnyValue>(mapArgs, 2));
170
- if (mapRes.is_promise()) {
171
- kVal = co_await mapRes;
172
- } else {
173
- kVal = mapRes;
174
- }
175
- }
176
- result.push_back(kVal);
177
- }
178
- }
179
-
180
- co_return jspp::AnyValue::make_array(std::move(result)); }, "fromAsync"));
181
-
182
- // Array[Symbol.species]
183
- Array.define_getter(jspp::AnyValue::from_symbol(jspp::WellKnownSymbols::species), jspp::AnyValue::make_function([](jspp::AnyValue thisVal, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
184
- { return thisVal; }, "get [Symbol.species]"));
185
- }
186
- } arrayInit;
13
+ using jspp::Array;
@@ -0,0 +1,30 @@
1
+ #include "jspp.hpp"
2
+ #include "library/boolean.hpp"
3
+
4
+ namespace jspp
5
+ {
6
+ // TODO: implement boolean constructor
7
+ jspp::AnyValue Boolean = jspp::AnyValue::make_function(
8
+ std::function<AnyValue(AnyValue, std::span<const AnyValue>)>([](jspp::AnyValue thisVal, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
9
+ {
10
+ if (args.empty())
11
+ return jspp::Constants::FALSE;
12
+ return jspp::AnyValue::make_boolean(jspp::is_truthy(args[0])); }),
13
+ "Boolean");
14
+
15
+ struct BooleanInit
16
+ {
17
+ BooleanInit()
18
+ { // TODO: implement boolean prototypes
19
+ // auto proto = Boolean.get_own_property("prototype");
20
+ // proto.define_data_property("valueOf", jspp::BooleanPrototypes::get("valueOf").value(), true, false, true);
21
+ // proto.define_data_property("toString", jspp::BooleanPrototypes::get("toString").value(), true, false, true);
22
+ }
23
+ };
24
+
25
+ void init_boolean()
26
+ {
27
+ static BooleanInit booleanInit;
28
+ }
29
+
30
+ }
@@ -0,0 +1,14 @@
1
+ #pragma once
2
+
3
+ #include "types.hpp"
4
+ #include "any_value.hpp"
5
+ #include "utils/operators.hpp"
6
+ #include "utils/access.hpp"
7
+
8
+ namespace jspp
9
+ {
10
+ extern AnyValue Boolean;
11
+ void init_boolean();
12
+ }
13
+
14
+ using jspp::Boolean;
@@ -0,0 +1,125 @@
1
+ #include "jspp.hpp"
2
+ #include "library/console.hpp"
3
+ #include <chrono>
4
+ #include <map>
5
+
6
+ static std::map<std::string, std::chrono::steady_clock::time_point> timers = {};
7
+
8
+ namespace jspp {
9
+ jspp::AnyValue logFn;
10
+ jspp::AnyValue warnFn;
11
+ jspp::AnyValue errorFn;
12
+ jspp::AnyValue timeFn;
13
+ jspp::AnyValue timeEndFn;
14
+ jspp::AnyValue console;
15
+
16
+ static auto format_duration = [](double ms) -> std::string
17
+ {
18
+ std::ostringstream ss;
19
+ if (ms < 1000.0)
20
+ {
21
+ ss << std::fixed << std::setprecision(4) << ms << "ms";
22
+ return ss.str();
23
+ }
24
+ double total_s = ms / 1000.0;
25
+ if (ms < 60000.0)
26
+ {
27
+ ss << std::fixed << std::setprecision(4) << total_s << "s";
28
+ return ss.str();
29
+ }
30
+ if (ms < 3600000.0)
31
+ {
32
+ int minutes = static_cast<int>(ms / 60000.0);
33
+ double seconds = (ms - minutes * 60000.0) / 1000.0;
34
+ ss << minutes << "m " << std::fixed << std::setprecision(4) << seconds << "s";
35
+ return ss.str();
36
+ }
37
+ int hours = static_cast<int>(ms / 3600000.0);
38
+ int minutes = static_cast<int>((ms - hours * 3600000.0) / 60000.0);
39
+ double seconds = (ms - hours * 3600000.0 - minutes * 60000.0) / 1000.0;
40
+ ss << hours << "h " << minutes << "m " << std::fixed << std::setprecision(4) << seconds << "s";
41
+ return ss.str();
42
+ };
43
+
44
+ void init_console() {
45
+ if (!console.is_undefined()) return;
46
+
47
+ logFn = jspp::AnyValue::make_function(
48
+ std::function<AnyValue(AnyValue, std::span<const AnyValue>)>([](jspp::AnyValue thisVal, std::span<const jspp::AnyValue> args)
49
+ {
50
+ for (size_t i = 0; i < args.size(); ++i)
51
+ {
52
+ std::cout << jspp::LogAnyValue::to_log_string(args[i]);
53
+ if (i < args.size() - 1)
54
+ std::cout << " ";
55
+ }
56
+ std::cout << "\n" << std::flush;
57
+ return jspp::Constants::UNDEFINED;
58
+ }), "log");
59
+
60
+ warnFn = jspp::AnyValue::make_function(
61
+ std::function<AnyValue(AnyValue, std::span<const AnyValue>)>([](jspp::AnyValue thisVal, std::span<const jspp::AnyValue> args)
62
+ {
63
+ std::cerr << "\033[33m";
64
+ for (size_t i = 0; i < args.size(); ++i)
65
+ {
66
+ std::cout << jspp::LogAnyValue::to_log_string(args[i]);
67
+ if (i < args.size() - 1)
68
+ std::cout << " ";
69
+ }
70
+ std::cerr << "\033[0m" << "\n" << std::flush;
71
+ return jspp::Constants::UNDEFINED;
72
+ }), "warn");
73
+
74
+ errorFn = jspp::AnyValue::make_function(
75
+ std::function<AnyValue(AnyValue, std::span<const AnyValue>)>([](jspp::AnyValue thisVal, std::span<const jspp::AnyValue> args)
76
+ {
77
+ std::cerr << "\033[31m";
78
+ for (size_t i = 0; i < args.size(); ++i)
79
+ {
80
+ std::cout << jspp::LogAnyValue::to_log_string(args[i]);
81
+ if (i < args.size() - 1)
82
+ std::cout << " ";
83
+ }
84
+ std::cerr << "\033[0m" << "\n" << std::flush;
85
+ return jspp::Constants::UNDEFINED;
86
+ }), "error");
87
+
88
+ timeFn = jspp::AnyValue::make_function(
89
+ std::function<AnyValue(AnyValue, std::span<const AnyValue>)>([](jspp::AnyValue thisVal, std::span<const jspp::AnyValue> args)
90
+ {
91
+ auto start = std::chrono::steady_clock::now();
92
+ auto key_str = args.size() > 0 ? args[0].to_std_string() : "default";
93
+ timers[key_str] = start;
94
+ return jspp::Constants::UNDEFINED;
95
+ }), "time");
96
+
97
+ timeEndFn = jspp::AnyValue::make_function(
98
+ std::function<AnyValue(AnyValue, std::span<const AnyValue>)>([](jspp::AnyValue thisVal, std::span<const jspp::AnyValue> args)
99
+ {
100
+ auto end = std::chrono::steady_clock::now();
101
+ auto key_str = args.size() > 0 ? args[0].to_std_string() : "default";
102
+ auto it = timers.find(key_str);
103
+ if (it != timers.end())
104
+ {
105
+ std::chrono::duration<double, std::milli> duration = end - it->second;
106
+ double ms = duration.count();
107
+ std::cout << "\033[90m" << "[" << format_duration(ms) << "] " << "\033[0m" << key_str << "\n";
108
+ timers.erase(it);
109
+ }
110
+ else
111
+ {
112
+ std::cout << "Timer '" << key_str << "' does not exist.\n";
113
+ }
114
+ return jspp::Constants::UNDEFINED;
115
+ }), "timeEnd");
116
+
117
+ console = jspp::AnyValue::make_object({
118
+ {"log", logFn},
119
+ {"warn", warnFn},
120
+ {"error", errorFn},
121
+ {"time", timeFn},
122
+ {"timeEnd", timeEndFn},
123
+ });
124
+ }
125
+ }
@@ -13,100 +13,12 @@
13
13
  #include <sstream>
14
14
  #include <iomanip>
15
15
 
16
- static std::map<std::string, std::chrono::steady_clock::time_point> timers = {};
17
-
18
- auto logFn = jspp::AnyValue::make_function([](jspp::AnyValue thisVal, std::span<const jspp::AnyValue> args)
19
- {
20
- for (size_t i = 0; i < args.size(); ++i)
21
- {
22
- std::cout << jspp::LogAnyValue::to_log_string(args[i]);
23
- if (i < args.size() - 1)
24
- std::cout << " ";
25
- }
26
- std::cout << "\n" << std::flush;
27
- return jspp::Constants::UNDEFINED; }, "log");
28
- auto warnFn = jspp::AnyValue::make_function([](jspp::AnyValue thisVal, std::span<const jspp::AnyValue> args)
29
- {
30
- std::cerr << "\033[33m";
31
- for (size_t i = 0; i < args.size(); ++i)
32
- {
33
- std::cout << jspp::LogAnyValue::to_log_string(args[i]);
34
- if (i < args.size() - 1)
35
- std::cout << " ";
36
- }
37
- std::cerr << "\033[0m" << "\n" << std::flush; // reset
38
- return jspp::Constants::UNDEFINED; }, "warn");
39
- auto errorFn = jspp::AnyValue::make_function([](jspp::AnyValue thisVal, std::span<const jspp::AnyValue> args)
40
- {
41
- std::cerr << "\033[31m";
42
- for (size_t i = 0; i < args.size(); ++i)
43
- {
44
- std::cout << jspp::LogAnyValue::to_log_string(args[i]);
45
- if (i < args.size() - 1)
46
- std::cout << " ";
47
- }
48
- std::cerr << "\033[0m" << "\n" << std::flush; // reset
49
- return jspp::Constants::UNDEFINED; }, "error");
50
- auto timeFn = jspp::AnyValue::make_function([](jspp::AnyValue thisVal, std::span<const jspp::AnyValue> args)
51
- {
52
- auto start = std::chrono::steady_clock::now(); // capture immediately
53
- auto key_str = args.size() > 0 ? args[0].to_std_string() : "default";
54
- timers[key_str] = start;
55
- return jspp::Constants::UNDEFINED; }, "time");
56
-
57
- // helper to format duration in ms -> ms/s/m/h with nice precision
58
- static auto format_duration = [](double ms) -> std::string
59
- {
60
- std::ostringstream ss;
61
- if (ms < 1000.0)
62
- {
63
- ss << std::fixed << std::setprecision(4) << ms << "ms";
64
- return ss.str();
65
- }
66
- double total_s = ms / 1000.0;
67
- if (ms < 60000.0)
68
- { // less than a minute -> show seconds
69
- ss << std::fixed << std::setprecision(4) << total_s << "s";
70
- return ss.str();
71
- }
72
- if (ms < 3600000.0)
73
- { // less than an hour -> show minutes + seconds
74
- int minutes = static_cast<int>(ms / 60000.0);
75
- double seconds = (ms - minutes * 60000.0) / 1000.0;
76
- ss << minutes << "m " << std::fixed << std::setprecision(4) << seconds << "s";
77
- return ss.str();
78
- }
79
- // hours, minutes, seconds
80
- int hours = static_cast<int>(ms / 3600000.0);
81
- int minutes = static_cast<int>((ms - hours * 3600000.0) / 60000.0);
82
- double seconds = (ms - hours * 3600000.0 - minutes * 60000.0) / 1000.0;
83
- ss << hours << "h " << minutes << "m " << std::fixed << std::setprecision(4) << seconds << "s";
84
- return ss.str();
85
- };
86
-
87
- auto timeEndFn = jspp::AnyValue::make_function([](jspp::AnyValue thisVal, std::span<const jspp::AnyValue> args)
88
- {
89
- auto end = std::chrono::steady_clock::now(); // capture immediately
90
- auto key_str = args.size() > 0 ? args[0].to_std_string() : "default";
91
- auto it = timers.find(key_str);
92
- if (it != timers.end())
93
- {
94
- std::chrono::duration<double, std::milli> duration = end - it->second;
95
- double ms = duration.count();
96
- std::string formatted = format_duration(ms);
97
- std::cout << "\033[90m" << "[" << format_duration(ms) << "] " << "\033[0m" << key_str << "\n";
98
- timers.erase(it); // remove the timer after ending it
99
- }
100
- else
101
- {
102
- std::cout << "Timer '" << key_str << "' does not exist." << "\n";
103
- }
104
- return jspp::Constants::UNDEFINED; }, "timeEnd");
105
-
106
- inline auto console = jspp::AnyValue::make_object({
107
- {"log", logFn},
108
- {"warn", warnFn},
109
- {"error", errorFn},
110
- {"time", timeFn},
111
- {"timeEnd", timeEndFn},
112
- });
16
+ namespace jspp {
17
+ extern AnyValue logFn;
18
+ extern AnyValue warnFn;
19
+ extern AnyValue errorFn;
20
+ extern AnyValue timeFn;
21
+ extern AnyValue timeEndFn;
22
+ extern AnyValue console;
23
+ void init_console();
24
+ }
@@ -0,0 +1,100 @@
1
+ #include "jspp.hpp"
2
+ #include "library/error.hpp"
3
+
4
+ namespace jspp
5
+ {
6
+ jspp::AnyValue Error;
7
+
8
+ auto errorConstructor = [](jspp::AnyValue thisVal, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
9
+ {
10
+ jspp::AnyValue proto = Error.get_own_property("prototype");
11
+ jspp::AnyValue target = thisVal;
12
+ bool is_construct_call = false;
13
+
14
+ if (target.is_object())
15
+ {
16
+ auto obj = target.as_object();
17
+ if (!obj->proto.is_null() && !obj->proto.is_undefined() && is_strictly_equal_to_native(obj->proto, proto))
18
+ {
19
+ is_construct_call = true;
20
+ }
21
+ }
22
+
23
+ if (!is_construct_call)
24
+ {
25
+ target = jspp::AnyValue::make_object({}).set_prototype(proto);
26
+ }
27
+
28
+ std::string name = "Error";
29
+ std::string message = "";
30
+ if (!args.empty() && !args[0].is_undefined())
31
+ {
32
+ message = args[0].to_std_string();
33
+ }
34
+
35
+ target.define_data_property("message", jspp::AnyValue::make_string(message), true, false, true);
36
+ target.define_data_property("name", jspp::AnyValue::make_string(name), true, false, true);
37
+ target.define_data_property("stack", jspp::AnyValue::make_string(name + ": " + message + "\n at <unknown>"), true, false, true);
38
+
39
+ if (args.size() > 1 && args[1].is_object())
40
+ {
41
+ jspp::AnyValue cause = args[1].get_own_property("cause");
42
+ if (!cause.is_undefined())
43
+ {
44
+ target.define_data_property("cause", cause, true, false, true);
45
+ }
46
+ }
47
+
48
+ return target;
49
+ };
50
+
51
+ jspp::AnyValue isErrorFn = jspp::AnyValue::make_function(
52
+ std::function<AnyValue(AnyValue, std::span<const AnyValue>)>([](jspp::AnyValue, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
53
+ {
54
+ if (args.empty()) return jspp::Constants::FALSE;
55
+ jspp::AnyValue val = args[0];
56
+ if (!val.is_object()) return jspp::Constants::FALSE;
57
+ jspp::AnyValue proto = Error.get_own_property("prototype");
58
+ if (val.is_object()) {
59
+ auto current = val.as_object()->proto;
60
+ while (!current.is_null()) {
61
+ if (is_strictly_equal_to_native(current, proto)) return jspp::Constants::TRUE;
62
+ if (current.is_object()) current = current.as_object()->proto;
63
+ else break;
64
+ }
65
+ }
66
+ return jspp::Constants::FALSE; }),
67
+ "isError");
68
+
69
+ jspp::AnyValue errorToStringFn = jspp::AnyValue::make_function(
70
+ std::function<AnyValue(AnyValue, std::span<const AnyValue>)>([](jspp::AnyValue thisVal, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
71
+ {
72
+ std::string name = "Error";
73
+ std::string msg = "";
74
+ jspp::AnyValue n = thisVal.get_own_property("name");
75
+ if (!n.is_undefined()) name = n.to_std_string();
76
+ jspp::AnyValue m = thisVal.get_own_property("message");
77
+ if (!m.is_undefined()) msg = m.to_std_string();
78
+ if (name.empty() && msg.empty()) return jspp::AnyValue::make_string("Error");
79
+ if (name.empty()) return jspp::AnyValue::make_string(msg);
80
+ if (msg.empty()) return jspp::AnyValue::make_string(name);
81
+ return jspp::AnyValue::make_string(name + ": " + msg); }),
82
+ "toString");
83
+
84
+ struct ErrorInit
85
+ {
86
+ ErrorInit()
87
+ {
88
+ Error = jspp::AnyValue::make_class(
89
+ std::function<AnyValue(AnyValue, std::span<const AnyValue>)>(errorConstructor), "Error");
90
+ auto proto = Error.get_own_property("prototype");
91
+ proto.define_data_property("toString", errorToStringFn, true, false, true);
92
+ proto.define_data_property(jspp::AnyValue::from_symbol(jspp::WellKnownSymbols::toStringTag), errorToStringFn, true, false, true);
93
+ Error.define_data_property("isError", isErrorFn, true, false, true);
94
+ }
95
+ };
96
+ void init_error()
97
+ {
98
+ static ErrorInit errorInit;
99
+ }
100
+ }