@ugo-studio/jspp 0.1.3 → 0.1.5
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.
- package/README.md +2 -2
- package/dist/analysis/scope.js +33 -4
- package/dist/analysis/typeAnalyzer.js +260 -21
- package/dist/ast/symbols.js +29 -0
- package/dist/cli-utils/args.js +57 -0
- package/dist/cli-utils/colors.js +9 -0
- package/dist/cli-utils/file-utils.js +20 -0
- package/dist/cli-utils/spinner.js +55 -0
- package/dist/cli.js +105 -31
- package/dist/core/codegen/class-handlers.js +131 -0
- package/dist/core/codegen/control-flow-handlers.js +474 -0
- package/dist/core/codegen/declaration-handlers.js +36 -15
- package/dist/core/codegen/expression-handlers.js +579 -125
- package/dist/core/codegen/function-handlers.js +222 -37
- package/dist/core/codegen/helpers.js +158 -4
- package/dist/core/codegen/index.js +20 -8
- package/dist/core/codegen/literal-handlers.js +18 -6
- package/dist/core/codegen/statement-handlers.js +171 -228
- package/dist/core/codegen/visitor.js +31 -3
- package/package.json +3 -3
- package/src/prelude/any_value.hpp +510 -633
- package/src/prelude/any_value_access.hpp +151 -0
- package/src/prelude/any_value_defines.hpp +190 -0
- package/src/prelude/any_value_helpers.hpp +139 -225
- package/src/prelude/exception.hpp +32 -0
- package/src/prelude/exception_helpers.hpp +49 -0
- package/src/prelude/index.hpp +25 -9
- package/src/prelude/library/array.hpp +190 -0
- package/src/prelude/library/console.hpp +14 -13
- package/src/prelude/library/error.hpp +113 -0
- package/src/prelude/library/function.hpp +10 -0
- package/src/prelude/library/global.hpp +35 -4
- package/src/prelude/library/math.hpp +308 -0
- package/src/prelude/library/object.hpp +288 -0
- package/src/prelude/library/performance.hpp +2 -2
- package/src/prelude/library/process.hpp +39 -0
- package/src/prelude/library/promise.hpp +131 -0
- package/src/prelude/library/symbol.hpp +46 -59
- package/src/prelude/library/timer.hpp +92 -0
- package/src/prelude/scheduler.hpp +145 -0
- package/src/prelude/types.hpp +58 -1
- package/src/prelude/utils/access.hpp +345 -0
- package/src/prelude/utils/assignment_operators.hpp +99 -0
- package/src/prelude/utils/log_any_value/array.hpp +245 -0
- package/src/prelude/utils/log_any_value/config.hpp +32 -0
- package/src/prelude/utils/log_any_value/function.hpp +39 -0
- package/src/prelude/utils/log_any_value/fwd.hpp +15 -0
- package/src/prelude/utils/log_any_value/helpers.hpp +62 -0
- package/src/prelude/utils/log_any_value/log_any_value.hpp +94 -0
- package/src/prelude/utils/log_any_value/object.hpp +136 -0
- package/src/prelude/utils/log_any_value/primitives.hpp +43 -0
- package/src/prelude/utils/operators.hpp +751 -0
- package/src/prelude/utils/well_known_symbols.hpp +25 -0
- package/src/prelude/values/array.hpp +10 -7
- package/src/prelude/{descriptors.hpp → values/descriptors.hpp} +2 -2
- package/src/prelude/values/function.hpp +85 -51
- package/src/prelude/values/helpers/array.hpp +80 -35
- package/src/prelude/values/helpers/function.hpp +110 -77
- package/src/prelude/values/helpers/iterator.hpp +16 -10
- package/src/prelude/values/helpers/object.hpp +85 -10
- package/src/prelude/values/helpers/promise.hpp +181 -0
- package/src/prelude/values/helpers/string.hpp +3 -3
- package/src/prelude/values/helpers/symbol.hpp +2 -2
- package/src/prelude/values/iterator.hpp +14 -6
- package/src/prelude/values/object.hpp +14 -3
- package/src/prelude/values/promise.hpp +73 -0
- package/src/prelude/values/prototypes/array.hpp +855 -16
- package/src/prelude/values/prototypes/function.hpp +4 -4
- package/src/prelude/values/prototypes/iterator.hpp +11 -10
- package/src/prelude/values/prototypes/number.hpp +153 -0
- package/src/prelude/values/prototypes/object.hpp +26 -0
- package/src/prelude/values/prototypes/promise.hpp +134 -0
- package/src/prelude/values/prototypes/string.hpp +29 -29
- package/src/prelude/values/prototypes/symbol.hpp +22 -3
- package/src/prelude/values/shape.hpp +52 -0
- package/src/prelude/values/string.hpp +1 -1
- package/src/prelude/values/symbol.hpp +1 -1
- package/src/prelude/access.hpp +0 -91
- package/src/prelude/error.hpp +0 -31
- package/src/prelude/error_helpers.hpp +0 -59
- package/src/prelude/log_string.hpp +0 -407
- package/src/prelude/operators.hpp +0 -256
- package/src/prelude/well_known_symbols.hpp +0 -14
|
@@ -0,0 +1,190 @@
|
|
|
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
|
+
inline auto Array = jspp::AnyValue::make_class([](const 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
|
+
arr.as_array()->length = static_cast<uint64_t>(len);
|
|
17
|
+
arr.as_array()->dense.resize(static_cast<size_t>(len), jspp::AnyValue::make_uninitialized());
|
|
18
|
+
return arr;
|
|
19
|
+
}
|
|
20
|
+
std::vector<jspp::AnyValue> elements;
|
|
21
|
+
for(const auto& arg : args) {
|
|
22
|
+
elements.push_back(arg);
|
|
23
|
+
}
|
|
24
|
+
return jspp::AnyValue::make_array(std::move(elements)); }, "Array");
|
|
25
|
+
|
|
26
|
+
struct ArrayInit
|
|
27
|
+
{
|
|
28
|
+
ArrayInit()
|
|
29
|
+
{
|
|
30
|
+
// Set Array.prototype.proto to Object.prototype
|
|
31
|
+
// Array.get_own_property("prototype").set_prototype(::Object.get_own_property("prototype"));
|
|
32
|
+
|
|
33
|
+
// Array.isArray(value)
|
|
34
|
+
Array.define_data_property("isArray", jspp::AnyValue::make_function([](const jspp::AnyValue &, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
|
|
35
|
+
{
|
|
36
|
+
if (args.empty()) return jspp::Constants::FALSE;
|
|
37
|
+
return jspp::AnyValue::make_boolean(args[0].is_array()); }, "isArray"));
|
|
38
|
+
|
|
39
|
+
// Array.of(...elements)
|
|
40
|
+
Array.define_data_property("of", jspp::AnyValue::make_function([](const jspp::AnyValue &, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
|
|
41
|
+
{
|
|
42
|
+
std::vector<jspp::AnyValue> elements;
|
|
43
|
+
for(const auto& arg : args) {
|
|
44
|
+
elements.push_back(arg);
|
|
45
|
+
}
|
|
46
|
+
return jspp::AnyValue::make_array(std::move(elements)); }, "of"));
|
|
47
|
+
|
|
48
|
+
// Array.from(arrayLike, mapFn?, thisArg?)
|
|
49
|
+
Array.define_data_property("from", jspp::AnyValue::make_function([](const jspp::AnyValue &, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
|
|
50
|
+
{
|
|
51
|
+
if (args.empty() || args[0].is_null() || args[0].is_undefined()) {
|
|
52
|
+
throw jspp::Exception::make_exception("Array.from requires an array-like object", "TypeError");
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const auto& items = args[0];
|
|
56
|
+
const auto& mapFn = (args.size() > 1 && args[1].is_function()) ? args[1] : jspp::Constants::UNDEFINED;
|
|
57
|
+
const auto& thisArg = (args.size() > 2) ? args[2] : jspp::Constants::UNDEFINED;
|
|
58
|
+
|
|
59
|
+
std::vector<jspp::AnyValue> result;
|
|
60
|
+
|
|
61
|
+
// Check if iterable
|
|
62
|
+
// Simple check: does it have [Symbol.iterator]?
|
|
63
|
+
auto iteratorSym = jspp::WellKnownSymbols::iterator;
|
|
64
|
+
if (items.has_property(iteratorSym->key)) {
|
|
65
|
+
auto iter = jspp::Access::get_object_value_iterator(items, "Array.from source");
|
|
66
|
+
auto nextFn = iter.get_own_property("next");
|
|
67
|
+
|
|
68
|
+
size_t k = 0;
|
|
69
|
+
while (true) {
|
|
70
|
+
auto nextRes = nextFn.call(iter, std::span<const jspp::AnyValue>{}, "next");
|
|
71
|
+
if (jspp::is_truthy(nextRes.get_own_property("done"))) break;
|
|
72
|
+
|
|
73
|
+
auto val = nextRes.get_own_property("value");
|
|
74
|
+
if (mapFn.is_function()) {
|
|
75
|
+
jspp::AnyValue kVal = jspp::AnyValue::make_number(k);
|
|
76
|
+
const jspp::AnyValue mapArgs[] = {val, kVal};
|
|
77
|
+
val = mapFn.call(thisArg, std::span<const jspp::AnyValue>(mapArgs, 2));
|
|
78
|
+
}
|
|
79
|
+
result.push_back(val);
|
|
80
|
+
k++;
|
|
81
|
+
}
|
|
82
|
+
} else {
|
|
83
|
+
// Array-like (length property)
|
|
84
|
+
auto lenVal = items.get_property_with_receiver("length", items);
|
|
85
|
+
size_t len = static_cast<size_t>(jspp::Operators_Private::ToUint32(lenVal));
|
|
86
|
+
|
|
87
|
+
for (size_t k = 0; k < len; ++k) {
|
|
88
|
+
auto kVal = items.get_property_with_receiver(std::to_string(k), items);
|
|
89
|
+
if (mapFn.is_function()) {
|
|
90
|
+
jspp::AnyValue kNum = jspp::AnyValue::make_number(k);
|
|
91
|
+
const jspp::AnyValue mapArgs[] = {kVal, kNum};
|
|
92
|
+
kVal = mapFn.call(thisArg, std::span<const jspp::AnyValue>(mapArgs, 2));
|
|
93
|
+
}
|
|
94
|
+
result.push_back(kVal);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return jspp::AnyValue::make_array(std::move(result)); }, "from"));
|
|
99
|
+
|
|
100
|
+
// Array.fromAsync(iterableOrArrayLike, mapFn?, thisArg?)
|
|
101
|
+
Array.define_data_property("fromAsync", jspp::AnyValue::make_async_function([](const jspp::AnyValue &, std::span<const jspp::AnyValue> args) -> jspp::JsPromise
|
|
102
|
+
{
|
|
103
|
+
if (args.empty() || args[0].is_null() || args[0].is_undefined()) {
|
|
104
|
+
throw jspp::Exception::make_exception("Array.fromAsync requires an iterable or array-like object", "TypeError");
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const auto& items = args[0];
|
|
108
|
+
const auto& mapFn = (args.size() > 1 && args[1].is_function()) ? args[1] : jspp::Constants::UNDEFINED;
|
|
109
|
+
const auto& thisArg = (args.size() > 2) ? args[2] : jspp::Constants::UNDEFINED;
|
|
110
|
+
|
|
111
|
+
std::vector<jspp::AnyValue> result;
|
|
112
|
+
|
|
113
|
+
bool isAsync = false;
|
|
114
|
+
jspp::AnyValue iter;
|
|
115
|
+
jspp::AnyValue nextFn;
|
|
116
|
+
|
|
117
|
+
if (items.has_property(jspp::WellKnownSymbols::asyncIterator->key)) {
|
|
118
|
+
auto method = items.get_property_with_receiver(jspp::WellKnownSymbols::asyncIterator->key, items);
|
|
119
|
+
if (method.is_function()) {
|
|
120
|
+
iter = method.call(items, {});
|
|
121
|
+
nextFn = iter.get_own_property("next");
|
|
122
|
+
isAsync = true;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (!isAsync && items.has_property(jspp::WellKnownSymbols::iterator->key)) {
|
|
127
|
+
auto method = items.get_property_with_receiver(jspp::WellKnownSymbols::iterator->key, items);
|
|
128
|
+
if (method.is_function()) {
|
|
129
|
+
iter = method.call(items, {});
|
|
130
|
+
nextFn = iter.get_own_property("next");
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (!iter.is_undefined()) {
|
|
135
|
+
size_t k = 0;
|
|
136
|
+
while (true) {
|
|
137
|
+
auto nextRes = nextFn.call(iter, {});
|
|
138
|
+
|
|
139
|
+
if (nextRes.is_promise()) {
|
|
140
|
+
nextRes = co_await nextRes;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (jspp::is_truthy(nextRes.get_own_property("done"))) break;
|
|
144
|
+
|
|
145
|
+
auto val = nextRes.get_own_property("value");
|
|
146
|
+
|
|
147
|
+
if (mapFn.is_function()) {
|
|
148
|
+
jspp::AnyValue kVal = jspp::AnyValue::make_number(k);
|
|
149
|
+
const jspp::AnyValue mapArgs[] = {val, kVal};
|
|
150
|
+
auto mapRes = mapFn.call(thisArg, std::span<const jspp::AnyValue>(mapArgs, 2));
|
|
151
|
+
if (mapRes.is_promise()) {
|
|
152
|
+
val = co_await mapRes;
|
|
153
|
+
} else {
|
|
154
|
+
val = mapRes;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
result.push_back(val);
|
|
158
|
+
k++;
|
|
159
|
+
}
|
|
160
|
+
} else {
|
|
161
|
+
auto lenVal = items.get_property_with_receiver("length", items);
|
|
162
|
+
size_t len = static_cast<size_t>(jspp::Operators_Private::ToUint32(lenVal));
|
|
163
|
+
|
|
164
|
+
for (size_t k = 0; k < len; ++k) {
|
|
165
|
+
auto kVal = items.get_property_with_receiver(std::to_string(k), items);
|
|
166
|
+
if (kVal.is_promise()) {
|
|
167
|
+
kVal = co_await kVal;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (mapFn.is_function()) {
|
|
171
|
+
jspp::AnyValue kNum = jspp::AnyValue::make_number(k);
|
|
172
|
+
const jspp::AnyValue mapArgs[] = {kVal, kNum};
|
|
173
|
+
auto mapRes = mapFn.call(thisArg, std::span<const jspp::AnyValue>(mapArgs, 2));
|
|
174
|
+
if (mapRes.is_promise()) {
|
|
175
|
+
kVal = co_await mapRes;
|
|
176
|
+
} else {
|
|
177
|
+
kVal = mapRes;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
result.push_back(kVal);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
co_return jspp::AnyValue::make_array(std::move(result)); }, "fromAsync"));
|
|
185
|
+
|
|
186
|
+
// Array[Symbol.species]
|
|
187
|
+
Array.define_getter(jspp::AnyValue::from_symbol(jspp::WellKnownSymbols::species), jspp::AnyValue::make_function([](const jspp::AnyValue &thisVal, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
|
|
188
|
+
{ return thisVal; }, "get [Symbol.species]"));
|
|
189
|
+
}
|
|
190
|
+
} arrayInit;
|
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
#include "values/non_values.hpp"
|
|
6
6
|
#include "values/object.hpp"
|
|
7
7
|
#include "values/function.hpp"
|
|
8
|
-
#include "operators.hpp"
|
|
9
|
-
#include "
|
|
8
|
+
#include "utils/operators.hpp"
|
|
9
|
+
#include "exception.hpp"
|
|
10
|
+
#include "utils/log_any_value/log_any_value.hpp"
|
|
10
11
|
|
|
11
12
|
#include <cmath>
|
|
12
13
|
#include <sstream>
|
|
@@ -14,39 +15,39 @@
|
|
|
14
15
|
|
|
15
16
|
static std::map<std::string, std::chrono::steady_clock::time_point> timers = {};
|
|
16
17
|
|
|
17
|
-
auto logFn = jspp::AnyValue::make_function([](const std::
|
|
18
|
+
auto logFn = jspp::AnyValue::make_function([](const jspp::AnyValue &thisVal, std::span<const jspp::AnyValue> args)
|
|
18
19
|
{
|
|
19
20
|
for (size_t i = 0; i < args.size(); ++i)
|
|
20
21
|
{
|
|
21
|
-
std::cout << jspp::
|
|
22
|
+
std::cout << jspp::LogAnyValue::to_log_string(args[i]);
|
|
22
23
|
if (i < args.size() - 1)
|
|
23
24
|
std::cout << " ";
|
|
24
25
|
}
|
|
25
|
-
std::cout << "\n";
|
|
26
|
+
std::cout << "\n" << std::flush;
|
|
26
27
|
return jspp::AnyValue::make_undefined(); }, "log");
|
|
27
|
-
auto warnFn = jspp::AnyValue::make_function([](const std::
|
|
28
|
+
auto warnFn = jspp::AnyValue::make_function([](const jspp::AnyValue &thisVal, std::span<const jspp::AnyValue> args)
|
|
28
29
|
{
|
|
29
30
|
std::cerr << "\033[33m";
|
|
30
31
|
for (size_t i = 0; i < args.size(); ++i)
|
|
31
32
|
{
|
|
32
|
-
std::cout << jspp::
|
|
33
|
+
std::cout << jspp::LogAnyValue::to_log_string(args[i]);
|
|
33
34
|
if (i < args.size() - 1)
|
|
34
35
|
std::cout << " ";
|
|
35
36
|
}
|
|
36
|
-
std::cerr << "\033[0m" << "\n"; // reset
|
|
37
|
+
std::cerr << "\033[0m" << "\n" << std::flush; // reset
|
|
37
38
|
return jspp::AnyValue::make_undefined(); }, "warn");
|
|
38
|
-
auto errorFn = jspp::AnyValue::make_function([](const std::
|
|
39
|
+
auto errorFn = jspp::AnyValue::make_function([](const jspp::AnyValue &thisVal, std::span<const jspp::AnyValue> args)
|
|
39
40
|
{
|
|
40
41
|
std::cerr << "\033[31m";
|
|
41
42
|
for (size_t i = 0; i < args.size(); ++i)
|
|
42
43
|
{
|
|
43
|
-
std::cout << jspp::
|
|
44
|
+
std::cout << jspp::LogAnyValue::to_log_string(args[i]);
|
|
44
45
|
if (i < args.size() - 1)
|
|
45
46
|
std::cout << " ";
|
|
46
47
|
}
|
|
47
|
-
std::cerr << "\033[0m" << "\n"; // reset
|
|
48
|
+
std::cerr << "\033[0m" << "\n" << std::flush; // reset
|
|
48
49
|
return jspp::AnyValue::make_undefined(); }, "error");
|
|
49
|
-
auto timeFn = jspp::AnyValue::make_function([](const std::
|
|
50
|
+
auto timeFn = jspp::AnyValue::make_function([](const jspp::AnyValue &thisVal, std::span<const jspp::AnyValue> args)
|
|
50
51
|
{
|
|
51
52
|
auto start = std::chrono::steady_clock::now(); // capture immediately
|
|
52
53
|
auto key_str = args.size() > 0 ? args[0].to_std_string() : "default";
|
|
@@ -83,7 +84,7 @@ static auto format_duration = [](double ms) -> std::string
|
|
|
83
84
|
return ss.str();
|
|
84
85
|
};
|
|
85
86
|
|
|
86
|
-
auto timeEndFn = jspp::AnyValue::make_function([](const std::
|
|
87
|
+
auto timeEndFn = jspp::AnyValue::make_function([](const jspp::AnyValue &thisVal, std::span<const jspp::AnyValue> args)
|
|
87
88
|
{
|
|
88
89
|
auto end = std::chrono::steady_clock::now(); // capture immediately
|
|
89
90
|
auto key_str = args.size() > 0 ? args[0].to_std_string() : "default";
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include "types.hpp"
|
|
4
|
+
#include "any_value.hpp"
|
|
5
|
+
|
|
6
|
+
// Declare Error variable
|
|
7
|
+
inline jspp::AnyValue Error;
|
|
8
|
+
|
|
9
|
+
// Constructor logic
|
|
10
|
+
inline auto errorConstructor = [](const jspp::AnyValue &thisVal, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
|
|
11
|
+
{
|
|
12
|
+
// Access global Error to get prototype
|
|
13
|
+
jspp::AnyValue proto = Error.get_own_property("prototype");
|
|
14
|
+
|
|
15
|
+
jspp::AnyValue target = thisVal;
|
|
16
|
+
bool is_construct_call = false;
|
|
17
|
+
|
|
18
|
+
if (target.is_object())
|
|
19
|
+
{
|
|
20
|
+
auto obj = target.as_object();
|
|
21
|
+
if (obj->proto && is_strictly_equal_to_primitive((*obj->proto), proto))
|
|
22
|
+
{
|
|
23
|
+
is_construct_call = true;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (!is_construct_call)
|
|
28
|
+
{
|
|
29
|
+
target = jspp::AnyValue::make_object_with_proto({}, proto);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
std::string name = "Error";
|
|
33
|
+
std::string message = "";
|
|
34
|
+
if (!args.empty() && !args[0].is_undefined())
|
|
35
|
+
{
|
|
36
|
+
message = args[0].to_std_string();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
target.define_data_property("message", jspp::AnyValue::make_string(message), true, false, true);
|
|
40
|
+
target.define_data_property("name", jspp::AnyValue::make_string(name), true, false, true);
|
|
41
|
+
target.define_data_property("stack", jspp::AnyValue::make_string(name + ": " + message + "\n at <unknown>"), true, false, true);
|
|
42
|
+
|
|
43
|
+
if (args.size() > 1 && args[1].is_object())
|
|
44
|
+
{
|
|
45
|
+
jspp::AnyValue cause = args[1].get_own_property("cause");
|
|
46
|
+
if (!cause.is_undefined())
|
|
47
|
+
{
|
|
48
|
+
target.define_data_property("cause", cause, true, false, true);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return target;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
// Static Error.isError(val) implementation
|
|
56
|
+
inline auto isErrorFn = jspp::AnyValue::make_function([](const jspp::AnyValue &thisVal, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
|
|
57
|
+
{
|
|
58
|
+
if (args.empty()) return jspp::AnyValue::make_boolean(false);
|
|
59
|
+
|
|
60
|
+
jspp::AnyValue val = args[0];
|
|
61
|
+
if (!val.is_object()) return jspp::AnyValue::make_boolean(false);
|
|
62
|
+
|
|
63
|
+
// Check if it inherits from Error.prototype
|
|
64
|
+
// This is essentially 'instanceof Error'
|
|
65
|
+
jspp::AnyValue proto = Error.get_own_property("prototype");
|
|
66
|
+
|
|
67
|
+
// Walk prototype chain
|
|
68
|
+
if (val.is_object()) {
|
|
69
|
+
auto current = val.as_object()->proto;
|
|
70
|
+
while (current && !(*current).is_null()) {
|
|
71
|
+
if (is_strictly_equal_to_primitive((*current),proto)) return jspp::AnyValue::make_boolean(true);
|
|
72
|
+
if ((*current).is_object()) current = (*current).as_object()->proto;
|
|
73
|
+
else break;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return jspp::AnyValue::make_boolean(false); }, "isError");
|
|
78
|
+
|
|
79
|
+
// toString method for Error.prototype
|
|
80
|
+
inline auto errorToStringFn = jspp::AnyValue::make_function([](const jspp::AnyValue &thisVal, std::span<const jspp::AnyValue> args) -> jspp::AnyValue
|
|
81
|
+
{
|
|
82
|
+
std::string name = "Error";
|
|
83
|
+
std::string msg = "";
|
|
84
|
+
|
|
85
|
+
jspp::AnyValue n = thisVal.get_own_property("name");
|
|
86
|
+
if (!n.is_undefined()) name = n.to_std_string();
|
|
87
|
+
|
|
88
|
+
jspp::AnyValue m = thisVal.get_own_property("message");
|
|
89
|
+
if (!m.is_undefined()) msg = m.to_std_string();
|
|
90
|
+
|
|
91
|
+
if (name.empty() && msg.empty()) return jspp::AnyValue::make_string("Error");
|
|
92
|
+
if (name.empty()) return jspp::AnyValue::make_string(msg);
|
|
93
|
+
if (msg.empty()) return jspp::AnyValue::make_string(name);
|
|
94
|
+
|
|
95
|
+
return jspp::AnyValue::make_string(name + ": " + msg); }, "toString");
|
|
96
|
+
|
|
97
|
+
// Initialize Error class and its prototype
|
|
98
|
+
struct ErrorInit
|
|
99
|
+
{
|
|
100
|
+
ErrorInit()
|
|
101
|
+
{
|
|
102
|
+
// Initialize Error class
|
|
103
|
+
Error = jspp::AnyValue::make_class(errorConstructor, "Error");
|
|
104
|
+
|
|
105
|
+
// Define Error.prototype.toString
|
|
106
|
+
auto proto = Error.get_own_property("prototype");
|
|
107
|
+
proto.define_data_property("toString", errorToStringFn, true, false, true);
|
|
108
|
+
proto.define_data_property(jspp::WellKnownSymbols::toStringTag->key, errorToStringFn, true, false, true);
|
|
109
|
+
|
|
110
|
+
// Define static Error.isError
|
|
111
|
+
Error.define_data_property("isError", isErrorFn, true, false, true);
|
|
112
|
+
}
|
|
113
|
+
} errorInit;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include "types.hpp"
|
|
4
|
+
#include "any_value.hpp"
|
|
5
|
+
|
|
6
|
+
// Define Function constructor
|
|
7
|
+
// In a full implementation, this would support 'new Function(args, body)'
|
|
8
|
+
inline auto Function = jspp::AnyValue::make_class([](const jspp::AnyValue& thisVal, std::span<const jspp::AnyValue> args) -> jspp::AnyValue {
|
|
9
|
+
return jspp::Constants::UNDEFINED;
|
|
10
|
+
}, "Function");
|
|
@@ -1,10 +1,41 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
|
|
3
3
|
#include "types.hpp"
|
|
4
|
-
#include "
|
|
5
|
-
#include "
|
|
4
|
+
#include "values/non_values.hpp"
|
|
5
|
+
#include "values/object.hpp"
|
|
6
|
+
#include "values/function.hpp"
|
|
7
|
+
#include "utils/operators.hpp"
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
#include "library/promise.hpp"
|
|
10
|
+
#include "library/timer.hpp"
|
|
11
|
+
#include "library/math.hpp"
|
|
12
|
+
|
|
13
|
+
inline auto global = jspp::AnyValue::make_object({
|
|
14
|
+
{"Symbol", Symbol},
|
|
15
|
+
{"process", process},
|
|
16
|
+
{"Function", Function},
|
|
8
17
|
{"console", console},
|
|
18
|
+
{"performance", performance},
|
|
19
|
+
{"Error", Error},
|
|
20
|
+
{"Promise", Promise},
|
|
21
|
+
{"setTimeout", setTimeout},
|
|
22
|
+
{"clearTimeout", clearTimeout},
|
|
23
|
+
{"setInterval", setInterval},
|
|
24
|
+
{"clearInterval", clearInterval},
|
|
25
|
+
{"Math", Math},
|
|
26
|
+
{"Object", Object},
|
|
27
|
+
{"Array", Array},
|
|
9
28
|
});
|
|
10
|
-
|
|
29
|
+
|
|
30
|
+
struct GlobalInit {
|
|
31
|
+
GlobalInit() {
|
|
32
|
+
auto objectProto = ::Object.get_own_property("prototype");
|
|
33
|
+
|
|
34
|
+
// Tie built-in prototypes to Object.prototype
|
|
35
|
+
::Array.get_own_property("prototype").set_prototype(objectProto);
|
|
36
|
+
::Function.get_own_property("prototype").set_prototype(objectProto);
|
|
37
|
+
::Error.get_own_property("prototype").set_prototype(objectProto);
|
|
38
|
+
::Promise.get_own_property("prototype").set_prototype(objectProto);
|
|
39
|
+
::Symbol.get_own_property("prototype").set_prototype(objectProto);
|
|
40
|
+
}
|
|
41
|
+
} globalInit;
|