@ugo-studio/jspp 0.1.2 → 0.1.4
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 +5 -3
- package/dist/analysis/scope.js +38 -15
- package/dist/analysis/typeAnalyzer.js +257 -23
- package/dist/ast/types.js +6 -0
- package/dist/cli.js +3 -4
- package/dist/core/codegen/class-handlers.js +127 -0
- package/dist/core/codegen/control-flow-handlers.js +464 -0
- package/dist/core/codegen/declaration-handlers.js +31 -14
- package/dist/core/codegen/expression-handlers.js +432 -116
- package/dist/core/codegen/function-handlers.js +110 -13
- package/dist/core/codegen/helpers.js +76 -8
- package/dist/core/codegen/index.js +18 -5
- package/dist/core/codegen/literal-handlers.js +3 -0
- package/dist/core/codegen/statement-handlers.js +152 -186
- package/dist/core/codegen/visitor.js +35 -3
- package/package.json +3 -3
- package/src/prelude/any_value.hpp +658 -734
- package/src/prelude/any_value_access.hpp +103 -0
- package/src/prelude/any_value_defines.hpp +151 -0
- package/src/prelude/any_value_helpers.hpp +246 -0
- package/src/prelude/exception.hpp +31 -0
- package/src/prelude/exception_helpers.hpp +49 -0
- package/src/prelude/index.hpp +35 -12
- package/src/prelude/library/console.hpp +20 -20
- package/src/prelude/library/error.hpp +111 -0
- package/src/prelude/library/global.hpp +15 -4
- package/src/prelude/library/performance.hpp +25 -0
- package/src/prelude/library/promise.hpp +121 -0
- package/src/prelude/library/symbol.hpp +60 -4
- package/src/prelude/library/timer.hpp +92 -0
- package/src/prelude/scheduler.hpp +145 -0
- package/src/prelude/types.hpp +33 -6
- package/src/prelude/utils/access.hpp +174 -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 +37 -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 +119 -0
- package/src/prelude/utils/log_any_value/primitives.hpp +41 -0
- package/src/prelude/{operators.hpp → utils/operators.hpp} +31 -12
- package/src/prelude/utils/well_known_symbols.hpp +13 -0
- package/src/prelude/values/array.hpp +5 -2
- package/src/prelude/{descriptors.hpp → values/descriptors.hpp} +2 -2
- package/src/prelude/values/function.hpp +76 -19
- package/src/prelude/values/{operators → helpers}/array.hpp +30 -14
- package/src/prelude/values/helpers/function.hpp +125 -0
- package/src/prelude/values/helpers/iterator.hpp +107 -0
- package/src/prelude/values/helpers/object.hpp +64 -0
- package/src/prelude/values/helpers/promise.hpp +181 -0
- package/src/prelude/values/helpers/string.hpp +50 -0
- package/src/prelude/values/helpers/symbol.hpp +23 -0
- package/src/prelude/values/iterator.hpp +96 -0
- package/src/prelude/values/object.hpp +8 -3
- package/src/prelude/values/promise.hpp +73 -0
- package/src/prelude/values/prototypes/array.hpp +23 -16
- package/src/prelude/values/prototypes/function.hpp +26 -0
- package/src/prelude/values/prototypes/iterator.hpp +58 -0
- package/src/prelude/values/prototypes/object.hpp +26 -0
- package/src/prelude/values/prototypes/promise.hpp +124 -0
- package/src/prelude/values/prototypes/string.hpp +366 -357
- package/src/prelude/values/prototypes/symbol.hpp +41 -0
- package/src/prelude/values/string.hpp +25 -0
- package/src/prelude/values/symbol.hpp +102 -0
- package/src/prelude/access.hpp +0 -86
- package/src/prelude/error.hpp +0 -31
- package/src/prelude/error_helpers.hpp +0 -59
- package/src/prelude/log_string.hpp +0 -403
- package/src/prelude/values/operators/function.hpp +0 -34
- package/src/prelude/values/operators/object.hpp +0 -34
- package/src/prelude/well_known_symbols.hpp +0 -10
|
@@ -1,57 +1,57 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
|
|
3
|
-
#include
|
|
3
|
+
#include <chrono>
|
|
4
4
|
#include "types.hpp"
|
|
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 "utils/log_any_value/log_any_value.hpp"
|
|
10
10
|
|
|
11
11
|
#include <cmath>
|
|
12
12
|
#include <sstream>
|
|
13
13
|
#include <iomanip>
|
|
14
14
|
|
|
15
|
-
static std::
|
|
15
|
+
static std::map<std::string, std::chrono::steady_clock::time_point> timers = {};
|
|
16
16
|
|
|
17
|
-
auto logFn = jspp::AnyValue::make_function([](const std::vector<jspp::AnyValue> &args)
|
|
17
|
+
auto logFn = jspp::AnyValue::make_function([](const jspp::AnyValue &thisVal, const std::vector<jspp::AnyValue> &args)
|
|
18
18
|
{
|
|
19
19
|
for (size_t i = 0; i < args.size(); ++i)
|
|
20
20
|
{
|
|
21
|
-
std::cout << jspp::
|
|
21
|
+
std::cout << jspp::LogAnyValue::to_log_string(args[i]);
|
|
22
22
|
if (i < args.size() - 1)
|
|
23
23
|
std::cout << " ";
|
|
24
24
|
}
|
|
25
|
-
std::cout << "\n";
|
|
26
|
-
return jspp::AnyValue::make_undefined(); }, "");
|
|
27
|
-
auto warnFn = jspp::AnyValue::make_function([](const std::vector<jspp::AnyValue> &args)
|
|
25
|
+
std::cout << "\n" << std::flush;
|
|
26
|
+
return jspp::AnyValue::make_undefined(); }, "log");
|
|
27
|
+
auto warnFn = jspp::AnyValue::make_function([](const jspp::AnyValue &thisVal, const std::vector<jspp::AnyValue> &args)
|
|
28
28
|
{
|
|
29
29
|
std::cerr << "\033[33m";
|
|
30
30
|
for (size_t i = 0; i < args.size(); ++i)
|
|
31
31
|
{
|
|
32
|
-
std::cout << jspp::
|
|
32
|
+
std::cout << jspp::LogAnyValue::to_log_string(args[i]);
|
|
33
33
|
if (i < args.size() - 1)
|
|
34
34
|
std::cout << " ";
|
|
35
35
|
}
|
|
36
|
-
std::cerr << "\033[0m" << "\n"; // reset
|
|
37
|
-
return jspp::AnyValue::make_undefined(); }, "");
|
|
38
|
-
auto errorFn = jspp::AnyValue::make_function([](const std::vector<jspp::AnyValue> &args)
|
|
36
|
+
std::cerr << "\033[0m" << "\n" << std::flush; // reset
|
|
37
|
+
return jspp::AnyValue::make_undefined(); }, "warn");
|
|
38
|
+
auto errorFn = jspp::AnyValue::make_function([](const jspp::AnyValue &thisVal, const std::vector<jspp::AnyValue> &args)
|
|
39
39
|
{
|
|
40
40
|
std::cerr << "\033[31m";
|
|
41
41
|
for (size_t i = 0; i < args.size(); ++i)
|
|
42
42
|
{
|
|
43
|
-
std::cout << jspp::
|
|
43
|
+
std::cout << jspp::LogAnyValue::to_log_string(args[i]);
|
|
44
44
|
if (i < args.size() - 1)
|
|
45
45
|
std::cout << " ";
|
|
46
46
|
}
|
|
47
|
-
std::cerr << "\033[0m" << "\n"; // reset
|
|
48
|
-
return jspp::AnyValue::make_undefined(); }, "");
|
|
49
|
-
auto timeFn = jspp::AnyValue::make_function([](const std::vector<jspp::AnyValue> &args)
|
|
47
|
+
std::cerr << "\033[0m" << "\n" << std::flush; // reset
|
|
48
|
+
return jspp::AnyValue::make_undefined(); }, "error");
|
|
49
|
+
auto timeFn = jspp::AnyValue::make_function([](const jspp::AnyValue &thisVal, const std::vector<jspp::AnyValue> &args)
|
|
50
50
|
{
|
|
51
51
|
auto start = std::chrono::steady_clock::now(); // capture immediately
|
|
52
52
|
auto key_str = args.size() > 0 ? args[0].to_std_string() : "default";
|
|
53
53
|
timers[key_str] = start;
|
|
54
|
-
return jspp::AnyValue::make_undefined(); }, "");
|
|
54
|
+
return jspp::AnyValue::make_undefined(); }, "time");
|
|
55
55
|
|
|
56
56
|
// helper to format duration in ms -> ms/s/m/h with nice precision
|
|
57
57
|
static auto format_duration = [](double ms) -> std::string
|
|
@@ -83,7 +83,7 @@ static auto format_duration = [](double ms) -> std::string
|
|
|
83
83
|
return ss.str();
|
|
84
84
|
};
|
|
85
85
|
|
|
86
|
-
auto timeEndFn = jspp::AnyValue::make_function([](const std::vector<jspp::AnyValue> &args)
|
|
86
|
+
auto timeEndFn = jspp::AnyValue::make_function([](const jspp::AnyValue &thisVal, const std::vector<jspp::AnyValue> &args)
|
|
87
87
|
{
|
|
88
88
|
auto end = std::chrono::steady_clock::now(); // capture immediately
|
|
89
89
|
auto key_str = args.size() > 0 ? args[0].to_std_string() : "default";
|
|
@@ -100,7 +100,7 @@ auto timeEndFn = jspp::AnyValue::make_function([](const std::vector<jspp::AnyVal
|
|
|
100
100
|
{
|
|
101
101
|
std::cout << "Timer '" << key_str << "' does not exist." << "\n";
|
|
102
102
|
}
|
|
103
|
-
return jspp::AnyValue::make_undefined(); }, "");
|
|
103
|
+
return jspp::AnyValue::make_undefined(); }, "timeEnd");
|
|
104
104
|
|
|
105
105
|
inline auto console = jspp::AnyValue::make_object({
|
|
106
106
|
{"log", logFn},
|
|
@@ -0,0 +1,111 @@
|
|
|
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, const std::vector<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 && (*obj->proto).is_strictly_equal_to_primitive(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 message = "";
|
|
33
|
+
if (!args.empty() && !args[0].is_undefined())
|
|
34
|
+
{
|
|
35
|
+
message = args[0].to_std_string();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
target.define_data_property("message", jspp::AnyValue::make_string(message), true, false, true);
|
|
39
|
+
target.define_data_property("name", jspp::AnyValue::make_string("Error"), true, false, true);
|
|
40
|
+
target.define_data_property("stack", jspp::AnyValue::make_string("Error: " + message + "\n at <unknown>"), true, false, true);
|
|
41
|
+
|
|
42
|
+
if (args.size() > 1 && args[1].is_object())
|
|
43
|
+
{
|
|
44
|
+
jspp::AnyValue cause = args[1].get_own_property("cause");
|
|
45
|
+
if (!cause.is_undefined())
|
|
46
|
+
{
|
|
47
|
+
target.define_data_property("cause", cause, true, false, true);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return target;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
// Static Error.isError(val) implementation
|
|
55
|
+
inline auto isErrorFn = jspp::AnyValue::make_function([](const jspp::AnyValue &thisVal, const std::vector<jspp::AnyValue> &args) -> jspp::AnyValue
|
|
56
|
+
{
|
|
57
|
+
if (args.empty()) return jspp::AnyValue::make_boolean(false);
|
|
58
|
+
|
|
59
|
+
jspp::AnyValue val = args[0];
|
|
60
|
+
if (!val.is_object()) return jspp::AnyValue::make_boolean(false);
|
|
61
|
+
|
|
62
|
+
// Check if it inherits from Error.prototype
|
|
63
|
+
// This is essentially 'instanceof Error'
|
|
64
|
+
jspp::AnyValue proto = Error.get_own_property("prototype");
|
|
65
|
+
|
|
66
|
+
// Walk prototype chain
|
|
67
|
+
if (val.is_object()) {
|
|
68
|
+
auto current = val.as_object()->proto;
|
|
69
|
+
while (current && !(*current).is_null()) {
|
|
70
|
+
if ((*current).is_strictly_equal_to_primitive(proto)) return jspp::AnyValue::make_boolean(true);
|
|
71
|
+
if ((*current).is_object()) current = (*current).as_object()->proto;
|
|
72
|
+
else break;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return jspp::AnyValue::make_boolean(false); }, "isError");
|
|
77
|
+
|
|
78
|
+
// toString method for Error.prototype
|
|
79
|
+
inline auto errorToStringFn = jspp::AnyValue::make_function([](const jspp::AnyValue &thisVal, const std::vector<jspp::AnyValue> &args) -> jspp::AnyValue
|
|
80
|
+
{
|
|
81
|
+
std::string name = "Error";
|
|
82
|
+
std::string msg = "";
|
|
83
|
+
|
|
84
|
+
jspp::AnyValue n = thisVal.get_own_property("name");
|
|
85
|
+
if (!n.is_undefined()) name = n.to_std_string();
|
|
86
|
+
|
|
87
|
+
jspp::AnyValue m = thisVal.get_own_property("message");
|
|
88
|
+
if (!m.is_undefined()) msg = m.to_std_string();
|
|
89
|
+
|
|
90
|
+
if (name.empty() && msg.empty()) return jspp::AnyValue::make_string("Error");
|
|
91
|
+
if (name.empty()) return jspp::AnyValue::make_string(msg);
|
|
92
|
+
if (msg.empty()) return jspp::AnyValue::make_string(name);
|
|
93
|
+
|
|
94
|
+
return jspp::AnyValue::make_string(name + ": " + msg); }, "toString");
|
|
95
|
+
|
|
96
|
+
// Initialize Error class and its prototype
|
|
97
|
+
struct ErrorInit
|
|
98
|
+
{
|
|
99
|
+
ErrorInit()
|
|
100
|
+
{
|
|
101
|
+
// Initialize Error class
|
|
102
|
+
Error = jspp::AnyValue::make_class(errorConstructor, "Error");
|
|
103
|
+
|
|
104
|
+
// Define Error.prototype.toString
|
|
105
|
+
auto proto = Error.get_own_property("prototype");
|
|
106
|
+
proto.define_data_property("toString", errorToStringFn, true, false, true);
|
|
107
|
+
|
|
108
|
+
// Define static Error.isError
|
|
109
|
+
Error.define_data_property("isError", isErrorFn,true ,false,true);
|
|
110
|
+
}
|
|
111
|
+
} errorInit;
|
|
@@ -1,10 +1,21 @@
|
|
|
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
|
+
|
|
12
|
+
inline auto global = jspp::AnyValue::make_object({
|
|
8
13
|
{"console", console},
|
|
14
|
+
{"performance", performance},
|
|
15
|
+
{"Error", Error},
|
|
16
|
+
{"Promise", Promise},
|
|
17
|
+
{"setTimeout", setTimeout},
|
|
18
|
+
{"clearTimeout", clearTimeout},
|
|
19
|
+
{"setInterval", setInterval},
|
|
20
|
+
{"clearInterval", clearInterval},
|
|
9
21
|
});
|
|
10
|
-
inline auto globalThis = global;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <chrono>
|
|
4
|
+
#include "types.hpp"
|
|
5
|
+
#include "values/non_values.hpp"
|
|
6
|
+
#include "values/object.hpp"
|
|
7
|
+
#include "values/function.hpp"
|
|
8
|
+
#include "utils/operators.hpp"
|
|
9
|
+
|
|
10
|
+
inline auto performance = jspp::AnyValue::make_object({
|
|
11
|
+
{"now",
|
|
12
|
+
jspp::AnyValue::make_function(
|
|
13
|
+
// [C++14 Feature] Generalized Lambda Capture
|
|
14
|
+
// We initialize 'startTime' RIGHT HERE inside the [].
|
|
15
|
+
// It acts like a private variable stored inside this specific function.
|
|
16
|
+
[startTime = std::chrono::steady_clock::now()](const jspp::AnyValue &thisVal, const std::vector<jspp::AnyValue> &)
|
|
17
|
+
{
|
|
18
|
+
// We calculate the diff against the captured startTime
|
|
19
|
+
std::chrono::duration<double, std::milli> duration =
|
|
20
|
+
std::chrono::steady_clock::now() - startTime;
|
|
21
|
+
|
|
22
|
+
return jspp::AnyValue::make_number(duration.count());
|
|
23
|
+
},
|
|
24
|
+
"now")},
|
|
25
|
+
});
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include "types.hpp"
|
|
4
|
+
#include "values/promise.hpp"
|
|
5
|
+
#include "any_value.hpp"
|
|
6
|
+
#include "exception.hpp"
|
|
7
|
+
|
|
8
|
+
inline auto Promise = jspp::AnyValue::make_function([](const jspp::AnyValue& thisVal, const std::vector<jspp::AnyValue>& args) -> jspp::AnyValue {
|
|
9
|
+
if (args.empty() || !args[0].is_function()) {
|
|
10
|
+
throw jspp::Exception::make_exception("Promise resolver undefined is not a function", "TypeError");
|
|
11
|
+
}
|
|
12
|
+
auto executor = args[0].as_function();
|
|
13
|
+
|
|
14
|
+
jspp::JsPromise promise;
|
|
15
|
+
auto state = promise.state; // Share state
|
|
16
|
+
|
|
17
|
+
// resolve function
|
|
18
|
+
auto resolveFn = jspp::AnyValue::make_function([state](const jspp::AnyValue&, const std::vector<jspp::AnyValue>& args) -> jspp::AnyValue {
|
|
19
|
+
jspp::JsPromise p; p.state = state;
|
|
20
|
+
p.resolve(args.empty() ? jspp::AnyValue::make_undefined() : args[0]);
|
|
21
|
+
return jspp::AnyValue::make_undefined();
|
|
22
|
+
}, "resolve");
|
|
23
|
+
|
|
24
|
+
// reject function
|
|
25
|
+
auto rejectFn = jspp::AnyValue::make_function([state](const jspp::AnyValue&, const std::vector<jspp::AnyValue>& args) -> jspp::AnyValue {
|
|
26
|
+
jspp::JsPromise p; p.state = state;
|
|
27
|
+
p.reject(args.empty() ? jspp::AnyValue::make_undefined() : args[0]);
|
|
28
|
+
return jspp::AnyValue::make_undefined();
|
|
29
|
+
}, "reject");
|
|
30
|
+
|
|
31
|
+
try {
|
|
32
|
+
executor->call(jspp::AnyValue::make_undefined(), {resolveFn, rejectFn});
|
|
33
|
+
} catch (const jspp::Exception& e) {
|
|
34
|
+
promise.reject(*e.data);
|
|
35
|
+
} catch (...) {
|
|
36
|
+
promise.reject(jspp::AnyValue::make_string("Unknown error during Promise execution"));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return jspp::AnyValue::make_promise(promise);
|
|
40
|
+
|
|
41
|
+
}, "Promise");
|
|
42
|
+
|
|
43
|
+
struct PromiseInit {
|
|
44
|
+
PromiseInit() {
|
|
45
|
+
// Promise.resolve(value)
|
|
46
|
+
Promise.define_data_property("resolve", jspp::AnyValue::make_function([](const jspp::AnyValue&, const std::vector<jspp::AnyValue>& args) -> jspp::AnyValue {
|
|
47
|
+
jspp::JsPromise p;
|
|
48
|
+
p.resolve(args.empty() ? jspp::AnyValue::make_undefined() : args[0]);
|
|
49
|
+
return jspp::AnyValue::make_promise(p);
|
|
50
|
+
}, "resolve"));
|
|
51
|
+
|
|
52
|
+
// Promise.reject(reason)
|
|
53
|
+
Promise.define_data_property("reject", jspp::AnyValue::make_function([](const jspp::AnyValue&, const std::vector<jspp::AnyValue>& args) -> jspp::AnyValue {
|
|
54
|
+
jspp::JsPromise p;
|
|
55
|
+
p.reject(args.empty() ? jspp::AnyValue::make_undefined() : args[0]);
|
|
56
|
+
return jspp::AnyValue::make_promise(p);
|
|
57
|
+
}, "reject"));
|
|
58
|
+
|
|
59
|
+
// Promise.all(iterable)
|
|
60
|
+
Promise.define_data_property("all", jspp::AnyValue::make_function([](const jspp::AnyValue&, const std::vector<jspp::AnyValue>& args) -> jspp::AnyValue {
|
|
61
|
+
// Basic implementation for arrays
|
|
62
|
+
if (args.empty() || !args[0].is_array()) {
|
|
63
|
+
// If not array, reject? Or treat as non-iterable?
|
|
64
|
+
// Should throw TypeError if not iterable. For now assume array.
|
|
65
|
+
// If empty array, return resolved empty array.
|
|
66
|
+
// TODO: Strict iterable check
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Handle non-array iterable or empty args
|
|
70
|
+
if (args.empty() || !args[0].is_array()) {
|
|
71
|
+
jspp::JsPromise p; p.reject(jspp::AnyValue::make_string("Promise.all argument must be an array"));
|
|
72
|
+
return jspp::AnyValue::make_promise(p);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
auto arr = args[0].as_array();
|
|
76
|
+
size_t len = arr->length;
|
|
77
|
+
if (len == 0) {
|
|
78
|
+
jspp::JsPromise p; p.resolve(jspp::AnyValue::make_array({}));
|
|
79
|
+
return jspp::AnyValue::make_promise(p);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
jspp::JsPromise masterPromise;
|
|
83
|
+
auto masterState = masterPromise.state;
|
|
84
|
+
|
|
85
|
+
auto results = std::make_shared<std::vector<std::optional<jspp::AnyValue>>>(len);
|
|
86
|
+
auto count = std::make_shared<size_t>(len);
|
|
87
|
+
|
|
88
|
+
// Check if already rejected to avoid further processing
|
|
89
|
+
auto rejected = std::make_shared<bool>(false);
|
|
90
|
+
|
|
91
|
+
for (size_t i = 0; i < len; ++i) {
|
|
92
|
+
jspp::AnyValue item = arr->get_property(static_cast<uint32_t>(i));
|
|
93
|
+
|
|
94
|
+
auto handleResult = [masterState, results, count, i, rejected](jspp::AnyValue res) {
|
|
95
|
+
if (*rejected) return;
|
|
96
|
+
(*results)[i] = res;
|
|
97
|
+
(*count)--;
|
|
98
|
+
if (*count == 0) {
|
|
99
|
+
jspp::JsPromise p; p.state = masterState;
|
|
100
|
+
p.resolve(jspp::AnyValue::make_array(*results));
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
auto handleReject = [masterState, rejected](jspp::AnyValue reason) {
|
|
105
|
+
if (*rejected) return;
|
|
106
|
+
*rejected = true;
|
|
107
|
+
jspp::JsPromise p; p.state = masterState;
|
|
108
|
+
p.reject(reason);
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
if (item.is_promise()) {
|
|
112
|
+
item.as_promise()->then(handleResult, handleReject);
|
|
113
|
+
} else {
|
|
114
|
+
handleResult(item);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return jspp::AnyValue::make_promise(masterPromise);
|
|
119
|
+
}, "all"));
|
|
120
|
+
}
|
|
121
|
+
} promiseInit;
|
|
@@ -1,8 +1,64 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
|
|
3
3
|
#include "types.hpp"
|
|
4
|
-
#include "
|
|
5
|
-
#include "well_known_symbols.hpp"
|
|
4
|
+
#include "utils/well_known_symbols.hpp"
|
|
6
5
|
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
#include "values/object.hpp"
|
|
7
|
+
#include "any_value.hpp"
|
|
8
|
+
|
|
9
|
+
inline auto Symbol = jspp::AnyValue::make_object({
|
|
10
|
+
{"iterator", jspp::AnyValue::from_symbol(jspp::WellKnownSymbols::iterator)},
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
// #pragma once
|
|
14
|
+
|
|
15
|
+
// #include "types.hpp"
|
|
16
|
+
// #include "utils/well_known_symbols.hpp"
|
|
17
|
+
// #include "values/object.hpp"
|
|
18
|
+
// #include "any_value.hpp"
|
|
19
|
+
|
|
20
|
+
// // We define the Symbol constructor function
|
|
21
|
+
// inline auto symbolConstructor = [](const std::vector<jspp::AnyValue>& args) -> jspp::AnyValue {
|
|
22
|
+
// std::string desc = "";
|
|
23
|
+
// if (!args.empty() && !args[0].is_undefined()) {
|
|
24
|
+
// desc = args[0].to_std_string();
|
|
25
|
+
// }
|
|
26
|
+
// return jspp::AnyValue::make_symbol(desc);
|
|
27
|
+
// };
|
|
28
|
+
|
|
29
|
+
// inline auto Symbol = jspp::AnyValue::make_function(symbolConstructor, "Symbol");
|
|
30
|
+
|
|
31
|
+
// // Implementation of Symbol.for(key)
|
|
32
|
+
// inline auto forFn = jspp::AnyValue::make_function([](const std::vector<jspp::AnyValue>& args) -> jspp::AnyValue {
|
|
33
|
+
// std::string key = "";
|
|
34
|
+
// if (!args.empty()) {
|
|
35
|
+
// key = args[0].to_std_string();
|
|
36
|
+
// }
|
|
37
|
+
// auto symPtr = jspp::JsSymbol::for_global(key);
|
|
38
|
+
// return jspp::AnyValue::from_symbol(symPtr);
|
|
39
|
+
// }, "for");
|
|
40
|
+
|
|
41
|
+
// // Implementation of Symbol.keyFor(sym)
|
|
42
|
+
// inline auto keyForFn = jspp::AnyValue::make_function([](const std::vector<jspp::AnyValue>& args) -> jspp::AnyValue {
|
|
43
|
+
// if (args.empty() || !args[0].is_symbol()) {
|
|
44
|
+
// throw jspp::Exception::make_exception("Symbol.keyFor requires a symbol argument", "TypeError");
|
|
45
|
+
// }
|
|
46
|
+
|
|
47
|
+
// jspp::JsSymbol* sym = args[0].as_symbol();
|
|
48
|
+
// auto result = jspp::JsSymbol::key_for(sym);
|
|
49
|
+
|
|
50
|
+
// if (result.has_value()) {
|
|
51
|
+
// return jspp::AnyValue::make_string(result.value());
|
|
52
|
+
// } else {
|
|
53
|
+
// return jspp::AnyValue::make_undefined();
|
|
54
|
+
// }
|
|
55
|
+
// }, "keyFor");
|
|
56
|
+
|
|
57
|
+
// // Attach static properties/methods to the Symbol object
|
|
58
|
+
// struct SymbolInit {
|
|
59
|
+
// SymbolInit() {
|
|
60
|
+
// Symbol.set_own_property("iterator", jspp::AnyValue::from_symbol(jspp::WellKnownSymbols::iterator));
|
|
61
|
+
// Symbol.set_own_property("for", forFn);
|
|
62
|
+
// Symbol.set_own_property("keyFor", keyForFn);
|
|
63
|
+
// }
|
|
64
|
+
// } symbolInit;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include "types.hpp"
|
|
4
|
+
#include "any_value.hpp"
|
|
5
|
+
#include "scheduler.hpp"
|
|
6
|
+
#include "values/function.hpp"
|
|
7
|
+
#include "exception.hpp"
|
|
8
|
+
|
|
9
|
+
// setTimeout(callback, delay, ...args)
|
|
10
|
+
inline auto setTimeout = jspp::AnyValue::make_function([](const jspp::AnyValue& thisVal, const std::vector<jspp::AnyValue>& args) -> jspp::AnyValue {
|
|
11
|
+
if (args.empty() || !args[0].is_function()) {
|
|
12
|
+
throw jspp::Exception::make_exception("Callback must be a function", "TypeError");
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
auto callback = args[0];
|
|
16
|
+
double delay = 0;
|
|
17
|
+
if (args.size() > 1 && args[1].is_number()) {
|
|
18
|
+
delay = args[1].as_double();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Capture arguments
|
|
22
|
+
std::vector<jspp::AnyValue> callArgs;
|
|
23
|
+
for (size_t i = 2; i < args.size(); ++i) {
|
|
24
|
+
callArgs.push_back(args[i]);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
auto task = [callback, callArgs]() {
|
|
28
|
+
try {
|
|
29
|
+
callback.as_function()->call(jspp::AnyValue::make_undefined(), callArgs);
|
|
30
|
+
} catch (const jspp::Exception& e) {
|
|
31
|
+
std::cerr << "Uncaught exception in setTimeout: " << e.what() << "\n";
|
|
32
|
+
} catch (const std::exception& e) {
|
|
33
|
+
std::cerr << "Uncaught exception in setTimeout: " << e.what() << "\n";
|
|
34
|
+
} catch (...) {
|
|
35
|
+
std::cerr << "Uncaught unknown exception in setTimeout\n";
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
size_t id = jspp::Scheduler::instance().set_timeout(task, static_cast<size_t>(delay));
|
|
40
|
+
return jspp::AnyValue::make_number(static_cast<double>(id));
|
|
41
|
+
}, "setTimeout");
|
|
42
|
+
|
|
43
|
+
// clearTimeout(id)
|
|
44
|
+
inline auto clearTimeout = jspp::AnyValue::make_function([](const jspp::AnyValue& thisVal, const std::vector<jspp::AnyValue>& args) -> jspp::AnyValue {
|
|
45
|
+
if (!args.empty() && args[0].is_number()) {
|
|
46
|
+
size_t id = static_cast<size_t>(args[0].as_double());
|
|
47
|
+
jspp::Scheduler::instance().clear_timer(id);
|
|
48
|
+
}
|
|
49
|
+
return jspp::AnyValue::make_undefined();
|
|
50
|
+
}, "clearTimeout");
|
|
51
|
+
|
|
52
|
+
// setInterval(callback, delay, ...args)
|
|
53
|
+
inline auto setInterval = jspp::AnyValue::make_function([](const jspp::AnyValue& thisVal, const std::vector<jspp::AnyValue>& args) -> jspp::AnyValue {
|
|
54
|
+
if (args.empty() || !args[0].is_function()) {
|
|
55
|
+
throw jspp::Exception::make_exception("Callback must be a function", "TypeError");
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
auto callback = args[0];
|
|
59
|
+
double delay = 0;
|
|
60
|
+
if (args.size() > 1 && args[1].is_number()) {
|
|
61
|
+
delay = args[1].as_double();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
std::vector<jspp::AnyValue> callArgs;
|
|
65
|
+
for (size_t i = 2; i < args.size(); ++i) {
|
|
66
|
+
callArgs.push_back(args[i]);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
auto task = [callback, callArgs]() {
|
|
70
|
+
try {
|
|
71
|
+
callback.as_function()->call(jspp::AnyValue::make_undefined(), callArgs);
|
|
72
|
+
} catch (const jspp::Exception& e) {
|
|
73
|
+
std::cerr << "Uncaught exception in setInterval: " << e.what() << "\n";
|
|
74
|
+
} catch (const std::exception& e) {
|
|
75
|
+
std::cerr << "Uncaught exception in setInterval: " << e.what() << "\n";
|
|
76
|
+
} catch (...) {
|
|
77
|
+
std::cerr << "Uncaught unknown exception in setInterval\n";
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
size_t id = jspp::Scheduler::instance().set_interval(task, static_cast<size_t>(delay));
|
|
82
|
+
return jspp::AnyValue::make_number(static_cast<double>(id));
|
|
83
|
+
}, "setInterval");
|
|
84
|
+
|
|
85
|
+
// clearInterval(id)
|
|
86
|
+
inline auto clearInterval = jspp::AnyValue::make_function([](const jspp::AnyValue& thisVal, const std::vector<jspp::AnyValue>& args) -> jspp::AnyValue {
|
|
87
|
+
if (!args.empty() && args[0].is_number()) {
|
|
88
|
+
size_t id = static_cast<size_t>(args[0].as_double());
|
|
89
|
+
jspp::Scheduler::instance().clear_timer(id);
|
|
90
|
+
}
|
|
91
|
+
return jspp::AnyValue::make_undefined();
|
|
92
|
+
}, "clearInterval");
|