From cd84c3f68ae292cb3e6f93b68f5a8ea4fcca90b7 Mon Sep 17 00:00:00 2001 From: ftk Date: Sun, 14 Jul 2019 19:03:15 +0000 Subject: [PATCH 001/185] more types --- main.cpp | 7 +++- quickjspp.hpp | 109 ++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 110 insertions(+), 6 deletions(-) diff --git a/main.cpp b/main.cpp index ec2c8f53b8..00e972da85 100644 --- a/main.cpp +++ b/main.cpp @@ -18,8 +18,6 @@ class test { int x; public: - inline static JSClassID QJSClassId; - test(int32_t x) : x{x} { printf("ctor %d!\n", x); } @@ -62,6 +60,11 @@ int main(int argc, char ** argv) obj["g"] = detail::fwrapper<&test::g>{"g"}; obj["fun2"] = detail::fwrapper<&f2>{"f2"}; obj["f"] = detail::fwrapper<&test::f>{"f"}; + obj[3u] = detail::js_string{"43!"}; + + int testint = obj[3u]; + std::string teststr = obj[3u]; + std::cout << testint<< teststr; context.registerClass("test_class", std::move(obj)); diff --git a/quickjspp.hpp b/quickjspp.hpp index 37bdf28e2c..c8569f5c19 100644 --- a/quickjspp.hpp +++ b/quickjspp.hpp @@ -56,7 +56,92 @@ namespace qjs { } }; -/* + template <> + struct js_traits + { + static bool unwrap(JSContext * ctx, JSValue v) noexcept + { + return JS_ToBool(ctx, v); + } + + static JSValue wrap(JSContext * ctx, bool i) noexcept + { + return JS_NewBool(ctx, i); + } + }; + + template <> + struct js_traits + { + static double unwrap(JSContext * ctx, JSValue v) + { + double r; + if(JS_ToFloat64(ctx, &r, v)) + throw exception{}; + return r; + } + + static JSValue wrap(JSContext * ctx, double i) noexcept + { + return JS_NewFloat64(ctx, i); + } + }; + + class js_string : public std::string_view + { + using Base = std::string_view; + JSContext * ctx = nullptr; + + friend struct js_traits; + js_string(JSContext * ctx, const char * ptr, std::size_t len) : Base(ptr, len), ctx(ctx) {} + public: + + template + js_string(Args&&... args) : Base(std::forward(args)...), ctx(nullptr) {} + + js_string(const js_string& other) = delete; + + ~js_string() + { + if(ctx) + JS_FreeCString(ctx, this->data()); + } + }; + + template <> + struct js_traits + { + static js_string unwrap(JSContext * ctx, JSValue v) + { + int plen; + const char * ptr = JS_ToCStringLen(ctx, &plen, v, 0); + if(!ptr) + throw exception{}; + return js_string{ctx, ptr, (std::size_t)plen}; + } + + static JSValue wrap(JSContext * ctx, js_string str) noexcept + { + return JS_NewStringLen(ctx, str.data(), (int)str.size()); + } + }; + + template <> // slower + struct js_traits + { + static std::string unwrap(JSContext * ctx, JSValue v) + { + auto str_view = js_traits::unwrap(ctx, v); + return std::string{str_view.data(), str_view.size()}; + } + + static JSValue wrap(JSContext * ctx, const std::string& str) noexcept + { + return JS_NewStringLen(ctx, str.data(), (int) str.size()); + } + }; + + /* template std::tuple to_tuple_impl(JSContext * ctx, JSValue * argv) { @@ -255,7 +340,22 @@ namespace qjs { { return JS_GetPropertyStr(ctx, this_obj, name); } + }; + template <> + struct js_property_traits + { + static void set_property(JSContext * ctx, JSValue this_obj, uint32_t idx, JSValue value) + { + int err = JS_SetPropertyUint32(ctx, this_obj, idx, value); + if(err < 0) + throw exception{}; + } + + static JSValue get_property(JSContext * ctx, JSValue this_obj, uint32_t idx) noexcept + { + return JS_GetPropertyUint32(ctx, this_obj, idx); + } }; template @@ -265,9 +365,10 @@ namespace qjs { JSValue this_obj; Key key; - operator JSValue() const + template + operator Value() const { - return js_property_traits::get_property(ctx, this_obj, key); + return js_traits::unwrap(ctx, js_property_traits::get_property(ctx, this_obj, key)); } template @@ -471,7 +572,7 @@ namespace qjs { { JSValue v = JS_Eval(ctx, buffer.data(), buffer.size(), filename, eval_flags); //if(JS_IsException(v)) - //throw detail::exception{}; + //throw detail::exception{}; return Value{ctx, v}; } From f4ce6085e51991ae319c2a6669027460f5106e21 Mon Sep 17 00:00:00 2001 From: ftk Date: Mon, 22 Jul 2019 15:38:30 +0000 Subject: [PATCH 002/185] more types, function support and some tests --- main.cpp | 99 +++++++++++++------ quickjspp.hpp | 259 ++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 265 insertions(+), 93 deletions(-) diff --git a/main.cpp b/main.cpp index 00e972da85..1924b1316e 100644 --- a/main.cpp +++ b/main.cpp @@ -8,38 +8,45 @@ #include #include - int32_t f(int32_t x) { return x * x; }; +#define TYPES bool, int32_t, double, std::shared_ptr, const std::shared_ptr&, std::string, const std::string& + class test { - int x; + bool b; + int32_t i; + double d; + std::shared_ptr spt; + std::string s; public: - test(int32_t x) : x{x} - { printf("ctor %d!\n", x); } + test(int32_t i, TYPES) : i(i) + { printf("ctor!\n"); } + + test(int32_t i) : i(i) + { printf("ctor %d!\n", i); } test(const test&) = delete; ~test() { printf("dtor!\n"); } - void f() - { printf("f(%p): x=%d\n", this, x); } + int32_t fi(TYPES) { i++; return i; } + bool fb(TYPES) { i++; return b; } + double fd(TYPES) { i++; return d; } + const std::shared_ptr& fspt(TYPES) { i++; return spt; } + const std::string& fs(TYPES) { i++; return s; } + void f(TYPES) { i++; } - static void g() - { printf("g()\n"); } + static void fstatic(TYPES) {} }; -int32_t f2(int32_t x, std::shared_ptr ptr) -{ - std::cout << ptr.get() << std::endl; - return x * x; -}; +void f(TYPES) {} int main(int argc, char ** argv) @@ -54,28 +61,31 @@ int main(int argc, char ** argv) Context context(runtime); ctx = context.ctx; - auto obj = context.newObject(); - obj["test"] = 54; - obj["test2"] = 56; - obj["g"] = detail::fwrapper<&test::g>{"g"}; - obj["fun2"] = detail::fwrapper<&f2>{"f2"}; - obj["f"] = detail::fwrapper<&test::f>{"f"}; - obj[3u] = detail::js_string{"43!"}; - - int testint = obj[3u]; - std::string teststr = obj[3u]; - std::cout << testint<< teststr; + { + auto obj = context.newObject(); + obj["vi"] = 54; + obj["vb"] = true; + obj["vd"] = 56.0; + obj["vs"] = std::string{"test string"}; + obj.add("lambda", [](int x) -> int { return x * x; }); + obj.add<&test::fi>("fi"); + obj.add<&test::fb>("fb"); + obj.add<&test::fd>("fd"); + obj.add<&test::fs>("fs"); + obj.add<&test::fspt>("fspt"); + obj.add<&test::f>("f"); + obj.add<&test::fstatic>("fstatic"); - context.registerClass("test_class", std::move(obj)); + context.registerClass("test_class", std::move(obj)); + } context.addModule("test") - .add("sqr", detail::fwrapper<&f>{"sqr"}) - .add("sqr2", detail::fwrapper<&f>{}) - .add("p", detail::fwrapper<&f2>{"p"}) - .add("obj", obj) - .add("Test", detail::ctor_wrapper{"Test"}); + //.add("obj", obj) + .add("Test", detail::ctor_wrapper{"Test"}) + .add("TestSimple", detail::ctor_wrapper{"TestSimple"}); + @@ -97,8 +107,37 @@ int main(int argc, char ** argv) context.eval(str, "", JS_EVAL_TYPE_MODULE); const char * filename = argv[1]; + { + auto xxx = context.eval("var t = new test.TestSimple(12);" + "var q = new test.Test(13, t.vb, t.vi, t.vd, t, t, t.vs, t.vs);" + "q.fb(t.vb, t.vi, t.vd, t, t, t.vs, \"test\");" + "q.fd(t.vb, t.vi, t.vd, t, t, t.vs, \"test\");" + "q.fs(t.vb, t.vi, t.vd, t, t, \"test\", t.vs);" + "q.fspt(t.vb, t.vi, t.vd, t, t, t.vs, \"test\");" + "q.fi(t.vb, t.vi, t.vd, t, t, t.vs, \"test\")"); + assert(xxx.cast() == 18); + auto yyy = context.eval("q.fi.bind(t)(t.vb, t.vi, t.vd, t, t, t.vs, \"test\")"); + assert(yyy.cast() == 13); + } + try + { + auto f = context.eval("q.fi.bind(q)").cast>(); + int xxx = f(false, 1, 0., context.eval("q").cast>(), + context.eval("t").cast>(), "test string", std::string{"test"}); + assert(xxx == 19); + } + catch(detail::exception) + { + js_std_dump_error(ctx); + } + + if(filename) context.evalFile(filename, JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_SHEBANG); + JSMemoryUsage mem; + JS_ComputeMemoryUsage(rt, &mem); + JS_DumpMemoryUsage(stderr, &mem, rt); + js_std_loop(ctx); js_std_free_handlers(rt); diff --git a/quickjspp.hpp b/quickjspp.hpp index c8569f5c19..fc4c6bd064 100644 --- a/quickjspp.hpp +++ b/quickjspp.hpp @@ -11,6 +11,7 @@ extern "C" { #include #include #include +#include namespace qjs { @@ -42,7 +43,7 @@ namespace qjs { template <> struct js_traits { - static int32_t unwrap(JSContext * ctx, JSValue v) + static int32_t unwrap(JSContext * ctx, JSValueConst v) { int32_t r; if(JS_ToInt32(ctx, &r, v)) @@ -59,7 +60,7 @@ namespace qjs { template <> struct js_traits { - static bool unwrap(JSContext * ctx, JSValue v) noexcept + static bool unwrap(JSContext * ctx, JSValueConst v) noexcept { return JS_ToBool(ctx, v); } @@ -70,10 +71,20 @@ namespace qjs { } }; + template <> + struct js_traits + { + static void unwrap(JSContext * ctx, JSValueConst undefined) + { + if(!JS_IsUndefined(undefined)) + throw exception{}; + } + }; + template <> struct js_traits { - static double unwrap(JSContext * ctx, JSValue v) + static double unwrap(JSContext * ctx, JSValueConst v) { double r; if(JS_ToFloat64(ctx, &r, v)) @@ -111,7 +122,7 @@ namespace qjs { template <> struct js_traits { - static js_string unwrap(JSContext * ctx, JSValue v) + static js_string unwrap(JSContext * ctx, JSValueConst v) { int plen; const char * ptr = JS_ToCStringLen(ctx, &plen, v, 0); @@ -129,7 +140,7 @@ namespace qjs { template <> // slower struct js_traits { - static std::string unwrap(JSContext * ctx, JSValue v) + static std::string unwrap(JSContext * ctx, JSValueConst v) { auto str_view = js_traits::unwrap(ctx, v); return std::string{str_view.data(), str_view.size()}; @@ -141,29 +152,51 @@ namespace qjs { } }; - /* - template - std::tuple to_tuple_impl(JSContext * ctx, JSValue * argv) - { - if constexpr (sizeof...(Args) == 0) - return std::make_tuple(js_traits>::unwrap(ctx, *argv)); - else // todo:rewrite - return std::tuple_cat(std::make_tuple(js_traits>::unwrap(ctx, *argv)), - to_tuple_impl(ctx, argv + 1)); - } -*/ + template - Tuple unwrap_args_impl(JSContext * ctx, JSValue * argv, std::index_sequence) + Tuple unwrap_args_impl(JSContext * ctx, JSValueConst * argv, std::index_sequence) { return Tuple{js_traits>>::unwrap(ctx, argv[I])...}; } template - std::tuple unwrap_args(JSContext * ctx, JSValue * argv) + std::tuple unwrap_args(JSContext * ctx, JSValueConst * argv) { return unwrap_args_impl>(ctx, argv, std::make_index_sequence()); } + template + JSValue wrap_call(JSContext * ctx, Callable&& f, JSValueConst * argv) noexcept + { + try + { + if constexpr(std::is_same_v) + { + std::apply(std::forward(f), unwrap_args(ctx, argv)); + return JS_UNDEFINED; + } else + { + return js_traits>::wrap(ctx, std::apply(std::forward(f), unwrap_args(ctx, argv))); + } + } + catch(exception) + { + return JS_EXCEPTION; + } + } + + + template + void wrap_args_impl(JSContext * ctx, JSValue * argv, Tuple tuple, std::index_sequence) + { + ((argv[I] = js_traits>>::wrap(ctx, std::get(tuple))), ...); + } + + template + void wrap_args(JSContext * ctx, JSValue * argv, Args&&... args) + { + wrap_args_impl(ctx, argv, std::make_tuple(std::forward(args)...), std::make_index_sequence()); + } // free function template @@ -177,24 +210,9 @@ namespace qjs { { static JSValue wrap(JSContext * ctx, fwrapper fw) { - return JS_NewCFunction(ctx, [](JSContext * ctx, JSValue this_value, int argc, - JSValue * argv) noexcept -> JSValue { - //if(argc < sizeof...(Args)) - //return JS_EXCEPTION; - try - { - if constexpr (std::is_same_v) - { - std::apply(F, detail::unwrap_args(ctx, argv)); - return JS_UNDEFINED; - } else - return js_traits::wrap(ctx, - std::apply(F, detail::unwrap_args(ctx, argv)) - ); - } catch(detail::exception) // todo: inspect exception - { - return JS_EXCEPTION; - } + return JS_NewCFunction(ctx, [](JSContext * ctx, JSValueConst this_value, int argc, + JSValueConst * argv) noexcept -> JSValue { + return wrap_call(ctx, F, argv); }, fw.name, sizeof...(Args)); } @@ -207,8 +225,8 @@ namespace qjs { { static JSValue wrap(JSContext * ctx, fwrapper fw) { - return JS_NewCFunction(ctx, [](JSContext * ctx, JSValue this_value, int argc, - JSValue * argv) noexcept -> JSValue { + return JS_NewCFunction(ctx, [](JSContext * ctx, JSValueConst this_value, int argc, + JSValueConst * argv) noexcept -> JSValue { //if(argc < sizeof...(Args)) //return JS_EXCEPTION; try @@ -221,7 +239,7 @@ namespace qjs { detail::unwrap_args(ctx, argv))); return JS_UNDEFINED; } else - return js_traits::wrap(ctx, + return js_traits>::wrap(ctx, std::apply(F, std::tuple_cat(std::make_tuple(this_sp.get()), detail::unwrap_args(ctx, argv))) @@ -241,6 +259,7 @@ namespace qjs { template struct ctor_wrapper { + static_assert(std::is_constructible::value, "no such constructor!"); const char * name = nullptr; }; @@ -249,19 +268,9 @@ namespace qjs { { static JSValue wrap(JSContext * ctx, ctor_wrapper cw) { - return JS_NewCFunction2(ctx, [](JSContext * ctx, JSValue this_value, int argc, - JSValue * argv) noexcept -> JSValue { - try - { - - return js_traits>::wrap(ctx, - std::apply(std::make_shared, - detail::unwrap_args(ctx, argv)) - ); - } catch(detail::exception) - { - return JS_EXCEPTION; - } + return JS_NewCFunction2(ctx, [](JSContext * ctx, JSValueConst this_value, int argc, + JSValueConst * argv) noexcept -> JSValue { + return wrap_call, Args...>(ctx, std::make_shared, argv); }, cw.name, sizeof...(Args), JS_CFUNC_constructor, 0); } @@ -289,12 +298,9 @@ namespace qjs { delete pptr; } }; - if(QJSClassId == 0) - { - int e = JS_NewClass(JS_GetRuntime(ctx), JS_NewClassID(&QJSClassId), &def); - if(e < 0) - throw exception{}; - } + int e = JS_NewClass(JS_GetRuntime(ctx), JS_NewClassID(&QJSClassId), &def); + if(e < 0) + throw exception{}; JS_SetClassProto(ctx, QJSClassId, proto); } @@ -302,13 +308,17 @@ namespace qjs { { if(QJSClassId == 0) // not registered throw exception{}; - auto pptr = new std::shared_ptr(std::move(ptr)); auto jsobj = JS_NewObjectClass(ctx, QJSClassId); + if(JS_IsException(jsobj)) + { + return jsobj; + } + auto pptr = new std::shared_ptr(std::move(ptr)); JS_SetOpaque(jsobj, pptr); return jsobj; } - static const std::shared_ptr& unwrap(JSContext * ctx, JSValue v) + static const std::shared_ptr& unwrap(JSContext * ctx, JSValueConst v) { auto ptr = reinterpret_cast *>(JS_GetOpaque2(ctx, v, QJSClassId)); if(!ptr) @@ -317,6 +327,69 @@ namespace qjs { } }; + + + struct function // std::function replacement + { + JSValue (*invoker)(function * self, JSContext * ctx, JSValueConst this_value, int argc, JSValueConst * argv) = nullptr; + void (*destroyer)(function * self) = nullptr; + alignas(std::max_align_t) char functor[]; + + template + static function * create(Functor&& f) + { + char * data = new char[sizeof(function) + sizeof(Functor)]; + auto fptr = reinterpret_cast(data); + auto functorptr = reinterpret_cast(fptr->functor); + new(functorptr) Functor(std::forward(f)); + fptr->destroyer = nullptr; + if constexpr(!std::is_trivially_destructible_v) + { + fptr->destroyer = [](function * fptr) { + auto functorptr = reinterpret_cast(fptr->functor); + functorptr->~Functor(); + }; + } + return fptr; + } + }; + + template <> + struct js_traits + { + inline static JSClassID QJSClassId; + static void register_class(JSContext * ctx, const char * name) + { + JSClassDef def{ + name, + // destructor + [](JSRuntime * rt, JSValue obj) noexcept { + auto pptr = reinterpret_cast(JS_GetOpaque(obj, QJSClassId)); + if(!pptr) + { + assert(false && "bad destructor"); + } + if(pptr->destroyer) + pptr->destroyer(pptr); + auto cptr = reinterpret_cast(pptr); + delete [] cptr; + }, + nullptr, // mark + // call + [](JSContext *ctx, JSValueConst func_obj, JSValueConst this_val, int argc, JSValueConst *argv) -> JSValue { + auto ptr = reinterpret_cast(JS_GetOpaque2(ctx, func_obj, QJSClassId)); + if(!ptr) + return JS_EXCEPTION; + return ptr->invoker(ptr, ctx, this_val, argc, argv); + } + }; + int e = JS_NewClass(JS_GetRuntime(ctx), JS_NewClassID(&QJSClassId), &def); + if(e < 0) + throw exception{}; + } + }; + + // properties template @@ -439,6 +512,21 @@ namespace qjs { } + template + Value& add(const char * name) + { + (*this)[name] = detail::fwrapper{name}; + return *this; + } + + template + //std::enable_if_t::value, Value&> + Value& add(const char * name, Function&& f) + { + (*this)[name] = detail::js_traits>::wrap(ctx, std::forward(f)); + return *this; + } + }; @@ -522,6 +610,11 @@ namespace qjs { std::vector modules; private: + void init() + { + JS_SetContextOpaque(ctx, this); + detail::js_traits::register_class(ctx, ""); + } public: Context(Runtime& rt) : Context(rt.rt) {} @@ -531,12 +624,12 @@ namespace qjs { ctx = JS_NewContext(rt); if(!ctx) throw detail::exception{}; - JS_SetContextOpaque(ctx, this); + init(); } Context(JSContext * ctx) : ctx{ctx} { - JS_SetContextOpaque(ctx, this); + init(); } Context(const Context&) = delete; @@ -568,7 +661,7 @@ namespace qjs { detail::js_traits>::register_class(ctx, name, proto); } - Value eval(std::string_view buffer, const char * filename, unsigned eval_flags = 0) + Value eval(std::string_view buffer, const char * filename = "eval", unsigned eval_flags = 0) { JSValue v = JS_Eval(ctx, buffer.data(), buffer.size(), filename, eval_flags); //if(JS_IsException(v)) @@ -589,4 +682,44 @@ namespace qjs { }; + namespace detail { + + template + struct js_traits> + { + static std::function unwrap(JSContext * ctx, JSValueConst fun_obj) + { + return [jsfun_obj = Value{ctx, JS_DupValue(ctx, fun_obj)}](Args&&... args) -> R { + const int argc = sizeof...(Args); + JSValue argv[argc]; + wrap_args(jsfun_obj.ctx, argv, std::forward(args)...); + JSValue result; + //if(JS_IsObject(argv[0])) // constexpr? + // result = JS_Call(ctx, fun_obj, argv[0], argc - 1, const_cast(argv + 1)); + //else + result = JS_Call(jsfun_obj.ctx, jsfun_obj.v, JS_UNDEFINED, argc, const_cast(argv)); + for(int i = 0; i < argc; i++) JS_FreeValue(jsfun_obj.ctx, argv[i]); + return js_traits::unwrap(jsfun_obj.ctx, result); + }; + } + + template + static JSValue wrap(JSContext * ctx, Functor&& functor) + { + auto obj = JS_NewObjectClass(ctx, js_traits::QJSClassId); + if(JS_IsException(obj)) + return JS_EXCEPTION; + auto fptr = function::create(std::forward(functor)); + fptr->invoker = [](function * self, JSContext * ctx, JSValueConst this_value, int argc, JSValueConst * argv) { + assert(self); + auto f = reinterpret_cast(&self->functor); + return wrap_call(ctx, *f, argv); + }; + JS_SetOpaque(obj, fptr); + return obj; + } + }; + + } + } \ No newline at end of file From c14b37d2ee8cbf45788217b0c2b802ee81e88c57 Mon Sep 17 00:00:00 2001 From: ftk Date: Mon, 22 Jul 2019 16:21:15 +0000 Subject: [PATCH 003/185] updated quickjs to 2019-07-21 --- quickjs/VERSION | 2 +- quickjs/libregexp.c | 2 +- quickjs/libunicode-table.h | 4120 ++++++++++++++++++------------------ quickjs/quickjs-atom.h | 2 - quickjs/quickjs-libc.c | 17 +- quickjs/quickjs.c | 594 +++--- quickjs/quickjs.h | 9 + 7 files changed, 2412 insertions(+), 2334 deletions(-) diff --git a/quickjs/VERSION b/quickjs/VERSION index 0a01e3ef04..51e58f773f 100644 --- a/quickjs/VERSION +++ b/quickjs/VERSION @@ -1 +1 @@ -2019-07-09 +2019-07-21 diff --git a/quickjs/libregexp.c b/quickjs/libregexp.c index 65f0d1b6dc..61177efab1 100644 --- a/quickjs/libregexp.c +++ b/quickjs/libregexp.c @@ -2407,7 +2407,7 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, for(;;) { res = lre_exec_backtrack(s, capture, stack, stack_len, pc1, cptr, TRUE); - if (res < 0) + if (res == -1) return res; if (!res) break; diff --git a/quickjs/libunicode-table.h b/quickjs/libunicode-table.h index 76ec87c4eb..521f2f3190 100644 --- a/quickjs/libunicode-table.h +++ b/quickjs/libunicode-table.h @@ -3,7 +3,7 @@ #include -static const uint32_t case_conv_table1[352] = { +static const uint32_t case_conv_table1[359] = { 0x00209a30, 0x00309a00, 0x005a8173, 0x00601730, 0x006c0730, 0x006f81b3, 0x00701700, 0x007c0700, 0x007f8100, 0x00803040, 0x009801c3, 0x00988190, @@ -29,116 +29,119 @@ static const uint32_t case_conv_table1[352] = { 0x01308101, 0x01318100, 0x01328101, 0x01330101, 0x01340100, 0x01348100, 0x01350101, 0x01358101, 0x01360101, 0x01378100, 0x01388101, 0x01390100, - 0x013a8100, 0x013e8101, 0x01400100, 0x01418100, - 0x01438101, 0x01440100, 0x01448100, 0x01450200, - 0x01460100, 0x01490100, 0x014e8101, 0x014f0101, - 0x01a28173, 0x01b80440, 0x01bb0240, 0x01bd8300, - 0x01bf8130, 0x01c30130, 0x01c40330, 0x01c60130, - 0x01c70230, 0x01c801d0, 0x01c89130, 0x01d18930, - 0x01d60100, 0x01d68300, 0x01d801d3, 0x01d89100, - 0x01e10173, 0x01e18900, 0x01e60100, 0x01e68200, - 0x01e78130, 0x01e80173, 0x01e88173, 0x01ea8173, - 0x01eb0173, 0x01eb8100, 0x01ec1840, 0x01f80173, - 0x01f88173, 0x01f90100, 0x01f98100, 0x01fa01a0, - 0x01fa8173, 0x01fb8240, 0x01fc8130, 0x01fd0240, - 0x01fe8330, 0x02001030, 0x02082030, 0x02182000, - 0x02281000, 0x02302240, 0x02453640, 0x02600130, - 0x02608e40, 0x02678100, 0x02686040, 0x0298a630, - 0x02b0a600, 0x02c381b5, 0x08502631, 0x08638131, - 0x08668131, 0x08682b00, 0x087e8300, 0x09d05011, - 0x09f80610, 0x09fc0620, 0x0e400174, 0x0e408174, - 0x0e410174, 0x0e418174, 0x0e420174, 0x0e428174, - 0x0e430174, 0x0e438180, 0x0e440180, 0x0e482b30, - 0x0e5e8330, 0x0ebc8101, 0x0ebe8101, 0x0f007e40, - 0x0f3f1840, 0x0f4b01b5, 0x0f4b81b6, 0x0f4c01b6, - 0x0f4c81b6, 0x0f4d01b7, 0x0f4d8180, 0x0f4f0130, - 0x0f506040, 0x0f800800, 0x0f840830, 0x0f880600, - 0x0f8c0630, 0x0f900800, 0x0f940830, 0x0f980800, - 0x0f9c0830, 0x0fa00600, 0x0fa40630, 0x0fa801b0, - 0x0fa88100, 0x0fa901d3, 0x0fa98100, 0x0faa01d3, - 0x0faa8100, 0x0fab01d3, 0x0fab8100, 0x0fac8130, - 0x0fad8130, 0x0fae8130, 0x0faf8130, 0x0fb00800, - 0x0fb40830, 0x0fb80200, 0x0fb90400, 0x0fbb0200, - 0x0fbc0201, 0x0fbd0201, 0x0fbe0201, 0x0fc008b7, - 0x0fc40867, 0x0fc808b8, 0x0fcc0868, 0x0fd008b8, - 0x0fd40868, 0x0fd80200, 0x0fd901b9, 0x0fd981b1, - 0x0fda01b9, 0x0fdb01b1, 0x0fdb81d7, 0x0fdc0230, - 0x0fdd0230, 0x0fde0161, 0x0fdf0173, 0x0fe101b9, - 0x0fe181b2, 0x0fe201ba, 0x0fe301b2, 0x0fe381d8, - 0x0fe40430, 0x0fe60162, 0x0fe80200, 0x0fe901d0, - 0x0fe981d0, 0x0feb01b0, 0x0feb81d0, 0x0fec0230, - 0x0fed0230, 0x0ff00201, 0x0ff101d3, 0x0ff181d3, - 0x0ff201ba, 0x0ff28101, 0x0ff301b0, 0x0ff381d3, - 0x0ff40230, 0x0ff50230, 0x0ff60131, 0x0ff901ba, - 0x0ff981b2, 0x0ffa01bb, 0x0ffb01b2, 0x0ffb81d9, - 0x0ffc0230, 0x0ffd0230, 0x0ffe0162, 0x109301a0, - 0x109501a0, 0x109581a0, 0x10990131, 0x10a70101, - 0x10b01031, 0x10b81001, 0x10c18240, 0x125b1a31, - 0x12681a01, 0x16002f31, 0x16182f01, 0x16300240, - 0x16310130, 0x16318130, 0x16320130, 0x16328100, - 0x16330100, 0x16338640, 0x16368130, 0x16370130, - 0x16378130, 0x16380130, 0x16390240, 0x163a8240, - 0x163f0230, 0x16406440, 0x16758440, 0x16790240, - 0x16802600, 0x16938100, 0x16968100, 0x53202e40, - 0x53401c40, 0x53910e40, 0x53993e40, 0x53bc8440, - 0x53be8130, 0x53bf0a40, 0x53c58240, 0x53c68130, - 0x53c80440, 0x53cb1440, 0x53d50130, 0x53d58130, - 0x53d60130, 0x53d68130, 0x53d70130, 0x53d80130, - 0x53d88130, 0x53d90130, 0x53d98131, 0x53da0640, - 0x55a98101, 0x55b85020, 0x7d8001b2, 0x7d8081b2, - 0x7d8101b2, 0x7d8181da, 0x7d8201da, 0x7d8281b3, - 0x7d8301b3, 0x7d8981bb, 0x7d8a01bb, 0x7d8a81bb, - 0x7d8b01bc, 0x7d8b81bb, 0x7f909a31, 0x7fa09a01, - 0x82002831, 0x82142801, 0x82582431, 0x826c2401, - 0x86403331, 0x86603301, 0x8c502031, 0x8c602001, - 0xb7202031, 0xb7302001, 0xf4802231, 0xf4912201, + 0x013a8100, 0x013e8101, 0x01400100, 0x01410101, + 0x01418100, 0x01438101, 0x01440100, 0x01448100, + 0x01450200, 0x01460100, 0x01490100, 0x014e8101, + 0x014f0101, 0x01a28173, 0x01b80440, 0x01bb0240, + 0x01bd8300, 0x01bf8130, 0x01c30130, 0x01c40330, + 0x01c60130, 0x01c70230, 0x01c801d0, 0x01c89130, + 0x01d18930, 0x01d60100, 0x01d68300, 0x01d801d3, + 0x01d89100, 0x01e10173, 0x01e18900, 0x01e60100, + 0x01e68200, 0x01e78130, 0x01e80173, 0x01e88173, + 0x01ea8173, 0x01eb0173, 0x01eb8100, 0x01ec1840, + 0x01f80173, 0x01f88173, 0x01f90100, 0x01f98100, + 0x01fa01a0, 0x01fa8173, 0x01fb8240, 0x01fc8130, + 0x01fd0240, 0x01fe8330, 0x02001030, 0x02082030, + 0x02182000, 0x02281000, 0x02302240, 0x02453640, + 0x02600130, 0x02608e40, 0x02678100, 0x02686040, + 0x0298a630, 0x02b0a600, 0x02c381b5, 0x08502631, + 0x08638131, 0x08668131, 0x08682b00, 0x087e8300, + 0x09d05011, 0x09f80610, 0x09fc0620, 0x0e400174, + 0x0e408174, 0x0e410174, 0x0e418174, 0x0e420174, + 0x0e428174, 0x0e430174, 0x0e438180, 0x0e440180, + 0x0e482b30, 0x0e5e8330, 0x0ebc8101, 0x0ebe8101, + 0x0ec70101, 0x0f007e40, 0x0f3f1840, 0x0f4b01b5, + 0x0f4b81b6, 0x0f4c01b6, 0x0f4c81b6, 0x0f4d01b7, + 0x0f4d8180, 0x0f4f0130, 0x0f506040, 0x0f800800, + 0x0f840830, 0x0f880600, 0x0f8c0630, 0x0f900800, + 0x0f940830, 0x0f980800, 0x0f9c0830, 0x0fa00600, + 0x0fa40630, 0x0fa801b0, 0x0fa88100, 0x0fa901d3, + 0x0fa98100, 0x0faa01d3, 0x0faa8100, 0x0fab01d3, + 0x0fab8100, 0x0fac8130, 0x0fad8130, 0x0fae8130, + 0x0faf8130, 0x0fb00800, 0x0fb40830, 0x0fb80200, + 0x0fb90400, 0x0fbb0200, 0x0fbc0201, 0x0fbd0201, + 0x0fbe0201, 0x0fc008b7, 0x0fc40867, 0x0fc808b8, + 0x0fcc0868, 0x0fd008b8, 0x0fd40868, 0x0fd80200, + 0x0fd901b9, 0x0fd981b1, 0x0fda01b9, 0x0fdb01b1, + 0x0fdb81d7, 0x0fdc0230, 0x0fdd0230, 0x0fde0161, + 0x0fdf0173, 0x0fe101b9, 0x0fe181b2, 0x0fe201ba, + 0x0fe301b2, 0x0fe381d8, 0x0fe40430, 0x0fe60162, + 0x0fe80200, 0x0fe901d0, 0x0fe981d0, 0x0feb01b0, + 0x0feb81d0, 0x0fec0230, 0x0fed0230, 0x0ff00201, + 0x0ff101d3, 0x0ff181d3, 0x0ff201ba, 0x0ff28101, + 0x0ff301b0, 0x0ff381d3, 0x0ff40230, 0x0ff50230, + 0x0ff60131, 0x0ff901ba, 0x0ff981b2, 0x0ffa01bb, + 0x0ffb01b2, 0x0ffb81d9, 0x0ffc0230, 0x0ffd0230, + 0x0ffe0162, 0x109301a0, 0x109501a0, 0x109581a0, + 0x10990131, 0x10a70101, 0x10b01031, 0x10b81001, + 0x10c18240, 0x125b1a31, 0x12681a01, 0x16002f31, + 0x16182f01, 0x16300240, 0x16310130, 0x16318130, + 0x16320130, 0x16328100, 0x16330100, 0x16338640, + 0x16368130, 0x16370130, 0x16378130, 0x16380130, + 0x16390240, 0x163a8240, 0x163f0230, 0x16406440, + 0x16758440, 0x16790240, 0x16802600, 0x16938100, + 0x16968100, 0x53202e40, 0x53401c40, 0x53910e40, + 0x53993e40, 0x53bc8440, 0x53be8130, 0x53bf0a40, + 0x53c58240, 0x53c68130, 0x53c80440, 0x53ca0101, + 0x53cb1440, 0x53d50130, 0x53d58130, 0x53d60130, + 0x53d68130, 0x53d70130, 0x53d80130, 0x53d88130, + 0x53d90130, 0x53d98131, 0x53da0c40, 0x53e10240, + 0x53e20131, 0x53e28130, 0x53e30130, 0x55a98101, + 0x55b85020, 0x7d8001b2, 0x7d8081b2, 0x7d8101b2, + 0x7d8181da, 0x7d8201da, 0x7d8281b3, 0x7d8301b3, + 0x7d8981bb, 0x7d8a01bb, 0x7d8a81bb, 0x7d8b01bc, + 0x7d8b81bb, 0x7f909a31, 0x7fa09a01, 0x82002831, + 0x82142801, 0x82582431, 0x826c2401, 0x86403331, + 0x86603301, 0x8c502031, 0x8c602001, 0xb7202031, + 0xb7302001, 0xf4802231, 0xf4912201, }; -static const uint8_t case_conv_table2[352] = { +static const uint8_t case_conv_table2[359] = { 0x01, 0x00, 0x9c, 0x06, 0x07, 0x4d, 0x03, 0x04, 0x10, 0x00, 0x8f, 0x0b, 0x00, 0x00, 0x11, 0x00, 0x08, 0x00, 0x53, 0x4a, 0x51, 0x00, 0x52, 0x00, 0x53, 0x00, 0x3a, 0x54, 0x55, 0x00, 0x57, 0x59, 0x3f, 0x5d, 0x5c, 0x00, 0x46, 0x61, 0x63, 0x42, - 0x64, 0x00, 0x66, 0x00, 0x67, 0x00, 0x69, 0x00, - 0x6b, 0x00, 0x6d, 0x00, 0x00, 0x40, 0x00, 0x00, + 0x64, 0x00, 0x66, 0x00, 0x68, 0x00, 0x6a, 0x00, + 0x6c, 0x00, 0x6e, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x93, 0x00, 0x00, 0x20, - 0x35, 0x00, 0x27, 0x00, 0x1f, 0x00, 0x24, 0x20, - 0x28, 0x00, 0x13, 0x6a, 0x6c, 0x00, 0x24, 0x22, - 0x25, 0x14, 0x16, 0x18, 0x1b, 0x1c, 0x3b, 0x1e, - 0x3c, 0x1f, 0x37, 0x3a, 0x22, 0x21, 0x3e, 0x1c, - 0x3d, 0x25, 0x23, 0x26, 0x28, 0x1e, 0x2a, 0x2c, - 0x40, 0x2e, 0x4b, 0x30, 0x4c, 0x32, 0x41, 0x3f, - 0x99, 0x00, 0x00, 0x94, 0x8e, 0x7c, 0x7d, 0x82, - 0x83, 0x12, 0x7f, 0x81, 0x75, 0x76, 0x12, 0x7a, - 0xa3, 0x7b, 0x77, 0x78, 0x89, 0x92, 0x98, 0xa6, - 0xa0, 0x84, 0x00, 0x9a, 0xa1, 0x92, 0x74, 0x33, - 0x95, 0x00, 0x8d, 0x00, 0x73, 0x98, 0x97, 0x96, - 0x95, 0x00, 0x00, 0x9d, 0x00, 0x9b, 0x00, 0xa0, - 0x9f, 0x15, 0x2c, 0x2d, 0x2e, 0xb3, 0xb4, 0x45, - 0xa9, 0xa8, 0x12, 0x14, 0x1e, 0x21, 0x22, 0x22, - 0x2a, 0x34, 0x35, 0xa5, 0xa6, 0x34, 0x1d, 0x00, - 0x00, 0x97, 0x01, 0x5a, 0xda, 0x1d, 0x36, 0x05, - 0x00, 0xc2, 0xc1, 0xc4, 0xc3, 0xc6, 0xc5, 0xc8, - 0xc7, 0xca, 0xc9, 0xc4, 0xd3, 0x45, 0xd4, 0x42, - 0xd5, 0x46, 0xd6, 0xcc, 0xce, 0xd0, 0xd2, 0xd8, - 0xd7, 0xec, 0xf4, 0xfc, 0x0c, 0x05, 0x0d, 0x80, - 0x9f, 0x00, 0x21, 0x80, 0xa3, 0xeb, 0x00, 0xc0, - 0x40, 0xc6, 0x60, 0xe5, 0xd9, 0xe6, 0x99, 0xc0, - 0x00, 0x00, 0x06, 0x60, 0xda, 0x29, 0xfb, 0x15, - 0x12, 0x06, 0x16, 0xf6, 0xdb, 0x04, 0x15, 0x12, - 0x84, 0x06, 0xc6, 0x16, 0xfd, 0xdd, 0x01, 0xc0, - 0x40, 0x00, 0x46, 0x60, 0xdc, 0xde, 0x6d, 0x37, - 0x38, 0x39, 0x13, 0x12, 0x15, 0x14, 0x00, 0x18, - 0x17, 0x1a, 0x19, 0x00, 0x5f, 0xb6, 0x65, 0x44, - 0x47, 0x00, 0x4f, 0x62, 0x4e, 0x50, 0x00, 0x00, - 0x48, 0x00, 0x00, 0x00, 0xa2, 0xa3, 0xa4, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xb5, 0x00, 0x00, 0x5a, - 0x00, 0x00, 0x5b, 0x56, 0x58, 0x60, 0x5e, 0x6f, - 0x68, 0x6e, 0x44, 0x00, 0x42, 0xa7, 0x8a, 0x8b, - 0x8c, 0xab, 0xac, 0x58, 0x58, 0xaf, 0x94, 0xb0, - 0x6f, 0xb2, 0x53, 0x52, 0x55, 0x54, 0x57, 0x56, - 0x59, 0x58, 0x5b, 0x5a, 0x5d, 0x5c, 0x5f, 0x5e, + 0x35, 0x00, 0x27, 0x00, 0x21, 0x00, 0x24, 0x22, + 0x2a, 0x00, 0x13, 0x6b, 0x6d, 0x00, 0x26, 0x24, + 0x27, 0x14, 0x16, 0x18, 0x1b, 0x1c, 0x3e, 0x1e, + 0x3f, 0x1f, 0x39, 0x3d, 0x22, 0x21, 0x41, 0x1e, + 0x40, 0x25, 0x25, 0x26, 0x28, 0x20, 0x2a, 0x49, + 0x2c, 0x43, 0x2e, 0x4b, 0x30, 0x4c, 0x32, 0x44, + 0x42, 0x99, 0x00, 0x00, 0x95, 0x8f, 0x7d, 0x7e, + 0x83, 0x84, 0x12, 0x80, 0x82, 0x76, 0x77, 0x12, + 0x7b, 0xa3, 0x7c, 0x78, 0x79, 0x8a, 0x92, 0x98, + 0xa6, 0xa0, 0x85, 0x00, 0x9a, 0xa1, 0x93, 0x75, + 0x33, 0x95, 0x00, 0x8e, 0x00, 0x74, 0x99, 0x98, + 0x97, 0x96, 0x00, 0x00, 0x9e, 0x00, 0x9c, 0x00, + 0xa1, 0xa0, 0x15, 0x2e, 0x2f, 0x30, 0xb4, 0xb5, + 0x4c, 0xaa, 0xa9, 0x12, 0x14, 0x1e, 0x21, 0x22, + 0x22, 0x2a, 0x34, 0x35, 0xa6, 0xa7, 0x36, 0x1f, + 0x4a, 0x00, 0x00, 0x97, 0x01, 0x5a, 0xda, 0x1d, + 0x36, 0x05, 0x00, 0xc4, 0xc3, 0xc6, 0xc5, 0xc8, + 0xc7, 0xca, 0xc9, 0xcc, 0xcb, 0xc4, 0xd5, 0x45, + 0xd6, 0x42, 0xd7, 0x46, 0xd8, 0xce, 0xd0, 0xd2, + 0xd4, 0xda, 0xd9, 0xee, 0xf6, 0xfe, 0x0e, 0x07, + 0x0f, 0x80, 0x9f, 0x00, 0x21, 0x80, 0xa3, 0xed, + 0x00, 0xc0, 0x40, 0xc6, 0x60, 0xe7, 0xdb, 0xe6, + 0x99, 0xc0, 0x00, 0x00, 0x06, 0x60, 0xdc, 0x29, + 0xfd, 0x15, 0x12, 0x06, 0x16, 0xf8, 0xdd, 0x06, + 0x15, 0x12, 0x84, 0x08, 0xc6, 0x16, 0xff, 0xdf, + 0x03, 0xc0, 0x40, 0x00, 0x46, 0x60, 0xde, 0xe0, + 0x6d, 0x37, 0x38, 0x39, 0x15, 0x14, 0x17, 0x16, + 0x00, 0x1a, 0x19, 0x1c, 0x1b, 0x00, 0x5f, 0xb7, + 0x65, 0x44, 0x47, 0x00, 0x4f, 0x62, 0x4e, 0x50, + 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0xa3, 0xa4, + 0xa5, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb6, 0x00, + 0x00, 0x5a, 0x00, 0x48, 0x00, 0x5b, 0x56, 0x58, + 0x60, 0x5e, 0x70, 0x69, 0x6f, 0x4b, 0x00, 0x00, + 0x3b, 0x67, 0xb8, 0x45, 0xa8, 0x8a, 0x8b, 0x8c, + 0xab, 0xac, 0x58, 0x58, 0xaf, 0x94, 0xb0, 0x6f, + 0xb2, 0x5a, 0x59, 0x5c, 0x5b, 0x5e, 0x5d, 0x60, + 0x5f, 0x62, 0x61, 0x64, 0x63, 0x66, 0x65, }; static const uint16_t case_conv_ext[58] = { @@ -152,38 +155,38 @@ static const uint16_t case_conv_ext[58] = { 0x006b, 0x00e5, }; -static const uint8_t unicode_prop_Cased1_table[170] = { +static const uint8_t unicode_prop_Cased1_table[172] = { 0x40, 0xa9, 0x80, 0x8e, 0x80, 0xfc, 0x80, 0xd3, 0x80, 0x8c, 0x80, 0x8d, 0x81, 0x8d, 0x02, 0x80, 0xe1, 0x80, 0x91, 0x85, 0x9a, 0x01, 0x00, 0x01, 0x11, 0x00, 0x01, 0x04, 0x08, 0x01, 0x08, 0x30, - 0x08, 0x08, 0x15, 0x20, 0x00, 0x39, 0x99, 0x31, + 0x08, 0x01, 0x15, 0x20, 0x00, 0x39, 0x99, 0x31, 0x9d, 0x84, 0x40, 0x94, 0x80, 0xd6, 0x82, 0xa6, 0x80, 0x41, 0x62, 0x80, 0xa6, 0x80, 0x57, 0x76, - 0xf8, 0x02, 0x80, 0xc1, 0x40, 0xdb, 0x08, 0x80, - 0x41, 0xd0, 0x80, 0x8c, 0x80, 0x8f, 0x8c, 0xe4, - 0x03, 0x01, 0x89, 0x00, 0x14, 0x28, 0x10, 0x11, - 0x02, 0x01, 0x18, 0x0b, 0x24, 0x4b, 0x26, 0x01, - 0x01, 0x86, 0xe5, 0x80, 0x60, 0x79, 0xb6, 0x81, - 0x40, 0x91, 0x81, 0xbd, 0x88, 0x94, 0x04, 0x81, - 0x98, 0x80, 0xc7, 0x82, 0x43, 0x34, 0xa2, 0x06, - 0x80, 0x89, 0x61, 0x28, 0x99, 0xd4, 0x80, 0xc6, - 0x01, 0x08, 0x09, 0x0b, 0x80, 0x8b, 0x00, 0x06, - 0x80, 0xc0, 0x03, 0x0f, 0x06, 0x80, 0x9b, 0x03, - 0x04, 0x00, 0x16, 0x80, 0x41, 0x53, 0x81, 0x98, - 0x80, 0x98, 0x80, 0x9e, 0x80, 0x98, 0x80, 0x9e, - 0x80, 0x98, 0x80, 0x9e, 0x80, 0x98, 0x80, 0x9e, - 0x80, 0x98, 0x07, 0x59, 0x63, 0x99, 0x85, 0x99, - 0x85, 0x99, + 0xf8, 0x02, 0x80, 0x8f, 0x80, 0xb0, 0x40, 0xdb, + 0x08, 0x80, 0x41, 0xd0, 0x80, 0x8c, 0x80, 0x8f, + 0x8c, 0xe4, 0x03, 0x01, 0x89, 0x00, 0x14, 0x28, + 0x10, 0x11, 0x02, 0x01, 0x18, 0x0b, 0x24, 0x4b, + 0x26, 0x01, 0x01, 0x86, 0xe5, 0x80, 0x60, 0x79, + 0xb6, 0x81, 0x40, 0x91, 0x81, 0xbd, 0x88, 0x94, + 0x05, 0x80, 0x98, 0x80, 0xc7, 0x82, 0x43, 0x34, + 0xa2, 0x06, 0x80, 0x8b, 0x61, 0x28, 0x97, 0xd4, + 0x80, 0xc6, 0x01, 0x08, 0x09, 0x0b, 0x80, 0x8b, + 0x00, 0x06, 0x80, 0xc0, 0x03, 0x0f, 0x06, 0x80, + 0x9b, 0x03, 0x04, 0x00, 0x16, 0x80, 0x41, 0x53, + 0x81, 0x98, 0x80, 0x98, 0x80, 0x9e, 0x80, 0x98, + 0x80, 0x9e, 0x80, 0x98, 0x80, 0x9e, 0x80, 0x98, + 0x80, 0x9e, 0x80, 0x98, 0x07, 0x59, 0x63, 0x99, + 0x85, 0x99, 0x85, 0x99, }; static const uint8_t unicode_prop_Cased1_index[18] = { - 0xb9, 0x02, 0xe0, 0xa0, 0x1e, 0x00, 0x9e, 0xa6, - 0x00, 0xc4, 0xd4, 0x01, 0xa9, 0xd7, 0x01, 0x8a, + 0xb9, 0x02, 0xe0, 0xa0, 0x1e, 0x40, 0x9e, 0xa6, + 0x40, 0xba, 0xd4, 0x01, 0x89, 0xd7, 0x01, 0x8a, 0xf1, 0x01, }; -static const uint8_t unicode_prop_Case_Ignorable_table[663] = { +static const uint8_t unicode_prop_Case_Ignorable_table[678] = { 0xa6, 0x05, 0x80, 0x8a, 0x80, 0xa2, 0x00, 0x80, 0xc6, 0x03, 0x00, 0x03, 0x01, 0x81, 0x41, 0xf6, 0x40, 0xbf, 0x19, 0x18, 0x88, 0x08, 0x80, 0x40, @@ -204,83 +207,86 @@ static const uint8_t unicode_prop_Case_Ignorable_table[663] = { 0x80, 0xb9, 0x01, 0x05, 0x04, 0x81, 0x93, 0x81, 0x9b, 0x81, 0xb8, 0x0b, 0x1f, 0x80, 0x93, 0x81, 0xe5, 0x06, 0x10, 0x80, 0xd9, 0x01, 0x86, 0x8a, - 0x88, 0xe1, 0x01, 0x28, 0x81, 0x88, 0x00, 0x85, - 0xc9, 0x81, 0x9a, 0x00, 0x00, 0x80, 0xb6, 0x8d, - 0x04, 0x01, 0x84, 0x8a, 0x80, 0xa3, 0x88, 0x80, - 0xe5, 0x18, 0x28, 0x09, 0x81, 0x98, 0x0b, 0x82, - 0x8f, 0x83, 0x8c, 0x01, 0x0d, 0x80, 0x8e, 0x80, - 0xdd, 0x80, 0x42, 0x5f, 0x82, 0x43, 0xb1, 0x82, - 0x9c, 0x82, 0x9c, 0x81, 0x9d, 0x81, 0xbf, 0x08, - 0x37, 0x01, 0x8a, 0x10, 0x20, 0xac, 0x83, 0xb3, - 0x80, 0xc0, 0x81, 0xa1, 0x80, 0xf5, 0x13, 0x81, - 0x88, 0x05, 0x82, 0x40, 0xda, 0x09, 0x80, 0xb9, - 0x00, 0x30, 0x00, 0x01, 0x3d, 0x89, 0x08, 0xa6, - 0x07, 0x8e, 0xc0, 0x83, 0xaf, 0x00, 0x20, 0x04, - 0x80, 0xa7, 0x88, 0x8b, 0x81, 0x9f, 0x19, 0x08, - 0x82, 0xb7, 0x00, 0x0a, 0x00, 0x82, 0xb9, 0x39, - 0x81, 0xbf, 0x85, 0xd1, 0x10, 0x8c, 0x06, 0x18, - 0x28, 0x11, 0xb1, 0xbe, 0x8c, 0x80, 0xa1, 0xde, - 0x04, 0x41, 0xbc, 0x00, 0x82, 0x8a, 0x82, 0x8c, - 0x82, 0x8c, 0x82, 0x8c, 0x81, 0x8b, 0x27, 0x81, - 0x89, 0x01, 0x01, 0x84, 0xb0, 0x20, 0x89, 0x00, - 0x8c, 0x80, 0x8f, 0x8c, 0xb2, 0xa0, 0x4b, 0x8a, - 0x81, 0xf0, 0x82, 0xfc, 0x80, 0x8e, 0x80, 0xdf, - 0x9f, 0xae, 0x80, 0x41, 0xd4, 0x80, 0xa3, 0x1a, - 0x24, 0x80, 0xdc, 0x85, 0xdc, 0x82, 0x60, 0x6f, - 0x15, 0x80, 0x44, 0xe1, 0x85, 0x41, 0x0d, 0x80, - 0xe1, 0x18, 0x89, 0x00, 0x9b, 0x83, 0xcf, 0x81, - 0x8d, 0xa1, 0xcd, 0x80, 0x96, 0x82, 0xec, 0x0f, - 0x02, 0x03, 0x80, 0x98, 0x81, 0x40, 0x9c, 0x81, - 0x99, 0x91, 0x8c, 0x80, 0xa5, 0x87, 0x98, 0x8a, - 0xad, 0x82, 0xaf, 0x01, 0x19, 0x80, 0x91, 0x80, - 0x94, 0x81, 0xc1, 0x29, 0x09, 0x81, 0x8b, 0x07, - 0x80, 0xa2, 0x80, 0x8a, 0x80, 0xb2, 0x00, 0x11, - 0x0c, 0x08, 0x80, 0x9a, 0x80, 0x8d, 0x0c, 0x08, - 0x80, 0xe3, 0x84, 0x40, 0x84, 0x01, 0x03, 0x80, - 0x60, 0x4f, 0x2f, 0x80, 0x40, 0x92, 0x8f, 0x42, - 0x3d, 0x8f, 0x10, 0x8b, 0x8f, 0xa1, 0x01, 0x80, - 0x40, 0xa8, 0x06, 0x05, 0x80, 0x8a, 0x80, 0xa2, - 0x00, 0x80, 0xae, 0x80, 0xac, 0x81, 0xc2, 0x80, - 0x94, 0x82, 0x42, 0x00, 0x80, 0x40, 0xe1, 0x80, - 0x40, 0x94, 0x84, 0x46, 0x85, 0x10, 0x0c, 0x83, - 0xa7, 0x13, 0x80, 0x40, 0xa4, 0x81, 0x42, 0x3c, - 0x83, 0x42, 0x1d, 0x8a, 0x40, 0xaf, 0x80, 0xb5, - 0x8e, 0xb7, 0x82, 0xb0, 0x19, 0x09, 0x80, 0x8e, - 0x80, 0xb1, 0x82, 0xa3, 0x20, 0x87, 0xbd, 0x80, - 0x8b, 0x81, 0xb3, 0x88, 0x89, 0x83, 0xe1, 0x11, - 0x00, 0x0d, 0x80, 0x40, 0x9f, 0x02, 0x87, 0x94, - 0x81, 0xb8, 0x0a, 0x80, 0xa4, 0x32, 0x84, 0x40, - 0xc2, 0x39, 0x10, 0x80, 0x96, 0x80, 0xd3, 0x28, - 0x03, 0x08, 0x81, 0x40, 0xed, 0x1d, 0x08, 0x81, - 0x9a, 0x81, 0xd4, 0x39, 0x00, 0x81, 0xe9, 0x00, - 0x01, 0x28, 0x80, 0xe4, 0x11, 0x18, 0x84, 0x41, - 0x02, 0x88, 0x01, 0x41, 0xc5, 0x89, 0xa7, 0x29, - 0x1f, 0x80, 0x88, 0x29, 0x82, 0xad, 0x8c, 0x01, - 0x41, 0x95, 0x30, 0x28, 0x80, 0xd1, 0x95, 0x0e, - 0x01, 0x01, 0xf9, 0x2a, 0x00, 0x08, 0x30, 0x80, - 0xc7, 0x0a, 0x00, 0x80, 0x41, 0x5a, 0x81, 0x60, - 0x4b, 0xfa, 0x84, 0xba, 0x86, 0x88, 0x83, 0x44, - 0x4a, 0x90, 0xbf, 0x81, 0x60, 0x4c, 0xba, 0x08, - 0x83, 0x54, 0xc2, 0x82, 0x88, 0x8f, 0x0e, 0x9d, - 0x83, 0x40, 0x93, 0x82, 0x47, 0xba, 0xb6, 0x83, - 0xb1, 0x38, 0x8d, 0x80, 0x95, 0x20, 0x8e, 0x45, - 0x4f, 0x30, 0x90, 0x0e, 0x01, 0x04, 0x48, 0xa4, - 0x86, 0xec, 0x86, 0x4a, 0xaf, 0x84, 0x6c, 0x0c, - 0x00, 0x80, 0x9d, 0xdf, 0xff, 0x40, 0xef, + 0x88, 0xe1, 0x01, 0x88, 0x88, 0x00, 0x85, 0xc9, + 0x81, 0x9a, 0x00, 0x00, 0x80, 0xb6, 0x8d, 0x04, + 0x01, 0x84, 0x8a, 0x80, 0xa3, 0x88, 0x80, 0xe5, + 0x18, 0x28, 0x09, 0x81, 0x98, 0x0b, 0x82, 0x8f, + 0x83, 0x8c, 0x01, 0x0d, 0x80, 0x8e, 0x80, 0xdd, + 0x80, 0x42, 0x5f, 0x82, 0x43, 0xb1, 0x82, 0x9c, + 0x82, 0x9c, 0x81, 0x9d, 0x81, 0xbf, 0x08, 0x37, + 0x01, 0x8a, 0x10, 0x20, 0xac, 0x83, 0xb3, 0x80, + 0xc0, 0x81, 0xa1, 0x80, 0xf5, 0x13, 0x81, 0x88, + 0x05, 0x82, 0x40, 0xda, 0x09, 0x80, 0xb9, 0x00, + 0x30, 0x00, 0x01, 0x3d, 0x89, 0x08, 0xa6, 0x07, + 0x8e, 0xc0, 0x83, 0xaf, 0x00, 0x20, 0x04, 0x80, + 0xa7, 0x88, 0x8b, 0x81, 0x9f, 0x19, 0x08, 0x82, + 0xb7, 0x00, 0x0a, 0x00, 0x82, 0xb9, 0x39, 0x81, + 0xbf, 0x85, 0xd1, 0x10, 0x8c, 0x06, 0x18, 0x28, + 0x11, 0xb1, 0xbe, 0x8c, 0x80, 0xa1, 0xde, 0x04, + 0x41, 0xbc, 0x00, 0x82, 0x8a, 0x82, 0x8c, 0x82, + 0x8c, 0x82, 0x8c, 0x81, 0x8b, 0x27, 0x81, 0x89, + 0x01, 0x01, 0x84, 0xb0, 0x20, 0x89, 0x00, 0x8c, + 0x80, 0x8f, 0x8c, 0xb2, 0xa0, 0x4b, 0x8a, 0x81, + 0xf0, 0x82, 0xfc, 0x80, 0x8e, 0x80, 0xdf, 0x9f, + 0xae, 0x80, 0x41, 0xd4, 0x80, 0xa3, 0x1a, 0x24, + 0x80, 0xdc, 0x85, 0xdc, 0x82, 0x60, 0x6f, 0x15, + 0x80, 0x44, 0xe1, 0x85, 0x41, 0x0d, 0x80, 0xe1, + 0x18, 0x89, 0x00, 0x9b, 0x83, 0xcf, 0x81, 0x8d, + 0xa1, 0xcd, 0x80, 0x96, 0x82, 0xec, 0x0f, 0x02, + 0x03, 0x80, 0x98, 0x81, 0x40, 0x9c, 0x81, 0x99, + 0x91, 0x8c, 0x80, 0xa5, 0x87, 0x98, 0x8a, 0xad, + 0x82, 0xaf, 0x01, 0x19, 0x81, 0x90, 0x80, 0x94, + 0x81, 0xc1, 0x29, 0x09, 0x81, 0x8b, 0x07, 0x80, + 0xa2, 0x80, 0x8a, 0x80, 0xb2, 0x00, 0x11, 0x0c, + 0x08, 0x80, 0x9a, 0x80, 0x8d, 0x0c, 0x08, 0x80, + 0xe3, 0x84, 0x40, 0x84, 0x01, 0x03, 0x80, 0x60, + 0x4f, 0x2f, 0x80, 0x40, 0x92, 0x8f, 0x42, 0x3d, + 0x8f, 0x10, 0x8b, 0x8f, 0xa1, 0x01, 0x80, 0x40, + 0xa8, 0x06, 0x05, 0x80, 0x8a, 0x80, 0xa2, 0x00, + 0x80, 0xae, 0x80, 0xac, 0x81, 0xc2, 0x80, 0x94, + 0x82, 0x42, 0x00, 0x80, 0x40, 0xe1, 0x80, 0x40, + 0x94, 0x84, 0x46, 0x85, 0x10, 0x0c, 0x83, 0xa7, + 0x13, 0x80, 0x40, 0xa4, 0x81, 0x42, 0x3c, 0x83, + 0x42, 0x1d, 0x8a, 0x40, 0xaf, 0x80, 0xb5, 0x8e, + 0xb7, 0x82, 0xb0, 0x19, 0x09, 0x80, 0x8e, 0x80, + 0xb1, 0x82, 0xa3, 0x20, 0x87, 0xbd, 0x80, 0x8b, + 0x81, 0xb3, 0x88, 0x89, 0x83, 0xe1, 0x11, 0x00, + 0x0d, 0x80, 0x40, 0x9f, 0x02, 0x87, 0x94, 0x81, + 0xb8, 0x0a, 0x80, 0xa4, 0x32, 0x84, 0x40, 0xc2, + 0x39, 0x10, 0x80, 0x96, 0x80, 0xd3, 0x28, 0x03, + 0x08, 0x81, 0x40, 0xed, 0x1d, 0x08, 0x81, 0x9a, + 0x81, 0xd4, 0x39, 0x00, 0x81, 0xe9, 0x00, 0x01, + 0x28, 0x80, 0xe4, 0x11, 0x18, 0x84, 0x41, 0x02, + 0x88, 0x01, 0x41, 0x98, 0x19, 0x0b, 0x80, 0x9f, + 0x89, 0xa7, 0x29, 0x1f, 0x80, 0x88, 0x29, 0x82, + 0xad, 0x8c, 0x01, 0x41, 0x95, 0x30, 0x28, 0x80, + 0xd1, 0x95, 0x0e, 0x01, 0x01, 0xf9, 0x2a, 0x00, + 0x08, 0x30, 0x80, 0xc7, 0x0a, 0x00, 0x80, 0x41, + 0x5a, 0x81, 0x55, 0x3a, 0x88, 0x60, 0x36, 0xb6, + 0x84, 0xba, 0x86, 0x88, 0x83, 0x44, 0x0a, 0x80, + 0xbe, 0x90, 0xbf, 0x08, 0x80, 0x60, 0x4c, 0xb8, + 0x08, 0x83, 0x54, 0xc2, 0x82, 0x88, 0x8f, 0x0e, + 0x9d, 0x83, 0x40, 0x93, 0x82, 0x47, 0xba, 0xb6, + 0x83, 0xb1, 0x38, 0x8d, 0x80, 0x95, 0x20, 0x8e, + 0x45, 0x4f, 0x30, 0x90, 0x0e, 0x01, 0x04, 0x41, + 0x04, 0x8d, 0x41, 0xad, 0x83, 0x45, 0xdf, 0x86, + 0xec, 0x87, 0x4a, 0xae, 0x84, 0x6c, 0x0c, 0x00, + 0x80, 0x9d, 0xdf, 0xff, 0x40, 0xef, }; -static const uint8_t unicode_prop_Case_Ignorable_index[63] = { +static const uint8_t unicode_prop_Case_Ignorable_index[66] = { 0xc0, 0x05, 0x00, 0x2e, 0x08, 0x20, 0x52, 0x0a, - 0x00, 0x05, 0x0c, 0x00, 0x4f, 0x0e, 0x20, 0x61, - 0x10, 0x00, 0x44, 0x18, 0x20, 0x43, 0x1b, 0x20, - 0xfa, 0x1d, 0x00, 0x7e, 0x2c, 0x20, 0x0d, 0xa6, - 0x00, 0x52, 0xa9, 0x00, 0xf7, 0xaa, 0x20, 0x41, - 0xff, 0x40, 0x28, 0x0d, 0x21, 0x3f, 0x12, 0x61, - 0xc1, 0x15, 0x01, 0x9a, 0x1a, 0x01, 0xa0, 0x6f, - 0x41, 0x19, 0xe0, 0x61, 0xf0, 0x01, 0x0e, + 0x00, 0x05, 0x0c, 0x00, 0x4f, 0x0e, 0x20, 0x75, + 0x10, 0x20, 0x44, 0x18, 0x00, 0x43, 0x1b, 0x00, + 0x00, 0x1e, 0x00, 0x7e, 0x2c, 0x00, 0x7e, 0xa6, + 0x40, 0x83, 0xa9, 0x20, 0xf7, 0xaa, 0x00, 0x41, + 0xff, 0x20, 0x28, 0x0d, 0x01, 0x3f, 0x12, 0x41, + 0xde, 0x15, 0x21, 0x5c, 0x1a, 0x01, 0xf5, 0x6a, + 0x21, 0x37, 0xda, 0x01, 0x02, 0x00, 0x2e, 0xf0, + 0x01, 0x0e, }; -static const uint8_t unicode_prop_ID_Start_table[1003] = { +static const uint8_t unicode_prop_ID_Start_table[1024] = { 0xc0, 0x99, 0x85, 0x99, 0xae, 0x80, 0x89, 0x03, 0x04, 0x96, 0x80, 0x9e, 0x80, 0x41, 0xc9, 0x83, 0x8b, 0x8d, 0x26, 0x00, 0x80, 0x40, 0x80, 0x20, @@ -307,124 +313,126 @@ static const uint8_t unicode_prop_ID_Start_table[1003] = { 0x81, 0x91, 0x38, 0x10, 0xa8, 0x08, 0x8f, 0x04, 0x17, 0x82, 0x97, 0x2c, 0x91, 0x82, 0x97, 0x80, 0x88, 0x00, 0x0e, 0xb9, 0xaf, 0x01, 0x8b, 0x86, - 0xb9, 0x08, 0x01, 0x08, 0x01, 0x05, 0x18, 0x30, - 0x10, 0x00, 0x01, 0x08, 0x18, 0x81, 0x88, 0x01, - 0x20, 0x80, 0x94, 0x83, 0x9f, 0x80, 0xbe, 0x38, - 0xa3, 0x9a, 0x84, 0xf2, 0xaa, 0x93, 0x80, 0x8f, - 0x2b, 0x1a, 0x02, 0x0e, 0x13, 0x8c, 0x8b, 0x80, - 0x90, 0xa5, 0x00, 0x20, 0x81, 0xaa, 0x80, 0x41, - 0x4c, 0x03, 0x0e, 0x00, 0x03, 0x81, 0xa8, 0x03, - 0x81, 0xa0, 0x03, 0x0e, 0x00, 0x03, 0x81, 0x8e, - 0x80, 0xb8, 0x03, 0x81, 0xc2, 0xa4, 0x8f, 0x8f, - 0xd5, 0x0d, 0x82, 0x42, 0x6b, 0x81, 0x90, 0x80, - 0x99, 0x84, 0xca, 0x82, 0x8a, 0x86, 0x8c, 0x03, - 0x8d, 0x91, 0x8d, 0x91, 0x8d, 0x8c, 0x02, 0x8e, - 0xb3, 0xa2, 0x03, 0x80, 0xc2, 0xd8, 0x86, 0xa8, - 0x00, 0x84, 0xc5, 0x89, 0x9e, 0xb0, 0x9d, 0x0c, - 0x8a, 0xab, 0x83, 0x99, 0xb5, 0x96, 0x88, 0xb4, - 0xd1, 0x80, 0xdc, 0xae, 0x90, 0x86, 0xb6, 0x9d, - 0x8c, 0x81, 0x89, 0xab, 0x99, 0xa3, 0xa8, 0x82, - 0x89, 0xa3, 0x81, 0x88, 0x86, 0xaa, 0x0a, 0xa8, - 0x18, 0x1a, 0x81, 0x88, 0x40, 0xbf, 0xbf, 0x41, - 0x15, 0x0d, 0x81, 0xa5, 0x0d, 0x0f, 0x00, 0x00, - 0x00, 0x80, 0x9e, 0x81, 0xb4, 0x06, 0x00, 0x12, - 0x06, 0x13, 0x0d, 0x83, 0x8c, 0x22, 0x06, 0xf3, - 0x80, 0x8c, 0x80, 0x8f, 0x8c, 0xe4, 0x03, 0x01, - 0x89, 0x00, 0x0d, 0x28, 0x00, 0x00, 0x80, 0x8f, - 0x0b, 0x24, 0x18, 0x90, 0xa8, 0x4a, 0x76, 0xae, - 0x80, 0xae, 0x80, 0x40, 0x84, 0x2b, 0x11, 0x8b, - 0xa5, 0x00, 0x20, 0x81, 0xb7, 0x30, 0x8f, 0x96, - 0x88, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x86, 0x42, 0x25, 0x82, 0x98, 0x88, 0x34, 0x0c, - 0x83, 0xd5, 0x1c, 0x80, 0xd9, 0x03, 0x84, 0xaa, - 0x80, 0xdd, 0x90, 0x9a, 0xb4, 0x8f, 0x41, 0xff, - 0x59, 0xb5, 0xc9, 0x60, 0x51, 0xef, 0x8f, 0x44, - 0x8c, 0xc2, 0xad, 0x81, 0x41, 0x0c, 0x82, 0x8f, - 0x89, 0x81, 0x93, 0xae, 0x8f, 0x9e, 0x81, 0xcf, - 0xa6, 0x88, 0x81, 0xe6, 0x81, 0xae, 0xbc, 0x8a, - 0x02, 0x03, 0x80, 0x96, 0x9c, 0xb3, 0x8d, 0xb1, - 0xbd, 0x2a, 0x00, 0x81, 0x8a, 0x9b, 0x89, 0x96, - 0x98, 0x9c, 0x86, 0xae, 0x9b, 0x80, 0x8f, 0x20, - 0x89, 0x89, 0x20, 0xa8, 0x96, 0x10, 0x87, 0x93, - 0x96, 0x10, 0x82, 0xb1, 0x00, 0x11, 0x0c, 0x08, - 0x00, 0x97, 0x11, 0x8a, 0x32, 0x8b, 0x29, 0x29, - 0x85, 0x88, 0x30, 0x30, 0xaa, 0x80, 0x89, 0x89, - 0xf2, 0x9c, 0x60, 0x2b, 0xa3, 0x8b, 0x96, 0x83, - 0xb0, 0x60, 0x21, 0x03, 0x41, 0x6d, 0x81, 0xe9, - 0xa5, 0x86, 0x8b, 0x24, 0x00, 0x89, 0x80, 0x8c, - 0x04, 0x00, 0x01, 0x01, 0x80, 0xeb, 0xa0, 0x41, - 0x6a, 0x91, 0xbf, 0x81, 0xb5, 0xa7, 0x8b, 0xf3, - 0x20, 0x40, 0x86, 0xa3, 0x99, 0x85, 0x99, 0x8a, - 0xd8, 0x15, 0x0d, 0x0d, 0x0a, 0xa2, 0x8b, 0x80, - 0x99, 0x80, 0x92, 0x01, 0x80, 0x8e, 0x81, 0x8d, - 0xa1, 0xfa, 0xc4, 0xb4, 0x41, 0x0a, 0x9c, 0x82, - 0xb0, 0xae, 0x9f, 0x8c, 0x9d, 0x84, 0xa5, 0x89, - 0x9d, 0x81, 0xa3, 0x1f, 0x04, 0xa9, 0x40, 0x9d, - 0x91, 0xa3, 0x83, 0xa3, 0x83, 0xa7, 0x87, 0xb3, - 0x40, 0x9b, 0x41, 0x36, 0x88, 0x95, 0x89, 0x87, - 0x40, 0x97, 0x29, 0x00, 0xab, 0x01, 0x10, 0x81, - 0x96, 0x89, 0x96, 0x88, 0x9e, 0xc0, 0x92, 0x01, - 0x89, 0x95, 0x89, 0x99, 0xc5, 0xb7, 0x29, 0xbf, - 0x80, 0x8e, 0x18, 0x10, 0x9c, 0xa9, 0x9c, 0x82, - 0x9c, 0xa2, 0x38, 0x9b, 0x9a, 0xb5, 0x89, 0x95, - 0x89, 0x92, 0x8c, 0x91, 0xed, 0xc8, 0xb6, 0xb2, - 0x8c, 0xb2, 0x8c, 0xa3, 0x41, 0xdb, 0x9c, 0x89, - 0x07, 0x95, 0x40, 0xbc, 0xb4, 0xca, 0xac, 0x9f, - 0x98, 0x99, 0xa3, 0x9c, 0x80, 0x8a, 0xa2, 0x10, - 0x8b, 0xaf, 0x8d, 0x83, 0x94, 0x00, 0x80, 0xa2, - 0x91, 0x80, 0x98, 0xd3, 0x30, 0x00, 0x18, 0x8e, - 0x80, 0x89, 0x86, 0xae, 0xa5, 0x39, 0x09, 0x95, - 0x06, 0x01, 0x04, 0x10, 0x91, 0x80, 0x8b, 0x84, - 0x40, 0x9d, 0xb4, 0x91, 0x83, 0xb4, 0xaf, 0x93, + 0xb9, 0x08, 0x00, 0x20, 0x97, 0x00, 0x80, 0x89, + 0x01, 0x88, 0x01, 0x20, 0x80, 0x94, 0x83, 0x9f, + 0x80, 0xbe, 0x38, 0xa3, 0x9a, 0x84, 0xf2, 0xaa, + 0x93, 0x80, 0x8f, 0x2b, 0x1a, 0x02, 0x0e, 0x13, + 0x8c, 0x8b, 0x80, 0x90, 0xa5, 0x00, 0x20, 0x81, + 0xaa, 0x80, 0x41, 0x4c, 0x03, 0x0e, 0x00, 0x03, + 0x81, 0xa8, 0x03, 0x81, 0xa0, 0x03, 0x0e, 0x00, + 0x03, 0x81, 0x8e, 0x80, 0xb8, 0x03, 0x81, 0xc2, + 0xa4, 0x8f, 0x8f, 0xd5, 0x0d, 0x82, 0x42, 0x6b, + 0x81, 0x90, 0x80, 0x99, 0x84, 0xca, 0x82, 0x8a, + 0x86, 0x8c, 0x03, 0x8d, 0x91, 0x8d, 0x91, 0x8d, + 0x8c, 0x02, 0x8e, 0xb3, 0xa2, 0x03, 0x80, 0xc2, + 0xd8, 0x86, 0xa8, 0x00, 0x84, 0xc5, 0x89, 0x9e, + 0xb0, 0x9d, 0x0c, 0x8a, 0xab, 0x83, 0x99, 0xb5, + 0x96, 0x88, 0xb4, 0xd1, 0x80, 0xdc, 0xae, 0x90, + 0x86, 0xb6, 0x9d, 0x8c, 0x81, 0x89, 0xab, 0x99, + 0xa3, 0xa8, 0x82, 0x89, 0xa3, 0x81, 0x88, 0x86, + 0xaa, 0x0a, 0xa8, 0x18, 0x28, 0x0a, 0x04, 0x40, + 0xbf, 0xbf, 0x41, 0x15, 0x0d, 0x81, 0xa5, 0x0d, + 0x0f, 0x00, 0x00, 0x00, 0x80, 0x9e, 0x81, 0xb4, + 0x06, 0x00, 0x12, 0x06, 0x13, 0x0d, 0x83, 0x8c, + 0x22, 0x06, 0xf3, 0x80, 0x8c, 0x80, 0x8f, 0x8c, + 0xe4, 0x03, 0x01, 0x89, 0x00, 0x0d, 0x28, 0x00, + 0x00, 0x80, 0x8f, 0x0b, 0x24, 0x18, 0x90, 0xa8, + 0x4a, 0x76, 0xae, 0x80, 0xae, 0x80, 0x40, 0x84, + 0x2b, 0x11, 0x8b, 0xa5, 0x00, 0x20, 0x81, 0xb7, + 0x30, 0x8f, 0x96, 0x88, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x86, 0x42, 0x25, 0x82, 0x98, + 0x88, 0x34, 0x0c, 0x83, 0xd5, 0x1c, 0x80, 0xd9, + 0x03, 0x84, 0xaa, 0x80, 0xdd, 0x90, 0x9a, 0xb4, + 0x8f, 0x41, 0xff, 0x59, 0xb5, 0xc9, 0x60, 0x51, + 0xef, 0x8f, 0x44, 0x8c, 0xc2, 0xad, 0x81, 0x41, + 0x0c, 0x82, 0x8f, 0x89, 0x81, 0x93, 0xae, 0x8f, + 0x9e, 0x81, 0xcf, 0xa6, 0x88, 0x81, 0xe6, 0x81, + 0xb4, 0x0c, 0xaf, 0x8a, 0x02, 0x03, 0x80, 0x96, + 0x9c, 0xb3, 0x8d, 0xb1, 0xbd, 0x2a, 0x00, 0x81, + 0x8a, 0x9b, 0x89, 0x96, 0x98, 0x9c, 0x86, 0xae, + 0x9b, 0x80, 0x8f, 0x20, 0x89, 0x89, 0x20, 0xa8, + 0x96, 0x10, 0x87, 0x93, 0x96, 0x10, 0x82, 0xb1, + 0x00, 0x11, 0x0c, 0x08, 0x00, 0x97, 0x11, 0x8a, + 0x32, 0x8b, 0x29, 0x29, 0x85, 0x88, 0x30, 0x30, + 0xaa, 0x80, 0x8b, 0x87, 0xf2, 0x9c, 0x60, 0x2b, + 0xa3, 0x8b, 0x96, 0x83, 0xb0, 0x60, 0x21, 0x03, + 0x41, 0x6d, 0x81, 0xe9, 0xa5, 0x86, 0x8b, 0x24, + 0x00, 0x89, 0x80, 0x8c, 0x04, 0x00, 0x01, 0x01, + 0x80, 0xeb, 0xa0, 0x41, 0x6a, 0x91, 0xbf, 0x81, + 0xb5, 0xa7, 0x8b, 0xf3, 0x20, 0x40, 0x86, 0xa3, + 0x99, 0x85, 0x99, 0x8a, 0xd8, 0x15, 0x0d, 0x0d, + 0x0a, 0xa2, 0x8b, 0x80, 0x99, 0x80, 0x92, 0x01, + 0x80, 0x8e, 0x81, 0x8d, 0xa1, 0xfa, 0xc4, 0xb4, + 0x41, 0x0a, 0x9c, 0x82, 0xb0, 0xae, 0x9f, 0x8c, + 0x9d, 0x84, 0xa5, 0x89, 0x9d, 0x81, 0xa3, 0x1f, + 0x04, 0xa9, 0x40, 0x9d, 0x91, 0xa3, 0x83, 0xa3, + 0x83, 0xa7, 0x87, 0xb3, 0x40, 0x9b, 0x41, 0x36, + 0x88, 0x95, 0x89, 0x87, 0x40, 0x97, 0x29, 0x00, + 0xab, 0x01, 0x10, 0x81, 0x96, 0x89, 0x96, 0x88, + 0x9e, 0xc0, 0x92, 0x01, 0x89, 0x95, 0x89, 0x99, + 0xc5, 0xb7, 0x29, 0xbf, 0x80, 0x8e, 0x18, 0x10, + 0x9c, 0xa9, 0x9c, 0x82, 0x9c, 0xa2, 0x38, 0x9b, + 0x9a, 0xb5, 0x89, 0x95, 0x89, 0x92, 0x8c, 0x91, + 0xed, 0xc8, 0xb6, 0xb2, 0x8c, 0xb2, 0x8c, 0xa3, + 0x41, 0xdb, 0x9c, 0x89, 0x07, 0x95, 0x40, 0x99, + 0x96, 0x8b, 0xb4, 0xca, 0xac, 0x9f, 0x98, 0x99, + 0xa3, 0x9c, 0x80, 0x8a, 0xa2, 0x10, 0x8b, 0xaf, + 0x8d, 0x83, 0x94, 0x00, 0x80, 0xa2, 0x91, 0x80, + 0x98, 0xd3, 0x30, 0x00, 0x18, 0x8e, 0x80, 0x89, + 0x86, 0xae, 0xa5, 0x39, 0x09, 0x95, 0x06, 0x01, + 0x04, 0x10, 0x91, 0x80, 0x8b, 0x84, 0x40, 0x9d, + 0xb4, 0x91, 0x83, 0x93, 0x80, 0x9f, 0xaf, 0x93, 0x08, 0x80, 0x40, 0xb7, 0xae, 0xa8, 0x83, 0xa3, - 0xaf, 0x93, 0x80, 0xba, 0xaa, 0xd4, 0x9a, 0x40, - 0xe4, 0xab, 0xf3, 0xbf, 0x9e, 0x80, 0x40, 0xff, - 0x80, 0x89, 0xa7, 0x30, 0x94, 0x80, 0x8a, 0xa7, - 0x0b, 0x92, 0x80, 0xa1, 0xb8, 0x41, 0x06, 0x88, - 0x80, 0xa4, 0x90, 0x80, 0xb0, 0x9d, 0xef, 0x30, - 0x08, 0xa5, 0x94, 0x80, 0x98, 0x28, 0x08, 0x9f, - 0x8d, 0x80, 0x41, 0x46, 0x92, 0x41, 0x0c, 0x43, - 0x99, 0xe5, 0xee, 0x90, 0x40, 0xc3, 0x4a, 0xbb, - 0x44, 0x2e, 0x4f, 0xd0, 0x42, 0x46, 0x60, 0x21, - 0xb8, 0x42, 0x38, 0x86, 0x9e, 0xf0, 0x9d, 0x91, - 0xaf, 0x8f, 0x83, 0x9e, 0x94, 0x84, 0x92, 0x42, - 0xaf, 0xbf, 0xff, 0xc4, 0x8a, 0x80, 0xc1, 0x8c, - 0xbf, 0x81, 0x9d, 0x57, 0xf1, 0x8d, 0x42, 0xf2, - 0x60, 0x25, 0x0c, 0x41, 0x1e, 0xd0, 0x41, 0x8b, - 0x49, 0x03, 0xea, 0x84, 0x8c, 0x82, 0x88, 0x86, - 0x89, 0x57, 0x65, 0xd4, 0x80, 0xc6, 0x01, 0x08, - 0x09, 0x0b, 0x80, 0x8b, 0x00, 0x06, 0x80, 0xc0, - 0x03, 0x0f, 0x06, 0x80, 0x9b, 0x03, 0x04, 0x00, - 0x16, 0x80, 0x41, 0x53, 0x81, 0x98, 0x80, 0x98, - 0x80, 0x9e, 0x80, 0x98, 0x80, 0x9e, 0x80, 0x98, - 0x80, 0x9e, 0x80, 0x98, 0x80, 0x9e, 0x80, 0x98, - 0x07, 0x50, 0x33, 0x40, 0xc4, 0xba, 0xc3, 0x44, - 0xbb, 0x18, 0x9a, 0x01, 0x00, 0x08, 0x80, 0x89, - 0x03, 0x00, 0x00, 0x28, 0x18, 0x00, 0x00, 0x02, - 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x0b, 0x06, 0x03, 0x03, 0x00, 0x80, 0x89, - 0x80, 0x90, 0x22, 0x04, 0x80, 0x90, 0x51, 0x43, - 0x60, 0xa6, 0xd6, 0xa8, 0x50, 0x34, 0x8a, 0x40, - 0xdd, 0x81, 0x56, 0x81, 0x8d, 0x5d, 0x30, 0x4c, - 0x1e, 0x42, 0x1d, + 0xaf, 0x93, 0x80, 0xba, 0xaa, 0x8c, 0x80, 0xc6, + 0x9a, 0x40, 0xe4, 0xab, 0xf3, 0xbf, 0x9e, 0x80, + 0x40, 0x9f, 0x39, 0xa6, 0x8f, 0x00, 0x80, 0x9b, + 0x80, 0x89, 0xa7, 0x30, 0x94, 0x80, 0x8a, 0xad, + 0x92, 0x80, 0xa1, 0xb8, 0x41, 0x06, 0x88, 0x80, + 0xa4, 0x90, 0x80, 0xb0, 0x9d, 0xef, 0x30, 0x08, + 0xa5, 0x94, 0x80, 0x98, 0x28, 0x08, 0x9f, 0x8d, + 0x80, 0x41, 0x46, 0x92, 0x41, 0x0c, 0x43, 0x99, + 0xe5, 0xee, 0x90, 0x40, 0xc3, 0x4a, 0xbb, 0x44, + 0x2e, 0x4f, 0xd0, 0x42, 0x46, 0x60, 0x21, 0xb8, + 0x42, 0x38, 0x86, 0x9e, 0xf0, 0x9d, 0x91, 0xaf, + 0x8f, 0x83, 0x9e, 0x94, 0x84, 0x92, 0x42, 0xaf, + 0xbf, 0xff, 0xca, 0x20, 0xc1, 0x8c, 0xbf, 0x08, + 0x80, 0x9b, 0x57, 0xf7, 0x87, 0x42, 0xf2, 0x60, + 0x25, 0x0c, 0x41, 0x1e, 0xb0, 0x82, 0x90, 0x1f, + 0x41, 0x8b, 0x49, 0x03, 0xea, 0x84, 0x8c, 0x82, + 0x88, 0x86, 0x89, 0x57, 0x65, 0xd4, 0x80, 0xc6, + 0x01, 0x08, 0x09, 0x0b, 0x80, 0x8b, 0x00, 0x06, + 0x80, 0xc0, 0x03, 0x0f, 0x06, 0x80, 0x9b, 0x03, + 0x04, 0x00, 0x16, 0x80, 0x41, 0x53, 0x81, 0x98, + 0x80, 0x98, 0x80, 0x9e, 0x80, 0x98, 0x80, 0x9e, + 0x80, 0x98, 0x80, 0x9e, 0x80, 0x98, 0x80, 0x9e, + 0x80, 0x98, 0x07, 0x49, 0x33, 0xac, 0x89, 0x86, + 0x8f, 0x80, 0x41, 0x70, 0xab, 0x45, 0x13, 0x40, + 0xc4, 0xba, 0xc3, 0x30, 0x44, 0xb3, 0x18, 0x9a, + 0x01, 0x00, 0x08, 0x80, 0x89, 0x03, 0x00, 0x00, + 0x28, 0x18, 0x00, 0x00, 0x02, 0x01, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0b, 0x06, + 0x03, 0x03, 0x00, 0x80, 0x89, 0x80, 0x90, 0x22, + 0x04, 0x80, 0x90, 0x51, 0x43, 0x60, 0xa6, 0xd6, + 0xa8, 0x50, 0x34, 0x8a, 0x40, 0xdd, 0x81, 0x56, + 0x81, 0x8d, 0x5d, 0x30, 0x4c, 0x1e, 0x42, 0x1d, }; static const uint8_t unicode_prop_ID_Start_index[96] = { 0xf6, 0x03, 0x20, 0xa6, 0x07, 0x00, 0xb1, 0x09, 0x00, 0xba, 0x0a, 0x00, 0xd1, 0x0b, 0x20, 0x62, - 0x0d, 0x40, 0xc7, 0x0e, 0x40, 0x49, 0x12, 0x20, - 0x9b, 0x16, 0x20, 0x75, 0x19, 0x00, 0xf7, 0x1c, - 0x60, 0x72, 0x20, 0x20, 0x26, 0x2d, 0x20, 0x30, - 0x31, 0x00, 0xf0, 0xa6, 0x00, 0xf0, 0xa9, 0x20, - 0xe3, 0xab, 0x20, 0x3e, 0xfd, 0x20, 0x5e, 0x00, - 0x01, 0x64, 0x05, 0x01, 0x01, 0x0a, 0x21, 0x46, - 0x0f, 0x41, 0x9e, 0x12, 0x01, 0x30, 0x16, 0x21, - 0x09, 0x1c, 0x01, 0x2f, 0x34, 0x41, 0xa0, 0x6f, - 0x01, 0xa3, 0xd4, 0x01, 0x4f, 0xd7, 0x01, 0x50, - 0xee, 0x01, 0x1e, 0xb8, 0x22, 0x1e, 0xfa, 0x02, + 0x0d, 0x40, 0x01, 0x0f, 0x20, 0x5e, 0x12, 0x00, + 0xf9, 0x16, 0x00, 0x17, 0x1a, 0x20, 0xc0, 0x1d, + 0x20, 0x9d, 0x20, 0x00, 0x68, 0x2d, 0x00, 0x00, + 0x32, 0x20, 0xc0, 0xa7, 0x20, 0x29, 0xaa, 0x00, + 0xa4, 0xd7, 0x20, 0xc8, 0xfd, 0x20, 0x75, 0x01, + 0x01, 0x37, 0x07, 0x01, 0x36, 0x0a, 0x21, 0xf7, + 0x0f, 0x21, 0xa9, 0x12, 0x01, 0x30, 0x16, 0x21, + 0x8a, 0x1a, 0x01, 0x9a, 0x23, 0x01, 0x80, 0x6e, + 0x21, 0x89, 0xbc, 0x21, 0xc1, 0xd6, 0x01, 0xc5, + 0xe8, 0x21, 0x73, 0xee, 0x01, 0x1e, 0xfa, 0x02, }; -static const uint8_t unicode_prop_ID_Continue1_table[596] = { +static const uint8_t unicode_prop_ID_Continue1_table[607] = { 0xaf, 0x89, 0xa4, 0x80, 0xd6, 0x80, 0x42, 0x47, 0xef, 0x96, 0x80, 0x40, 0xfa, 0x84, 0x41, 0x08, 0xac, 0x00, 0x01, 0x01, 0x00, 0xc7, 0x8a, 0xaf, @@ -446,76 +454,77 @@ static const uint8_t unicode_prop_ID_Continue1_table[596] = { 0x10, 0x83, 0x88, 0x80, 0x89, 0x09, 0x89, 0x91, 0x81, 0xc5, 0x03, 0x28, 0x00, 0x3d, 0x89, 0x09, 0xbc, 0x01, 0x86, 0x8b, 0x38, 0x89, 0xd6, 0x01, - 0x28, 0x81, 0x8a, 0x29, 0x89, 0xbd, 0x0d, 0x89, - 0x8a, 0x00, 0x00, 0x03, 0x81, 0xb0, 0x93, 0x01, - 0x84, 0x8a, 0x80, 0xa3, 0x88, 0x80, 0xe3, 0x93, - 0x80, 0x89, 0x8b, 0x1b, 0x10, 0x11, 0x32, 0x83, - 0x8c, 0x8b, 0x80, 0x8e, 0x42, 0xbe, 0x82, 0x88, - 0x88, 0x43, 0x9f, 0x82, 0x9c, 0x82, 0x9c, 0x81, - 0x9d, 0x81, 0xbf, 0x9f, 0x88, 0x01, 0x89, 0xa0, - 0x11, 0x89, 0x40, 0x8e, 0x80, 0xf5, 0x8b, 0x83, - 0x8b, 0x89, 0x89, 0xff, 0x8a, 0xbb, 0x84, 0xb8, - 0x89, 0x80, 0x9c, 0x81, 0x8a, 0x85, 0x89, 0x95, - 0x8d, 0xc1, 0x84, 0xae, 0x90, 0x8a, 0x89, 0x90, - 0x88, 0x8b, 0x82, 0x9d, 0x8c, 0x81, 0x89, 0xab, - 0x8d, 0xaf, 0x93, 0x87, 0x89, 0x85, 0x89, 0xf5, - 0x10, 0x94, 0x18, 0x1a, 0x0a, 0x40, 0xc5, 0xb9, - 0x04, 0x42, 0x3e, 0x81, 0x92, 0x80, 0xfa, 0x8c, - 0x18, 0x82, 0x8b, 0x4b, 0xfd, 0x82, 0x40, 0x8c, - 0x80, 0xdf, 0x9f, 0x42, 0x29, 0x85, 0xe8, 0x81, - 0x60, 0x75, 0x84, 0x89, 0xc4, 0x03, 0x89, 0x9f, - 0x81, 0xcf, 0x81, 0x41, 0x0f, 0x02, 0x03, 0x80, - 0x96, 0x84, 0xd7, 0x81, 0xb1, 0x91, 0x89, 0x89, - 0x85, 0x91, 0x8c, 0x8a, 0x9b, 0x87, 0x98, 0x8c, - 0xab, 0x83, 0xae, 0x8d, 0x8e, 0x89, 0x8a, 0x80, - 0x89, 0x89, 0xae, 0x8d, 0x8b, 0x07, 0x09, 0x89, - 0xa0, 0x82, 0xb1, 0x00, 0x11, 0x0c, 0x08, 0x80, - 0xa8, 0x24, 0x81, 0x40, 0xeb, 0x38, 0x09, 0x89, - 0x60, 0x4f, 0x23, 0x80, 0x42, 0xe0, 0x8f, 0x8f, - 0x8f, 0x11, 0x97, 0x82, 0x40, 0xbf, 0x89, 0xa4, - 0x80, 0x42, 0xbc, 0x80, 0x40, 0xe1, 0x80, 0x40, - 0x94, 0x84, 0x41, 0x24, 0x89, 0x45, 0x56, 0x10, - 0x0c, 0x83, 0xa7, 0x13, 0x80, 0x40, 0xa4, 0x81, - 0x42, 0x3c, 0x1f, 0x89, 0x42, 0x0b, 0x8a, 0x40, - 0xae, 0x82, 0xb4, 0x8e, 0x9e, 0x89, 0x8e, 0x83, - 0xac, 0x8a, 0xb4, 0x89, 0x2a, 0xa3, 0x8d, 0x80, - 0x89, 0x21, 0xab, 0x80, 0x8b, 0x82, 0xaf, 0x8d, - 0x3b, 0x82, 0x89, 0xd1, 0x8b, 0x28, 0x40, 0x9f, - 0x8b, 0x84, 0x89, 0x2b, 0xb6, 0x08, 0x31, 0x09, - 0x82, 0x88, 0x80, 0x89, 0x09, 0x32, 0x84, 0x40, - 0xbf, 0x91, 0x88, 0x89, 0x18, 0xd0, 0x93, 0x8b, - 0x89, 0x40, 0xd4, 0x31, 0x88, 0x9a, 0x81, 0xd1, - 0x90, 0x8e, 0x89, 0xd0, 0x8c, 0x87, 0x89, 0xd2, - 0x8e, 0x83, 0x89, 0x40, 0xf1, 0x8e, 0x40, 0xa4, - 0x89, 0x41, 0x16, 0x89, 0xa7, 0x30, 0x1f, 0x80, - 0x88, 0x8a, 0xad, 0x8f, 0x41, 0x94, 0x38, 0x87, - 0x8f, 0x89, 0xb7, 0x95, 0x80, 0x8d, 0xf9, 0x2a, - 0x00, 0x08, 0x30, 0x07, 0x89, 0xaf, 0x20, 0x08, - 0x27, 0x89, 0x41, 0x48, 0x83, 0x60, 0x4b, 0x68, - 0x89, 0x40, 0x85, 0x84, 0xba, 0x86, 0x98, 0x89, - 0x43, 0xf6, 0xad, 0x8f, 0x83, 0x60, 0x4d, 0x09, - 0x81, 0x54, 0xc5, 0x22, 0x2f, 0x39, 0x86, 0x9d, - 0x83, 0x40, 0x93, 0x82, 0x45, 0x88, 0xb1, 0x41, - 0xff, 0xb6, 0x83, 0xb1, 0x38, 0x8d, 0x80, 0x95, - 0x20, 0x8e, 0x45, 0x4f, 0x30, 0x90, 0x0e, 0x01, - 0x04, 0x48, 0xa4, 0x86, 0xec, 0x34, 0x89, 0x6c, - 0x17, 0xa5, 0x40, 0xef, + 0x88, 0x8a, 0x29, 0x89, 0xbd, 0x0d, 0x89, 0x8a, + 0x00, 0x00, 0x03, 0x81, 0xb0, 0x93, 0x01, 0x84, + 0x8a, 0x80, 0xa3, 0x88, 0x80, 0xe3, 0x93, 0x80, + 0x89, 0x8b, 0x1b, 0x10, 0x11, 0x32, 0x83, 0x8c, + 0x8b, 0x80, 0x8e, 0x42, 0xbe, 0x82, 0x88, 0x88, + 0x43, 0x9f, 0x82, 0x9c, 0x82, 0x9c, 0x81, 0x9d, + 0x81, 0xbf, 0x9f, 0x88, 0x01, 0x89, 0xa0, 0x11, + 0x89, 0x40, 0x8e, 0x80, 0xf5, 0x8b, 0x83, 0x8b, + 0x89, 0x89, 0xff, 0x8a, 0xbb, 0x84, 0xb8, 0x89, + 0x80, 0x9c, 0x81, 0x8a, 0x85, 0x89, 0x95, 0x8d, + 0xc1, 0x84, 0xae, 0x90, 0x8a, 0x89, 0x90, 0x88, + 0x8b, 0x82, 0x9d, 0x8c, 0x81, 0x89, 0xab, 0x8d, + 0xaf, 0x93, 0x87, 0x89, 0x85, 0x89, 0xf5, 0x10, + 0x94, 0x18, 0x28, 0x0a, 0x40, 0xc5, 0xb9, 0x04, + 0x42, 0x3e, 0x81, 0x92, 0x80, 0xfa, 0x8c, 0x18, + 0x82, 0x8b, 0x4b, 0xfd, 0x82, 0x40, 0x8c, 0x80, + 0xdf, 0x9f, 0x42, 0x29, 0x85, 0xe8, 0x81, 0x60, + 0x75, 0x84, 0x89, 0xc4, 0x03, 0x89, 0x9f, 0x81, + 0xcf, 0x81, 0x41, 0x0f, 0x02, 0x03, 0x80, 0x96, + 0x84, 0xd7, 0x81, 0xb1, 0x91, 0x89, 0x89, 0x85, + 0x91, 0x8c, 0x8a, 0x9b, 0x87, 0x98, 0x8c, 0xab, + 0x83, 0xae, 0x8d, 0x8e, 0x89, 0x8a, 0x80, 0x89, + 0x89, 0xae, 0x8d, 0x8b, 0x07, 0x09, 0x89, 0xa0, + 0x82, 0xb1, 0x00, 0x11, 0x0c, 0x08, 0x80, 0xa8, + 0x24, 0x81, 0x40, 0xeb, 0x38, 0x09, 0x89, 0x60, + 0x4f, 0x23, 0x80, 0x42, 0xe0, 0x8f, 0x8f, 0x8f, + 0x11, 0x97, 0x82, 0x40, 0xbf, 0x89, 0xa4, 0x80, + 0x42, 0xbc, 0x80, 0x40, 0xe1, 0x80, 0x40, 0x94, + 0x84, 0x41, 0x24, 0x89, 0x45, 0x56, 0x10, 0x0c, + 0x83, 0xa7, 0x13, 0x80, 0x40, 0xa4, 0x81, 0x42, + 0x3c, 0x1f, 0x89, 0x42, 0x0b, 0x8a, 0x40, 0xae, + 0x82, 0xb4, 0x8e, 0x9e, 0x89, 0x8e, 0x83, 0xac, + 0x8a, 0xb4, 0x89, 0x2a, 0xa3, 0x8d, 0x80, 0x89, + 0x21, 0xab, 0x80, 0x8b, 0x82, 0xaf, 0x8d, 0x3b, + 0x82, 0x89, 0xd1, 0x8b, 0x28, 0x40, 0x9f, 0x8b, + 0x84, 0x89, 0x2b, 0xb6, 0x08, 0x31, 0x09, 0x82, + 0x88, 0x80, 0x89, 0x09, 0x32, 0x84, 0x40, 0xbf, + 0x91, 0x88, 0x89, 0x18, 0xd0, 0x93, 0x8b, 0x89, + 0x40, 0xd4, 0x31, 0x88, 0x9a, 0x81, 0xd1, 0x90, + 0x8e, 0x89, 0xd0, 0x8c, 0x87, 0x89, 0xd2, 0x8e, + 0x83, 0x89, 0x40, 0xf1, 0x8e, 0x40, 0xa4, 0x89, + 0x40, 0xe6, 0x31, 0x32, 0x80, 0x9b, 0x89, 0xa7, + 0x30, 0x1f, 0x80, 0x88, 0x8a, 0xad, 0x8f, 0x41, + 0x94, 0x38, 0x87, 0x8f, 0x89, 0xb7, 0x95, 0x80, + 0x8d, 0xf9, 0x2a, 0x00, 0x08, 0x30, 0x07, 0x89, + 0xaf, 0x20, 0x08, 0x27, 0x89, 0x41, 0x48, 0x83, + 0x60, 0x4b, 0x68, 0x89, 0x40, 0x85, 0x84, 0xba, + 0x86, 0x98, 0x89, 0x43, 0xf4, 0x00, 0xb6, 0x33, + 0x60, 0x4d, 0x09, 0x81, 0x54, 0xc5, 0x22, 0x2f, + 0x39, 0x86, 0x9d, 0x83, 0x40, 0x93, 0x82, 0x45, + 0x88, 0xb1, 0x41, 0xff, 0xb6, 0x83, 0xb1, 0x38, + 0x8d, 0x80, 0x95, 0x20, 0x8e, 0x45, 0x4f, 0x30, + 0x90, 0x0e, 0x01, 0x04, 0x41, 0x04, 0x86, 0x88, + 0x89, 0x41, 0xa1, 0x8d, 0x45, 0xd5, 0x86, 0xec, + 0x34, 0x89, 0x6c, 0x17, 0xa5, 0x40, 0xef, }; static const uint8_t unicode_prop_ID_Continue1_index[57] = { 0xfa, 0x06, 0x00, 0x84, 0x09, 0x00, 0xf0, 0x0a, - 0x00, 0x70, 0x0c, 0x00, 0xf4, 0x0d, 0x00, 0x3f, - 0x10, 0x00, 0x1a, 0x18, 0x40, 0x74, 0x1b, 0x20, - 0xdd, 0x20, 0x00, 0x0c, 0xa8, 0x00, 0x5a, 0xaa, - 0x00, 0x40, 0xff, 0x20, 0x03, 0x10, 0x41, 0xeb, - 0x12, 0x21, 0x41, 0x16, 0x21, 0x40, 0x1c, 0x01, - 0x5a, 0x6b, 0x01, 0xb0, 0xda, 0x41, 0xf0, 0x01, + 0x00, 0x70, 0x0c, 0x00, 0xf4, 0x0d, 0x00, 0x4a, + 0x10, 0x20, 0x1a, 0x18, 0x20, 0x74, 0x1b, 0x00, + 0xe2, 0x20, 0x00, 0x28, 0xa8, 0x20, 0x7e, 0xaa, + 0x20, 0x40, 0xff, 0x00, 0x03, 0x10, 0x21, 0xeb, + 0x12, 0x01, 0x41, 0x16, 0x01, 0x40, 0x1c, 0x61, + 0x37, 0x6b, 0x21, 0x76, 0xda, 0x01, 0xf0, 0x01, 0x0e, }; #ifdef CONFIG_ALL_UNICODE -static const uint8_t unicode_cc_table[820] = { +static const uint8_t unicode_cc_table[831] = { 0xb2, 0xcf, 0xd4, 0x00, 0xe8, 0x03, 0xdc, 0x00, 0xe8, 0x00, 0xd8, 0x04, 0xdc, 0x01, 0xca, 0x03, 0xdc, 0x01, 0xca, 0x0a, 0xdc, 0x04, 0x01, 0x03, @@ -553,88 +562,89 @@ static const uint8_t unicode_cc_table[820] = { 0x8f, 0x00, 0x09, 0xb0, 0x3c, 0x01, 0x09, 0x8f, 0x00, 0x09, 0xb0, 0x4b, 0x00, 0x09, 0xb0, 0x3c, 0x01, 0x67, 0x00, 0x09, 0x8c, 0x03, 0x6b, 0xb0, - 0x3b, 0x01, 0x76, 0x8d, 0x03, 0x7a, 0xb0, 0x1b, - 0x01, 0xdc, 0x9a, 0x00, 0xdc, 0x80, 0x00, 0xdc, - 0x80, 0x00, 0xd8, 0xb0, 0x06, 0x41, 0x81, 0x80, - 0x00, 0x84, 0x84, 0x03, 0x82, 0x81, 0x00, 0x82, - 0x80, 0xc1, 0x00, 0x09, 0x80, 0xc1, 0xb0, 0x0d, - 0x00, 0xdc, 0xb0, 0x3f, 0x00, 0x07, 0x80, 0x01, - 0x09, 0xb0, 0x21, 0x00, 0xdc, 0xb2, 0x9e, 0xc2, - 0xb3, 0x83, 0x00, 0x09, 0x9e, 0x00, 0x09, 0xb0, - 0x6c, 0x00, 0x09, 0x89, 0xc0, 0xb0, 0x9a, 0x00, - 0xe4, 0xb0, 0x5e, 0x00, 0xde, 0xc0, 0x00, 0xdc, - 0xb0, 0xaa, 0xc0, 0x00, 0xdc, 0xb0, 0x16, 0x00, - 0x09, 0x93, 0xc7, 0x81, 0x00, 0xdc, 0xaf, 0xc4, - 0x05, 0xdc, 0xc1, 0x00, 0xdc, 0xb0, 0x45, 0x00, - 0x07, 0x8e, 0x00, 0x09, 0xa5, 0xc0, 0x00, 0xdc, - 0xc6, 0xb0, 0x05, 0x01, 0x09, 0xb0, 0x09, 0x00, - 0x07, 0x8a, 0x01, 0x09, 0xb0, 0x12, 0x00, 0x07, - 0xb0, 0x67, 0xc2, 0x41, 0x00, 0x04, 0xdc, 0xc1, - 0x03, 0xdc, 0xc0, 0x41, 0x00, 0x05, 0x01, 0x83, - 0x00, 0xdc, 0x85, 0xc0, 0x82, 0xc1, 0xb0, 0x95, - 0xc1, 0x00, 0xdc, 0xc6, 0x00, 0xdc, 0xc1, 0x00, - 0xea, 0x00, 0xd6, 0x00, 0xdc, 0x00, 0xca, 0xe4, - 0x00, 0xe8, 0x01, 0xe4, 0x00, 0xdc, 0x80, 0xc0, - 0x00, 0xe9, 0x00, 0xdc, 0xc0, 0x00, 0xdc, 0xb2, - 0x9f, 0xc1, 0x01, 0x01, 0xc3, 0x02, 0x01, 0xc1, - 0x83, 0xc0, 0x82, 0x01, 0x01, 0xc0, 0x00, 0xdc, - 0xc0, 0x01, 0x01, 0x03, 0xdc, 0xc0, 0xb8, 0x03, - 0xcd, 0xc2, 0xb0, 0x5c, 0x00, 0x09, 0xb0, 0x2f, - 0xdf, 0xb1, 0xf9, 0x00, 0xda, 0x00, 0xe4, 0x00, - 0xe8, 0x00, 0xde, 0x01, 0xe0, 0xb0, 0x38, 0x01, - 0x08, 0xb8, 0x6d, 0xa3, 0xc0, 0x83, 0xc9, 0x9f, - 0xc1, 0xb0, 0x1f, 0xc1, 0xb0, 0xe3, 0x00, 0x09, - 0xb0, 0x8c, 0x00, 0x09, 0x9a, 0xd1, 0xb0, 0x08, - 0x02, 0xdc, 0xa4, 0x00, 0x09, 0xb0, 0x2e, 0x00, - 0x07, 0x8b, 0x00, 0x09, 0xb0, 0xbe, 0xc0, 0x80, - 0xc1, 0x00, 0xdc, 0x81, 0xc1, 0x84, 0xc1, 0x80, - 0xc0, 0xb0, 0x03, 0x00, 0x09, 0xb0, 0xc5, 0x00, - 0x09, 0xb8, 0x46, 0xff, 0x00, 0x1a, 0xb2, 0xd0, - 0xc6, 0x06, 0xdc, 0xc1, 0xb3, 0x9c, 0x00, 0xdc, - 0xb0, 0xb1, 0x00, 0xdc, 0xb0, 0x64, 0xc4, 0xb6, - 0x61, 0x00, 0xdc, 0x80, 0xc0, 0xa7, 0xc0, 0x00, - 0x01, 0x00, 0xdc, 0x83, 0x00, 0x09, 0xb0, 0x74, - 0xc0, 0x00, 0xdc, 0xb2, 0x0c, 0xc3, 0xb1, 0xed, - 0x01, 0xdc, 0xc2, 0x00, 0xdc, 0xc0, 0x03, 0xdc, - 0xb0, 0xc4, 0x00, 0x09, 0xb0, 0x07, 0x00, 0x09, - 0xb0, 0x08, 0x00, 0x09, 0x00, 0x07, 0xb0, 0x14, - 0xc2, 0xaf, 0x01, 0x09, 0xb0, 0x0d, 0x00, 0x07, - 0xb0, 0x1b, 0x00, 0x09, 0x88, 0x00, 0x07, 0xb0, - 0x39, 0x00, 0x09, 0x00, 0x07, 0xb0, 0x81, 0x00, - 0x07, 0x00, 0x09, 0xb0, 0x1f, 0x01, 0x07, 0x8f, - 0x00, 0x09, 0x97, 0xc6, 0x82, 0xc4, 0xb0, 0x9c, - 0x00, 0x09, 0x82, 0x00, 0x07, 0x96, 0xc0, 0xb0, - 0x32, 0x00, 0x09, 0x00, 0x07, 0xb0, 0xca, 0x00, - 0x09, 0x00, 0x07, 0xb0, 0x4d, 0x00, 0x09, 0xb0, - 0x45, 0x00, 0x09, 0x00, 0x07, 0xb0, 0x42, 0x00, - 0x09, 0xb0, 0xdc, 0x00, 0x09, 0x00, 0x07, 0xb1, - 0xc8, 0x00, 0x09, 0x91, 0x00, 0x09, 0xb0, 0x20, - 0x00, 0x09, 0xb1, 0x74, 0x00, 0x09, 0xb0, 0xd1, - 0x00, 0x07, 0x80, 0x01, 0x09, 0xb0, 0x20, 0x00, - 0x09, 0xb8, 0x45, 0x27, 0x04, 0x01, 0xb0, 0x0a, - 0xc6, 0xb8, 0x49, 0x36, 0x00, 0x01, 0xb8, 0x0c, - 0x95, 0x01, 0xd8, 0x02, 0x01, 0x82, 0x00, 0xe2, - 0x04, 0xd8, 0x87, 0x07, 0xdc, 0x81, 0xc4, 0x01, - 0xdc, 0x9d, 0xc3, 0xb0, 0x63, 0xc2, 0xb8, 0x05, - 0x8a, 0xc6, 0x80, 0xd0, 0x81, 0xc6, 0x80, 0xc1, - 0x80, 0xc4, 0xb8, 0x00, 0x74, 0x06, 0xdc, 0xb0, - 0x3c, 0xc5, 0x00, 0x07, + 0x3b, 0x01, 0x76, 0x00, 0x09, 0x8c, 0x03, 0x7a, + 0xb0, 0x1b, 0x01, 0xdc, 0x9a, 0x00, 0xdc, 0x80, + 0x00, 0xdc, 0x80, 0x00, 0xd8, 0xb0, 0x06, 0x41, + 0x81, 0x80, 0x00, 0x84, 0x84, 0x03, 0x82, 0x81, + 0x00, 0x82, 0x80, 0xc1, 0x00, 0x09, 0x80, 0xc1, + 0xb0, 0x0d, 0x00, 0xdc, 0xb0, 0x3f, 0x00, 0x07, + 0x80, 0x01, 0x09, 0xb0, 0x21, 0x00, 0xdc, 0xb2, + 0x9e, 0xc2, 0xb3, 0x83, 0x00, 0x09, 0x9e, 0x00, + 0x09, 0xb0, 0x6c, 0x00, 0x09, 0x89, 0xc0, 0xb0, + 0x9a, 0x00, 0xe4, 0xb0, 0x5e, 0x00, 0xde, 0xc0, + 0x00, 0xdc, 0xb0, 0xaa, 0xc0, 0x00, 0xdc, 0xb0, + 0x16, 0x00, 0x09, 0x93, 0xc7, 0x81, 0x00, 0xdc, + 0xaf, 0xc4, 0x05, 0xdc, 0xc1, 0x00, 0xdc, 0xb0, + 0x45, 0x00, 0x07, 0x8e, 0x00, 0x09, 0xa5, 0xc0, + 0x00, 0xdc, 0xc6, 0xb0, 0x05, 0x01, 0x09, 0xb0, + 0x09, 0x00, 0x07, 0x8a, 0x01, 0x09, 0xb0, 0x12, + 0x00, 0x07, 0xb0, 0x67, 0xc2, 0x41, 0x00, 0x04, + 0xdc, 0xc1, 0x03, 0xdc, 0xc0, 0x41, 0x00, 0x05, + 0x01, 0x83, 0x00, 0xdc, 0x85, 0xc0, 0x82, 0xc1, + 0xb0, 0x95, 0xc1, 0x00, 0xdc, 0xc6, 0x00, 0xdc, + 0xc1, 0x00, 0xea, 0x00, 0xd6, 0x00, 0xdc, 0x00, + 0xca, 0xe4, 0x00, 0xe8, 0x01, 0xe4, 0x00, 0xdc, + 0x80, 0xc0, 0x00, 0xe9, 0x00, 0xdc, 0xc0, 0x00, + 0xdc, 0xb2, 0x9f, 0xc1, 0x01, 0x01, 0xc3, 0x02, + 0x01, 0xc1, 0x83, 0xc0, 0x82, 0x01, 0x01, 0xc0, + 0x00, 0xdc, 0xc0, 0x01, 0x01, 0x03, 0xdc, 0xc0, + 0xb8, 0x03, 0xcd, 0xc2, 0xb0, 0x5c, 0x00, 0x09, + 0xb0, 0x2f, 0xdf, 0xb1, 0xf9, 0x00, 0xda, 0x00, + 0xe4, 0x00, 0xe8, 0x00, 0xde, 0x01, 0xe0, 0xb0, + 0x38, 0x01, 0x08, 0xb8, 0x6d, 0xa3, 0xc0, 0x83, + 0xc9, 0x9f, 0xc1, 0xb0, 0x1f, 0xc1, 0xb0, 0xe3, + 0x00, 0x09, 0xb0, 0x8c, 0x00, 0x09, 0x9a, 0xd1, + 0xb0, 0x08, 0x02, 0xdc, 0xa4, 0x00, 0x09, 0xb0, + 0x2e, 0x00, 0x07, 0x8b, 0x00, 0x09, 0xb0, 0xbe, + 0xc0, 0x80, 0xc1, 0x00, 0xdc, 0x81, 0xc1, 0x84, + 0xc1, 0x80, 0xc0, 0xb0, 0x03, 0x00, 0x09, 0xb0, + 0xc5, 0x00, 0x09, 0xb8, 0x46, 0xff, 0x00, 0x1a, + 0xb2, 0xd0, 0xc6, 0x06, 0xdc, 0xc1, 0xb3, 0x9c, + 0x00, 0xdc, 0xb0, 0xb1, 0x00, 0xdc, 0xb0, 0x64, + 0xc4, 0xb6, 0x61, 0x00, 0xdc, 0x80, 0xc0, 0xa7, + 0xc0, 0x00, 0x01, 0x00, 0xdc, 0x83, 0x00, 0x09, + 0xb0, 0x74, 0xc0, 0x00, 0xdc, 0xb2, 0x0c, 0xc3, + 0xb1, 0xed, 0x01, 0xdc, 0xc2, 0x00, 0xdc, 0xc0, + 0x03, 0xdc, 0xb0, 0xc4, 0x00, 0x09, 0xb0, 0x07, + 0x00, 0x09, 0xb0, 0x08, 0x00, 0x09, 0x00, 0x07, + 0xb0, 0x14, 0xc2, 0xaf, 0x01, 0x09, 0xb0, 0x0d, + 0x00, 0x07, 0xb0, 0x1b, 0x00, 0x09, 0x88, 0x00, + 0x07, 0xb0, 0x39, 0x00, 0x09, 0x00, 0x07, 0xb0, + 0x81, 0x00, 0x07, 0x00, 0x09, 0xb0, 0x1f, 0x01, + 0x07, 0x8f, 0x00, 0x09, 0x97, 0xc6, 0x82, 0xc4, + 0xb0, 0x9c, 0x00, 0x09, 0x82, 0x00, 0x07, 0x96, + 0xc0, 0xb0, 0x32, 0x00, 0x09, 0x00, 0x07, 0xb0, + 0xca, 0x00, 0x09, 0x00, 0x07, 0xb0, 0x4d, 0x00, + 0x09, 0xb0, 0x45, 0x00, 0x09, 0x00, 0x07, 0xb0, + 0x42, 0x00, 0x09, 0xb0, 0xdc, 0x00, 0x09, 0x00, + 0x07, 0xb1, 0x74, 0x00, 0x09, 0xb0, 0x22, 0x00, + 0x09, 0x91, 0x00, 0x09, 0xb0, 0x20, 0x00, 0x09, + 0xb1, 0x74, 0x00, 0x09, 0xb0, 0xd1, 0x00, 0x07, + 0x80, 0x01, 0x09, 0xb0, 0x20, 0x00, 0x09, 0xb8, + 0x45, 0x27, 0x04, 0x01, 0xb0, 0x0a, 0xc6, 0xb8, + 0x49, 0x36, 0x00, 0x01, 0xb8, 0x0c, 0x95, 0x01, + 0xd8, 0x02, 0x01, 0x82, 0x00, 0xe2, 0x04, 0xd8, + 0x87, 0x07, 0xdc, 0x81, 0xc4, 0x01, 0xdc, 0x9d, + 0xc3, 0xb0, 0x63, 0xc2, 0xb8, 0x05, 0x8a, 0xc6, + 0x80, 0xd0, 0x81, 0xc6, 0x80, 0xc1, 0x80, 0xc4, + 0xb0, 0xd4, 0xc6, 0xb1, 0x84, 0xc3, 0xb5, 0xaf, + 0x06, 0xdc, 0xb0, 0x3c, 0xc5, 0x00, 0x07, }; static const uint8_t unicode_cc_index[78] = { 0x4d, 0x03, 0x00, 0x97, 0x05, 0x20, 0xc6, 0x05, 0x00, 0xe7, 0x06, 0x00, 0x45, 0x07, 0x00, 0xe2, 0x08, 0x00, 0x53, 0x09, 0x00, 0xcd, 0x0b, 0x20, - 0x38, 0x0e, 0x00, 0x74, 0x0f, 0x00, 0x60, 0x13, - 0x00, 0x61, 0x1a, 0x20, 0xe7, 0x1b, 0x20, 0xc0, - 0x1d, 0x00, 0xd0, 0x20, 0x20, 0xe0, 0x2d, 0x00, - 0x07, 0xa8, 0x00, 0xc1, 0xaa, 0x00, 0x0d, 0x0a, - 0x21, 0x51, 0x0f, 0x01, 0x35, 0x12, 0x21, 0xc2, - 0x14, 0x21, 0x34, 0x1a, 0x21, 0x30, 0x6b, 0x01, - 0x00, 0xe0, 0x21, 0x4b, 0xe9, 0x01, + 0x38, 0x0e, 0x00, 0x73, 0x0f, 0x20, 0x5d, 0x13, + 0x20, 0x60, 0x1a, 0x20, 0xe6, 0x1b, 0x20, 0xfa, + 0x1c, 0x00, 0x00, 0x1e, 0x20, 0x80, 0x2d, 0x00, + 0x06, 0xa8, 0x00, 0xbe, 0xaa, 0x00, 0x76, 0x03, + 0x01, 0x4d, 0x0f, 0x01, 0xcb, 0x11, 0x21, 0x5e, + 0x14, 0x01, 0x3b, 0x18, 0x21, 0xf0, 0x6a, 0x41, + 0xaa, 0xd1, 0x01, 0x4b, 0xe9, 0x01, }; -static const uint32_t unicode_decomp_table1[686] = { +static const uint32_t unicode_decomp_table1[687] = { 0x00280081, 0x002a0097, 0x002a8081, 0x002bc097, 0x002c8115, 0x002d0097, 0x002d4081, 0x002e0097, 0x002e4115, 0x002f0199, 0x00302016, 0x00400842, @@ -734,82 +744,82 @@ static const uint32_t unicode_decomp_table1[686] = { 0x0c9f8085, 0x0ca01883, 0x0cac4223, 0x0cad4523, 0x0cafc097, 0x0cb004a1, 0x0cb241a5, 0x0cb30097, 0x0cb34099, 0x0cb38097, 0x0cb3c099, 0x0cb417ad, - 0x0cc001b3, 0x0cc0c0b1, 0x0cc100b3, 0x0cc14131, - 0x0cc1c0b5, 0x0cc200b3, 0x0cc241b1, 0x0cc30133, - 0x0cc38131, 0x0cc40085, 0x0cc440b1, 0x0cc48133, - 0x0cc50085, 0x0cc540b5, 0x0cc580b7, 0x0cc5c0b5, - 0x0cc600b1, 0x0cc64135, 0x0cc6c0b3, 0x0cc701b1, - 0x0cc7c0b3, 0x0cc800b5, 0x0cc840b3, 0x0cc881b1, - 0x0cc9422f, 0x0cca4131, 0x0ccac0b5, 0x0ccb00b1, - 0x0ccb40b3, 0x0ccb80b5, 0x0ccbc0b1, 0x0ccc012f, - 0x0ccc80b5, 0x0cccc0b3, 0x0ccd00b5, 0x0ccd40b1, - 0x0ccd80b5, 0x0ccdc085, 0x0cce02b1, 0x0ccf40b3, - 0x0ccf80b1, 0x0ccfc085, 0x0cd001b1, 0x0cd0c0b3, - 0x0cd101b1, 0x0cd1c0b5, 0x0cd200b3, 0x0cd24085, - 0x0cd280b5, 0x0cd2c085, 0x0cd30133, 0x0cd381b1, - 0x0cd440b3, 0x0cd48085, 0x0cd4c0b1, 0x0cd500b3, - 0x0cd54085, 0x0cd580b5, 0x0cd5c0b1, 0x0cd60521, - 0x0cd88525, 0x0cdb02a5, 0x0cdc4099, 0x0cdc8117, - 0x0cdd0099, 0x0cdd4197, 0x0cde0127, 0x0cde8285, - 0x0cdfc089, 0x0ce0043f, 0x0ce20099, 0x0ce2409b, - 0x0ce283bf, 0x0ce44219, 0x0ce54205, 0x0ce6433f, - 0x0ce7c131, 0x0ce84085, 0x0ce881b1, 0x0ce94085, - 0x0ce98107, 0x0cea0089, 0x0cea4097, 0x0cea8219, - 0x0ceb809d, 0x0cebc08d, 0x0cec083f, 0x0cf00105, - 0x0cf0809b, 0x0cf0c197, 0x0cf1809b, 0x0cf1c099, - 0x0cf20517, 0x0cf48099, 0x0cf4c117, 0x0cf54119, - 0x0cf5c097, 0x0cf6009b, 0x0cf64099, 0x0cf68217, - 0x0cf78119, 0x0cf804a1, 0x0cfa4525, 0x0cfcc525, - 0x0cff4125, 0x0cffc099, 0x29a70103, 0x29dc0081, - 0x29fe0103, 0x2ad70203, 0x3e401482, 0x3e4a7f82, - 0x3e6a3f82, 0x3e8aa102, 0x3e9b0110, 0x3e9c2f82, - 0x3eb3c590, 0x3ec00197, 0x3ec0c119, 0x3ec1413f, - 0x3ec4c2af, 0x3ec74184, 0x3ec804ad, 0x3eca4081, - 0x3eca8304, 0x3ecc03a0, 0x3ece02a0, 0x3ecf8084, - 0x3ed00120, 0x3ed0c120, 0x3ed184ae, 0x3ed3c085, - 0x3ed4312d, 0x3ef4cbad, 0x3efa892f, 0x3eff022d, - 0x3f002f2f, 0x3f1782a5, 0x3f18c0b1, 0x3f1907af, - 0x3f1cffaf, 0x3f3c81a5, 0x3f3d64af, 0x3f542031, - 0x3f649b31, 0x3f7c0131, 0x3f7c83b3, 0x3f7e40b1, - 0x3f7e80bd, 0x3f7ec0bb, 0x3f7f00b3, 0x3f840503, - 0x3f8c01ad, 0x3f8cc315, 0x3f8e462d, 0x3f91cc03, - 0x3f97c695, 0x3f9c01af, 0x3f9d0085, 0x3f9d852f, - 0x3fa03aad, 0x3fbd442f, 0x3fc06f1f, 0x3fd7c11f, - 0x3fd85fad, 0x3fe80081, 0x3fe84f1f, 0x3ff0831f, - 0x3ff2831f, 0x3ff4831f, 0x3ff6819f, 0x3ff80783, - 0x44268192, 0x442ac092, 0x444b8112, 0x44d2c112, - 0x452ec212, 0x456e8112, 0x74578392, 0x746ec312, - 0x75000d1f, 0x75068d1f, 0x750d0d1f, 0x7513839f, - 0x7515891f, 0x751a0d1f, 0x75208d1f, 0x75271015, - 0x752f439f, 0x7531459f, 0x75340d1f, 0x753a8d1f, - 0x75410395, 0x7543441f, 0x7545839f, 0x75478d1f, - 0x754e0795, 0x7552839f, 0x75548d1f, 0x755b0d1f, - 0x75618d1f, 0x75680d1f, 0x756e8d1f, 0x75750d1f, - 0x757b8d1f, 0x75820d1f, 0x75888d1f, 0x758f0d1f, - 0x75958d1f, 0x759c0d1f, 0x75a28d1f, 0x75a90103, - 0x75aa089f, 0x75ae4081, 0x75ae839f, 0x75b04081, - 0x75b08c9f, 0x75b6c081, 0x75b7032d, 0x75b8889f, - 0x75bcc081, 0x75bd039f, 0x75bec081, 0x75bf0c9f, - 0x75c54081, 0x75c5832d, 0x75c7089f, 0x75cb4081, - 0x75cb839f, 0x75cd4081, 0x75cd8c9f, 0x75d3c081, - 0x75d4032d, 0x75d5889f, 0x75d9c081, 0x75da039f, - 0x75dbc081, 0x75dc0c9f, 0x75e24081, 0x75e2832d, - 0x75e4089f, 0x75e84081, 0x75e8839f, 0x75ea4081, - 0x75ea8c9f, 0x75f0c081, 0x75f1042d, 0x75f3851f, - 0x75f6051f, 0x75f8851f, 0x75fb051f, 0x75fd851f, - 0x7b80022d, 0x7b814dad, 0x7b884203, 0x7b89c081, - 0x7b8a452d, 0x7b8d0403, 0x7b908081, 0x7b91dc03, - 0x7ba0052d, 0x7ba2c8ad, 0x7ba84483, 0x7baac8ad, - 0x7c400097, 0x7c404521, 0x7c440d25, 0x7c4a8087, - 0x7c4ac115, 0x7c4b4117, 0x7c4c0d1f, 0x7c528217, - 0x7c538099, 0x7c53c097, 0x7c5a8117, 0x7c640097, - 0x7c80012f, 0x7c808081, 0x7c841603, 0x7c9004c1, - 0x7c940103, 0xbe0001ac, 0xbe00d110, 0xbe0947ac, - 0xbe0d3910, 0xbe29872c, 0xbe2d022c, 0xbe2e3790, - 0xbe49ff90, 0xbe69bc10, + 0x0cbfc085, 0x0cc001b3, 0x0cc0c0b1, 0x0cc100b3, + 0x0cc14131, 0x0cc1c0b5, 0x0cc200b3, 0x0cc241b1, + 0x0cc30133, 0x0cc38131, 0x0cc40085, 0x0cc440b1, + 0x0cc48133, 0x0cc50085, 0x0cc540b5, 0x0cc580b7, + 0x0cc5c0b5, 0x0cc600b1, 0x0cc64135, 0x0cc6c0b3, + 0x0cc701b1, 0x0cc7c0b3, 0x0cc800b5, 0x0cc840b3, + 0x0cc881b1, 0x0cc9422f, 0x0cca4131, 0x0ccac0b5, + 0x0ccb00b1, 0x0ccb40b3, 0x0ccb80b5, 0x0ccbc0b1, + 0x0ccc012f, 0x0ccc80b5, 0x0cccc0b3, 0x0ccd00b5, + 0x0ccd40b1, 0x0ccd80b5, 0x0ccdc085, 0x0cce02b1, + 0x0ccf40b3, 0x0ccf80b1, 0x0ccfc085, 0x0cd001b1, + 0x0cd0c0b3, 0x0cd101b1, 0x0cd1c0b5, 0x0cd200b3, + 0x0cd24085, 0x0cd280b5, 0x0cd2c085, 0x0cd30133, + 0x0cd381b1, 0x0cd440b3, 0x0cd48085, 0x0cd4c0b1, + 0x0cd500b3, 0x0cd54085, 0x0cd580b5, 0x0cd5c0b1, + 0x0cd60521, 0x0cd88525, 0x0cdb02a5, 0x0cdc4099, + 0x0cdc8117, 0x0cdd0099, 0x0cdd4197, 0x0cde0127, + 0x0cde8285, 0x0cdfc089, 0x0ce0043f, 0x0ce20099, + 0x0ce2409b, 0x0ce283bf, 0x0ce44219, 0x0ce54205, + 0x0ce6433f, 0x0ce7c131, 0x0ce84085, 0x0ce881b1, + 0x0ce94085, 0x0ce98107, 0x0cea0089, 0x0cea4097, + 0x0cea8219, 0x0ceb809d, 0x0cebc08d, 0x0cec083f, + 0x0cf00105, 0x0cf0809b, 0x0cf0c197, 0x0cf1809b, + 0x0cf1c099, 0x0cf20517, 0x0cf48099, 0x0cf4c117, + 0x0cf54119, 0x0cf5c097, 0x0cf6009b, 0x0cf64099, + 0x0cf68217, 0x0cf78119, 0x0cf804a1, 0x0cfa4525, + 0x0cfcc525, 0x0cff4125, 0x0cffc099, 0x29a70103, + 0x29dc0081, 0x29fe0103, 0x2ad70203, 0x3e401482, + 0x3e4a7f82, 0x3e6a3f82, 0x3e8aa102, 0x3e9b0110, + 0x3e9c2f82, 0x3eb3c590, 0x3ec00197, 0x3ec0c119, + 0x3ec1413f, 0x3ec4c2af, 0x3ec74184, 0x3ec804ad, + 0x3eca4081, 0x3eca8304, 0x3ecc03a0, 0x3ece02a0, + 0x3ecf8084, 0x3ed00120, 0x3ed0c120, 0x3ed184ae, + 0x3ed3c085, 0x3ed4312d, 0x3ef4cbad, 0x3efa892f, + 0x3eff022d, 0x3f002f2f, 0x3f1782a5, 0x3f18c0b1, + 0x3f1907af, 0x3f1cffaf, 0x3f3c81a5, 0x3f3d64af, + 0x3f542031, 0x3f649b31, 0x3f7c0131, 0x3f7c83b3, + 0x3f7e40b1, 0x3f7e80bd, 0x3f7ec0bb, 0x3f7f00b3, + 0x3f840503, 0x3f8c01ad, 0x3f8cc315, 0x3f8e462d, + 0x3f91cc03, 0x3f97c695, 0x3f9c01af, 0x3f9d0085, + 0x3f9d852f, 0x3fa03aad, 0x3fbd442f, 0x3fc06f1f, + 0x3fd7c11f, 0x3fd85fad, 0x3fe80081, 0x3fe84f1f, + 0x3ff0831f, 0x3ff2831f, 0x3ff4831f, 0x3ff6819f, + 0x3ff80783, 0x44268192, 0x442ac092, 0x444b8112, + 0x44d2c112, 0x452ec212, 0x456e8112, 0x74578392, + 0x746ec312, 0x75000d1f, 0x75068d1f, 0x750d0d1f, + 0x7513839f, 0x7515891f, 0x751a0d1f, 0x75208d1f, + 0x75271015, 0x752f439f, 0x7531459f, 0x75340d1f, + 0x753a8d1f, 0x75410395, 0x7543441f, 0x7545839f, + 0x75478d1f, 0x754e0795, 0x7552839f, 0x75548d1f, + 0x755b0d1f, 0x75618d1f, 0x75680d1f, 0x756e8d1f, + 0x75750d1f, 0x757b8d1f, 0x75820d1f, 0x75888d1f, + 0x758f0d1f, 0x75958d1f, 0x759c0d1f, 0x75a28d1f, + 0x75a90103, 0x75aa089f, 0x75ae4081, 0x75ae839f, + 0x75b04081, 0x75b08c9f, 0x75b6c081, 0x75b7032d, + 0x75b8889f, 0x75bcc081, 0x75bd039f, 0x75bec081, + 0x75bf0c9f, 0x75c54081, 0x75c5832d, 0x75c7089f, + 0x75cb4081, 0x75cb839f, 0x75cd4081, 0x75cd8c9f, + 0x75d3c081, 0x75d4032d, 0x75d5889f, 0x75d9c081, + 0x75da039f, 0x75dbc081, 0x75dc0c9f, 0x75e24081, + 0x75e2832d, 0x75e4089f, 0x75e84081, 0x75e8839f, + 0x75ea4081, 0x75ea8c9f, 0x75f0c081, 0x75f1042d, + 0x75f3851f, 0x75f6051f, 0x75f8851f, 0x75fb051f, + 0x75fd851f, 0x7b80022d, 0x7b814dad, 0x7b884203, + 0x7b89c081, 0x7b8a452d, 0x7b8d0403, 0x7b908081, + 0x7b91dc03, 0x7ba0052d, 0x7ba2c8ad, 0x7ba84483, + 0x7baac8ad, 0x7c400097, 0x7c404521, 0x7c440d25, + 0x7c4a8087, 0x7c4ac115, 0x7c4b4117, 0x7c4c0d1f, + 0x7c528217, 0x7c538099, 0x7c53c097, 0x7c5a8197, + 0x7c640097, 0x7c80012f, 0x7c808081, 0x7c841603, + 0x7c9004c1, 0x7c940103, 0xbe0001ac, 0xbe00d110, + 0xbe0947ac, 0xbe0d3910, 0xbe29872c, 0xbe2d022c, + 0xbe2e3790, 0xbe49ff90, 0xbe69bc10, }; -static const uint16_t unicode_decomp_table2[686] = { +static const uint16_t unicode_decomp_table2[687] = { 0x0020, 0x0000, 0x0061, 0x0002, 0x0004, 0x0006, 0x03bc, 0x0008, 0x000a, 0x000c, 0x0015, 0x0095, 0x00a5, 0x00b9, 0x00c1, 0x00c3, 0x00c7, 0x00cb, 0x00d1, 0x00d7, 0x00dd, 0x00e0, 0x00e6, 0x00f8, @@ -859,46 +869,46 @@ static const uint16_t unicode_decomp_table2[686] = { 0x0cf4, 0x0cfc, 0x0d04, 0x0d0c, 0x0d14, 0x0d22, 0x0d2e, 0x0d7a, 0x0d82, 0x0d85, 0x0d89, 0x0d8d, 0x0d9d, 0x0db1, 0x0db5, 0x0dbc, 0x0dc2, 0x0dc6, 0x0e28, 0x0e2c, 0x0e30, 0x0e32, 0x0e36, 0x0e3c, - 0x0e3e, 0x0e41, 0x0e43, 0x0e46, 0x0e77, 0x0e85, 0x0e8a, 0x0e90, - 0x0e98, 0x0e9f, 0x0ea5, 0x0eb0, 0x0eba, 0x0ec2, 0x0ec6, 0x0ecb, - 0x0ed5, 0x0ed9, 0x0ee0, 0x0ee8, 0x0eef, 0x0ef4, 0x0f00, 0x0f06, - 0x0f11, 0x0f17, 0x0f1e, 0x0f24, 0x0f2f, 0x0f39, 0x0f41, 0x0f48, - 0x0f4d, 0x0f53, 0x0f5a, 0x0f5f, 0x0f65, 0x0f6c, 0x0f72, 0x0f79, - 0x0f7e, 0x0f85, 0x0f89, 0x0f9a, 0x0fa0, 0x0fa5, 0x0fa9, 0x0fb4, - 0x0fba, 0x0fc5, 0x0fcc, 0x0fd2, 0x0fd6, 0x0fdd, 0x0fe1, 0x0feb, - 0x0ff6, 0x0ffc, 0x1000, 0x1005, 0x100b, 0x100f, 0x1016, 0x101b, - 0x101f, 0x1025, 0x102b, 0x102e, 0x1032, 0x1035, 0x103b, 0x1041, - 0x1055, 0x105d, 0x1075, 0x1078, 0x107c, 0x1091, 0x109d, 0x10ad, - 0x10bf, 0x10c7, 0x10cb, 0x10d6, 0x10da, 0x10e6, 0x10ee, 0x10f0, - 0x10fc, 0x1101, 0x110d, 0x113d, 0x1145, 0x1149, 0x114f, 0x1153, - 0x1156, 0x116a, 0x116d, 0x1171, 0x1177, 0x1179, 0x117d, 0x1180, - 0x1188, 0x118e, 0x1192, 0x1198, 0x119e, 0x11a4, 0x11a7, 0xa76f, - 0x11ab, 0x11af, 0x11b7, 0x1209, 0x1307, 0x1405, 0x1489, 0x148e, - 0x154c, 0x1565, 0x156b, 0x1571, 0x1577, 0x1583, 0x158f, 0x002b, - 0x159a, 0x15b2, 0x15b6, 0x15ba, 0x15be, 0x15c2, 0x15c6, 0x15da, - 0x15de, 0x1642, 0x165b, 0x1681, 0x1687, 0x1745, 0x174b, 0x1750, - 0x1770, 0x1870, 0x1876, 0x190a, 0x19cc, 0x1a70, 0x1a78, 0x1a96, - 0x1a9b, 0x1aaf, 0x1ab9, 0x1abf, 0x1ad3, 0x1ad8, 0x1ade, 0x1aec, - 0x1b1c, 0x1b29, 0x1b31, 0x1b35, 0x1b4b, 0x1bc2, 0x1bd4, 0x1bd6, - 0x1bd8, 0x3164, 0x1c19, 0x1c1b, 0x1c1d, 0x1c1f, 0x1c21, 0x1c23, - 0x1c41, 0x1c4f, 0x1c54, 0x1c5d, 0x1c66, 0x1c78, 0x1c81, 0x1ca1, - 0x1cbc, 0x1cbe, 0x1cc0, 0x1cc2, 0x1cc4, 0x1cc6, 0x1cc8, 0x1cca, - 0x1cea, 0x1cec, 0x1cee, 0x1cf0, 0x1cf2, 0x1cf9, 0x1cfb, 0x1cfd, - 0x1cff, 0x1d0e, 0x1d10, 0x1d12, 0x1d14, 0x1d16, 0x1d18, 0x1d1a, - 0x1d1c, 0x1d1e, 0x1d20, 0x1d22, 0x1d24, 0x1d26, 0x1d28, 0x1d2a, - 0x1d2e, 0x03f4, 0x1d30, 0x2207, 0x1d32, 0x2202, 0x1d34, 0x1d3c, - 0x03f4, 0x1d3e, 0x2207, 0x1d40, 0x2202, 0x1d42, 0x1d4a, 0x03f4, - 0x1d4c, 0x2207, 0x1d4e, 0x2202, 0x1d50, 0x1d58, 0x03f4, 0x1d5a, - 0x2207, 0x1d5c, 0x2202, 0x1d5e, 0x1d66, 0x03f4, 0x1d68, 0x2207, - 0x1d6a, 0x2202, 0x1d6c, 0x1d76, 0x1d78, 0x1d7a, 0x1d7c, 0x1d7e, - 0x1d80, 0x1d86, 0x1da3, 0x062d, 0x1dab, 0x1db7, 0x062c, 0x1dc7, - 0x1e37, 0x1e43, 0x1e56, 0x1e68, 0x1e7b, 0x1e7d, 0x1e81, 0x1e87, - 0x1e8d, 0x1e8f, 0x1e93, 0x1e95, 0x1e9d, 0x1ea0, 0x1ea2, 0x1ea6, - 0x1ea8, 0x30b5, 0x1eae, 0x1f06, 0x1f1c, 0x1f20, 0x1f25, 0x1f72, - 0x1f83, 0x2084, 0x2094, 0x209a, 0x2194, 0x22b2, + 0x0e3e, 0x0e41, 0x0e43, 0x0e46, 0x0e77, 0x0e7b, 0x0e89, 0x0e8e, + 0x0e94, 0x0e9c, 0x0ea3, 0x0ea9, 0x0eb4, 0x0ebe, 0x0ec6, 0x0eca, + 0x0ecf, 0x0ed9, 0x0edd, 0x0ee4, 0x0eec, 0x0ef3, 0x0ef8, 0x0f04, + 0x0f0a, 0x0f15, 0x0f1b, 0x0f22, 0x0f28, 0x0f33, 0x0f3d, 0x0f45, + 0x0f4c, 0x0f51, 0x0f57, 0x0f5e, 0x0f63, 0x0f69, 0x0f70, 0x0f76, + 0x0f7d, 0x0f82, 0x0f89, 0x0f8d, 0x0f9e, 0x0fa4, 0x0fa9, 0x0fad, + 0x0fb8, 0x0fbe, 0x0fc9, 0x0fd0, 0x0fd6, 0x0fda, 0x0fe1, 0x0fe5, + 0x0fef, 0x0ffa, 0x1000, 0x1004, 0x1009, 0x100f, 0x1013, 0x101a, + 0x101f, 0x1023, 0x1029, 0x102f, 0x1032, 0x1036, 0x1039, 0x103f, + 0x1045, 0x1059, 0x1061, 0x1079, 0x107c, 0x1080, 0x1095, 0x10a1, + 0x10b1, 0x10c3, 0x10cb, 0x10cf, 0x10da, 0x10de, 0x10ea, 0x10f2, + 0x10f4, 0x1100, 0x1105, 0x1111, 0x1141, 0x1149, 0x114d, 0x1153, + 0x1157, 0x115a, 0x116e, 0x1171, 0x1175, 0x117b, 0x117d, 0x1181, + 0x1184, 0x118c, 0x1192, 0x1196, 0x119c, 0x11a2, 0x11a8, 0x11ab, + 0xa76f, 0x11af, 0x11b3, 0x11bb, 0x120d, 0x130b, 0x1409, 0x148d, + 0x1492, 0x1550, 0x1569, 0x156f, 0x1575, 0x157b, 0x1587, 0x1593, + 0x002b, 0x159e, 0x15b6, 0x15ba, 0x15be, 0x15c2, 0x15c6, 0x15ca, + 0x15de, 0x15e2, 0x1646, 0x165f, 0x1685, 0x168b, 0x1749, 0x174f, + 0x1754, 0x1774, 0x1874, 0x187a, 0x190e, 0x19d0, 0x1a74, 0x1a7c, + 0x1a9a, 0x1a9f, 0x1ab3, 0x1abd, 0x1ac3, 0x1ad7, 0x1adc, 0x1ae2, + 0x1af0, 0x1b20, 0x1b2d, 0x1b35, 0x1b39, 0x1b4f, 0x1bc6, 0x1bd8, + 0x1bda, 0x1bdc, 0x3164, 0x1c1d, 0x1c1f, 0x1c21, 0x1c23, 0x1c25, + 0x1c27, 0x1c45, 0x1c53, 0x1c58, 0x1c61, 0x1c6a, 0x1c7c, 0x1c85, + 0x1ca5, 0x1cc0, 0x1cc2, 0x1cc4, 0x1cc6, 0x1cc8, 0x1cca, 0x1ccc, + 0x1cce, 0x1cee, 0x1cf0, 0x1cf2, 0x1cf4, 0x1cf6, 0x1cfd, 0x1cff, + 0x1d01, 0x1d03, 0x1d12, 0x1d14, 0x1d16, 0x1d18, 0x1d1a, 0x1d1c, + 0x1d1e, 0x1d20, 0x1d22, 0x1d24, 0x1d26, 0x1d28, 0x1d2a, 0x1d2c, + 0x1d2e, 0x1d32, 0x03f4, 0x1d34, 0x2207, 0x1d36, 0x2202, 0x1d38, + 0x1d40, 0x03f4, 0x1d42, 0x2207, 0x1d44, 0x2202, 0x1d46, 0x1d4e, + 0x03f4, 0x1d50, 0x2207, 0x1d52, 0x2202, 0x1d54, 0x1d5c, 0x03f4, + 0x1d5e, 0x2207, 0x1d60, 0x2202, 0x1d62, 0x1d6a, 0x03f4, 0x1d6c, + 0x2207, 0x1d6e, 0x2202, 0x1d70, 0x1d7a, 0x1d7c, 0x1d7e, 0x1d80, + 0x1d82, 0x1d84, 0x1d8a, 0x1da7, 0x062d, 0x1daf, 0x1dbb, 0x062c, + 0x1dcb, 0x1e3b, 0x1e47, 0x1e5a, 0x1e6c, 0x1e7f, 0x1e81, 0x1e85, + 0x1e8b, 0x1e91, 0x1e93, 0x1e97, 0x1e99, 0x1ea1, 0x1ea4, 0x1ea6, + 0x1eac, 0x1eae, 0x30b5, 0x1eb4, 0x1f0c, 0x1f22, 0x1f26, 0x1f2b, + 0x1f78, 0x1f89, 0x208a, 0x209a, 0x20a0, 0x219a, 0x22b8, }; -static const uint8_t unicode_decomp_data[9152] = { +static const uint8_t unicode_decomp_data[9158] = { 0x20, 0x88, 0x20, 0x84, 0x32, 0x33, 0x20, 0x81, 0x20, 0xa7, 0x31, 0x6f, 0x31, 0xd0, 0x34, 0x31, 0xd0, 0x32, 0x33, 0xd0, 0x34, 0x41, 0x80, 0x41, @@ -1361,688 +1371,689 @@ static const uint8_t unicode_decomp_data[9152] = { 0x1f, 0x22, 0x24, 0x26, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x30, 0x33, 0x36, 0x39, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x42, 0x44, 0x46, 0x47, 0x48, - 0x49, 0x4a, 0x4b, 0x4d, 0x4e, 0x4f, 0x50, 0xa1, - 0x30, 0x01, 0x30, 0x5b, 0x27, 0x01, 0x4a, 0x34, - 0x00, 0x01, 0x52, 0x39, 0x01, 0xa2, 0x30, 0x00, - 0x5a, 0x49, 0xa4, 0x30, 0x00, 0x27, 0x4f, 0x0c, - 0xa4, 0x30, 0x00, 0x4f, 0x1d, 0x02, 0x05, 0x4f, - 0xa8, 0x30, 0x00, 0x11, 0x07, 0x54, 0x21, 0xa8, - 0x30, 0x00, 0x54, 0x03, 0x54, 0xa4, 0x30, 0x06, - 0x4f, 0x15, 0x06, 0x58, 0x3c, 0x07, 0x00, 0x46, - 0xab, 0x30, 0x00, 0x3e, 0x18, 0x1d, 0x00, 0x42, - 0x3f, 0x51, 0xac, 0x30, 0x00, 0x41, 0x47, 0x00, - 0x47, 0x32, 0xae, 0x30, 0xac, 0x30, 0xae, 0x30, - 0x00, 0x1d, 0x4e, 0xad, 0x30, 0x00, 0x38, 0x3d, - 0x4f, 0x01, 0x3e, 0x13, 0x4f, 0xad, 0x30, 0xed, - 0x30, 0xad, 0x30, 0x00, 0x40, 0x03, 0x3c, 0x33, - 0xad, 0x30, 0x00, 0x40, 0x34, 0x4f, 0x1b, 0x3e, - 0xad, 0x30, 0x00, 0x40, 0x42, 0x16, 0x1b, 0xb0, - 0x30, 0x00, 0x39, 0x30, 0xa4, 0x30, 0x0c, 0x45, - 0x3c, 0x24, 0x4f, 0x0b, 0x47, 0x18, 0x00, 0x49, - 0xaf, 0x30, 0x00, 0x3e, 0x4d, 0x1e, 0xb1, 0x30, - 0x00, 0x4b, 0x08, 0x02, 0x3a, 0x19, 0x02, 0x4b, - 0x2c, 0xa4, 0x30, 0x11, 0x00, 0x0b, 0x47, 0xb5, - 0x30, 0x00, 0x3e, 0x0c, 0x47, 0x2b, 0xb0, 0x30, - 0x07, 0x3a, 0x43, 0x00, 0xb9, 0x30, 0x02, 0x3a, - 0x08, 0x02, 0x3a, 0x0f, 0x07, 0x43, 0x00, 0xb7, - 0x30, 0x10, 0x00, 0x12, 0x34, 0x11, 0x3c, 0x13, - 0x17, 0xa4, 0x30, 0x2a, 0x1f, 0x24, 0x2b, 0x00, - 0x20, 0xbb, 0x30, 0x16, 0x41, 0x00, 0x38, 0x0d, - 0xc4, 0x30, 0x0d, 0x38, 0x00, 0xd0, 0x30, 0x00, - 0x2c, 0x1c, 0x1b, 0xa2, 0x30, 0x32, 0x00, 0x17, - 0x26, 0x49, 0xaf, 0x30, 0x25, 0x00, 0x3c, 0xb3, - 0x30, 0x21, 0x00, 0x20, 0x38, 0xa1, 0x30, 0x34, - 0x00, 0x48, 0x22, 0x28, 0xa3, 0x30, 0x32, 0x00, - 0x59, 0x25, 0xa7, 0x30, 0x2f, 0x1c, 0x10, 0x00, - 0x44, 0xd5, 0x30, 0x00, 0x14, 0x1e, 0xaf, 0x30, - 0x29, 0x00, 0x10, 0x4d, 0x3c, 0xda, 0x30, 0xbd, - 0x30, 0xb8, 0x30, 0x22, 0x13, 0x1a, 0x20, 0x33, - 0x0c, 0x22, 0x3b, 0x01, 0x22, 0x44, 0x00, 0x21, - 0x44, 0x07, 0xa4, 0x30, 0x39, 0x00, 0x4f, 0x24, - 0xc8, 0x30, 0x14, 0x23, 0x00, 0xdb, 0x30, 0xf3, - 0x30, 0xc9, 0x30, 0x14, 0x2a, 0x00, 0x12, 0x33, - 0x22, 0x12, 0x33, 0x2a, 0xa4, 0x30, 0x3a, 0x00, - 0x0b, 0x49, 0xa4, 0x30, 0x3a, 0x00, 0x47, 0x3a, - 0x1f, 0x2b, 0x3a, 0x47, 0x0b, 0xb7, 0x30, 0x27, - 0x3c, 0x00, 0x30, 0x3c, 0xaf, 0x30, 0x30, 0x00, - 0x3e, 0x44, 0xdf, 0x30, 0xea, 0x30, 0xd0, 0x30, - 0x0f, 0x1a, 0x00, 0x2c, 0x1b, 0xe1, 0x30, 0xac, - 0x30, 0xac, 0x30, 0x35, 0x00, 0x1c, 0x47, 0x35, - 0x50, 0x1c, 0x3f, 0xa2, 0x30, 0x42, 0x5a, 0x27, - 0x42, 0x5a, 0x49, 0x44, 0x00, 0x51, 0xc3, 0x30, - 0x27, 0x00, 0x05, 0x28, 0xea, 0x30, 0xe9, 0x30, - 0xd4, 0x30, 0x17, 0x00, 0x28, 0xd6, 0x30, 0x15, - 0x26, 0x00, 0x15, 0xec, 0x30, 0xe0, 0x30, 0xb2, - 0x30, 0x3a, 0x41, 0x16, 0x00, 0x41, 0xc3, 0x30, - 0x2c, 0x00, 0x05, 0x30, 0x00, 0xb9, 0x70, 0x31, - 0x00, 0x30, 0x00, 0xb9, 0x70, 0x32, 0x00, 0x30, - 0x00, 0xb9, 0x70, 0x68, 0x50, 0x61, 0x64, 0x61, - 0x41, 0x55, 0x62, 0x61, 0x72, 0x6f, 0x56, 0x70, - 0x63, 0x64, 0x6d, 0x64, 0x00, 0x6d, 0x00, 0xb2, - 0x00, 0x49, 0x00, 0x55, 0x00, 0x73, 0x5e, 0x10, - 0x62, 0x2d, 0x66, 0x8c, 0x54, 0x27, 0x59, 0x63, - 0x6b, 0x0e, 0x66, 0xbb, 0x6c, 0x2a, 0x68, 0x0f, - 0x5f, 0x1a, 0x4f, 0x3e, 0x79, 0x70, 0x00, 0x41, - 0x6e, 0x00, 0x41, 0xbc, 0x03, 0x41, 0x6d, 0x00, - 0x41, 0x6b, 0x00, 0x41, 0x4b, 0x00, 0x42, 0x4d, - 0x00, 0x42, 0x47, 0x00, 0x42, 0x63, 0x61, 0x6c, - 0x6b, 0x63, 0x61, 0x6c, 0x70, 0x00, 0x46, 0x6e, - 0x00, 0x46, 0xbc, 0x03, 0x46, 0xbc, 0x03, 0x67, - 0x6d, 0x00, 0x67, 0x6b, 0x00, 0x67, 0x48, 0x00, - 0x7a, 0x6b, 0x48, 0x7a, 0x4d, 0x48, 0x7a, 0x47, - 0x48, 0x7a, 0x54, 0x48, 0x7a, 0xbc, 0x03, 0x13, - 0x21, 0x6d, 0x00, 0x13, 0x21, 0x64, 0x00, 0x13, - 0x21, 0x6b, 0x00, 0x13, 0x21, 0x66, 0x00, 0x6d, - 0x6e, 0x00, 0x6d, 0xbc, 0x03, 0x6d, 0x6d, 0x00, - 0x6d, 0x63, 0x00, 0x6d, 0x6b, 0x00, 0x6d, 0x63, - 0x00, 0x0a, 0x0a, 0x4f, 0x00, 0x0a, 0x4f, 0x6d, - 0x00, 0xb2, 0x00, 0x63, 0x00, 0x08, 0x0a, 0x4f, - 0x0a, 0x0a, 0x50, 0x00, 0x0a, 0x50, 0x6d, 0x00, - 0xb3, 0x00, 0x6b, 0x00, 0x6d, 0x00, 0xb3, 0x00, - 0x6d, 0x00, 0x15, 0x22, 0x73, 0x00, 0x6d, 0x00, - 0x15, 0x22, 0x73, 0x00, 0xb2, 0x00, 0x50, 0x61, - 0x6b, 0x50, 0x61, 0x4d, 0x50, 0x61, 0x47, 0x50, - 0x61, 0x72, 0x61, 0x64, 0x72, 0x61, 0x64, 0xd1, - 0x73, 0x72, 0x00, 0x61, 0x00, 0x64, 0x00, 0x15, - 0x22, 0x73, 0x00, 0xb2, 0x00, 0x70, 0x00, 0x73, - 0x6e, 0x00, 0x73, 0xbc, 0x03, 0x73, 0x6d, 0x00, - 0x73, 0x70, 0x00, 0x56, 0x6e, 0x00, 0x56, 0xbc, - 0x03, 0x56, 0x6d, 0x00, 0x56, 0x6b, 0x00, 0x56, - 0x4d, 0x00, 0x56, 0x70, 0x00, 0x57, 0x6e, 0x00, - 0x57, 0xbc, 0x03, 0x57, 0x6d, 0x00, 0x57, 0x6b, - 0x00, 0x57, 0x4d, 0x00, 0x57, 0x6b, 0x00, 0xa9, - 0x03, 0x4d, 0x00, 0xa9, 0x03, 0x61, 0x2e, 0x6d, - 0x2e, 0x42, 0x71, 0x63, 0x63, 0x63, 0x64, 0x43, - 0xd1, 0x6b, 0x67, 0x43, 0x6f, 0x2e, 0x64, 0x42, - 0x47, 0x79, 0x68, 0x61, 0x48, 0x50, 0x69, 0x6e, - 0x4b, 0x4b, 0x4b, 0x4d, 0x6b, 0x74, 0x6c, 0x6d, - 0x6c, 0x6e, 0x6c, 0x6f, 0x67, 0x6c, 0x78, 0x6d, - 0x62, 0x6d, 0x69, 0x6c, 0x6d, 0x6f, 0x6c, 0x50, - 0x48, 0x70, 0x2e, 0x6d, 0x2e, 0x50, 0x50, 0x4d, - 0x50, 0x52, 0x73, 0x72, 0x53, 0x76, 0x57, 0x62, - 0x56, 0xd1, 0x6d, 0x41, 0xd1, 0x6d, 0x31, 0x00, - 0xe5, 0x65, 0x31, 0x00, 0x30, 0x00, 0xe5, 0x65, - 0x32, 0x00, 0x30, 0x00, 0xe5, 0x65, 0x33, 0x00, - 0x30, 0x00, 0xe5, 0x65, 0x67, 0x61, 0x6c, 0x4a, - 0x04, 0x4c, 0x04, 0x26, 0x01, 0x53, 0x01, 0x27, - 0xa7, 0x37, 0xab, 0x6b, 0x02, 0x52, 0xab, 0x48, - 0x8c, 0xf4, 0x66, 0xca, 0x8e, 0xc8, 0x8c, 0xd1, - 0x6e, 0x32, 0x4e, 0xe5, 0x53, 0x9c, 0x9f, 0x9c, - 0x9f, 0x51, 0x59, 0xd1, 0x91, 0x87, 0x55, 0x48, - 0x59, 0xf6, 0x61, 0x69, 0x76, 0x85, 0x7f, 0x3f, - 0x86, 0xba, 0x87, 0xf8, 0x88, 0x8f, 0x90, 0x02, - 0x6a, 0x1b, 0x6d, 0xd9, 0x70, 0xde, 0x73, 0x3d, - 0x84, 0x6a, 0x91, 0xf1, 0x99, 0x82, 0x4e, 0x75, - 0x53, 0x04, 0x6b, 0x1b, 0x72, 0x2d, 0x86, 0x1e, - 0x9e, 0x50, 0x5d, 0xeb, 0x6f, 0xcd, 0x85, 0x64, - 0x89, 0xc9, 0x62, 0xd8, 0x81, 0x1f, 0x88, 0xca, - 0x5e, 0x17, 0x67, 0x6a, 0x6d, 0xfc, 0x72, 0xce, - 0x90, 0x86, 0x4f, 0xb7, 0x51, 0xde, 0x52, 0xc4, - 0x64, 0xd3, 0x6a, 0x10, 0x72, 0xe7, 0x76, 0x01, - 0x80, 0x06, 0x86, 0x5c, 0x86, 0xef, 0x8d, 0x32, - 0x97, 0x6f, 0x9b, 0xfa, 0x9d, 0x8c, 0x78, 0x7f, - 0x79, 0xa0, 0x7d, 0xc9, 0x83, 0x04, 0x93, 0x7f, - 0x9e, 0xd6, 0x8a, 0xdf, 0x58, 0x04, 0x5f, 0x60, - 0x7c, 0x7e, 0x80, 0x62, 0x72, 0xca, 0x78, 0xc2, - 0x8c, 0xf7, 0x96, 0xd8, 0x58, 0x62, 0x5c, 0x13, - 0x6a, 0xda, 0x6d, 0x0f, 0x6f, 0x2f, 0x7d, 0x37, - 0x7e, 0x4b, 0x96, 0xd2, 0x52, 0x8b, 0x80, 0xdc, - 0x51, 0xcc, 0x51, 0x1c, 0x7a, 0xbe, 0x7d, 0xf1, - 0x83, 0x75, 0x96, 0x80, 0x8b, 0xcf, 0x62, 0x02, - 0x6a, 0xfe, 0x8a, 0x39, 0x4e, 0xe7, 0x5b, 0x12, - 0x60, 0x87, 0x73, 0x70, 0x75, 0x17, 0x53, 0xfb, - 0x78, 0xbf, 0x4f, 0xa9, 0x5f, 0x0d, 0x4e, 0xcc, - 0x6c, 0x78, 0x65, 0x22, 0x7d, 0xc3, 0x53, 0x5e, - 0x58, 0x01, 0x77, 0x49, 0x84, 0xaa, 0x8a, 0xba, - 0x6b, 0xb0, 0x8f, 0x88, 0x6c, 0xfe, 0x62, 0xe5, - 0x82, 0xa0, 0x63, 0x65, 0x75, 0xae, 0x4e, 0x69, - 0x51, 0xc9, 0x51, 0x81, 0x68, 0xe7, 0x7c, 0x6f, - 0x82, 0xd2, 0x8a, 0xcf, 0x91, 0xf5, 0x52, 0x42, - 0x54, 0x73, 0x59, 0xec, 0x5e, 0xc5, 0x65, 0xfe, - 0x6f, 0x2a, 0x79, 0xad, 0x95, 0x6a, 0x9a, 0x97, - 0x9e, 0xce, 0x9e, 0x9b, 0x52, 0xc6, 0x66, 0x77, - 0x6b, 0x62, 0x8f, 0x74, 0x5e, 0x90, 0x61, 0x00, - 0x62, 0x9a, 0x64, 0x23, 0x6f, 0x49, 0x71, 0x89, - 0x74, 0xca, 0x79, 0xf4, 0x7d, 0x6f, 0x80, 0x26, - 0x8f, 0xee, 0x84, 0x23, 0x90, 0x4a, 0x93, 0x17, - 0x52, 0xa3, 0x52, 0xbd, 0x54, 0xc8, 0x70, 0xc2, - 0x88, 0xaa, 0x8a, 0xc9, 0x5e, 0xf5, 0x5f, 0x7b, - 0x63, 0xae, 0x6b, 0x3e, 0x7c, 0x75, 0x73, 0xe4, - 0x4e, 0xf9, 0x56, 0xe7, 0x5b, 0xba, 0x5d, 0x1c, - 0x60, 0xb2, 0x73, 0x69, 0x74, 0x9a, 0x7f, 0x46, - 0x80, 0x34, 0x92, 0xf6, 0x96, 0x48, 0x97, 0x18, - 0x98, 0x8b, 0x4f, 0xae, 0x79, 0xb4, 0x91, 0xb8, - 0x96, 0xe1, 0x60, 0x86, 0x4e, 0xda, 0x50, 0xee, - 0x5b, 0x3f, 0x5c, 0x99, 0x65, 0x02, 0x6a, 0xce, - 0x71, 0x42, 0x76, 0xfc, 0x84, 0x7c, 0x90, 0x8d, - 0x9f, 0x88, 0x66, 0x2e, 0x96, 0x89, 0x52, 0x7b, - 0x67, 0xf3, 0x67, 0x41, 0x6d, 0x9c, 0x6e, 0x09, - 0x74, 0x59, 0x75, 0x6b, 0x78, 0x10, 0x7d, 0x5e, - 0x98, 0x6d, 0x51, 0x2e, 0x62, 0x78, 0x96, 0x2b, - 0x50, 0x19, 0x5d, 0xea, 0x6d, 0x2a, 0x8f, 0x8b, - 0x5f, 0x44, 0x61, 0x17, 0x68, 0x87, 0x73, 0x86, - 0x96, 0x29, 0x52, 0x0f, 0x54, 0x65, 0x5c, 0x13, - 0x66, 0x4e, 0x67, 0xa8, 0x68, 0xe5, 0x6c, 0x06, - 0x74, 0xe2, 0x75, 0x79, 0x7f, 0xcf, 0x88, 0xe1, - 0x88, 0xcc, 0x91, 0xe2, 0x96, 0x3f, 0x53, 0xba, - 0x6e, 0x1d, 0x54, 0xd0, 0x71, 0x98, 0x74, 0xfa, - 0x85, 0xa3, 0x96, 0x57, 0x9c, 0x9f, 0x9e, 0x97, - 0x67, 0xcb, 0x6d, 0xe8, 0x81, 0xcb, 0x7a, 0x20, - 0x7b, 0x92, 0x7c, 0xc0, 0x72, 0x99, 0x70, 0x58, - 0x8b, 0xc0, 0x4e, 0x36, 0x83, 0x3a, 0x52, 0x07, - 0x52, 0xa6, 0x5e, 0xd3, 0x62, 0xd6, 0x7c, 0x85, - 0x5b, 0x1e, 0x6d, 0xb4, 0x66, 0x3b, 0x8f, 0x4c, - 0x88, 0x4d, 0x96, 0x8b, 0x89, 0xd3, 0x5e, 0x40, - 0x51, 0xc0, 0x55, 0x00, 0x00, 0x00, 0x00, 0x5a, - 0x58, 0x00, 0x00, 0x74, 0x66, 0x00, 0x00, 0x00, - 0x00, 0xde, 0x51, 0x2a, 0x73, 0xca, 0x76, 0x3c, - 0x79, 0x5e, 0x79, 0x65, 0x79, 0x8f, 0x79, 0x56, - 0x97, 0xbe, 0x7c, 0xbd, 0x7f, 0x00, 0x00, 0x12, - 0x86, 0x00, 0x00, 0xf8, 0x8a, 0x00, 0x00, 0x00, - 0x00, 0x38, 0x90, 0xfd, 0x90, 0xef, 0x98, 0xfc, - 0x98, 0x28, 0x99, 0xb4, 0x9d, 0xde, 0x90, 0xb7, - 0x96, 0xae, 0x4f, 0xe7, 0x50, 0x4d, 0x51, 0xc9, - 0x52, 0xe4, 0x52, 0x51, 0x53, 0x9d, 0x55, 0x06, - 0x56, 0x68, 0x56, 0x40, 0x58, 0xa8, 0x58, 0x64, - 0x5c, 0x6e, 0x5c, 0x94, 0x60, 0x68, 0x61, 0x8e, - 0x61, 0xf2, 0x61, 0x4f, 0x65, 0xe2, 0x65, 0x91, - 0x66, 0x85, 0x68, 0x77, 0x6d, 0x1a, 0x6e, 0x22, - 0x6f, 0x6e, 0x71, 0x2b, 0x72, 0x22, 0x74, 0x91, - 0x78, 0x3e, 0x79, 0x49, 0x79, 0x48, 0x79, 0x50, - 0x79, 0x56, 0x79, 0x5d, 0x79, 0x8d, 0x79, 0x8e, - 0x79, 0x40, 0x7a, 0x81, 0x7a, 0xc0, 0x7b, 0xf4, - 0x7d, 0x09, 0x7e, 0x41, 0x7e, 0x72, 0x7f, 0x05, - 0x80, 0xed, 0x81, 0x79, 0x82, 0x79, 0x82, 0x57, - 0x84, 0x10, 0x89, 0x96, 0x89, 0x01, 0x8b, 0x39, - 0x8b, 0xd3, 0x8c, 0x08, 0x8d, 0xb6, 0x8f, 0x38, - 0x90, 0xe3, 0x96, 0xff, 0x97, 0x3b, 0x98, 0x75, - 0x60, 0xee, 0x42, 0x18, 0x82, 0x02, 0x26, 0x4e, - 0xb5, 0x51, 0x68, 0x51, 0x80, 0x4f, 0x45, 0x51, - 0x80, 0x51, 0xc7, 0x52, 0xfa, 0x52, 0x9d, 0x55, - 0x55, 0x55, 0x99, 0x55, 0xe2, 0x55, 0x5a, 0x58, - 0xb3, 0x58, 0x44, 0x59, 0x54, 0x59, 0x62, 0x5a, - 0x28, 0x5b, 0xd2, 0x5e, 0xd9, 0x5e, 0x69, 0x5f, - 0xad, 0x5f, 0xd8, 0x60, 0x4e, 0x61, 0x08, 0x61, - 0x8e, 0x61, 0x60, 0x61, 0xf2, 0x61, 0x34, 0x62, - 0xc4, 0x63, 0x1c, 0x64, 0x52, 0x64, 0x56, 0x65, - 0x74, 0x66, 0x17, 0x67, 0x1b, 0x67, 0x56, 0x67, - 0x79, 0x6b, 0xba, 0x6b, 0x41, 0x6d, 0xdb, 0x6e, - 0xcb, 0x6e, 0x22, 0x6f, 0x1e, 0x70, 0x6e, 0x71, - 0xa7, 0x77, 0x35, 0x72, 0xaf, 0x72, 0x2a, 0x73, - 0x71, 0x74, 0x06, 0x75, 0x3b, 0x75, 0x1d, 0x76, - 0x1f, 0x76, 0xca, 0x76, 0xdb, 0x76, 0xf4, 0x76, - 0x4a, 0x77, 0x40, 0x77, 0xcc, 0x78, 0xb1, 0x7a, - 0xc0, 0x7b, 0x7b, 0x7c, 0x5b, 0x7d, 0xf4, 0x7d, - 0x3e, 0x7f, 0x05, 0x80, 0x52, 0x83, 0xef, 0x83, - 0x79, 0x87, 0x41, 0x89, 0x86, 0x89, 0x96, 0x89, - 0xbf, 0x8a, 0xf8, 0x8a, 0xcb, 0x8a, 0x01, 0x8b, - 0xfe, 0x8a, 0xed, 0x8a, 0x39, 0x8b, 0x8a, 0x8b, - 0x08, 0x8d, 0x38, 0x8f, 0x72, 0x90, 0x99, 0x91, - 0x76, 0x92, 0x7c, 0x96, 0xe3, 0x96, 0x56, 0x97, - 0xdb, 0x97, 0xff, 0x97, 0x0b, 0x98, 0x3b, 0x98, - 0x12, 0x9b, 0x9c, 0x9f, 0x4a, 0x28, 0x44, 0x28, - 0xd5, 0x33, 0x9d, 0x3b, 0x18, 0x40, 0x39, 0x40, - 0x49, 0x52, 0xd0, 0x5c, 0xd3, 0x7e, 0x43, 0x9f, - 0x8e, 0x9f, 0x2a, 0xa0, 0x02, 0x66, 0x66, 0x66, - 0x69, 0x66, 0x6c, 0x66, 0x66, 0x69, 0x66, 0x66, - 0x6c, 0x7f, 0x01, 0x74, 0x73, 0x00, 0x74, 0x65, - 0x05, 0x0f, 0x11, 0x0f, 0x00, 0x0f, 0x06, 0x19, - 0x11, 0x0f, 0x08, 0xd9, 0x05, 0xb4, 0x05, 0x00, - 0x00, 0x00, 0x00, 0xf2, 0x05, 0xb7, 0x05, 0xd0, - 0x05, 0x12, 0x00, 0x03, 0x04, 0x0b, 0x0c, 0x0d, - 0x18, 0x1a, 0xe9, 0x05, 0xc1, 0x05, 0xe9, 0x05, - 0xc2, 0x05, 0x49, 0xfb, 0xc1, 0x05, 0x49, 0xfb, - 0xc2, 0x05, 0xd0, 0x05, 0xb7, 0x05, 0xd0, 0x05, - 0xb8, 0x05, 0xd0, 0x05, 0xbc, 0x05, 0xd8, 0x05, - 0xbc, 0x05, 0xde, 0x05, 0xbc, 0x05, 0xe0, 0x05, - 0xbc, 0x05, 0xe3, 0x05, 0xbc, 0x05, 0xb9, 0x05, - 0x2d, 0x03, 0x2e, 0x03, 0x2f, 0x03, 0x30, 0x03, - 0x31, 0x03, 0x1c, 0x00, 0x18, 0x06, 0x22, 0x06, - 0x2b, 0x06, 0xd0, 0x05, 0xdc, 0x05, 0x71, 0x06, - 0x00, 0x00, 0x0a, 0x0a, 0x0a, 0x0a, 0x0d, 0x0d, - 0x0d, 0x0d, 0x0f, 0x0f, 0x0f, 0x0f, 0x09, 0x09, - 0x09, 0x09, 0x0e, 0x0e, 0x0e, 0x0e, 0x08, 0x08, - 0x08, 0x08, 0x33, 0x33, 0x33, 0x33, 0x35, 0x35, - 0x35, 0x35, 0x13, 0x13, 0x13, 0x13, 0x12, 0x12, - 0x12, 0x12, 0x15, 0x15, 0x15, 0x15, 0x16, 0x16, - 0x16, 0x16, 0x1c, 0x1c, 0x1b, 0x1b, 0x1d, 0x1d, - 0x17, 0x17, 0x27, 0x27, 0x20, 0x20, 0x38, 0x38, - 0x38, 0x38, 0x3e, 0x3e, 0x3e, 0x3e, 0x42, 0x42, - 0x42, 0x42, 0x40, 0x40, 0x40, 0x40, 0x49, 0x49, - 0x4a, 0x4a, 0x4a, 0x4a, 0x4f, 0x4f, 0x50, 0x50, - 0x50, 0x50, 0x4d, 0x4d, 0x4d, 0x4d, 0x61, 0x61, - 0x62, 0x62, 0x49, 0x06, 0x64, 0x64, 0x64, 0x64, - 0x7e, 0x7e, 0x7d, 0x7d, 0x7f, 0x7f, 0x2e, 0x82, - 0x82, 0x7c, 0x7c, 0x80, 0x80, 0x87, 0x87, 0x87, - 0x87, 0x00, 0x00, 0x26, 0x06, 0x00, 0x01, 0x00, - 0x01, 0x00, 0xaf, 0x00, 0xaf, 0x00, 0x22, 0x00, - 0x22, 0x00, 0xa1, 0x00, 0xa1, 0x00, 0xa0, 0x00, - 0xa0, 0x00, 0xa2, 0x00, 0xa2, 0x00, 0xaa, 0x00, - 0xaa, 0x00, 0xaa, 0x00, 0x23, 0x00, 0x23, 0x00, - 0x23, 0xcc, 0x06, 0x00, 0x00, 0x00, 0x00, 0x26, - 0x06, 0x00, 0x06, 0x00, 0x07, 0x00, 0x1f, 0x00, - 0x23, 0x00, 0x24, 0x02, 0x06, 0x02, 0x07, 0x02, - 0x08, 0x02, 0x1f, 0x02, 0x23, 0x02, 0x24, 0x04, - 0x06, 0x04, 0x07, 0x04, 0x08, 0x04, 0x1f, 0x04, - 0x23, 0x04, 0x24, 0x05, 0x06, 0x05, 0x1f, 0x05, - 0x23, 0x05, 0x24, 0x06, 0x07, 0x06, 0x1f, 0x07, - 0x06, 0x07, 0x1f, 0x08, 0x06, 0x08, 0x07, 0x08, - 0x1f, 0x0d, 0x06, 0x0d, 0x07, 0x0d, 0x08, 0x0d, - 0x1f, 0x0f, 0x07, 0x0f, 0x1f, 0x10, 0x06, 0x10, - 0x07, 0x10, 0x08, 0x10, 0x1f, 0x11, 0x07, 0x11, - 0x1f, 0x12, 0x1f, 0x13, 0x06, 0x13, 0x1f, 0x14, - 0x06, 0x14, 0x1f, 0x1b, 0x06, 0x1b, 0x07, 0x1b, - 0x08, 0x1b, 0x1f, 0x1b, 0x23, 0x1b, 0x24, 0x1c, - 0x07, 0x1c, 0x1f, 0x1c, 0x23, 0x1c, 0x24, 0x1d, - 0x01, 0x1d, 0x06, 0x1d, 0x07, 0x1d, 0x08, 0x1d, - 0x1e, 0x1d, 0x1f, 0x1d, 0x23, 0x1d, 0x24, 0x1e, - 0x06, 0x1e, 0x07, 0x1e, 0x08, 0x1e, 0x1f, 0x1e, - 0x23, 0x1e, 0x24, 0x1f, 0x06, 0x1f, 0x07, 0x1f, - 0x08, 0x1f, 0x1f, 0x1f, 0x23, 0x1f, 0x24, 0x20, - 0x06, 0x20, 0x07, 0x20, 0x08, 0x20, 0x1f, 0x20, - 0x23, 0x20, 0x24, 0x21, 0x06, 0x21, 0x1f, 0x21, - 0x23, 0x21, 0x24, 0x24, 0x06, 0x24, 0x07, 0x24, - 0x08, 0x24, 0x1f, 0x24, 0x23, 0x24, 0x24, 0x0a, - 0x4a, 0x0b, 0x4a, 0x23, 0x4a, 0x20, 0x00, 0x4c, - 0x06, 0x51, 0x06, 0x51, 0x06, 0xff, 0x00, 0x1f, - 0x26, 0x06, 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x1f, - 0x00, 0x20, 0x00, 0x23, 0x00, 0x24, 0x02, 0x0b, - 0x02, 0x0c, 0x02, 0x1f, 0x02, 0x20, 0x02, 0x23, - 0x02, 0x24, 0x04, 0x0b, 0x04, 0x0c, 0x04, 0x1f, - 0x26, 0x06, 0x04, 0x20, 0x04, 0x23, 0x04, 0x24, - 0x05, 0x0b, 0x05, 0x0c, 0x05, 0x1f, 0x05, 0x20, - 0x05, 0x23, 0x05, 0x24, 0x1b, 0x23, 0x1b, 0x24, - 0x1c, 0x23, 0x1c, 0x24, 0x1d, 0x01, 0x1d, 0x1e, - 0x1d, 0x1f, 0x1d, 0x23, 0x1d, 0x24, 0x1e, 0x1f, - 0x1e, 0x23, 0x1e, 0x24, 0x1f, 0x01, 0x1f, 0x1f, - 0x20, 0x0b, 0x20, 0x0c, 0x20, 0x1f, 0x20, 0x20, - 0x20, 0x23, 0x20, 0x24, 0x23, 0x4a, 0x24, 0x0b, - 0x24, 0x0c, 0x24, 0x1f, 0x24, 0x20, 0x24, 0x23, - 0x24, 0x24, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08, - 0x00, 0x1f, 0x00, 0x21, 0x02, 0x06, 0x02, 0x07, - 0x02, 0x08, 0x02, 0x1f, 0x02, 0x21, 0x04, 0x06, - 0x04, 0x07, 0x04, 0x08, 0x04, 0x1f, 0x04, 0x21, - 0x05, 0x1f, 0x06, 0x07, 0x06, 0x1f, 0x07, 0x06, - 0x07, 0x1f, 0x08, 0x06, 0x08, 0x1f, 0x0d, 0x06, - 0x0d, 0x07, 0x0d, 0x08, 0x0d, 0x1f, 0x0f, 0x07, - 0x0f, 0x08, 0x0f, 0x1f, 0x10, 0x06, 0x10, 0x07, - 0x10, 0x08, 0x10, 0x1f, 0x11, 0x07, 0x12, 0x1f, - 0x13, 0x06, 0x13, 0x1f, 0x14, 0x06, 0x14, 0x1f, - 0x1b, 0x06, 0x1b, 0x07, 0x1b, 0x08, 0x1b, 0x1f, - 0x1c, 0x07, 0x1c, 0x1f, 0x1d, 0x06, 0x1d, 0x07, - 0x1d, 0x08, 0x1d, 0x1e, 0x1d, 0x1f, 0x1e, 0x06, - 0x1e, 0x07, 0x1e, 0x08, 0x1e, 0x1f, 0x1e, 0x21, - 0x1f, 0x06, 0x1f, 0x07, 0x1f, 0x08, 0x1f, 0x1f, - 0x20, 0x06, 0x20, 0x07, 0x20, 0x08, 0x20, 0x1f, - 0x20, 0x21, 0x21, 0x06, 0x21, 0x1f, 0x21, 0x4a, - 0x24, 0x06, 0x24, 0x07, 0x24, 0x08, 0x24, 0x1f, - 0x24, 0x21, 0x00, 0x1f, 0x00, 0x21, 0x02, 0x1f, - 0x02, 0x21, 0x04, 0x1f, 0x04, 0x21, 0x05, 0x1f, - 0x05, 0x21, 0x0d, 0x1f, 0x0d, 0x21, 0x0e, 0x1f, - 0x0e, 0x21, 0x1d, 0x1e, 0x1d, 0x1f, 0x1e, 0x1f, - 0x20, 0x1f, 0x20, 0x21, 0x24, 0x1f, 0x24, 0x21, - 0x40, 0x06, 0x4e, 0x06, 0x51, 0x06, 0x27, 0x06, - 0x10, 0x22, 0x10, 0x23, 0x12, 0x22, 0x12, 0x23, - 0x13, 0x22, 0x13, 0x23, 0x0c, 0x22, 0x0c, 0x23, - 0x0d, 0x22, 0x0d, 0x23, 0x06, 0x22, 0x06, 0x23, - 0x05, 0x22, 0x05, 0x23, 0x07, 0x22, 0x07, 0x23, - 0x0e, 0x22, 0x0e, 0x23, 0x0f, 0x22, 0x0f, 0x23, - 0x0d, 0x05, 0x0d, 0x06, 0x0d, 0x07, 0x0d, 0x1e, - 0x0d, 0x0a, 0x0c, 0x0a, 0x0e, 0x0a, 0x0f, 0x0a, - 0x10, 0x22, 0x10, 0x23, 0x12, 0x22, 0x12, 0x23, - 0x13, 0x22, 0x13, 0x23, 0x0c, 0x22, 0x0c, 0x23, - 0x0d, 0x22, 0x0d, 0x23, 0x06, 0x22, 0x06, 0x23, - 0x05, 0x22, 0x05, 0x23, 0x07, 0x22, 0x07, 0x23, - 0x0e, 0x22, 0x0e, 0x23, 0x0f, 0x22, 0x0f, 0x23, - 0x0d, 0x05, 0x0d, 0x06, 0x0d, 0x07, 0x0d, 0x1e, - 0x0d, 0x0a, 0x0c, 0x0a, 0x0e, 0x0a, 0x0f, 0x0a, - 0x0d, 0x05, 0x0d, 0x06, 0x0d, 0x07, 0x0d, 0x1e, - 0x0c, 0x20, 0x0d, 0x20, 0x10, 0x1e, 0x0c, 0x05, - 0x0c, 0x06, 0x0c, 0x07, 0x0d, 0x05, 0x0d, 0x06, - 0x0d, 0x07, 0x10, 0x1e, 0x11, 0x1e, 0x00, 0x24, - 0x00, 0x24, 0x2a, 0x06, 0x00, 0x02, 0x1b, 0x00, - 0x03, 0x02, 0x00, 0x03, 0x02, 0x00, 0x03, 0x1b, - 0x00, 0x04, 0x1b, 0x00, 0x1b, 0x02, 0x00, 0x1b, - 0x03, 0x00, 0x1b, 0x04, 0x02, 0x1b, 0x03, 0x02, - 0x1b, 0x03, 0x03, 0x1b, 0x20, 0x03, 0x1b, 0x1f, - 0x09, 0x03, 0x02, 0x09, 0x02, 0x03, 0x09, 0x02, - 0x1f, 0x09, 0x1b, 0x03, 0x09, 0x1b, 0x03, 0x09, - 0x1b, 0x02, 0x09, 0x1b, 0x1b, 0x09, 0x1b, 0x1b, - 0x0b, 0x03, 0x03, 0x0b, 0x03, 0x03, 0x0b, 0x1b, - 0x1b, 0x0a, 0x03, 0x1b, 0x0a, 0x03, 0x1b, 0x0a, - 0x02, 0x20, 0x0a, 0x1b, 0x04, 0x0a, 0x1b, 0x04, - 0x0a, 0x1b, 0x1b, 0x0a, 0x1b, 0x1b, 0x0c, 0x03, - 0x1f, 0x0c, 0x04, 0x1b, 0x0c, 0x04, 0x1b, 0x0d, - 0x1b, 0x03, 0x0d, 0x1b, 0x03, 0x0d, 0x1b, 0x1b, - 0x0d, 0x1b, 0x20, 0x0f, 0x02, 0x1b, 0x0f, 0x1b, - 0x1b, 0x0f, 0x1b, 0x1b, 0x0f, 0x1b, 0x1f, 0x10, - 0x1b, 0x1b, 0x10, 0x1b, 0x20, 0x10, 0x1b, 0x1f, - 0x17, 0x04, 0x1b, 0x17, 0x04, 0x1b, 0x18, 0x1b, - 0x03, 0x18, 0x1b, 0x1b, 0x1a, 0x03, 0x1b, 0x1a, - 0x03, 0x20, 0x1a, 0x03, 0x1f, 0x1a, 0x02, 0x02, - 0x1a, 0x02, 0x02, 0x1a, 0x04, 0x1b, 0x1a, 0x04, - 0x1b, 0x1a, 0x1b, 0x03, 0x1a, 0x1b, 0x03, 0x1b, - 0x03, 0x02, 0x1b, 0x03, 0x1b, 0x1b, 0x03, 0x20, - 0x1b, 0x02, 0x03, 0x1b, 0x02, 0x1b, 0x1b, 0x04, - 0x02, 0x1b, 0x04, 0x1b, 0x28, 0x06, 0x1d, 0x04, - 0x06, 0x1f, 0x1d, 0x04, 0x1f, 0x1d, 0x1d, 0x1e, - 0x05, 0x1d, 0x1e, 0x05, 0x21, 0x1e, 0x04, 0x1d, - 0x1e, 0x04, 0x1d, 0x1e, 0x04, 0x21, 0x1e, 0x1d, - 0x22, 0x1e, 0x1d, 0x21, 0x22, 0x1d, 0x1d, 0x22, - 0x1d, 0x1d, 0x00, 0x06, 0x22, 0x02, 0x04, 0x22, - 0x02, 0x04, 0x21, 0x02, 0x06, 0x22, 0x02, 0x06, - 0x21, 0x02, 0x1d, 0x22, 0x02, 0x1d, 0x21, 0x04, - 0x1d, 0x22, 0x04, 0x05, 0x21, 0x04, 0x1d, 0x21, - 0x0b, 0x06, 0x21, 0x0d, 0x05, 0x22, 0x0c, 0x05, - 0x22, 0x0e, 0x05, 0x22, 0x1c, 0x04, 0x22, 0x1c, - 0x1d, 0x22, 0x22, 0x05, 0x22, 0x22, 0x04, 0x22, - 0x22, 0x1d, 0x22, 0x1d, 0x1d, 0x22, 0x1a, 0x1d, - 0x22, 0x1e, 0x05, 0x22, 0x1a, 0x1d, 0x05, 0x1c, - 0x05, 0x1d, 0x11, 0x1d, 0x22, 0x1b, 0x1d, 0x22, - 0x1e, 0x04, 0x05, 0x1d, 0x06, 0x22, 0x1c, 0x04, - 0x1d, 0x1b, 0x1d, 0x1d, 0x1c, 0x04, 0x1d, 0x1e, - 0x04, 0x05, 0x04, 0x05, 0x22, 0x05, 0x04, 0x22, - 0x1d, 0x04, 0x22, 0x19, 0x1d, 0x22, 0x00, 0x05, - 0x22, 0x1b, 0x1d, 0x1d, 0x11, 0x04, 0x1d, 0x0d, - 0x1d, 0x1d, 0x0b, 0x06, 0x22, 0x1e, 0x04, 0x22, - 0x35, 0x06, 0x00, 0x0f, 0x9d, 0x0d, 0x0f, 0x9d, - 0x27, 0x06, 0x00, 0x1d, 0x1d, 0x20, 0x00, 0x1c, - 0x01, 0x0a, 0x1e, 0x06, 0x1e, 0x08, 0x0e, 0x1d, - 0x12, 0x1e, 0x0a, 0x0c, 0x21, 0x1d, 0x12, 0x1d, - 0x23, 0x20, 0x21, 0x0c, 0x1d, 0x1e, 0x35, 0x06, - 0x00, 0x0f, 0x14, 0x27, 0x06, 0x0e, 0x1d, 0x22, - 0xff, 0x00, 0x1d, 0x1d, 0x20, 0xff, 0x12, 0x1d, - 0x23, 0x20, 0xff, 0x21, 0x0c, 0x1d, 0x1e, 0x27, - 0x06, 0x05, 0x1d, 0xff, 0x05, 0x1d, 0x00, 0x1d, - 0x20, 0x27, 0x06, 0x0a, 0xa5, 0x00, 0x1d, 0x2c, - 0x00, 0x01, 0x30, 0x02, 0x30, 0x3a, 0x00, 0x3b, - 0x00, 0x21, 0x00, 0x3f, 0x00, 0x16, 0x30, 0x17, - 0x30, 0x26, 0x20, 0x13, 0x20, 0x12, 0x01, 0x00, - 0x5f, 0x5f, 0x28, 0x29, 0x7b, 0x7d, 0x08, 0x30, - 0x0c, 0x0d, 0x08, 0x09, 0x02, 0x03, 0x00, 0x01, - 0x04, 0x05, 0x06, 0x07, 0x5b, 0x00, 0x5d, 0x00, - 0x3e, 0x20, 0x3e, 0x20, 0x3e, 0x20, 0x3e, 0x20, - 0x5f, 0x00, 0x5f, 0x00, 0x5f, 0x00, 0x2c, 0x00, - 0x01, 0x30, 0x2e, 0x00, 0x00, 0x00, 0x3b, 0x00, - 0x3a, 0x00, 0x3f, 0x00, 0x21, 0x00, 0x14, 0x20, - 0x28, 0x00, 0x29, 0x00, 0x7b, 0x00, 0x7d, 0x00, - 0x14, 0x30, 0x15, 0x30, 0x23, 0x26, 0x2a, 0x2b, - 0x2d, 0x3c, 0x3e, 0x3d, 0x00, 0x5c, 0x24, 0x25, - 0x40, 0x40, 0x06, 0xff, 0x0b, 0x00, 0x0b, 0xff, - 0x0c, 0x20, 0x00, 0x4d, 0x06, 0x40, 0x06, 0xff, - 0x0e, 0x00, 0x0e, 0xff, 0x0f, 0x00, 0x0f, 0xff, - 0x10, 0x00, 0x10, 0xff, 0x11, 0x00, 0x11, 0xff, - 0x12, 0x00, 0x12, 0x21, 0x06, 0x00, 0x01, 0x01, - 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, 0x05, 0x05, - 0x05, 0x05, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, - 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x0a, 0x0a, - 0x0a, 0x0a, 0x0b, 0x0b, 0x0b, 0x0b, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0d, 0x0d, 0x0d, 0x0d, 0x0e, 0x0e, - 0x0f, 0x0f, 0x10, 0x10, 0x11, 0x11, 0x12, 0x12, - 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, 0x14, 0x14, - 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, 0x16, 0x16, - 0x16, 0x16, 0x17, 0x17, 0x17, 0x17, 0x18, 0x18, - 0x18, 0x18, 0x19, 0x19, 0x19, 0x19, 0x20, 0x20, - 0x20, 0x20, 0x21, 0x21, 0x21, 0x21, 0x22, 0x22, - 0x22, 0x22, 0x23, 0x23, 0x23, 0x23, 0x24, 0x24, - 0x24, 0x24, 0x25, 0x25, 0x25, 0x25, 0x26, 0x26, - 0x26, 0x26, 0x27, 0x27, 0x28, 0x28, 0x29, 0x29, - 0x29, 0x29, 0x22, 0x06, 0x22, 0x00, 0x22, 0x00, - 0x22, 0x01, 0x22, 0x01, 0x22, 0x03, 0x22, 0x03, - 0x22, 0x05, 0x22, 0x05, 0x21, 0x00, 0x85, 0x29, - 0x01, 0x30, 0x01, 0x0b, 0x0c, 0x00, 0xfa, 0xf1, - 0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xe2, 0xe4, 0xe6, - 0xc2, 0xfb, 0xa1, 0xa3, 0xa5, 0xa7, 0xa9, 0xaa, - 0xac, 0xae, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, - 0xbc, 0xbe, 0xc0, 0xc3, 0xc5, 0xc7, 0xc9, 0xca, - 0xcb, 0xcc, 0xcd, 0xce, 0xd1, 0xd4, 0xd7, 0xda, - 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe3, 0xe5, 0xe7, - 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xee, 0xf2, 0x98, - 0x99, 0x31, 0x31, 0x4f, 0x31, 0x55, 0x31, 0x5b, - 0x31, 0x61, 0x31, 0xa2, 0x00, 0xa3, 0x00, 0xac, - 0x00, 0xaf, 0x00, 0xa6, 0x00, 0xa5, 0x00, 0xa9, - 0x20, 0x00, 0x00, 0x02, 0x25, 0x90, 0x21, 0x91, - 0x21, 0x92, 0x21, 0x93, 0x21, 0xa0, 0x25, 0xcb, - 0x25, 0x99, 0x10, 0xba, 0x10, 0x00, 0x00, 0x00, - 0x00, 0x9b, 0x10, 0xba, 0x10, 0x05, 0x05, 0xa5, - 0x10, 0xba, 0x10, 0x05, 0x31, 0x11, 0x27, 0x11, - 0x32, 0x11, 0x27, 0x11, 0x55, 0x47, 0x13, 0x3e, - 0x13, 0x47, 0x13, 0x57, 0x13, 0x55, 0xb9, 0x14, - 0xba, 0x14, 0xb9, 0x14, 0xb0, 0x14, 0x00, 0x00, - 0x00, 0x00, 0xb9, 0x14, 0xbd, 0x14, 0x55, 0x50, - 0xb8, 0x15, 0xaf, 0x15, 0xb9, 0x15, 0xaf, 0x15, - 0x55, 0x57, 0xd1, 0x65, 0xd1, 0x58, 0xd1, 0x65, - 0xd1, 0x5f, 0xd1, 0x6e, 0xd1, 0x5f, 0xd1, 0x6f, - 0xd1, 0x5f, 0xd1, 0x70, 0xd1, 0x5f, 0xd1, 0x71, - 0xd1, 0x5f, 0xd1, 0x72, 0xd1, 0x55, 0x55, 0x55, - 0x05, 0xb9, 0xd1, 0x65, 0xd1, 0xba, 0xd1, 0x65, - 0xd1, 0xbb, 0xd1, 0x6e, 0xd1, 0xbc, 0xd1, 0x6e, - 0xd1, 0xbb, 0xd1, 0x6f, 0xd1, 0xbc, 0xd1, 0x6f, - 0xd1, 0x55, 0x55, 0x55, 0x41, 0x00, 0x61, 0x00, - 0x41, 0x00, 0x61, 0x00, 0x69, 0x00, 0x41, 0x00, - 0x61, 0x00, 0x41, 0x00, 0x43, 0x44, 0x00, 0x00, - 0x47, 0x00, 0x00, 0x4a, 0x4b, 0x00, 0x00, 0x4e, - 0x4f, 0x50, 0x51, 0x00, 0x53, 0x54, 0x55, 0x56, - 0x57, 0x58, 0x59, 0x5a, 0x61, 0x62, 0x63, 0x64, - 0x00, 0x66, 0x68, 0x00, 0x70, 0x00, 0x41, 0x00, - 0x61, 0x00, 0x41, 0x42, 0x00, 0x44, 0x45, 0x46, - 0x47, 0x4a, 0x00, 0x53, 0x00, 0x61, 0x00, 0x41, - 0x42, 0x00, 0x44, 0x45, 0x46, 0x47, 0x00, 0x49, - 0x4a, 0x4b, 0x4c, 0x4d, 0x00, 0x4f, 0x53, 0x00, - 0x61, 0x00, 0x41, 0x00, 0x61, 0x00, 0x41, 0x00, + 0x49, 0x4a, 0x4b, 0x4d, 0x4e, 0x4f, 0x50, 0xe4, + 0x4e, 0x8c, 0x54, 0xa1, 0x30, 0x01, 0x30, 0x5b, + 0x27, 0x01, 0x4a, 0x34, 0x00, 0x01, 0x52, 0x39, + 0x01, 0xa2, 0x30, 0x00, 0x5a, 0x49, 0xa4, 0x30, + 0x00, 0x27, 0x4f, 0x0c, 0xa4, 0x30, 0x00, 0x4f, + 0x1d, 0x02, 0x05, 0x4f, 0xa8, 0x30, 0x00, 0x11, + 0x07, 0x54, 0x21, 0xa8, 0x30, 0x00, 0x54, 0x03, + 0x54, 0xa4, 0x30, 0x06, 0x4f, 0x15, 0x06, 0x58, + 0x3c, 0x07, 0x00, 0x46, 0xab, 0x30, 0x00, 0x3e, + 0x18, 0x1d, 0x00, 0x42, 0x3f, 0x51, 0xac, 0x30, + 0x00, 0x41, 0x47, 0x00, 0x47, 0x32, 0xae, 0x30, + 0xac, 0x30, 0xae, 0x30, 0x00, 0x1d, 0x4e, 0xad, + 0x30, 0x00, 0x38, 0x3d, 0x4f, 0x01, 0x3e, 0x13, + 0x4f, 0xad, 0x30, 0xed, 0x30, 0xad, 0x30, 0x00, + 0x40, 0x03, 0x3c, 0x33, 0xad, 0x30, 0x00, 0x40, + 0x34, 0x4f, 0x1b, 0x3e, 0xad, 0x30, 0x00, 0x40, + 0x42, 0x16, 0x1b, 0xb0, 0x30, 0x00, 0x39, 0x30, + 0xa4, 0x30, 0x0c, 0x45, 0x3c, 0x24, 0x4f, 0x0b, + 0x47, 0x18, 0x00, 0x49, 0xaf, 0x30, 0x00, 0x3e, + 0x4d, 0x1e, 0xb1, 0x30, 0x00, 0x4b, 0x08, 0x02, + 0x3a, 0x19, 0x02, 0x4b, 0x2c, 0xa4, 0x30, 0x11, + 0x00, 0x0b, 0x47, 0xb5, 0x30, 0x00, 0x3e, 0x0c, + 0x47, 0x2b, 0xb0, 0x30, 0x07, 0x3a, 0x43, 0x00, + 0xb9, 0x30, 0x02, 0x3a, 0x08, 0x02, 0x3a, 0x0f, + 0x07, 0x43, 0x00, 0xb7, 0x30, 0x10, 0x00, 0x12, + 0x34, 0x11, 0x3c, 0x13, 0x17, 0xa4, 0x30, 0x2a, + 0x1f, 0x24, 0x2b, 0x00, 0x20, 0xbb, 0x30, 0x16, + 0x41, 0x00, 0x38, 0x0d, 0xc4, 0x30, 0x0d, 0x38, + 0x00, 0xd0, 0x30, 0x00, 0x2c, 0x1c, 0x1b, 0xa2, + 0x30, 0x32, 0x00, 0x17, 0x26, 0x49, 0xaf, 0x30, + 0x25, 0x00, 0x3c, 0xb3, 0x30, 0x21, 0x00, 0x20, + 0x38, 0xa1, 0x30, 0x34, 0x00, 0x48, 0x22, 0x28, + 0xa3, 0x30, 0x32, 0x00, 0x59, 0x25, 0xa7, 0x30, + 0x2f, 0x1c, 0x10, 0x00, 0x44, 0xd5, 0x30, 0x00, + 0x14, 0x1e, 0xaf, 0x30, 0x29, 0x00, 0x10, 0x4d, + 0x3c, 0xda, 0x30, 0xbd, 0x30, 0xb8, 0x30, 0x22, + 0x13, 0x1a, 0x20, 0x33, 0x0c, 0x22, 0x3b, 0x01, + 0x22, 0x44, 0x00, 0x21, 0x44, 0x07, 0xa4, 0x30, + 0x39, 0x00, 0x4f, 0x24, 0xc8, 0x30, 0x14, 0x23, + 0x00, 0xdb, 0x30, 0xf3, 0x30, 0xc9, 0x30, 0x14, + 0x2a, 0x00, 0x12, 0x33, 0x22, 0x12, 0x33, 0x2a, + 0xa4, 0x30, 0x3a, 0x00, 0x0b, 0x49, 0xa4, 0x30, + 0x3a, 0x00, 0x47, 0x3a, 0x1f, 0x2b, 0x3a, 0x47, + 0x0b, 0xb7, 0x30, 0x27, 0x3c, 0x00, 0x30, 0x3c, + 0xaf, 0x30, 0x30, 0x00, 0x3e, 0x44, 0xdf, 0x30, + 0xea, 0x30, 0xd0, 0x30, 0x0f, 0x1a, 0x00, 0x2c, + 0x1b, 0xe1, 0x30, 0xac, 0x30, 0xac, 0x30, 0x35, + 0x00, 0x1c, 0x47, 0x35, 0x50, 0x1c, 0x3f, 0xa2, + 0x30, 0x42, 0x5a, 0x27, 0x42, 0x5a, 0x49, 0x44, + 0x00, 0x51, 0xc3, 0x30, 0x27, 0x00, 0x05, 0x28, + 0xea, 0x30, 0xe9, 0x30, 0xd4, 0x30, 0x17, 0x00, + 0x28, 0xd6, 0x30, 0x15, 0x26, 0x00, 0x15, 0xec, + 0x30, 0xe0, 0x30, 0xb2, 0x30, 0x3a, 0x41, 0x16, + 0x00, 0x41, 0xc3, 0x30, 0x2c, 0x00, 0x05, 0x30, + 0x00, 0xb9, 0x70, 0x31, 0x00, 0x30, 0x00, 0xb9, + 0x70, 0x32, 0x00, 0x30, 0x00, 0xb9, 0x70, 0x68, + 0x50, 0x61, 0x64, 0x61, 0x41, 0x55, 0x62, 0x61, + 0x72, 0x6f, 0x56, 0x70, 0x63, 0x64, 0x6d, 0x64, + 0x00, 0x6d, 0x00, 0xb2, 0x00, 0x49, 0x00, 0x55, + 0x00, 0x73, 0x5e, 0x10, 0x62, 0x2d, 0x66, 0x8c, + 0x54, 0x27, 0x59, 0x63, 0x6b, 0x0e, 0x66, 0xbb, + 0x6c, 0x2a, 0x68, 0x0f, 0x5f, 0x1a, 0x4f, 0x3e, + 0x79, 0x70, 0x00, 0x41, 0x6e, 0x00, 0x41, 0xbc, + 0x03, 0x41, 0x6d, 0x00, 0x41, 0x6b, 0x00, 0x41, + 0x4b, 0x00, 0x42, 0x4d, 0x00, 0x42, 0x47, 0x00, + 0x42, 0x63, 0x61, 0x6c, 0x6b, 0x63, 0x61, 0x6c, + 0x70, 0x00, 0x46, 0x6e, 0x00, 0x46, 0xbc, 0x03, + 0x46, 0xbc, 0x03, 0x67, 0x6d, 0x00, 0x67, 0x6b, + 0x00, 0x67, 0x48, 0x00, 0x7a, 0x6b, 0x48, 0x7a, + 0x4d, 0x48, 0x7a, 0x47, 0x48, 0x7a, 0x54, 0x48, + 0x7a, 0xbc, 0x03, 0x13, 0x21, 0x6d, 0x00, 0x13, + 0x21, 0x64, 0x00, 0x13, 0x21, 0x6b, 0x00, 0x13, + 0x21, 0x66, 0x00, 0x6d, 0x6e, 0x00, 0x6d, 0xbc, + 0x03, 0x6d, 0x6d, 0x00, 0x6d, 0x63, 0x00, 0x6d, + 0x6b, 0x00, 0x6d, 0x63, 0x00, 0x0a, 0x0a, 0x4f, + 0x00, 0x0a, 0x4f, 0x6d, 0x00, 0xb2, 0x00, 0x63, + 0x00, 0x08, 0x0a, 0x4f, 0x0a, 0x0a, 0x50, 0x00, + 0x0a, 0x50, 0x6d, 0x00, 0xb3, 0x00, 0x6b, 0x00, + 0x6d, 0x00, 0xb3, 0x00, 0x6d, 0x00, 0x15, 0x22, + 0x73, 0x00, 0x6d, 0x00, 0x15, 0x22, 0x73, 0x00, + 0xb2, 0x00, 0x50, 0x61, 0x6b, 0x50, 0x61, 0x4d, + 0x50, 0x61, 0x47, 0x50, 0x61, 0x72, 0x61, 0x64, + 0x72, 0x61, 0x64, 0xd1, 0x73, 0x72, 0x00, 0x61, + 0x00, 0x64, 0x00, 0x15, 0x22, 0x73, 0x00, 0xb2, + 0x00, 0x70, 0x00, 0x73, 0x6e, 0x00, 0x73, 0xbc, + 0x03, 0x73, 0x6d, 0x00, 0x73, 0x70, 0x00, 0x56, + 0x6e, 0x00, 0x56, 0xbc, 0x03, 0x56, 0x6d, 0x00, + 0x56, 0x6b, 0x00, 0x56, 0x4d, 0x00, 0x56, 0x70, + 0x00, 0x57, 0x6e, 0x00, 0x57, 0xbc, 0x03, 0x57, + 0x6d, 0x00, 0x57, 0x6b, 0x00, 0x57, 0x4d, 0x00, + 0x57, 0x6b, 0x00, 0xa9, 0x03, 0x4d, 0x00, 0xa9, + 0x03, 0x61, 0x2e, 0x6d, 0x2e, 0x42, 0x71, 0x63, + 0x63, 0x63, 0x64, 0x43, 0xd1, 0x6b, 0x67, 0x43, + 0x6f, 0x2e, 0x64, 0x42, 0x47, 0x79, 0x68, 0x61, + 0x48, 0x50, 0x69, 0x6e, 0x4b, 0x4b, 0x4b, 0x4d, + 0x6b, 0x74, 0x6c, 0x6d, 0x6c, 0x6e, 0x6c, 0x6f, + 0x67, 0x6c, 0x78, 0x6d, 0x62, 0x6d, 0x69, 0x6c, + 0x6d, 0x6f, 0x6c, 0x50, 0x48, 0x70, 0x2e, 0x6d, + 0x2e, 0x50, 0x50, 0x4d, 0x50, 0x52, 0x73, 0x72, + 0x53, 0x76, 0x57, 0x62, 0x56, 0xd1, 0x6d, 0x41, + 0xd1, 0x6d, 0x31, 0x00, 0xe5, 0x65, 0x31, 0x00, + 0x30, 0x00, 0xe5, 0x65, 0x32, 0x00, 0x30, 0x00, + 0xe5, 0x65, 0x33, 0x00, 0x30, 0x00, 0xe5, 0x65, + 0x67, 0x61, 0x6c, 0x4a, 0x04, 0x4c, 0x04, 0x26, + 0x01, 0x53, 0x01, 0x27, 0xa7, 0x37, 0xab, 0x6b, + 0x02, 0x52, 0xab, 0x48, 0x8c, 0xf4, 0x66, 0xca, + 0x8e, 0xc8, 0x8c, 0xd1, 0x6e, 0x32, 0x4e, 0xe5, + 0x53, 0x9c, 0x9f, 0x9c, 0x9f, 0x51, 0x59, 0xd1, + 0x91, 0x87, 0x55, 0x48, 0x59, 0xf6, 0x61, 0x69, + 0x76, 0x85, 0x7f, 0x3f, 0x86, 0xba, 0x87, 0xf8, + 0x88, 0x8f, 0x90, 0x02, 0x6a, 0x1b, 0x6d, 0xd9, + 0x70, 0xde, 0x73, 0x3d, 0x84, 0x6a, 0x91, 0xf1, + 0x99, 0x82, 0x4e, 0x75, 0x53, 0x04, 0x6b, 0x1b, + 0x72, 0x2d, 0x86, 0x1e, 0x9e, 0x50, 0x5d, 0xeb, + 0x6f, 0xcd, 0x85, 0x64, 0x89, 0xc9, 0x62, 0xd8, + 0x81, 0x1f, 0x88, 0xca, 0x5e, 0x17, 0x67, 0x6a, + 0x6d, 0xfc, 0x72, 0xce, 0x90, 0x86, 0x4f, 0xb7, + 0x51, 0xde, 0x52, 0xc4, 0x64, 0xd3, 0x6a, 0x10, + 0x72, 0xe7, 0x76, 0x01, 0x80, 0x06, 0x86, 0x5c, + 0x86, 0xef, 0x8d, 0x32, 0x97, 0x6f, 0x9b, 0xfa, + 0x9d, 0x8c, 0x78, 0x7f, 0x79, 0xa0, 0x7d, 0xc9, + 0x83, 0x04, 0x93, 0x7f, 0x9e, 0xd6, 0x8a, 0xdf, + 0x58, 0x04, 0x5f, 0x60, 0x7c, 0x7e, 0x80, 0x62, + 0x72, 0xca, 0x78, 0xc2, 0x8c, 0xf7, 0x96, 0xd8, + 0x58, 0x62, 0x5c, 0x13, 0x6a, 0xda, 0x6d, 0x0f, + 0x6f, 0x2f, 0x7d, 0x37, 0x7e, 0x4b, 0x96, 0xd2, + 0x52, 0x8b, 0x80, 0xdc, 0x51, 0xcc, 0x51, 0x1c, + 0x7a, 0xbe, 0x7d, 0xf1, 0x83, 0x75, 0x96, 0x80, + 0x8b, 0xcf, 0x62, 0x02, 0x6a, 0xfe, 0x8a, 0x39, + 0x4e, 0xe7, 0x5b, 0x12, 0x60, 0x87, 0x73, 0x70, + 0x75, 0x17, 0x53, 0xfb, 0x78, 0xbf, 0x4f, 0xa9, + 0x5f, 0x0d, 0x4e, 0xcc, 0x6c, 0x78, 0x65, 0x22, + 0x7d, 0xc3, 0x53, 0x5e, 0x58, 0x01, 0x77, 0x49, + 0x84, 0xaa, 0x8a, 0xba, 0x6b, 0xb0, 0x8f, 0x88, + 0x6c, 0xfe, 0x62, 0xe5, 0x82, 0xa0, 0x63, 0x65, + 0x75, 0xae, 0x4e, 0x69, 0x51, 0xc9, 0x51, 0x81, + 0x68, 0xe7, 0x7c, 0x6f, 0x82, 0xd2, 0x8a, 0xcf, + 0x91, 0xf5, 0x52, 0x42, 0x54, 0x73, 0x59, 0xec, + 0x5e, 0xc5, 0x65, 0xfe, 0x6f, 0x2a, 0x79, 0xad, + 0x95, 0x6a, 0x9a, 0x97, 0x9e, 0xce, 0x9e, 0x9b, + 0x52, 0xc6, 0x66, 0x77, 0x6b, 0x62, 0x8f, 0x74, + 0x5e, 0x90, 0x61, 0x00, 0x62, 0x9a, 0x64, 0x23, + 0x6f, 0x49, 0x71, 0x89, 0x74, 0xca, 0x79, 0xf4, + 0x7d, 0x6f, 0x80, 0x26, 0x8f, 0xee, 0x84, 0x23, + 0x90, 0x4a, 0x93, 0x17, 0x52, 0xa3, 0x52, 0xbd, + 0x54, 0xc8, 0x70, 0xc2, 0x88, 0xaa, 0x8a, 0xc9, + 0x5e, 0xf5, 0x5f, 0x7b, 0x63, 0xae, 0x6b, 0x3e, + 0x7c, 0x75, 0x73, 0xe4, 0x4e, 0xf9, 0x56, 0xe7, + 0x5b, 0xba, 0x5d, 0x1c, 0x60, 0xb2, 0x73, 0x69, + 0x74, 0x9a, 0x7f, 0x46, 0x80, 0x34, 0x92, 0xf6, + 0x96, 0x48, 0x97, 0x18, 0x98, 0x8b, 0x4f, 0xae, + 0x79, 0xb4, 0x91, 0xb8, 0x96, 0xe1, 0x60, 0x86, + 0x4e, 0xda, 0x50, 0xee, 0x5b, 0x3f, 0x5c, 0x99, + 0x65, 0x02, 0x6a, 0xce, 0x71, 0x42, 0x76, 0xfc, + 0x84, 0x7c, 0x90, 0x8d, 0x9f, 0x88, 0x66, 0x2e, + 0x96, 0x89, 0x52, 0x7b, 0x67, 0xf3, 0x67, 0x41, + 0x6d, 0x9c, 0x6e, 0x09, 0x74, 0x59, 0x75, 0x6b, + 0x78, 0x10, 0x7d, 0x5e, 0x98, 0x6d, 0x51, 0x2e, + 0x62, 0x78, 0x96, 0x2b, 0x50, 0x19, 0x5d, 0xea, + 0x6d, 0x2a, 0x8f, 0x8b, 0x5f, 0x44, 0x61, 0x17, + 0x68, 0x87, 0x73, 0x86, 0x96, 0x29, 0x52, 0x0f, + 0x54, 0x65, 0x5c, 0x13, 0x66, 0x4e, 0x67, 0xa8, + 0x68, 0xe5, 0x6c, 0x06, 0x74, 0xe2, 0x75, 0x79, + 0x7f, 0xcf, 0x88, 0xe1, 0x88, 0xcc, 0x91, 0xe2, + 0x96, 0x3f, 0x53, 0xba, 0x6e, 0x1d, 0x54, 0xd0, + 0x71, 0x98, 0x74, 0xfa, 0x85, 0xa3, 0x96, 0x57, + 0x9c, 0x9f, 0x9e, 0x97, 0x67, 0xcb, 0x6d, 0xe8, + 0x81, 0xcb, 0x7a, 0x20, 0x7b, 0x92, 0x7c, 0xc0, + 0x72, 0x99, 0x70, 0x58, 0x8b, 0xc0, 0x4e, 0x36, + 0x83, 0x3a, 0x52, 0x07, 0x52, 0xa6, 0x5e, 0xd3, + 0x62, 0xd6, 0x7c, 0x85, 0x5b, 0x1e, 0x6d, 0xb4, + 0x66, 0x3b, 0x8f, 0x4c, 0x88, 0x4d, 0x96, 0x8b, + 0x89, 0xd3, 0x5e, 0x40, 0x51, 0xc0, 0x55, 0x00, + 0x00, 0x00, 0x00, 0x5a, 0x58, 0x00, 0x00, 0x74, + 0x66, 0x00, 0x00, 0x00, 0x00, 0xde, 0x51, 0x2a, + 0x73, 0xca, 0x76, 0x3c, 0x79, 0x5e, 0x79, 0x65, + 0x79, 0x8f, 0x79, 0x56, 0x97, 0xbe, 0x7c, 0xbd, + 0x7f, 0x00, 0x00, 0x12, 0x86, 0x00, 0x00, 0xf8, + 0x8a, 0x00, 0x00, 0x00, 0x00, 0x38, 0x90, 0xfd, + 0x90, 0xef, 0x98, 0xfc, 0x98, 0x28, 0x99, 0xb4, + 0x9d, 0xde, 0x90, 0xb7, 0x96, 0xae, 0x4f, 0xe7, + 0x50, 0x4d, 0x51, 0xc9, 0x52, 0xe4, 0x52, 0x51, + 0x53, 0x9d, 0x55, 0x06, 0x56, 0x68, 0x56, 0x40, + 0x58, 0xa8, 0x58, 0x64, 0x5c, 0x6e, 0x5c, 0x94, + 0x60, 0x68, 0x61, 0x8e, 0x61, 0xf2, 0x61, 0x4f, + 0x65, 0xe2, 0x65, 0x91, 0x66, 0x85, 0x68, 0x77, + 0x6d, 0x1a, 0x6e, 0x22, 0x6f, 0x6e, 0x71, 0x2b, + 0x72, 0x22, 0x74, 0x91, 0x78, 0x3e, 0x79, 0x49, + 0x79, 0x48, 0x79, 0x50, 0x79, 0x56, 0x79, 0x5d, + 0x79, 0x8d, 0x79, 0x8e, 0x79, 0x40, 0x7a, 0x81, + 0x7a, 0xc0, 0x7b, 0xf4, 0x7d, 0x09, 0x7e, 0x41, + 0x7e, 0x72, 0x7f, 0x05, 0x80, 0xed, 0x81, 0x79, + 0x82, 0x79, 0x82, 0x57, 0x84, 0x10, 0x89, 0x96, + 0x89, 0x01, 0x8b, 0x39, 0x8b, 0xd3, 0x8c, 0x08, + 0x8d, 0xb6, 0x8f, 0x38, 0x90, 0xe3, 0x96, 0xff, + 0x97, 0x3b, 0x98, 0x75, 0x60, 0xee, 0x42, 0x18, + 0x82, 0x02, 0x26, 0x4e, 0xb5, 0x51, 0x68, 0x51, + 0x80, 0x4f, 0x45, 0x51, 0x80, 0x51, 0xc7, 0x52, + 0xfa, 0x52, 0x9d, 0x55, 0x55, 0x55, 0x99, 0x55, + 0xe2, 0x55, 0x5a, 0x58, 0xb3, 0x58, 0x44, 0x59, + 0x54, 0x59, 0x62, 0x5a, 0x28, 0x5b, 0xd2, 0x5e, + 0xd9, 0x5e, 0x69, 0x5f, 0xad, 0x5f, 0xd8, 0x60, + 0x4e, 0x61, 0x08, 0x61, 0x8e, 0x61, 0x60, 0x61, + 0xf2, 0x61, 0x34, 0x62, 0xc4, 0x63, 0x1c, 0x64, + 0x52, 0x64, 0x56, 0x65, 0x74, 0x66, 0x17, 0x67, + 0x1b, 0x67, 0x56, 0x67, 0x79, 0x6b, 0xba, 0x6b, + 0x41, 0x6d, 0xdb, 0x6e, 0xcb, 0x6e, 0x22, 0x6f, + 0x1e, 0x70, 0x6e, 0x71, 0xa7, 0x77, 0x35, 0x72, + 0xaf, 0x72, 0x2a, 0x73, 0x71, 0x74, 0x06, 0x75, + 0x3b, 0x75, 0x1d, 0x76, 0x1f, 0x76, 0xca, 0x76, + 0xdb, 0x76, 0xf4, 0x76, 0x4a, 0x77, 0x40, 0x77, + 0xcc, 0x78, 0xb1, 0x7a, 0xc0, 0x7b, 0x7b, 0x7c, + 0x5b, 0x7d, 0xf4, 0x7d, 0x3e, 0x7f, 0x05, 0x80, + 0x52, 0x83, 0xef, 0x83, 0x79, 0x87, 0x41, 0x89, + 0x86, 0x89, 0x96, 0x89, 0xbf, 0x8a, 0xf8, 0x8a, + 0xcb, 0x8a, 0x01, 0x8b, 0xfe, 0x8a, 0xed, 0x8a, + 0x39, 0x8b, 0x8a, 0x8b, 0x08, 0x8d, 0x38, 0x8f, + 0x72, 0x90, 0x99, 0x91, 0x76, 0x92, 0x7c, 0x96, + 0xe3, 0x96, 0x56, 0x97, 0xdb, 0x97, 0xff, 0x97, + 0x0b, 0x98, 0x3b, 0x98, 0x12, 0x9b, 0x9c, 0x9f, + 0x4a, 0x28, 0x44, 0x28, 0xd5, 0x33, 0x9d, 0x3b, + 0x18, 0x40, 0x39, 0x40, 0x49, 0x52, 0xd0, 0x5c, + 0xd3, 0x7e, 0x43, 0x9f, 0x8e, 0x9f, 0x2a, 0xa0, + 0x02, 0x66, 0x66, 0x66, 0x69, 0x66, 0x6c, 0x66, + 0x66, 0x69, 0x66, 0x66, 0x6c, 0x7f, 0x01, 0x74, + 0x73, 0x00, 0x74, 0x65, 0x05, 0x0f, 0x11, 0x0f, + 0x00, 0x0f, 0x06, 0x19, 0x11, 0x0f, 0x08, 0xd9, + 0x05, 0xb4, 0x05, 0x00, 0x00, 0x00, 0x00, 0xf2, + 0x05, 0xb7, 0x05, 0xd0, 0x05, 0x12, 0x00, 0x03, + 0x04, 0x0b, 0x0c, 0x0d, 0x18, 0x1a, 0xe9, 0x05, + 0xc1, 0x05, 0xe9, 0x05, 0xc2, 0x05, 0x49, 0xfb, + 0xc1, 0x05, 0x49, 0xfb, 0xc2, 0x05, 0xd0, 0x05, + 0xb7, 0x05, 0xd0, 0x05, 0xb8, 0x05, 0xd0, 0x05, + 0xbc, 0x05, 0xd8, 0x05, 0xbc, 0x05, 0xde, 0x05, + 0xbc, 0x05, 0xe0, 0x05, 0xbc, 0x05, 0xe3, 0x05, + 0xbc, 0x05, 0xb9, 0x05, 0x2d, 0x03, 0x2e, 0x03, + 0x2f, 0x03, 0x30, 0x03, 0x31, 0x03, 0x1c, 0x00, + 0x18, 0x06, 0x22, 0x06, 0x2b, 0x06, 0xd0, 0x05, + 0xdc, 0x05, 0x71, 0x06, 0x00, 0x00, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0d, 0x0d, 0x0d, 0x0d, 0x0f, 0x0f, + 0x0f, 0x0f, 0x09, 0x09, 0x09, 0x09, 0x0e, 0x0e, + 0x0e, 0x0e, 0x08, 0x08, 0x08, 0x08, 0x33, 0x33, + 0x33, 0x33, 0x35, 0x35, 0x35, 0x35, 0x13, 0x13, + 0x13, 0x13, 0x12, 0x12, 0x12, 0x12, 0x15, 0x15, + 0x15, 0x15, 0x16, 0x16, 0x16, 0x16, 0x1c, 0x1c, + 0x1b, 0x1b, 0x1d, 0x1d, 0x17, 0x17, 0x27, 0x27, + 0x20, 0x20, 0x38, 0x38, 0x38, 0x38, 0x3e, 0x3e, + 0x3e, 0x3e, 0x42, 0x42, 0x42, 0x42, 0x40, 0x40, + 0x40, 0x40, 0x49, 0x49, 0x4a, 0x4a, 0x4a, 0x4a, + 0x4f, 0x4f, 0x50, 0x50, 0x50, 0x50, 0x4d, 0x4d, + 0x4d, 0x4d, 0x61, 0x61, 0x62, 0x62, 0x49, 0x06, + 0x64, 0x64, 0x64, 0x64, 0x7e, 0x7e, 0x7d, 0x7d, + 0x7f, 0x7f, 0x2e, 0x82, 0x82, 0x7c, 0x7c, 0x80, + 0x80, 0x87, 0x87, 0x87, 0x87, 0x00, 0x00, 0x26, + 0x06, 0x00, 0x01, 0x00, 0x01, 0x00, 0xaf, 0x00, + 0xaf, 0x00, 0x22, 0x00, 0x22, 0x00, 0xa1, 0x00, + 0xa1, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa2, 0x00, + 0xa2, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, + 0x23, 0x00, 0x23, 0x00, 0x23, 0xcc, 0x06, 0x00, + 0x00, 0x00, 0x00, 0x26, 0x06, 0x00, 0x06, 0x00, + 0x07, 0x00, 0x1f, 0x00, 0x23, 0x00, 0x24, 0x02, + 0x06, 0x02, 0x07, 0x02, 0x08, 0x02, 0x1f, 0x02, + 0x23, 0x02, 0x24, 0x04, 0x06, 0x04, 0x07, 0x04, + 0x08, 0x04, 0x1f, 0x04, 0x23, 0x04, 0x24, 0x05, + 0x06, 0x05, 0x1f, 0x05, 0x23, 0x05, 0x24, 0x06, + 0x07, 0x06, 0x1f, 0x07, 0x06, 0x07, 0x1f, 0x08, + 0x06, 0x08, 0x07, 0x08, 0x1f, 0x0d, 0x06, 0x0d, + 0x07, 0x0d, 0x08, 0x0d, 0x1f, 0x0f, 0x07, 0x0f, + 0x1f, 0x10, 0x06, 0x10, 0x07, 0x10, 0x08, 0x10, + 0x1f, 0x11, 0x07, 0x11, 0x1f, 0x12, 0x1f, 0x13, + 0x06, 0x13, 0x1f, 0x14, 0x06, 0x14, 0x1f, 0x1b, + 0x06, 0x1b, 0x07, 0x1b, 0x08, 0x1b, 0x1f, 0x1b, + 0x23, 0x1b, 0x24, 0x1c, 0x07, 0x1c, 0x1f, 0x1c, + 0x23, 0x1c, 0x24, 0x1d, 0x01, 0x1d, 0x06, 0x1d, + 0x07, 0x1d, 0x08, 0x1d, 0x1e, 0x1d, 0x1f, 0x1d, + 0x23, 0x1d, 0x24, 0x1e, 0x06, 0x1e, 0x07, 0x1e, + 0x08, 0x1e, 0x1f, 0x1e, 0x23, 0x1e, 0x24, 0x1f, + 0x06, 0x1f, 0x07, 0x1f, 0x08, 0x1f, 0x1f, 0x1f, + 0x23, 0x1f, 0x24, 0x20, 0x06, 0x20, 0x07, 0x20, + 0x08, 0x20, 0x1f, 0x20, 0x23, 0x20, 0x24, 0x21, + 0x06, 0x21, 0x1f, 0x21, 0x23, 0x21, 0x24, 0x24, + 0x06, 0x24, 0x07, 0x24, 0x08, 0x24, 0x1f, 0x24, + 0x23, 0x24, 0x24, 0x0a, 0x4a, 0x0b, 0x4a, 0x23, + 0x4a, 0x20, 0x00, 0x4c, 0x06, 0x51, 0x06, 0x51, + 0x06, 0xff, 0x00, 0x1f, 0x26, 0x06, 0x00, 0x0b, + 0x00, 0x0c, 0x00, 0x1f, 0x00, 0x20, 0x00, 0x23, + 0x00, 0x24, 0x02, 0x0b, 0x02, 0x0c, 0x02, 0x1f, + 0x02, 0x20, 0x02, 0x23, 0x02, 0x24, 0x04, 0x0b, + 0x04, 0x0c, 0x04, 0x1f, 0x26, 0x06, 0x04, 0x20, + 0x04, 0x23, 0x04, 0x24, 0x05, 0x0b, 0x05, 0x0c, + 0x05, 0x1f, 0x05, 0x20, 0x05, 0x23, 0x05, 0x24, + 0x1b, 0x23, 0x1b, 0x24, 0x1c, 0x23, 0x1c, 0x24, + 0x1d, 0x01, 0x1d, 0x1e, 0x1d, 0x1f, 0x1d, 0x23, + 0x1d, 0x24, 0x1e, 0x1f, 0x1e, 0x23, 0x1e, 0x24, + 0x1f, 0x01, 0x1f, 0x1f, 0x20, 0x0b, 0x20, 0x0c, + 0x20, 0x1f, 0x20, 0x20, 0x20, 0x23, 0x20, 0x24, + 0x23, 0x4a, 0x24, 0x0b, 0x24, 0x0c, 0x24, 0x1f, + 0x24, 0x20, 0x24, 0x23, 0x24, 0x24, 0x00, 0x06, + 0x00, 0x07, 0x00, 0x08, 0x00, 0x1f, 0x00, 0x21, + 0x02, 0x06, 0x02, 0x07, 0x02, 0x08, 0x02, 0x1f, + 0x02, 0x21, 0x04, 0x06, 0x04, 0x07, 0x04, 0x08, + 0x04, 0x1f, 0x04, 0x21, 0x05, 0x1f, 0x06, 0x07, + 0x06, 0x1f, 0x07, 0x06, 0x07, 0x1f, 0x08, 0x06, + 0x08, 0x1f, 0x0d, 0x06, 0x0d, 0x07, 0x0d, 0x08, + 0x0d, 0x1f, 0x0f, 0x07, 0x0f, 0x08, 0x0f, 0x1f, + 0x10, 0x06, 0x10, 0x07, 0x10, 0x08, 0x10, 0x1f, + 0x11, 0x07, 0x12, 0x1f, 0x13, 0x06, 0x13, 0x1f, + 0x14, 0x06, 0x14, 0x1f, 0x1b, 0x06, 0x1b, 0x07, + 0x1b, 0x08, 0x1b, 0x1f, 0x1c, 0x07, 0x1c, 0x1f, + 0x1d, 0x06, 0x1d, 0x07, 0x1d, 0x08, 0x1d, 0x1e, + 0x1d, 0x1f, 0x1e, 0x06, 0x1e, 0x07, 0x1e, 0x08, + 0x1e, 0x1f, 0x1e, 0x21, 0x1f, 0x06, 0x1f, 0x07, + 0x1f, 0x08, 0x1f, 0x1f, 0x20, 0x06, 0x20, 0x07, + 0x20, 0x08, 0x20, 0x1f, 0x20, 0x21, 0x21, 0x06, + 0x21, 0x1f, 0x21, 0x4a, 0x24, 0x06, 0x24, 0x07, + 0x24, 0x08, 0x24, 0x1f, 0x24, 0x21, 0x00, 0x1f, + 0x00, 0x21, 0x02, 0x1f, 0x02, 0x21, 0x04, 0x1f, + 0x04, 0x21, 0x05, 0x1f, 0x05, 0x21, 0x0d, 0x1f, + 0x0d, 0x21, 0x0e, 0x1f, 0x0e, 0x21, 0x1d, 0x1e, + 0x1d, 0x1f, 0x1e, 0x1f, 0x20, 0x1f, 0x20, 0x21, + 0x24, 0x1f, 0x24, 0x21, 0x40, 0x06, 0x4e, 0x06, + 0x51, 0x06, 0x27, 0x06, 0x10, 0x22, 0x10, 0x23, + 0x12, 0x22, 0x12, 0x23, 0x13, 0x22, 0x13, 0x23, + 0x0c, 0x22, 0x0c, 0x23, 0x0d, 0x22, 0x0d, 0x23, + 0x06, 0x22, 0x06, 0x23, 0x05, 0x22, 0x05, 0x23, + 0x07, 0x22, 0x07, 0x23, 0x0e, 0x22, 0x0e, 0x23, + 0x0f, 0x22, 0x0f, 0x23, 0x0d, 0x05, 0x0d, 0x06, + 0x0d, 0x07, 0x0d, 0x1e, 0x0d, 0x0a, 0x0c, 0x0a, + 0x0e, 0x0a, 0x0f, 0x0a, 0x10, 0x22, 0x10, 0x23, + 0x12, 0x22, 0x12, 0x23, 0x13, 0x22, 0x13, 0x23, + 0x0c, 0x22, 0x0c, 0x23, 0x0d, 0x22, 0x0d, 0x23, + 0x06, 0x22, 0x06, 0x23, 0x05, 0x22, 0x05, 0x23, + 0x07, 0x22, 0x07, 0x23, 0x0e, 0x22, 0x0e, 0x23, + 0x0f, 0x22, 0x0f, 0x23, 0x0d, 0x05, 0x0d, 0x06, + 0x0d, 0x07, 0x0d, 0x1e, 0x0d, 0x0a, 0x0c, 0x0a, + 0x0e, 0x0a, 0x0f, 0x0a, 0x0d, 0x05, 0x0d, 0x06, + 0x0d, 0x07, 0x0d, 0x1e, 0x0c, 0x20, 0x0d, 0x20, + 0x10, 0x1e, 0x0c, 0x05, 0x0c, 0x06, 0x0c, 0x07, + 0x0d, 0x05, 0x0d, 0x06, 0x0d, 0x07, 0x10, 0x1e, + 0x11, 0x1e, 0x00, 0x24, 0x00, 0x24, 0x2a, 0x06, + 0x00, 0x02, 0x1b, 0x00, 0x03, 0x02, 0x00, 0x03, + 0x02, 0x00, 0x03, 0x1b, 0x00, 0x04, 0x1b, 0x00, + 0x1b, 0x02, 0x00, 0x1b, 0x03, 0x00, 0x1b, 0x04, + 0x02, 0x1b, 0x03, 0x02, 0x1b, 0x03, 0x03, 0x1b, + 0x20, 0x03, 0x1b, 0x1f, 0x09, 0x03, 0x02, 0x09, + 0x02, 0x03, 0x09, 0x02, 0x1f, 0x09, 0x1b, 0x03, + 0x09, 0x1b, 0x03, 0x09, 0x1b, 0x02, 0x09, 0x1b, + 0x1b, 0x09, 0x1b, 0x1b, 0x0b, 0x03, 0x03, 0x0b, + 0x03, 0x03, 0x0b, 0x1b, 0x1b, 0x0a, 0x03, 0x1b, + 0x0a, 0x03, 0x1b, 0x0a, 0x02, 0x20, 0x0a, 0x1b, + 0x04, 0x0a, 0x1b, 0x04, 0x0a, 0x1b, 0x1b, 0x0a, + 0x1b, 0x1b, 0x0c, 0x03, 0x1f, 0x0c, 0x04, 0x1b, + 0x0c, 0x04, 0x1b, 0x0d, 0x1b, 0x03, 0x0d, 0x1b, + 0x03, 0x0d, 0x1b, 0x1b, 0x0d, 0x1b, 0x20, 0x0f, + 0x02, 0x1b, 0x0f, 0x1b, 0x1b, 0x0f, 0x1b, 0x1b, + 0x0f, 0x1b, 0x1f, 0x10, 0x1b, 0x1b, 0x10, 0x1b, + 0x20, 0x10, 0x1b, 0x1f, 0x17, 0x04, 0x1b, 0x17, + 0x04, 0x1b, 0x18, 0x1b, 0x03, 0x18, 0x1b, 0x1b, + 0x1a, 0x03, 0x1b, 0x1a, 0x03, 0x20, 0x1a, 0x03, + 0x1f, 0x1a, 0x02, 0x02, 0x1a, 0x02, 0x02, 0x1a, + 0x04, 0x1b, 0x1a, 0x04, 0x1b, 0x1a, 0x1b, 0x03, + 0x1a, 0x1b, 0x03, 0x1b, 0x03, 0x02, 0x1b, 0x03, + 0x1b, 0x1b, 0x03, 0x20, 0x1b, 0x02, 0x03, 0x1b, + 0x02, 0x1b, 0x1b, 0x04, 0x02, 0x1b, 0x04, 0x1b, + 0x28, 0x06, 0x1d, 0x04, 0x06, 0x1f, 0x1d, 0x04, + 0x1f, 0x1d, 0x1d, 0x1e, 0x05, 0x1d, 0x1e, 0x05, + 0x21, 0x1e, 0x04, 0x1d, 0x1e, 0x04, 0x1d, 0x1e, + 0x04, 0x21, 0x1e, 0x1d, 0x22, 0x1e, 0x1d, 0x21, + 0x22, 0x1d, 0x1d, 0x22, 0x1d, 0x1d, 0x00, 0x06, + 0x22, 0x02, 0x04, 0x22, 0x02, 0x04, 0x21, 0x02, + 0x06, 0x22, 0x02, 0x06, 0x21, 0x02, 0x1d, 0x22, + 0x02, 0x1d, 0x21, 0x04, 0x1d, 0x22, 0x04, 0x05, + 0x21, 0x04, 0x1d, 0x21, 0x0b, 0x06, 0x21, 0x0d, + 0x05, 0x22, 0x0c, 0x05, 0x22, 0x0e, 0x05, 0x22, + 0x1c, 0x04, 0x22, 0x1c, 0x1d, 0x22, 0x22, 0x05, + 0x22, 0x22, 0x04, 0x22, 0x22, 0x1d, 0x22, 0x1d, + 0x1d, 0x22, 0x1a, 0x1d, 0x22, 0x1e, 0x05, 0x22, + 0x1a, 0x1d, 0x05, 0x1c, 0x05, 0x1d, 0x11, 0x1d, + 0x22, 0x1b, 0x1d, 0x22, 0x1e, 0x04, 0x05, 0x1d, + 0x06, 0x22, 0x1c, 0x04, 0x1d, 0x1b, 0x1d, 0x1d, + 0x1c, 0x04, 0x1d, 0x1e, 0x04, 0x05, 0x04, 0x05, + 0x22, 0x05, 0x04, 0x22, 0x1d, 0x04, 0x22, 0x19, + 0x1d, 0x22, 0x00, 0x05, 0x22, 0x1b, 0x1d, 0x1d, + 0x11, 0x04, 0x1d, 0x0d, 0x1d, 0x1d, 0x0b, 0x06, + 0x22, 0x1e, 0x04, 0x22, 0x35, 0x06, 0x00, 0x0f, + 0x9d, 0x0d, 0x0f, 0x9d, 0x27, 0x06, 0x00, 0x1d, + 0x1d, 0x20, 0x00, 0x1c, 0x01, 0x0a, 0x1e, 0x06, + 0x1e, 0x08, 0x0e, 0x1d, 0x12, 0x1e, 0x0a, 0x0c, + 0x21, 0x1d, 0x12, 0x1d, 0x23, 0x20, 0x21, 0x0c, + 0x1d, 0x1e, 0x35, 0x06, 0x00, 0x0f, 0x14, 0x27, + 0x06, 0x0e, 0x1d, 0x22, 0xff, 0x00, 0x1d, 0x1d, + 0x20, 0xff, 0x12, 0x1d, 0x23, 0x20, 0xff, 0x21, + 0x0c, 0x1d, 0x1e, 0x27, 0x06, 0x05, 0x1d, 0xff, + 0x05, 0x1d, 0x00, 0x1d, 0x20, 0x27, 0x06, 0x0a, + 0xa5, 0x00, 0x1d, 0x2c, 0x00, 0x01, 0x30, 0x02, + 0x30, 0x3a, 0x00, 0x3b, 0x00, 0x21, 0x00, 0x3f, + 0x00, 0x16, 0x30, 0x17, 0x30, 0x26, 0x20, 0x13, + 0x20, 0x12, 0x01, 0x00, 0x5f, 0x5f, 0x28, 0x29, + 0x7b, 0x7d, 0x08, 0x30, 0x0c, 0x0d, 0x08, 0x09, + 0x02, 0x03, 0x00, 0x01, 0x04, 0x05, 0x06, 0x07, + 0x5b, 0x00, 0x5d, 0x00, 0x3e, 0x20, 0x3e, 0x20, + 0x3e, 0x20, 0x3e, 0x20, 0x5f, 0x00, 0x5f, 0x00, + 0x5f, 0x00, 0x2c, 0x00, 0x01, 0x30, 0x2e, 0x00, + 0x00, 0x00, 0x3b, 0x00, 0x3a, 0x00, 0x3f, 0x00, + 0x21, 0x00, 0x14, 0x20, 0x28, 0x00, 0x29, 0x00, + 0x7b, 0x00, 0x7d, 0x00, 0x14, 0x30, 0x15, 0x30, + 0x23, 0x26, 0x2a, 0x2b, 0x2d, 0x3c, 0x3e, 0x3d, + 0x00, 0x5c, 0x24, 0x25, 0x40, 0x40, 0x06, 0xff, + 0x0b, 0x00, 0x0b, 0xff, 0x0c, 0x20, 0x00, 0x4d, + 0x06, 0x40, 0x06, 0xff, 0x0e, 0x00, 0x0e, 0xff, + 0x0f, 0x00, 0x0f, 0xff, 0x10, 0x00, 0x10, 0xff, + 0x11, 0x00, 0x11, 0xff, 0x12, 0x00, 0x12, 0x21, + 0x06, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, + 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, + 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, 0x09, 0x09, + 0x09, 0x09, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0c, 0x0c, 0x0c, 0x0c, 0x0d, 0x0d, + 0x0d, 0x0d, 0x0e, 0x0e, 0x0f, 0x0f, 0x10, 0x10, + 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, + 0x13, 0x13, 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, + 0x15, 0x15, 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, + 0x17, 0x17, 0x18, 0x18, 0x18, 0x18, 0x19, 0x19, + 0x19, 0x19, 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, + 0x21, 0x21, 0x22, 0x22, 0x22, 0x22, 0x23, 0x23, + 0x23, 0x23, 0x24, 0x24, 0x24, 0x24, 0x25, 0x25, + 0x25, 0x25, 0x26, 0x26, 0x26, 0x26, 0x27, 0x27, + 0x28, 0x28, 0x29, 0x29, 0x29, 0x29, 0x22, 0x06, + 0x22, 0x00, 0x22, 0x00, 0x22, 0x01, 0x22, 0x01, + 0x22, 0x03, 0x22, 0x03, 0x22, 0x05, 0x22, 0x05, + 0x21, 0x00, 0x85, 0x29, 0x01, 0x30, 0x01, 0x0b, + 0x0c, 0x00, 0xfa, 0xf1, 0xa0, 0xa2, 0xa4, 0xa6, + 0xa8, 0xe2, 0xe4, 0xe6, 0xc2, 0xfb, 0xa1, 0xa3, + 0xa5, 0xa7, 0xa9, 0xaa, 0xac, 0xae, 0xb0, 0xb2, + 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe, 0xc0, 0xc3, + 0xc5, 0xc7, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, + 0xd1, 0xd4, 0xd7, 0xda, 0xdd, 0xde, 0xdf, 0xe0, + 0xe1, 0xe3, 0xe5, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, + 0xec, 0xee, 0xf2, 0x98, 0x99, 0x31, 0x31, 0x4f, + 0x31, 0x55, 0x31, 0x5b, 0x31, 0x61, 0x31, 0xa2, + 0x00, 0xa3, 0x00, 0xac, 0x00, 0xaf, 0x00, 0xa6, + 0x00, 0xa5, 0x00, 0xa9, 0x20, 0x00, 0x00, 0x02, + 0x25, 0x90, 0x21, 0x91, 0x21, 0x92, 0x21, 0x93, + 0x21, 0xa0, 0x25, 0xcb, 0x25, 0x99, 0x10, 0xba, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x9b, 0x10, 0xba, + 0x10, 0x05, 0x05, 0xa5, 0x10, 0xba, 0x10, 0x05, + 0x31, 0x11, 0x27, 0x11, 0x32, 0x11, 0x27, 0x11, + 0x55, 0x47, 0x13, 0x3e, 0x13, 0x47, 0x13, 0x57, + 0x13, 0x55, 0xb9, 0x14, 0xba, 0x14, 0xb9, 0x14, + 0xb0, 0x14, 0x00, 0x00, 0x00, 0x00, 0xb9, 0x14, + 0xbd, 0x14, 0x55, 0x50, 0xb8, 0x15, 0xaf, 0x15, + 0xb9, 0x15, 0xaf, 0x15, 0x55, 0x57, 0xd1, 0x65, + 0xd1, 0x58, 0xd1, 0x65, 0xd1, 0x5f, 0xd1, 0x6e, + 0xd1, 0x5f, 0xd1, 0x6f, 0xd1, 0x5f, 0xd1, 0x70, + 0xd1, 0x5f, 0xd1, 0x71, 0xd1, 0x5f, 0xd1, 0x72, + 0xd1, 0x55, 0x55, 0x55, 0x05, 0xb9, 0xd1, 0x65, + 0xd1, 0xba, 0xd1, 0x65, 0xd1, 0xbb, 0xd1, 0x6e, + 0xd1, 0xbc, 0xd1, 0x6e, 0xd1, 0xbb, 0xd1, 0x6f, + 0xd1, 0xbc, 0xd1, 0x6f, 0xd1, 0x55, 0x55, 0x55, + 0x41, 0x00, 0x61, 0x00, 0x41, 0x00, 0x61, 0x00, + 0x69, 0x00, 0x41, 0x00, 0x61, 0x00, 0x41, 0x00, + 0x43, 0x44, 0x00, 0x00, 0x47, 0x00, 0x00, 0x4a, + 0x4b, 0x00, 0x00, 0x4e, 0x4f, 0x50, 0x51, 0x00, + 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, + 0x61, 0x62, 0x63, 0x64, 0x00, 0x66, 0x68, 0x00, + 0x70, 0x00, 0x41, 0x00, 0x61, 0x00, 0x41, 0x42, + 0x00, 0x44, 0x45, 0x46, 0x47, 0x4a, 0x00, 0x53, + 0x00, 0x61, 0x00, 0x41, 0x42, 0x00, 0x44, 0x45, + 0x46, 0x47, 0x00, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, + 0x00, 0x4f, 0x53, 0x00, 0x61, 0x00, 0x41, 0x00, 0x61, 0x00, 0x41, 0x00, 0x61, 0x00, 0x41, 0x00, 0x61, 0x00, 0x41, 0x00, 0x61, 0x00, 0x41, 0x00, - 0x61, 0x00, 0x31, 0x01, 0x37, 0x02, 0x91, 0x03, + 0x61, 0x00, 0x41, 0x00, 0x61, 0x00, 0x31, 0x01, + 0x37, 0x02, 0x91, 0x03, 0xa3, 0x03, 0xb1, 0x03, + 0xd1, 0x03, 0x24, 0x00, 0x1f, 0x04, 0x20, 0x05, + 0x91, 0x03, 0xa3, 0x03, 0xb1, 0x03, 0xd1, 0x03, + 0x24, 0x00, 0x1f, 0x04, 0x20, 0x05, 0x91, 0x03, 0xa3, 0x03, 0xb1, 0x03, 0xd1, 0x03, 0x24, 0x00, 0x1f, 0x04, 0x20, 0x05, 0x91, 0x03, 0xa3, 0x03, 0xb1, 0x03, 0xd1, 0x03, 0x24, 0x00, 0x1f, 0x04, 0x20, 0x05, 0x91, 0x03, 0xa3, 0x03, 0xb1, 0x03, 0xd1, 0x03, 0x24, 0x00, 0x1f, 0x04, 0x20, 0x05, - 0x91, 0x03, 0xa3, 0x03, 0xb1, 0x03, 0xd1, 0x03, - 0x24, 0x00, 0x1f, 0x04, 0x20, 0x05, 0x91, 0x03, - 0xa3, 0x03, 0xb1, 0x03, 0xd1, 0x03, 0x24, 0x00, - 0x1f, 0x04, 0x20, 0x05, 0x0b, 0x0c, 0x30, 0x00, - 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, - 0x27, 0x06, 0x00, 0x01, 0x05, 0x08, 0x2a, 0x06, - 0x1e, 0x08, 0x03, 0x0d, 0x20, 0x19, 0x1a, 0x1b, - 0x1c, 0x09, 0x0f, 0x17, 0x0b, 0x18, 0x07, 0x0a, - 0x00, 0x01, 0x04, 0x06, 0x0c, 0x0e, 0x10, 0x44, - 0x90, 0x77, 0x45, 0x28, 0x06, 0x2c, 0x06, 0x00, - 0x00, 0x47, 0x06, 0x33, 0x06, 0x17, 0x10, 0x11, - 0x12, 0x13, 0x00, 0x06, 0x0e, 0x02, 0x0f, 0x34, - 0x06, 0x2a, 0x06, 0x2b, 0x06, 0x2e, 0x06, 0x00, - 0x00, 0x36, 0x06, 0x00, 0x00, 0x3a, 0x06, 0x2d, - 0x06, 0x00, 0x00, 0x4a, 0x06, 0x00, 0x00, 0x44, - 0x06, 0x00, 0x00, 0x46, 0x06, 0x33, 0x06, 0x39, - 0x06, 0x00, 0x00, 0x35, 0x06, 0x42, 0x06, 0x00, - 0x00, 0x34, 0x06, 0x00, 0x00, 0x00, 0x00, 0x2e, - 0x06, 0x00, 0x00, 0x36, 0x06, 0x00, 0x00, 0x3a, - 0x06, 0x00, 0x00, 0xba, 0x06, 0x00, 0x00, 0x6f, - 0x06, 0x00, 0x00, 0x28, 0x06, 0x2c, 0x06, 0x00, - 0x00, 0x47, 0x06, 0x00, 0x00, 0x00, 0x00, 0x2d, - 0x06, 0x37, 0x06, 0x4a, 0x06, 0x43, 0x06, 0x00, - 0x00, 0x45, 0x06, 0x46, 0x06, 0x33, 0x06, 0x39, - 0x06, 0x41, 0x06, 0x35, 0x06, 0x42, 0x06, 0x00, - 0x00, 0x34, 0x06, 0x2a, 0x06, 0x2b, 0x06, 0x2e, - 0x06, 0x00, 0x00, 0x36, 0x06, 0x38, 0x06, 0x3a, - 0x06, 0x6e, 0x06, 0x00, 0x00, 0xa1, 0x06, 0x27, - 0x06, 0x00, 0x01, 0x05, 0x08, 0x20, 0x21, 0x0b, - 0x06, 0x10, 0x23, 0x2a, 0x06, 0x1a, 0x1b, 0x1c, - 0x09, 0x0f, 0x17, 0x0b, 0x18, 0x07, 0x0a, 0x00, - 0x01, 0x04, 0x06, 0x0c, 0x0e, 0x10, 0x28, 0x06, - 0x2c, 0x06, 0x2f, 0x06, 0x00, 0x00, 0x48, 0x06, - 0x32, 0x06, 0x2d, 0x06, 0x37, 0x06, 0x4a, 0x06, - 0x2a, 0x06, 0x1a, 0x1b, 0x1c, 0x09, 0x0f, 0x17, + 0x0b, 0x0c, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, + 0x30, 0x00, 0x30, 0x00, 0x27, 0x06, 0x00, 0x01, + 0x05, 0x08, 0x2a, 0x06, 0x1e, 0x08, 0x03, 0x0d, + 0x20, 0x19, 0x1a, 0x1b, 0x1c, 0x09, 0x0f, 0x17, 0x0b, 0x18, 0x07, 0x0a, 0x00, 0x01, 0x04, 0x06, - 0x0c, 0x0e, 0x10, 0x30, 0x2e, 0x30, 0x00, 0x2c, - 0x00, 0x28, 0x00, 0x41, 0x00, 0x29, 0x00, 0x14, - 0x30, 0x53, 0x00, 0x15, 0x30, 0x43, 0x52, 0x43, - 0x44, 0x57, 0x5a, 0x41, 0x00, 0x48, 0x56, 0x4d, - 0x56, 0x53, 0x44, 0x53, 0x53, 0x50, 0x50, 0x56, - 0x57, 0x43, 0x4d, 0x43, 0x4d, 0x44, 0x44, 0x4a, - 0x4b, 0x30, 0x30, 0x00, 0x68, 0x68, 0x4b, 0x62, - 0x57, 0x5b, 0xcc, 0x53, 0xc7, 0x30, 0x8c, 0x4e, - 0x1a, 0x59, 0xe3, 0x89, 0x29, 0x59, 0xa4, 0x4e, - 0x20, 0x66, 0x21, 0x71, 0x99, 0x65, 0x4d, 0x52, - 0x8c, 0x5f, 0x8d, 0x51, 0xb0, 0x65, 0x1d, 0x52, - 0x42, 0x7d, 0x1f, 0x75, 0xa9, 0x8c, 0xf0, 0x58, - 0x39, 0x54, 0x14, 0x6f, 0x95, 0x62, 0x55, 0x63, - 0x00, 0x4e, 0x09, 0x4e, 0x4a, 0x90, 0xe6, 0x5d, - 0x2d, 0x4e, 0xf3, 0x53, 0x07, 0x63, 0x70, 0x8d, - 0x53, 0x62, 0x81, 0x79, 0x7a, 0x7a, 0x08, 0x54, - 0x80, 0x6e, 0x09, 0x67, 0x08, 0x67, 0x33, 0x75, - 0x72, 0x52, 0xb6, 0x55, 0x4d, 0x91, 0x14, 0x30, - 0x15, 0x30, 0x2c, 0x67, 0x09, 0x4e, 0x8c, 0x4e, - 0x89, 0x5b, 0xb9, 0x70, 0x53, 0x62, 0xd7, 0x76, - 0xdd, 0x52, 0x57, 0x65, 0x97, 0x5f, 0xef, 0x53, - 0x38, 0x4e, 0x05, 0x00, 0x09, 0x22, 0x01, 0x60, - 0x4f, 0xae, 0x4f, 0xbb, 0x4f, 0x02, 0x50, 0x7a, - 0x50, 0x99, 0x50, 0xe7, 0x50, 0xcf, 0x50, 0x9e, - 0x34, 0x3a, 0x06, 0x4d, 0x51, 0x54, 0x51, 0x64, - 0x51, 0x77, 0x51, 0x1c, 0x05, 0xb9, 0x34, 0x67, - 0x51, 0x8d, 0x51, 0x4b, 0x05, 0x97, 0x51, 0xa4, - 0x51, 0xcc, 0x4e, 0xac, 0x51, 0xb5, 0x51, 0xdf, - 0x91, 0xf5, 0x51, 0x03, 0x52, 0xdf, 0x34, 0x3b, - 0x52, 0x46, 0x52, 0x72, 0x52, 0x77, 0x52, 0x15, - 0x35, 0x02, 0x00, 0x20, 0x80, 0x80, 0x00, 0x08, - 0x00, 0x00, 0xc7, 0x52, 0x00, 0x02, 0x1d, 0x33, - 0x3e, 0x3f, 0x50, 0x82, 0x8a, 0x93, 0xac, 0xb6, - 0xb8, 0xb8, 0xb8, 0x2c, 0x0a, 0x70, 0x70, 0xca, - 0x53, 0xdf, 0x53, 0x63, 0x0b, 0xeb, 0x53, 0xf1, - 0x53, 0x06, 0x54, 0x9e, 0x54, 0x38, 0x54, 0x48, - 0x54, 0x68, 0x54, 0xa2, 0x54, 0xf6, 0x54, 0x10, - 0x55, 0x53, 0x55, 0x63, 0x55, 0x84, 0x55, 0x84, - 0x55, 0x99, 0x55, 0xab, 0x55, 0xb3, 0x55, 0xc2, - 0x55, 0x16, 0x57, 0x06, 0x56, 0x17, 0x57, 0x51, - 0x56, 0x74, 0x56, 0x07, 0x52, 0xee, 0x58, 0xce, - 0x57, 0xf4, 0x57, 0x0d, 0x58, 0x8b, 0x57, 0x32, - 0x58, 0x31, 0x58, 0xac, 0x58, 0xe4, 0x14, 0xf2, - 0x58, 0xf7, 0x58, 0x06, 0x59, 0x1a, 0x59, 0x22, - 0x59, 0x62, 0x59, 0xa8, 0x16, 0xea, 0x16, 0xec, - 0x59, 0x1b, 0x5a, 0x27, 0x5a, 0xd8, 0x59, 0x66, - 0x5a, 0xee, 0x36, 0xfc, 0x36, 0x08, 0x5b, 0x3e, - 0x5b, 0x3e, 0x5b, 0xc8, 0x19, 0xc3, 0x5b, 0xd8, - 0x5b, 0xe7, 0x5b, 0xf3, 0x5b, 0x18, 0x1b, 0xff, - 0x5b, 0x06, 0x5c, 0x53, 0x5f, 0x22, 0x5c, 0x81, - 0x37, 0x60, 0x5c, 0x6e, 0x5c, 0xc0, 0x5c, 0x8d, - 0x5c, 0xe4, 0x1d, 0x43, 0x5d, 0xe6, 0x1d, 0x6e, - 0x5d, 0x6b, 0x5d, 0x7c, 0x5d, 0xe1, 0x5d, 0xe2, - 0x5d, 0x2f, 0x38, 0xfd, 0x5d, 0x28, 0x5e, 0x3d, - 0x5e, 0x69, 0x5e, 0x62, 0x38, 0x83, 0x21, 0x7c, - 0x38, 0xb0, 0x5e, 0xb3, 0x5e, 0xb6, 0x5e, 0xca, - 0x5e, 0x92, 0xa3, 0xfe, 0x5e, 0x31, 0x23, 0x31, - 0x23, 0x01, 0x82, 0x22, 0x5f, 0x22, 0x5f, 0xc7, - 0x38, 0xb8, 0x32, 0xda, 0x61, 0x62, 0x5f, 0x6b, - 0x5f, 0xe3, 0x38, 0x9a, 0x5f, 0xcd, 0x5f, 0xd7, - 0x5f, 0xf9, 0x5f, 0x81, 0x60, 0x3a, 0x39, 0x1c, - 0x39, 0x94, 0x60, 0xd4, 0x26, 0xc7, 0x60, 0x02, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x0a, 0x00, 0x00, 0x02, 0x08, 0x00, - 0x80, 0x08, 0x00, 0x00, 0x08, 0x80, 0x28, 0x80, - 0x02, 0x00, 0x00, 0x02, 0x48, 0x61, 0x00, 0x04, - 0x06, 0x04, 0x32, 0x46, 0x6a, 0x5c, 0x67, 0x96, - 0xaa, 0xae, 0xc8, 0xd3, 0x5d, 0x62, 0x00, 0x54, - 0x77, 0xf3, 0x0c, 0x2b, 0x3d, 0x63, 0xfc, 0x62, - 0x68, 0x63, 0x83, 0x63, 0xe4, 0x63, 0xf1, 0x2b, - 0x22, 0x64, 0xc5, 0x63, 0xa9, 0x63, 0x2e, 0x3a, - 0x69, 0x64, 0x7e, 0x64, 0x9d, 0x64, 0x77, 0x64, - 0x6c, 0x3a, 0x4f, 0x65, 0x6c, 0x65, 0x0a, 0x30, - 0xe3, 0x65, 0xf8, 0x66, 0x49, 0x66, 0x19, 0x3b, - 0x91, 0x66, 0x08, 0x3b, 0xe4, 0x3a, 0x92, 0x51, - 0x95, 0x51, 0x00, 0x67, 0x9c, 0x66, 0xad, 0x80, - 0xd9, 0x43, 0x17, 0x67, 0x1b, 0x67, 0x21, 0x67, - 0x5e, 0x67, 0x53, 0x67, 0xc3, 0x33, 0x49, 0x3b, - 0xfa, 0x67, 0x85, 0x67, 0x52, 0x68, 0x85, 0x68, - 0x6d, 0x34, 0x8e, 0x68, 0x1f, 0x68, 0x14, 0x69, - 0x9d, 0x3b, 0x42, 0x69, 0xa3, 0x69, 0xea, 0x69, - 0xa8, 0x6a, 0xa3, 0x36, 0xdb, 0x6a, 0x18, 0x3c, - 0x21, 0x6b, 0xa7, 0x38, 0x54, 0x6b, 0x4e, 0x3c, - 0x72, 0x6b, 0x9f, 0x6b, 0xba, 0x6b, 0xbb, 0x6b, - 0x8d, 0x3a, 0x0b, 0x1d, 0xfa, 0x3a, 0x4e, 0x6c, - 0xbc, 0x3c, 0xbf, 0x6c, 0xcd, 0x6c, 0x67, 0x6c, - 0x16, 0x6d, 0x3e, 0x6d, 0x77, 0x6d, 0x41, 0x6d, - 0x69, 0x6d, 0x78, 0x6d, 0x85, 0x6d, 0x1e, 0x3d, - 0x34, 0x6d, 0x2f, 0x6e, 0x6e, 0x6e, 0x33, 0x3d, - 0xcb, 0x6e, 0xc7, 0x6e, 0xd1, 0x3e, 0xf9, 0x6d, - 0x6e, 0x6f, 0x5e, 0x3f, 0x8e, 0x3f, 0xc6, 0x6f, - 0x39, 0x70, 0x1e, 0x70, 0x1b, 0x70, 0x96, 0x3d, - 0x4a, 0x70, 0x7d, 0x70, 0x77, 0x70, 0xad, 0x70, - 0x25, 0x05, 0x45, 0x71, 0x63, 0x42, 0x9c, 0x71, - 0xab, 0x43, 0x28, 0x72, 0x35, 0x72, 0x50, 0x72, - 0x08, 0x46, 0x80, 0x72, 0x95, 0x72, 0x35, 0x47, - 0x02, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, - 0x00, 0x08, 0x80, 0x00, 0x00, 0x02, 0x02, 0x80, - 0x8a, 0x00, 0x00, 0x20, 0x00, 0x08, 0x0a, 0x00, - 0x80, 0x88, 0x80, 0x20, 0x14, 0x48, 0x7a, 0x73, - 0x8b, 0x73, 0xac, 0x3e, 0xa5, 0x73, 0xb8, 0x3e, - 0xb8, 0x3e, 0x47, 0x74, 0x5c, 0x74, 0x71, 0x74, - 0x85, 0x74, 0xca, 0x74, 0x1b, 0x3f, 0x24, 0x75, - 0x36, 0x4c, 0x3e, 0x75, 0x92, 0x4c, 0x70, 0x75, - 0x9f, 0x21, 0x10, 0x76, 0xa1, 0x4f, 0xb8, 0x4f, - 0x44, 0x50, 0xfc, 0x3f, 0x08, 0x40, 0xf4, 0x76, - 0xf3, 0x50, 0xf2, 0x50, 0x19, 0x51, 0x33, 0x51, - 0x1e, 0x77, 0x1f, 0x77, 0x1f, 0x77, 0x4a, 0x77, - 0x39, 0x40, 0x8b, 0x77, 0x46, 0x40, 0x96, 0x40, - 0x1d, 0x54, 0x4e, 0x78, 0x8c, 0x78, 0xcc, 0x78, - 0xe3, 0x40, 0x26, 0x56, 0x56, 0x79, 0x9a, 0x56, - 0xc5, 0x56, 0x8f, 0x79, 0xeb, 0x79, 0x2f, 0x41, - 0x40, 0x7a, 0x4a, 0x7a, 0x4f, 0x7a, 0x7c, 0x59, - 0xa7, 0x5a, 0xa7, 0x5a, 0xee, 0x7a, 0x02, 0x42, - 0xab, 0x5b, 0xc6, 0x7b, 0xc9, 0x7b, 0x27, 0x42, - 0x80, 0x5c, 0xd2, 0x7c, 0xa0, 0x42, 0xe8, 0x7c, - 0xe3, 0x7c, 0x00, 0x7d, 0x86, 0x5f, 0x63, 0x7d, - 0x01, 0x43, 0xc7, 0x7d, 0x02, 0x7e, 0x45, 0x7e, - 0x34, 0x43, 0x28, 0x62, 0x47, 0x62, 0x59, 0x43, - 0xd9, 0x62, 0x7a, 0x7f, 0x3e, 0x63, 0x95, 0x7f, - 0xfa, 0x7f, 0x05, 0x80, 0xda, 0x64, 0x23, 0x65, - 0x60, 0x80, 0xa8, 0x65, 0x70, 0x80, 0x5f, 0x33, - 0xd5, 0x43, 0xb2, 0x80, 0x03, 0x81, 0x0b, 0x44, - 0x3e, 0x81, 0xb5, 0x5a, 0xa7, 0x67, 0xb5, 0x67, - 0x93, 0x33, 0x9c, 0x33, 0x01, 0x82, 0x04, 0x82, - 0x9e, 0x8f, 0x6b, 0x44, 0x91, 0x82, 0x8b, 0x82, - 0x9d, 0x82, 0xb3, 0x52, 0xb1, 0x82, 0xb3, 0x82, - 0xbd, 0x82, 0xe6, 0x82, 0x3c, 0x6b, 0xe5, 0x82, - 0x1d, 0x83, 0x63, 0x83, 0xad, 0x83, 0x23, 0x83, - 0xbd, 0x83, 0xe7, 0x83, 0x57, 0x84, 0x53, 0x83, - 0xca, 0x83, 0xcc, 0x83, 0xdc, 0x83, 0x36, 0x6c, - 0x6b, 0x6d, 0x02, 0x00, 0x00, 0x20, 0x22, 0x2a, - 0xa0, 0x0a, 0x00, 0x20, 0x80, 0x28, 0x00, 0xa8, - 0x20, 0x20, 0x00, 0x02, 0x80, 0x22, 0x02, 0x8a, - 0x08, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x28, 0xd5, 0x6c, 0x2b, 0x45, 0xf1, 0x84, - 0xf3, 0x84, 0x16, 0x85, 0xca, 0x73, 0x64, 0x85, - 0x2c, 0x6f, 0x5d, 0x45, 0x61, 0x45, 0xb1, 0x6f, - 0xd2, 0x70, 0x6b, 0x45, 0x50, 0x86, 0x5c, 0x86, - 0x67, 0x86, 0x69, 0x86, 0xa9, 0x86, 0x88, 0x86, - 0x0e, 0x87, 0xe2, 0x86, 0x79, 0x87, 0x28, 0x87, - 0x6b, 0x87, 0x86, 0x87, 0xd7, 0x45, 0xe1, 0x87, - 0x01, 0x88, 0xf9, 0x45, 0x60, 0x88, 0x63, 0x88, - 0x67, 0x76, 0xd7, 0x88, 0xde, 0x88, 0x35, 0x46, - 0xfa, 0x88, 0xbb, 0x34, 0xae, 0x78, 0x66, 0x79, - 0xbe, 0x46, 0xc7, 0x46, 0xa0, 0x8a, 0xed, 0x8a, - 0x8a, 0x8b, 0x55, 0x8c, 0xa8, 0x7c, 0xab, 0x8c, - 0xc1, 0x8c, 0x1b, 0x8d, 0x77, 0x8d, 0x2f, 0x7f, - 0x04, 0x08, 0xcb, 0x8d, 0xbc, 0x8d, 0xf0, 0x8d, - 0xde, 0x08, 0xd4, 0x8e, 0x38, 0x8f, 0xd2, 0x85, - 0xed, 0x85, 0x94, 0x90, 0xf1, 0x90, 0x11, 0x91, - 0x2e, 0x87, 0x1b, 0x91, 0x38, 0x92, 0xd7, 0x92, - 0xd8, 0x92, 0x7c, 0x92, 0xf9, 0x93, 0x15, 0x94, - 0xfa, 0x8b, 0x8b, 0x95, 0x95, 0x49, 0xb7, 0x95, - 0x77, 0x8d, 0xe6, 0x49, 0xc3, 0x96, 0xb2, 0x5d, - 0x23, 0x97, 0x45, 0x91, 0x1a, 0x92, 0x6e, 0x4a, - 0x76, 0x4a, 0xe0, 0x97, 0x0a, 0x94, 0xb2, 0x4a, - 0x96, 0x94, 0x0b, 0x98, 0x0b, 0x98, 0x29, 0x98, - 0xb6, 0x95, 0xe2, 0x98, 0x33, 0x4b, 0x29, 0x99, - 0xa7, 0x99, 0xc2, 0x99, 0xfe, 0x99, 0xce, 0x4b, - 0x30, 0x9b, 0x12, 0x9b, 0x40, 0x9c, 0xfd, 0x9c, - 0xce, 0x4c, 0xed, 0x4c, 0x67, 0x9d, 0xce, 0xa0, - 0xf8, 0x4c, 0x05, 0xa1, 0x0e, 0xa2, 0x91, 0xa2, - 0xbb, 0x9e, 0x56, 0x4d, 0xf9, 0x9e, 0xfe, 0x9e, - 0x05, 0x9f, 0x0f, 0x9f, 0x16, 0x9f, 0x3b, 0x9f, - 0x00, 0xa6, 0x02, 0x88, 0xa0, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x28, 0x00, 0x08, 0xa0, 0x80, - 0xa0, 0x80, 0x00, 0x80, 0x80, 0x00, 0x0a, 0x88, - 0x80, 0x00, 0x80, 0x00, 0x20, 0x2a, 0x00, 0x80, + 0x0c, 0x0e, 0x10, 0x44, 0x90, 0x77, 0x45, 0x28, + 0x06, 0x2c, 0x06, 0x00, 0x00, 0x47, 0x06, 0x33, + 0x06, 0x17, 0x10, 0x11, 0x12, 0x13, 0x00, 0x06, + 0x0e, 0x02, 0x0f, 0x34, 0x06, 0x2a, 0x06, 0x2b, + 0x06, 0x2e, 0x06, 0x00, 0x00, 0x36, 0x06, 0x00, + 0x00, 0x3a, 0x06, 0x2d, 0x06, 0x00, 0x00, 0x4a, + 0x06, 0x00, 0x00, 0x44, 0x06, 0x00, 0x00, 0x46, + 0x06, 0x33, 0x06, 0x39, 0x06, 0x00, 0x00, 0x35, + 0x06, 0x42, 0x06, 0x00, 0x00, 0x34, 0x06, 0x00, + 0x00, 0x00, 0x00, 0x2e, 0x06, 0x00, 0x00, 0x36, + 0x06, 0x00, 0x00, 0x3a, 0x06, 0x00, 0x00, 0xba, + 0x06, 0x00, 0x00, 0x6f, 0x06, 0x00, 0x00, 0x28, + 0x06, 0x2c, 0x06, 0x00, 0x00, 0x47, 0x06, 0x00, + 0x00, 0x00, 0x00, 0x2d, 0x06, 0x37, 0x06, 0x4a, + 0x06, 0x43, 0x06, 0x00, 0x00, 0x45, 0x06, 0x46, + 0x06, 0x33, 0x06, 0x39, 0x06, 0x41, 0x06, 0x35, + 0x06, 0x42, 0x06, 0x00, 0x00, 0x34, 0x06, 0x2a, + 0x06, 0x2b, 0x06, 0x2e, 0x06, 0x00, 0x00, 0x36, + 0x06, 0x38, 0x06, 0x3a, 0x06, 0x6e, 0x06, 0x00, + 0x00, 0xa1, 0x06, 0x27, 0x06, 0x00, 0x01, 0x05, + 0x08, 0x20, 0x21, 0x0b, 0x06, 0x10, 0x23, 0x2a, + 0x06, 0x1a, 0x1b, 0x1c, 0x09, 0x0f, 0x17, 0x0b, + 0x18, 0x07, 0x0a, 0x00, 0x01, 0x04, 0x06, 0x0c, + 0x0e, 0x10, 0x28, 0x06, 0x2c, 0x06, 0x2f, 0x06, + 0x00, 0x00, 0x48, 0x06, 0x32, 0x06, 0x2d, 0x06, + 0x37, 0x06, 0x4a, 0x06, 0x2a, 0x06, 0x1a, 0x1b, + 0x1c, 0x09, 0x0f, 0x17, 0x0b, 0x18, 0x07, 0x0a, + 0x00, 0x01, 0x04, 0x06, 0x0c, 0x0e, 0x10, 0x30, + 0x2e, 0x30, 0x00, 0x2c, 0x00, 0x28, 0x00, 0x41, + 0x00, 0x29, 0x00, 0x14, 0x30, 0x53, 0x00, 0x15, + 0x30, 0x43, 0x52, 0x43, 0x44, 0x57, 0x5a, 0x41, + 0x00, 0x48, 0x56, 0x4d, 0x56, 0x53, 0x44, 0x53, + 0x53, 0x50, 0x50, 0x56, 0x57, 0x43, 0x4d, 0x43, + 0x4d, 0x44, 0x4d, 0x52, 0x44, 0x4a, 0x4b, 0x30, + 0x30, 0x00, 0x68, 0x68, 0x4b, 0x62, 0x57, 0x5b, + 0xcc, 0x53, 0xc7, 0x30, 0x8c, 0x4e, 0x1a, 0x59, + 0xe3, 0x89, 0x29, 0x59, 0xa4, 0x4e, 0x20, 0x66, + 0x21, 0x71, 0x99, 0x65, 0x4d, 0x52, 0x8c, 0x5f, + 0x8d, 0x51, 0xb0, 0x65, 0x1d, 0x52, 0x42, 0x7d, + 0x1f, 0x75, 0xa9, 0x8c, 0xf0, 0x58, 0x39, 0x54, + 0x14, 0x6f, 0x95, 0x62, 0x55, 0x63, 0x00, 0x4e, + 0x09, 0x4e, 0x4a, 0x90, 0xe6, 0x5d, 0x2d, 0x4e, + 0xf3, 0x53, 0x07, 0x63, 0x70, 0x8d, 0x53, 0x62, + 0x81, 0x79, 0x7a, 0x7a, 0x08, 0x54, 0x80, 0x6e, + 0x09, 0x67, 0x08, 0x67, 0x33, 0x75, 0x72, 0x52, + 0xb6, 0x55, 0x4d, 0x91, 0x14, 0x30, 0x15, 0x30, + 0x2c, 0x67, 0x09, 0x4e, 0x8c, 0x4e, 0x89, 0x5b, + 0xb9, 0x70, 0x53, 0x62, 0xd7, 0x76, 0xdd, 0x52, + 0x57, 0x65, 0x97, 0x5f, 0xef, 0x53, 0x38, 0x4e, + 0x05, 0x00, 0x09, 0x22, 0x01, 0x60, 0x4f, 0xae, + 0x4f, 0xbb, 0x4f, 0x02, 0x50, 0x7a, 0x50, 0x99, + 0x50, 0xe7, 0x50, 0xcf, 0x50, 0x9e, 0x34, 0x3a, + 0x06, 0x4d, 0x51, 0x54, 0x51, 0x64, 0x51, 0x77, + 0x51, 0x1c, 0x05, 0xb9, 0x34, 0x67, 0x51, 0x8d, + 0x51, 0x4b, 0x05, 0x97, 0x51, 0xa4, 0x51, 0xcc, + 0x4e, 0xac, 0x51, 0xb5, 0x51, 0xdf, 0x91, 0xf5, + 0x51, 0x03, 0x52, 0xdf, 0x34, 0x3b, 0x52, 0x46, + 0x52, 0x72, 0x52, 0x77, 0x52, 0x15, 0x35, 0x02, + 0x00, 0x20, 0x80, 0x80, 0x00, 0x08, 0x00, 0x00, + 0xc7, 0x52, 0x00, 0x02, 0x1d, 0x33, 0x3e, 0x3f, + 0x50, 0x82, 0x8a, 0x93, 0xac, 0xb6, 0xb8, 0xb8, + 0xb8, 0x2c, 0x0a, 0x70, 0x70, 0xca, 0x53, 0xdf, + 0x53, 0x63, 0x0b, 0xeb, 0x53, 0xf1, 0x53, 0x06, + 0x54, 0x9e, 0x54, 0x38, 0x54, 0x48, 0x54, 0x68, + 0x54, 0xa2, 0x54, 0xf6, 0x54, 0x10, 0x55, 0x53, + 0x55, 0x63, 0x55, 0x84, 0x55, 0x84, 0x55, 0x99, + 0x55, 0xab, 0x55, 0xb3, 0x55, 0xc2, 0x55, 0x16, + 0x57, 0x06, 0x56, 0x17, 0x57, 0x51, 0x56, 0x74, + 0x56, 0x07, 0x52, 0xee, 0x58, 0xce, 0x57, 0xf4, + 0x57, 0x0d, 0x58, 0x8b, 0x57, 0x32, 0x58, 0x31, + 0x58, 0xac, 0x58, 0xe4, 0x14, 0xf2, 0x58, 0xf7, + 0x58, 0x06, 0x59, 0x1a, 0x59, 0x22, 0x59, 0x62, + 0x59, 0xa8, 0x16, 0xea, 0x16, 0xec, 0x59, 0x1b, + 0x5a, 0x27, 0x5a, 0xd8, 0x59, 0x66, 0x5a, 0xee, + 0x36, 0xfc, 0x36, 0x08, 0x5b, 0x3e, 0x5b, 0x3e, + 0x5b, 0xc8, 0x19, 0xc3, 0x5b, 0xd8, 0x5b, 0xe7, + 0x5b, 0xf3, 0x5b, 0x18, 0x1b, 0xff, 0x5b, 0x06, + 0x5c, 0x53, 0x5f, 0x22, 0x5c, 0x81, 0x37, 0x60, + 0x5c, 0x6e, 0x5c, 0xc0, 0x5c, 0x8d, 0x5c, 0xe4, + 0x1d, 0x43, 0x5d, 0xe6, 0x1d, 0x6e, 0x5d, 0x6b, + 0x5d, 0x7c, 0x5d, 0xe1, 0x5d, 0xe2, 0x5d, 0x2f, + 0x38, 0xfd, 0x5d, 0x28, 0x5e, 0x3d, 0x5e, 0x69, + 0x5e, 0x62, 0x38, 0x83, 0x21, 0x7c, 0x38, 0xb0, + 0x5e, 0xb3, 0x5e, 0xb6, 0x5e, 0xca, 0x5e, 0x92, + 0xa3, 0xfe, 0x5e, 0x31, 0x23, 0x31, 0x23, 0x01, + 0x82, 0x22, 0x5f, 0x22, 0x5f, 0xc7, 0x38, 0xb8, + 0x32, 0xda, 0x61, 0x62, 0x5f, 0x6b, 0x5f, 0xe3, + 0x38, 0x9a, 0x5f, 0xcd, 0x5f, 0xd7, 0x5f, 0xf9, + 0x5f, 0x81, 0x60, 0x3a, 0x39, 0x1c, 0x39, 0x94, + 0x60, 0xd4, 0x26, 0xc7, 0x60, 0x02, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x0a, 0x00, 0x00, 0x02, 0x08, 0x00, 0x80, 0x08, + 0x00, 0x00, 0x08, 0x80, 0x28, 0x80, 0x02, 0x00, + 0x00, 0x02, 0x48, 0x61, 0x00, 0x04, 0x06, 0x04, + 0x32, 0x46, 0x6a, 0x5c, 0x67, 0x96, 0xaa, 0xae, + 0xc8, 0xd3, 0x5d, 0x62, 0x00, 0x54, 0x77, 0xf3, + 0x0c, 0x2b, 0x3d, 0x63, 0xfc, 0x62, 0x68, 0x63, + 0x83, 0x63, 0xe4, 0x63, 0xf1, 0x2b, 0x22, 0x64, + 0xc5, 0x63, 0xa9, 0x63, 0x2e, 0x3a, 0x69, 0x64, + 0x7e, 0x64, 0x9d, 0x64, 0x77, 0x64, 0x6c, 0x3a, + 0x4f, 0x65, 0x6c, 0x65, 0x0a, 0x30, 0xe3, 0x65, + 0xf8, 0x66, 0x49, 0x66, 0x19, 0x3b, 0x91, 0x66, + 0x08, 0x3b, 0xe4, 0x3a, 0x92, 0x51, 0x95, 0x51, + 0x00, 0x67, 0x9c, 0x66, 0xad, 0x80, 0xd9, 0x43, + 0x17, 0x67, 0x1b, 0x67, 0x21, 0x67, 0x5e, 0x67, + 0x53, 0x67, 0xc3, 0x33, 0x49, 0x3b, 0xfa, 0x67, + 0x85, 0x67, 0x52, 0x68, 0x85, 0x68, 0x6d, 0x34, + 0x8e, 0x68, 0x1f, 0x68, 0x14, 0x69, 0x9d, 0x3b, + 0x42, 0x69, 0xa3, 0x69, 0xea, 0x69, 0xa8, 0x6a, + 0xa3, 0x36, 0xdb, 0x6a, 0x18, 0x3c, 0x21, 0x6b, + 0xa7, 0x38, 0x54, 0x6b, 0x4e, 0x3c, 0x72, 0x6b, + 0x9f, 0x6b, 0xba, 0x6b, 0xbb, 0x6b, 0x8d, 0x3a, + 0x0b, 0x1d, 0xfa, 0x3a, 0x4e, 0x6c, 0xbc, 0x3c, + 0xbf, 0x6c, 0xcd, 0x6c, 0x67, 0x6c, 0x16, 0x6d, + 0x3e, 0x6d, 0x77, 0x6d, 0x41, 0x6d, 0x69, 0x6d, + 0x78, 0x6d, 0x85, 0x6d, 0x1e, 0x3d, 0x34, 0x6d, + 0x2f, 0x6e, 0x6e, 0x6e, 0x33, 0x3d, 0xcb, 0x6e, + 0xc7, 0x6e, 0xd1, 0x3e, 0xf9, 0x6d, 0x6e, 0x6f, + 0x5e, 0x3f, 0x8e, 0x3f, 0xc6, 0x6f, 0x39, 0x70, + 0x1e, 0x70, 0x1b, 0x70, 0x96, 0x3d, 0x4a, 0x70, + 0x7d, 0x70, 0x77, 0x70, 0xad, 0x70, 0x25, 0x05, + 0x45, 0x71, 0x63, 0x42, 0x9c, 0x71, 0xab, 0x43, + 0x28, 0x72, 0x35, 0x72, 0x50, 0x72, 0x08, 0x46, + 0x80, 0x72, 0x95, 0x72, 0x35, 0x47, 0x02, 0x20, + 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x80, 0x00, 0x00, 0x02, 0x02, 0x80, 0x8a, 0x00, + 0x00, 0x20, 0x00, 0x08, 0x0a, 0x00, 0x80, 0x88, + 0x80, 0x20, 0x14, 0x48, 0x7a, 0x73, 0x8b, 0x73, + 0xac, 0x3e, 0xa5, 0x73, 0xb8, 0x3e, 0xb8, 0x3e, + 0x47, 0x74, 0x5c, 0x74, 0x71, 0x74, 0x85, 0x74, + 0xca, 0x74, 0x1b, 0x3f, 0x24, 0x75, 0x36, 0x4c, + 0x3e, 0x75, 0x92, 0x4c, 0x70, 0x75, 0x9f, 0x21, + 0x10, 0x76, 0xa1, 0x4f, 0xb8, 0x4f, 0x44, 0x50, + 0xfc, 0x3f, 0x08, 0x40, 0xf4, 0x76, 0xf3, 0x50, + 0xf2, 0x50, 0x19, 0x51, 0x33, 0x51, 0x1e, 0x77, + 0x1f, 0x77, 0x1f, 0x77, 0x4a, 0x77, 0x39, 0x40, + 0x8b, 0x77, 0x46, 0x40, 0x96, 0x40, 0x1d, 0x54, + 0x4e, 0x78, 0x8c, 0x78, 0xcc, 0x78, 0xe3, 0x40, + 0x26, 0x56, 0x56, 0x79, 0x9a, 0x56, 0xc5, 0x56, + 0x8f, 0x79, 0xeb, 0x79, 0x2f, 0x41, 0x40, 0x7a, + 0x4a, 0x7a, 0x4f, 0x7a, 0x7c, 0x59, 0xa7, 0x5a, + 0xa7, 0x5a, 0xee, 0x7a, 0x02, 0x42, 0xab, 0x5b, + 0xc6, 0x7b, 0xc9, 0x7b, 0x27, 0x42, 0x80, 0x5c, + 0xd2, 0x7c, 0xa0, 0x42, 0xe8, 0x7c, 0xe3, 0x7c, + 0x00, 0x7d, 0x86, 0x5f, 0x63, 0x7d, 0x01, 0x43, + 0xc7, 0x7d, 0x02, 0x7e, 0x45, 0x7e, 0x34, 0x43, + 0x28, 0x62, 0x47, 0x62, 0x59, 0x43, 0xd9, 0x62, + 0x7a, 0x7f, 0x3e, 0x63, 0x95, 0x7f, 0xfa, 0x7f, + 0x05, 0x80, 0xda, 0x64, 0x23, 0x65, 0x60, 0x80, + 0xa8, 0x65, 0x70, 0x80, 0x5f, 0x33, 0xd5, 0x43, + 0xb2, 0x80, 0x03, 0x81, 0x0b, 0x44, 0x3e, 0x81, + 0xb5, 0x5a, 0xa7, 0x67, 0xb5, 0x67, 0x93, 0x33, + 0x9c, 0x33, 0x01, 0x82, 0x04, 0x82, 0x9e, 0x8f, + 0x6b, 0x44, 0x91, 0x82, 0x8b, 0x82, 0x9d, 0x82, + 0xb3, 0x52, 0xb1, 0x82, 0xb3, 0x82, 0xbd, 0x82, + 0xe6, 0x82, 0x3c, 0x6b, 0xe5, 0x82, 0x1d, 0x83, + 0x63, 0x83, 0xad, 0x83, 0x23, 0x83, 0xbd, 0x83, + 0xe7, 0x83, 0x57, 0x84, 0x53, 0x83, 0xca, 0x83, + 0xcc, 0x83, 0xdc, 0x83, 0x36, 0x6c, 0x6b, 0x6d, + 0x02, 0x00, 0x00, 0x20, 0x22, 0x2a, 0xa0, 0x0a, + 0x00, 0x20, 0x80, 0x28, 0x00, 0xa8, 0x20, 0x20, + 0x00, 0x02, 0x80, 0x22, 0x02, 0x8a, 0x08, 0x00, + 0xaa, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x28, + 0xd5, 0x6c, 0x2b, 0x45, 0xf1, 0x84, 0xf3, 0x84, + 0x16, 0x85, 0xca, 0x73, 0x64, 0x85, 0x2c, 0x6f, + 0x5d, 0x45, 0x61, 0x45, 0xb1, 0x6f, 0xd2, 0x70, + 0x6b, 0x45, 0x50, 0x86, 0x5c, 0x86, 0x67, 0x86, + 0x69, 0x86, 0xa9, 0x86, 0x88, 0x86, 0x0e, 0x87, + 0xe2, 0x86, 0x79, 0x87, 0x28, 0x87, 0x6b, 0x87, + 0x86, 0x87, 0xd7, 0x45, 0xe1, 0x87, 0x01, 0x88, + 0xf9, 0x45, 0x60, 0x88, 0x63, 0x88, 0x67, 0x76, + 0xd7, 0x88, 0xde, 0x88, 0x35, 0x46, 0xfa, 0x88, + 0xbb, 0x34, 0xae, 0x78, 0x66, 0x79, 0xbe, 0x46, + 0xc7, 0x46, 0xa0, 0x8a, 0xed, 0x8a, 0x8a, 0x8b, + 0x55, 0x8c, 0xa8, 0x7c, 0xab, 0x8c, 0xc1, 0x8c, + 0x1b, 0x8d, 0x77, 0x8d, 0x2f, 0x7f, 0x04, 0x08, + 0xcb, 0x8d, 0xbc, 0x8d, 0xf0, 0x8d, 0xde, 0x08, + 0xd4, 0x8e, 0x38, 0x8f, 0xd2, 0x85, 0xed, 0x85, + 0x94, 0x90, 0xf1, 0x90, 0x11, 0x91, 0x2e, 0x87, + 0x1b, 0x91, 0x38, 0x92, 0xd7, 0x92, 0xd8, 0x92, + 0x7c, 0x92, 0xf9, 0x93, 0x15, 0x94, 0xfa, 0x8b, + 0x8b, 0x95, 0x95, 0x49, 0xb7, 0x95, 0x77, 0x8d, + 0xe6, 0x49, 0xc3, 0x96, 0xb2, 0x5d, 0x23, 0x97, + 0x45, 0x91, 0x1a, 0x92, 0x6e, 0x4a, 0x76, 0x4a, + 0xe0, 0x97, 0x0a, 0x94, 0xb2, 0x4a, 0x96, 0x94, + 0x0b, 0x98, 0x0b, 0x98, 0x29, 0x98, 0xb6, 0x95, + 0xe2, 0x98, 0x33, 0x4b, 0x29, 0x99, 0xa7, 0x99, + 0xc2, 0x99, 0xfe, 0x99, 0xce, 0x4b, 0x30, 0x9b, + 0x12, 0x9b, 0x40, 0x9c, 0xfd, 0x9c, 0xce, 0x4c, + 0xed, 0x4c, 0x67, 0x9d, 0xce, 0xa0, 0xf8, 0x4c, + 0x05, 0xa1, 0x0e, 0xa2, 0x91, 0xa2, 0xbb, 0x9e, + 0x56, 0x4d, 0xf9, 0x9e, 0xfe, 0x9e, 0x05, 0x9f, + 0x0f, 0x9f, 0x16, 0x9f, 0x3b, 0x9f, 0x00, 0xa6, + 0x02, 0x88, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0x28, 0x00, 0x08, 0xa0, 0x80, 0xa0, 0x80, + 0x00, 0x80, 0x80, 0x00, 0x0a, 0x88, 0x80, 0x00, + 0x80, 0x00, 0x20, 0x2a, 0x00, 0x80, }; static const uint16_t unicode_comp_table[944] = { @@ -2162,8 +2173,8 @@ static const uint16_t unicode_comp_table[944] = { 0x5704, 0x5706, 0x5708, 0x570a, 0x570c, 0x570e, 0x5710, 0x5712, 0x5714, 0x5716, 0x5740, 0x5742, 0x5744, 0x5780, 0x5781, 0x57c0, 0x57c1, 0x5800, 0x5801, 0x5840, 0x5841, 0x5880, 0x5881, 0x5900, - 0x5901, 0x5902, 0x5903, 0x5940, 0x8e00, 0x8e02, 0x8e40, 0x8e80, - 0x8e81, 0x8ec0, 0x8ec1, 0x8f01, 0x8f00, 0x8f03, 0x8f40, 0x8f41, + 0x5901, 0x5902, 0x5903, 0x5940, 0x8e40, 0x8e42, 0x8e80, 0x8ec0, + 0x8ec1, 0x8f00, 0x8f01, 0x8f41, 0x8f40, 0x8f43, 0x8f80, 0x8f81, }; typedef enum { @@ -2249,7 +2260,7 @@ static const char unicode_gc_name_table[] = "C,Other" "\0" ; -static const uint8_t unicode_gc_table[3655] = { +static const uint8_t unicode_gc_table[3719] = { 0xfa, 0x18, 0x17, 0x56, 0x0d, 0x56, 0x12, 0x13, 0x16, 0x0c, 0x16, 0x11, 0x36, 0xe9, 0x02, 0x36, 0x4c, 0x36, 0xe1, 0x12, 0x12, 0x16, 0x13, 0x0e, @@ -2329,7 +2340,7 @@ static const uint8_t unicode_gc_table[3655] = { 0x00, 0xe5, 0x0f, 0x00, 0xe5, 0x08, 0x40, 0x05, 0x46, 0x67, 0x00, 0x46, 0x00, 0x66, 0xc0, 0x26, 0x00, 0x45, 0x80, 0x25, 0x26, 0x20, 0xe9, 0x02, - 0xe0, 0x00, 0xcb, 0x0f, 0x05, 0x06, 0x27, 0x16, + 0xc0, 0x16, 0xcb, 0x0f, 0x05, 0x06, 0x27, 0x16, 0xe5, 0x00, 0x00, 0x45, 0x00, 0xe5, 0x0f, 0x00, 0xe5, 0x02, 0x00, 0x85, 0x20, 0x06, 0x05, 0x07, 0x06, 0x87, 0x00, 0x06, 0x27, 0x00, 0x27, 0x26, @@ -2345,260 +2356,259 @@ static const uint8_t unicode_gc_table[3655] = { 0x00, 0xa0, 0xe9, 0x02, 0x20, 0x27, 0x16, 0xe0, 0x04, 0xe5, 0x28, 0x06, 0x25, 0xc6, 0x60, 0x0d, 0xa5, 0x04, 0xe6, 0x00, 0x16, 0xe9, 0x02, 0x36, - 0xe0, 0x1d, 0x25, 0x00, 0x05, 0x20, 0x25, 0x00, - 0x05, 0x20, 0x05, 0xa0, 0x65, 0x00, 0xc5, 0x00, - 0x45, 0x00, 0x05, 0x00, 0x05, 0x20, 0x25, 0x00, - 0x65, 0x06, 0x25, 0xa6, 0x00, 0x26, 0x05, 0x20, - 0x85, 0x00, 0x04, 0x00, 0xa6, 0x20, 0xe9, 0x02, - 0x20, 0x65, 0xe0, 0x18, 0x05, 0x4f, 0xf6, 0x07, - 0x0f, 0x16, 0x4f, 0x26, 0xaf, 0xe9, 0x02, 0xeb, - 0x02, 0x0f, 0x06, 0x0f, 0x06, 0x0f, 0x06, 0x12, - 0x13, 0x12, 0x13, 0x27, 0xe5, 0x00, 0x00, 0xe5, - 0x1c, 0x60, 0xe6, 0x06, 0x07, 0x86, 0x16, 0x26, - 0x85, 0xe6, 0x03, 0x00, 0xe6, 0x1c, 0x00, 0xef, - 0x00, 0x06, 0xaf, 0x00, 0x2f, 0x96, 0x6f, 0x36, - 0xe0, 0x1d, 0xe5, 0x23, 0x27, 0x66, 0x07, 0xa6, - 0x07, 0x26, 0x27, 0x26, 0x05, 0xe9, 0x02, 0xb6, - 0xa5, 0x27, 0x26, 0x65, 0x46, 0x05, 0x47, 0x25, - 0xc7, 0x45, 0x66, 0xe5, 0x05, 0x06, 0x27, 0x26, - 0xa7, 0x06, 0x05, 0x07, 0xe9, 0x02, 0x47, 0x06, - 0x2f, 0xe1, 0x1e, 0x00, 0x01, 0x80, 0x01, 0x20, - 0xe2, 0x23, 0x16, 0x04, 0x42, 0xe5, 0x80, 0xc1, - 0x00, 0x65, 0x20, 0xc5, 0x00, 0x05, 0x00, 0x65, - 0x20, 0xe5, 0x21, 0x00, 0x65, 0x20, 0xe5, 0x19, - 0x00, 0x65, 0x20, 0xc5, 0x00, 0x05, 0x00, 0x65, - 0x20, 0xe5, 0x07, 0x00, 0xe5, 0x31, 0x00, 0x65, - 0x20, 0xe5, 0x3b, 0x20, 0x46, 0xf6, 0x01, 0xeb, - 0x0c, 0x40, 0xe5, 0x08, 0xef, 0x02, 0xa0, 0xe1, - 0x4e, 0x20, 0xa2, 0x20, 0x11, 0xe5, 0x81, 0xe4, - 0x36, 0xe5, 0x09, 0x17, 0xe5, 0x12, 0x12, 0x13, - 0x40, 0xe5, 0x43, 0x56, 0x4a, 0xe5, 0x00, 0xc0, - 0xe5, 0x05, 0x00, 0x65, 0x46, 0xe0, 0x03, 0xe5, - 0x0a, 0x46, 0x36, 0xe0, 0x01, 0xe5, 0x0a, 0x26, - 0xe0, 0x04, 0xe5, 0x05, 0x00, 0x45, 0x00, 0x26, - 0xe0, 0x04, 0xe5, 0x2c, 0x26, 0x07, 0xc6, 0xe7, - 0x00, 0x06, 0x27, 0xe6, 0x03, 0x56, 0x04, 0x56, - 0x0d, 0x05, 0x06, 0x20, 0xe9, 0x02, 0xa0, 0xeb, - 0x02, 0xa0, 0xb6, 0x11, 0x76, 0x46, 0x1b, 0x00, - 0xe9, 0x02, 0xa0, 0xe5, 0x1b, 0x04, 0xe5, 0x2d, - 0xc0, 0x85, 0x26, 0xe5, 0x1a, 0x06, 0x05, 0x80, - 0xe5, 0x3e, 0xe0, 0x02, 0xe5, 0x17, 0x00, 0x46, - 0x67, 0x26, 0x47, 0x60, 0x27, 0x06, 0xa7, 0x46, - 0x60, 0x0f, 0x40, 0x36, 0xe9, 0x02, 0xe5, 0x16, - 0x20, 0x85, 0xe0, 0x03, 0xe5, 0x24, 0x60, 0xe5, - 0x12, 0xa0, 0xe9, 0x02, 0x0b, 0x40, 0xef, 0x1a, - 0xe5, 0x0f, 0x26, 0x27, 0x06, 0x20, 0x36, 0xe5, - 0x2d, 0x07, 0x06, 0x07, 0xc6, 0x00, 0x06, 0x07, - 0x06, 0x27, 0xe6, 0x00, 0xa7, 0xe6, 0x02, 0x20, - 0x06, 0xe9, 0x02, 0xa0, 0xe9, 0x02, 0xa0, 0xd6, - 0x04, 0xb6, 0x20, 0xe6, 0x06, 0x08, 0xe0, 0x39, - 0x66, 0x07, 0xe5, 0x27, 0x06, 0x07, 0x86, 0x07, - 0x06, 0x87, 0x06, 0x27, 0xc5, 0x60, 0xe9, 0x02, - 0xd6, 0xef, 0x02, 0xe6, 0x01, 0xef, 0x01, 0x40, - 0x26, 0x07, 0xe5, 0x16, 0x07, 0x66, 0x27, 0x26, - 0x07, 0x46, 0x25, 0xe9, 0x02, 0xe5, 0x24, 0x06, - 0x07, 0x26, 0x47, 0x06, 0x07, 0x46, 0x27, 0xe0, - 0x00, 0x76, 0xe5, 0x1c, 0xe7, 0x00, 0xe6, 0x00, - 0x27, 0x26, 0x40, 0x96, 0xe9, 0x02, 0x40, 0x45, - 0xe9, 0x02, 0xe5, 0x16, 0xa4, 0x36, 0xe2, 0x01, - 0xc0, 0xe1, 0x23, 0x20, 0x41, 0xf6, 0x00, 0xe0, - 0x00, 0x46, 0x16, 0xe6, 0x05, 0x07, 0xc6, 0x65, - 0x06, 0x65, 0x27, 0x06, 0x25, 0x07, 0x26, 0xa0, - 0xe2, 0x24, 0xe4, 0x37, 0xe2, 0x05, 0x04, 0xe2, - 0x1a, 0xe4, 0x1d, 0xe6, 0x32, 0x00, 0x86, 0xff, - 0x80, 0x0e, 0xe2, 0x00, 0xff, 0x5a, 0xe2, 0x00, - 0xe1, 0x00, 0xa2, 0x20, 0xa1, 0x20, 0xe2, 0x00, - 0xe1, 0x00, 0xe2, 0x00, 0xe1, 0x00, 0xa2, 0x20, - 0xa1, 0x20, 0xe2, 0x00, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x01, 0x00, 0x3f, 0xc2, 0xe1, 0x00, 0xe2, - 0x06, 0x20, 0xe2, 0x00, 0xe3, 0x00, 0xe2, 0x00, - 0xe3, 0x00, 0xe2, 0x00, 0xe3, 0x00, 0x82, 0x00, - 0x22, 0x61, 0x03, 0x0e, 0x02, 0x4e, 0x42, 0x00, - 0x22, 0x61, 0x03, 0x4e, 0x62, 0x20, 0x22, 0x61, - 0x00, 0x4e, 0xe2, 0x00, 0x81, 0x4e, 0x20, 0x42, - 0x00, 0x22, 0x61, 0x03, 0x2e, 0x00, 0xf7, 0x03, - 0x9b, 0xb1, 0x36, 0x14, 0x15, 0x12, 0x34, 0x15, - 0x12, 0x14, 0xf6, 0x00, 0x18, 0x19, 0x9b, 0x17, - 0xf6, 0x01, 0x14, 0x15, 0x76, 0x30, 0x56, 0x0c, - 0x12, 0x13, 0xf6, 0x03, 0x0c, 0x16, 0x10, 0xf6, - 0x02, 0x17, 0x9b, 0x00, 0xfb, 0x02, 0x0b, 0x04, - 0x20, 0xab, 0x4c, 0x12, 0x13, 0x04, 0xeb, 0x02, - 0x4c, 0x12, 0x13, 0x00, 0xe4, 0x05, 0x40, 0xed, - 0x18, 0xe0, 0x08, 0xe6, 0x05, 0x68, 0x06, 0x48, - 0xe6, 0x04, 0xe0, 0x07, 0x2f, 0x01, 0x6f, 0x01, - 0x2f, 0x02, 0x41, 0x22, 0x41, 0x02, 0x0f, 0x01, - 0x2f, 0x0c, 0x81, 0xaf, 0x01, 0x0f, 0x01, 0x0f, - 0x01, 0x0f, 0x61, 0x0f, 0x02, 0x61, 0x02, 0x65, - 0x02, 0x2f, 0x22, 0x21, 0x8c, 0x3f, 0x42, 0x0f, - 0x0c, 0x2f, 0x02, 0x0f, 0xeb, 0x08, 0xea, 0x1b, - 0x3f, 0x6a, 0x0b, 0x2f, 0x60, 0x8c, 0x8f, 0x2c, - 0x6f, 0x0c, 0x2f, 0x0c, 0x2f, 0x0c, 0xcf, 0x0c, - 0xef, 0x17, 0x2c, 0x2f, 0x0c, 0x0f, 0x0c, 0xef, - 0x17, 0xec, 0x80, 0x84, 0xef, 0x00, 0x12, 0x13, - 0x12, 0x13, 0xef, 0x0c, 0x2c, 0xcf, 0x12, 0x13, - 0xef, 0x49, 0x0c, 0xef, 0x16, 0xec, 0x11, 0xef, - 0x20, 0xac, 0xef, 0x3d, 0xe0, 0x11, 0xef, 0x03, - 0xe0, 0x0d, 0xeb, 0x34, 0xef, 0x46, 0xeb, 0x0e, - 0xef, 0x80, 0x2f, 0x0c, 0xef, 0x01, 0x0c, 0xef, - 0x2e, 0xec, 0x00, 0xef, 0x67, 0x0c, 0xef, 0x80, - 0x70, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, - 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0xeb, - 0x16, 0xef, 0x24, 0x8c, 0x12, 0x13, 0xec, 0x17, + 0xe0, 0x1d, 0x25, 0x00, 0x05, 0x00, 0x85, 0x00, + 0xe5, 0x10, 0x00, 0x05, 0x00, 0xe5, 0x02, 0x06, + 0x25, 0xe6, 0x01, 0x05, 0x20, 0x85, 0x00, 0x04, + 0x00, 0xa6, 0x20, 0xe9, 0x02, 0x20, 0x65, 0xe0, + 0x18, 0x05, 0x4f, 0xf6, 0x07, 0x0f, 0x16, 0x4f, + 0x26, 0xaf, 0xe9, 0x02, 0xeb, 0x02, 0x0f, 0x06, + 0x0f, 0x06, 0x0f, 0x06, 0x12, 0x13, 0x12, 0x13, + 0x27, 0xe5, 0x00, 0x00, 0xe5, 0x1c, 0x60, 0xe6, + 0x06, 0x07, 0x86, 0x16, 0x26, 0x85, 0xe6, 0x03, + 0x00, 0xe6, 0x1c, 0x00, 0xef, 0x00, 0x06, 0xaf, + 0x00, 0x2f, 0x96, 0x6f, 0x36, 0xe0, 0x1d, 0xe5, + 0x23, 0x27, 0x66, 0x07, 0xa6, 0x07, 0x26, 0x27, + 0x26, 0x05, 0xe9, 0x02, 0xb6, 0xa5, 0x27, 0x26, + 0x65, 0x46, 0x05, 0x47, 0x25, 0xc7, 0x45, 0x66, + 0xe5, 0x05, 0x06, 0x27, 0x26, 0xa7, 0x06, 0x05, + 0x07, 0xe9, 0x02, 0x47, 0x06, 0x2f, 0xe1, 0x1e, + 0x00, 0x01, 0x80, 0x01, 0x20, 0xe2, 0x23, 0x16, + 0x04, 0x42, 0xe5, 0x80, 0xc1, 0x00, 0x65, 0x20, + 0xc5, 0x00, 0x05, 0x00, 0x65, 0x20, 0xe5, 0x21, + 0x00, 0x65, 0x20, 0xe5, 0x19, 0x00, 0x65, 0x20, + 0xc5, 0x00, 0x05, 0x00, 0x65, 0x20, 0xe5, 0x07, + 0x00, 0xe5, 0x31, 0x00, 0x65, 0x20, 0xe5, 0x3b, + 0x20, 0x46, 0xf6, 0x01, 0xeb, 0x0c, 0x40, 0xe5, + 0x08, 0xef, 0x02, 0xa0, 0xe1, 0x4e, 0x20, 0xa2, + 0x20, 0x11, 0xe5, 0x81, 0xe4, 0x0f, 0x16, 0xe5, + 0x09, 0x17, 0xe5, 0x12, 0x12, 0x13, 0x40, 0xe5, + 0x43, 0x56, 0x4a, 0xe5, 0x00, 0xc0, 0xe5, 0x05, + 0x00, 0x65, 0x46, 0xe0, 0x03, 0xe5, 0x0a, 0x46, + 0x36, 0xe0, 0x01, 0xe5, 0x0a, 0x26, 0xe0, 0x04, + 0xe5, 0x05, 0x00, 0x45, 0x00, 0x26, 0xe0, 0x04, + 0xe5, 0x2c, 0x26, 0x07, 0xc6, 0xe7, 0x00, 0x06, + 0x27, 0xe6, 0x03, 0x56, 0x04, 0x56, 0x0d, 0x05, + 0x06, 0x20, 0xe9, 0x02, 0xa0, 0xeb, 0x02, 0xa0, + 0xb6, 0x11, 0x76, 0x46, 0x1b, 0x00, 0xe9, 0x02, + 0xa0, 0xe5, 0x1b, 0x04, 0xe5, 0x2d, 0xc0, 0x85, + 0x26, 0xe5, 0x1a, 0x06, 0x05, 0x80, 0xe5, 0x3e, + 0xe0, 0x02, 0xe5, 0x17, 0x00, 0x46, 0x67, 0x26, + 0x47, 0x60, 0x27, 0x06, 0xa7, 0x46, 0x60, 0x0f, + 0x40, 0x36, 0xe9, 0x02, 0xe5, 0x16, 0x20, 0x85, + 0xe0, 0x03, 0xe5, 0x24, 0x60, 0xe5, 0x12, 0xa0, + 0xe9, 0x02, 0x0b, 0x40, 0xef, 0x1a, 0xe5, 0x0f, + 0x26, 0x27, 0x06, 0x20, 0x36, 0xe5, 0x2d, 0x07, + 0x06, 0x07, 0xc6, 0x00, 0x06, 0x07, 0x06, 0x27, + 0xe6, 0x00, 0xa7, 0xe6, 0x02, 0x20, 0x06, 0xe9, + 0x02, 0xa0, 0xe9, 0x02, 0xa0, 0xd6, 0x04, 0xb6, + 0x20, 0xe6, 0x06, 0x08, 0xe0, 0x39, 0x66, 0x07, + 0xe5, 0x27, 0x06, 0x07, 0x86, 0x07, 0x06, 0x87, + 0x06, 0x27, 0xc5, 0x60, 0xe9, 0x02, 0xd6, 0xef, + 0x02, 0xe6, 0x01, 0xef, 0x01, 0x40, 0x26, 0x07, + 0xe5, 0x16, 0x07, 0x66, 0x27, 0x26, 0x07, 0x46, + 0x25, 0xe9, 0x02, 0xe5, 0x24, 0x06, 0x07, 0x26, + 0x47, 0x06, 0x07, 0x46, 0x27, 0xe0, 0x00, 0x76, + 0xe5, 0x1c, 0xe7, 0x00, 0xe6, 0x00, 0x27, 0x26, + 0x40, 0x96, 0xe9, 0x02, 0x40, 0x45, 0xe9, 0x02, + 0xe5, 0x16, 0xa4, 0x36, 0xe2, 0x01, 0xc0, 0xe1, + 0x23, 0x20, 0x41, 0xf6, 0x00, 0xe0, 0x00, 0x46, + 0x16, 0xe6, 0x05, 0x07, 0xc6, 0x65, 0x06, 0xa5, + 0x06, 0x25, 0x07, 0x26, 0x05, 0x80, 0xe2, 0x24, + 0xe4, 0x37, 0xe2, 0x05, 0x04, 0xe2, 0x1a, 0xe4, + 0x1d, 0xe6, 0x32, 0x00, 0x86, 0xff, 0x80, 0x0e, + 0xe2, 0x00, 0xff, 0x5a, 0xe2, 0x00, 0xe1, 0x00, + 0xa2, 0x20, 0xa1, 0x20, 0xe2, 0x00, 0xe1, 0x00, + 0xe2, 0x00, 0xe1, 0x00, 0xa2, 0x20, 0xa1, 0x20, + 0xe2, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x3f, 0xc2, 0xe1, 0x00, 0xe2, 0x06, 0x20, + 0xe2, 0x00, 0xe3, 0x00, 0xe2, 0x00, 0xe3, 0x00, + 0xe2, 0x00, 0xe3, 0x00, 0x82, 0x00, 0x22, 0x61, + 0x03, 0x0e, 0x02, 0x4e, 0x42, 0x00, 0x22, 0x61, + 0x03, 0x4e, 0x62, 0x20, 0x22, 0x61, 0x00, 0x4e, + 0xe2, 0x00, 0x81, 0x4e, 0x20, 0x42, 0x00, 0x22, + 0x61, 0x03, 0x2e, 0x00, 0xf7, 0x03, 0x9b, 0xb1, + 0x36, 0x14, 0x15, 0x12, 0x34, 0x15, 0x12, 0x14, + 0xf6, 0x00, 0x18, 0x19, 0x9b, 0x17, 0xf6, 0x01, + 0x14, 0x15, 0x76, 0x30, 0x56, 0x0c, 0x12, 0x13, + 0xf6, 0x03, 0x0c, 0x16, 0x10, 0xf6, 0x02, 0x17, + 0x9b, 0x00, 0xfb, 0x02, 0x0b, 0x04, 0x20, 0xab, + 0x4c, 0x12, 0x13, 0x04, 0xeb, 0x02, 0x4c, 0x12, + 0x13, 0x00, 0xe4, 0x05, 0x40, 0xed, 0x18, 0xe0, + 0x08, 0xe6, 0x05, 0x68, 0x06, 0x48, 0xe6, 0x04, + 0xe0, 0x07, 0x2f, 0x01, 0x6f, 0x01, 0x2f, 0x02, + 0x41, 0x22, 0x41, 0x02, 0x0f, 0x01, 0x2f, 0x0c, + 0x81, 0xaf, 0x01, 0x0f, 0x01, 0x0f, 0x01, 0x0f, + 0x61, 0x0f, 0x02, 0x61, 0x02, 0x65, 0x02, 0x2f, + 0x22, 0x21, 0x8c, 0x3f, 0x42, 0x0f, 0x0c, 0x2f, + 0x02, 0x0f, 0xeb, 0x08, 0xea, 0x1b, 0x3f, 0x6a, + 0x0b, 0x2f, 0x60, 0x8c, 0x8f, 0x2c, 0x6f, 0x0c, + 0x2f, 0x0c, 0x2f, 0x0c, 0xcf, 0x0c, 0xef, 0x17, + 0x2c, 0x2f, 0x0c, 0x0f, 0x0c, 0xef, 0x17, 0xec, + 0x80, 0x84, 0xef, 0x00, 0x12, 0x13, 0x12, 0x13, + 0xef, 0x0c, 0x2c, 0xcf, 0x12, 0x13, 0xef, 0x49, + 0x0c, 0xef, 0x16, 0xec, 0x11, 0xef, 0x20, 0xac, + 0xef, 0x3d, 0xe0, 0x11, 0xef, 0x03, 0xe0, 0x0d, + 0xeb, 0x34, 0xef, 0x46, 0xeb, 0x0e, 0xef, 0x80, + 0x2f, 0x0c, 0xef, 0x01, 0x0c, 0xef, 0x2e, 0xec, + 0x00, 0xef, 0x67, 0x0c, 0xef, 0x80, 0x70, 0x12, + 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, + 0x13, 0x12, 0x13, 0x12, 0x13, 0xeb, 0x16, 0xef, + 0x24, 0x8c, 0x12, 0x13, 0xec, 0x17, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, - 0x12, 0x13, 0xec, 0x08, 0xef, 0x80, 0x78, 0xec, - 0x7b, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, + 0xec, 0x08, 0xef, 0x80, 0x78, 0xec, 0x7b, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, - 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0xec, - 0x37, 0x12, 0x13, 0x12, 0x13, 0xec, 0x18, 0x12, - 0x13, 0xec, 0x80, 0x7a, 0xef, 0x28, 0xec, 0x0d, - 0x2f, 0xac, 0xef, 0x1f, 0x20, 0xef, 0x18, 0x20, - 0xef, 0x29, 0x00, 0xef, 0x2d, 0x00, 0xe1, 0x27, - 0x00, 0xe2, 0x27, 0x00, 0x5f, 0x21, 0x22, 0xdf, - 0x41, 0x02, 0x3f, 0x02, 0x3f, 0x82, 0x24, 0x41, - 0x02, 0xff, 0x5a, 0x02, 0xaf, 0x7f, 0x46, 0x3f, - 0x80, 0x76, 0x0b, 0x36, 0xe2, 0x1e, 0x00, 0x02, - 0x80, 0x02, 0x20, 0xe5, 0x30, 0xc0, 0x04, 0x16, - 0xe0, 0x06, 0x06, 0xe5, 0x0f, 0xe0, 0x01, 0xc5, + 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, + 0x13, 0x12, 0x13, 0x12, 0x13, 0xec, 0x37, 0x12, + 0x13, 0x12, 0x13, 0xec, 0x18, 0x12, 0x13, 0xec, + 0x80, 0x7a, 0xef, 0x28, 0xec, 0x0d, 0x2f, 0xac, + 0xef, 0x1f, 0x20, 0xef, 0x18, 0x20, 0xef, 0x60, + 0xe1, 0x27, 0x00, 0xe2, 0x27, 0x00, 0x5f, 0x21, + 0x22, 0xdf, 0x41, 0x02, 0x3f, 0x02, 0x3f, 0x82, + 0x24, 0x41, 0x02, 0xff, 0x5a, 0x02, 0xaf, 0x7f, + 0x46, 0x3f, 0x80, 0x76, 0x0b, 0x36, 0xe2, 0x1e, + 0x00, 0x02, 0x80, 0x02, 0x20, 0xe5, 0x30, 0xc0, + 0x04, 0x16, 0xe0, 0x06, 0x06, 0xe5, 0x0f, 0xe0, + 0x01, 0xc5, 0x00, 0xc5, 0x00, 0xc5, 0x00, 0xc5, 0x00, 0xc5, 0x00, 0xc5, 0x00, 0xc5, 0x00, 0xc5, - 0x00, 0xc5, 0x00, 0xc5, 0x00, 0xc5, 0x00, 0xe6, - 0x18, 0x36, 0x14, 0x15, 0x14, 0x15, 0x56, 0x14, - 0x15, 0x16, 0x14, 0x15, 0xf6, 0x01, 0x11, 0x36, - 0x11, 0x16, 0x14, 0x15, 0x36, 0x14, 0x15, 0x12, - 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x96, - 0x04, 0xf6, 0x02, 0x31, 0x76, 0x11, 0x16, 0x12, - 0xf6, 0x04, 0xe0, 0x29, 0xef, 0x12, 0x00, 0xef, - 0x51, 0xe0, 0x04, 0xef, 0x80, 0x4e, 0xe0, 0x12, - 0xef, 0x04, 0x60, 0x17, 0x56, 0x0f, 0x04, 0x05, - 0x0a, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, - 0x13, 0x12, 0x13, 0x2f, 0x12, 0x13, 0x12, 0x13, - 0x12, 0x13, 0x12, 0x13, 0x11, 0x12, 0x33, 0x0f, - 0xea, 0x01, 0x66, 0x27, 0x11, 0x84, 0x2f, 0x4a, - 0x04, 0x05, 0x16, 0x2f, 0x00, 0xe5, 0x4e, 0x20, - 0x26, 0x2e, 0x24, 0x05, 0x11, 0xe5, 0x52, 0x16, - 0x44, 0x05, 0x80, 0xe5, 0x23, 0x00, 0xe5, 0x56, - 0x00, 0x2f, 0x6b, 0xef, 0x02, 0xe5, 0x13, 0x80, - 0xef, 0x1c, 0xe0, 0x04, 0xe5, 0x08, 0xef, 0x17, - 0x00, 0xeb, 0x02, 0xef, 0x16, 0xeb, 0x00, 0x0f, - 0xeb, 0x07, 0xef, 0x18, 0xeb, 0x02, 0xef, 0x1f, - 0xeb, 0x07, 0xef, 0x37, 0x00, 0xef, 0x80, 0x78, - 0xe5, 0x99, 0x2e, 0xe0, 0x02, 0xef, 0x38, 0xe5, - 0xc0, 0x11, 0x68, 0xe0, 0x08, 0xe5, 0x0d, 0x04, - 0xe5, 0x83, 0xef, 0x40, 0xef, 0x2f, 0xe0, 0x01, - 0xe5, 0x20, 0xa4, 0x36, 0xe5, 0x80, 0x84, 0x04, - 0x56, 0xe5, 0x08, 0xe9, 0x02, 0x25, 0xe0, 0x0c, - 0xff, 0x26, 0x05, 0x06, 0x48, 0x16, 0xe6, 0x02, - 0x16, 0x04, 0xff, 0x14, 0x24, 0x26, 0xe5, 0x3e, - 0xea, 0x02, 0x26, 0xb6, 0xe0, 0x00, 0xee, 0x0f, - 0xe4, 0x01, 0x2e, 0xff, 0x06, 0x22, 0xff, 0x36, - 0x04, 0xe2, 0x00, 0x9f, 0xff, 0x02, 0x04, 0x2e, - 0x7f, 0x05, 0x7f, 0x22, 0xff, 0x0d, 0x61, 0x02, - 0x81, 0x02, 0x7f, 0xe0, 0x35, 0x05, 0x24, 0x02, - 0xc5, 0x06, 0x45, 0x06, 0x65, 0x06, 0xe5, 0x0f, - 0x27, 0x26, 0x07, 0x6f, 0x60, 0xab, 0x2f, 0x0d, - 0x0f, 0xa0, 0xe5, 0x2c, 0x76, 0xe0, 0x00, 0x27, - 0xe5, 0x2a, 0xe7, 0x08, 0x26, 0xe0, 0x00, 0x36, - 0xe9, 0x02, 0xa0, 0xe6, 0x0a, 0xa5, 0x56, 0x05, - 0x16, 0x25, 0x06, 0xe9, 0x02, 0xe5, 0x14, 0xe6, - 0x00, 0x36, 0xe5, 0x0f, 0xe6, 0x03, 0x27, 0xe0, - 0x03, 0x16, 0xe5, 0x15, 0x40, 0x46, 0x07, 0xe5, - 0x27, 0x06, 0x27, 0x66, 0x27, 0x06, 0x67, 0xf6, - 0x05, 0x00, 0x04, 0xe9, 0x02, 0x60, 0x36, 0x85, - 0x06, 0x04, 0xe5, 0x01, 0xe9, 0x02, 0x85, 0x00, - 0xe5, 0x21, 0xa6, 0x27, 0x26, 0x27, 0x26, 0xe0, - 0x01, 0x45, 0x06, 0xe5, 0x00, 0x06, 0x07, 0x20, - 0xe9, 0x02, 0x20, 0x76, 0xe5, 0x08, 0x04, 0xa5, - 0x4f, 0x05, 0x07, 0x06, 0x07, 0xe5, 0x2a, 0x06, - 0x05, 0x46, 0x25, 0x26, 0x85, 0x26, 0x05, 0x06, - 0x05, 0xe0, 0x10, 0x25, 0x04, 0x36, 0xe5, 0x03, - 0x07, 0x26, 0x27, 0x36, 0x05, 0x24, 0x07, 0x06, - 0xe0, 0x02, 0xa5, 0x20, 0xa5, 0x20, 0xa5, 0xe0, - 0x01, 0xc5, 0x00, 0xc5, 0x00, 0xe2, 0x23, 0x0e, - 0x64, 0xa2, 0xe0, 0x02, 0xe2, 0x48, 0xe5, 0x1b, - 0x27, 0x06, 0x27, 0x06, 0x27, 0x16, 0x07, 0x06, - 0x20, 0xe9, 0x02, 0xa0, 0xe5, 0xab, 0x1c, 0xe0, - 0x04, 0xe5, 0x0f, 0x60, 0xe5, 0x29, 0x60, 0xfc, - 0x87, 0x78, 0xfd, 0x98, 0x78, 0xe5, 0x80, 0xe6, - 0x20, 0xe5, 0x62, 0xe0, 0x1e, 0xc2, 0xe0, 0x04, - 0x82, 0x80, 0x05, 0x06, 0xe5, 0x02, 0x0c, 0xe5, - 0x05, 0x00, 0x85, 0x00, 0x05, 0x00, 0x25, 0x00, - 0x25, 0x00, 0xe5, 0x64, 0xee, 0x08, 0xe0, 0x09, - 0xe5, 0x80, 0xe3, 0x13, 0x12, 0xe0, 0x08, 0xe5, - 0x38, 0x20, 0xe5, 0x2e, 0xe0, 0x20, 0xe5, 0x04, - 0x0d, 0x0f, 0x20, 0xe6, 0x08, 0xd6, 0x12, 0x13, - 0x16, 0xa0, 0xe6, 0x08, 0x16, 0x31, 0x30, 0x12, + 0x00, 0xe6, 0x18, 0x36, 0x14, 0x15, 0x14, 0x15, + 0x56, 0x14, 0x15, 0x16, 0x14, 0x15, 0xf6, 0x01, + 0x11, 0x36, 0x11, 0x16, 0x14, 0x15, 0x36, 0x14, + 0x15, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, + 0x13, 0x96, 0x04, 0xf6, 0x02, 0x31, 0x76, 0x11, + 0x16, 0x12, 0xf6, 0x05, 0xe0, 0x28, 0xef, 0x12, + 0x00, 0xef, 0x51, 0xe0, 0x04, 0xef, 0x80, 0x4e, + 0xe0, 0x12, 0xef, 0x04, 0x60, 0x17, 0x56, 0x0f, + 0x04, 0x05, 0x0a, 0x12, 0x13, 0x12, 0x13, 0x12, + 0x13, 0x12, 0x13, 0x12, 0x13, 0x2f, 0x12, 0x13, + 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x11, 0x12, + 0x33, 0x0f, 0xea, 0x01, 0x66, 0x27, 0x11, 0x84, + 0x2f, 0x4a, 0x04, 0x05, 0x16, 0x2f, 0x00, 0xe5, + 0x4e, 0x20, 0x26, 0x2e, 0x24, 0x05, 0x11, 0xe5, + 0x52, 0x16, 0x44, 0x05, 0x80, 0xe5, 0x23, 0x00, + 0xe5, 0x56, 0x00, 0x2f, 0x6b, 0xef, 0x02, 0xe5, + 0x13, 0x80, 0xef, 0x1c, 0xe0, 0x04, 0xe5, 0x08, + 0xef, 0x17, 0x00, 0xeb, 0x02, 0xef, 0x16, 0xeb, + 0x00, 0x0f, 0xeb, 0x07, 0xef, 0x18, 0xeb, 0x02, + 0xef, 0x1f, 0xeb, 0x07, 0xef, 0x80, 0xb8, 0xe5, + 0x99, 0x2e, 0xe0, 0x02, 0xef, 0x38, 0xe5, 0xc0, + 0x11, 0x68, 0xe0, 0x08, 0xe5, 0x0d, 0x04, 0xe5, + 0x83, 0xef, 0x40, 0xef, 0x2f, 0xe0, 0x01, 0xe5, + 0x20, 0xa4, 0x36, 0xe5, 0x80, 0x84, 0x04, 0x56, + 0xe5, 0x08, 0xe9, 0x02, 0x25, 0xe0, 0x0c, 0xff, + 0x26, 0x05, 0x06, 0x48, 0x16, 0xe6, 0x02, 0x16, + 0x04, 0xff, 0x14, 0x24, 0x26, 0xe5, 0x3e, 0xea, + 0x02, 0x26, 0xb6, 0xe0, 0x00, 0xee, 0x0f, 0xe4, + 0x01, 0x2e, 0xff, 0x06, 0x22, 0xff, 0x36, 0x04, + 0xe2, 0x00, 0x9f, 0xff, 0x02, 0x04, 0x2e, 0x7f, + 0x05, 0x7f, 0x22, 0xff, 0x0d, 0x61, 0x02, 0x81, + 0x02, 0xff, 0x02, 0x20, 0x5f, 0x21, 0xe0, 0x28, + 0x05, 0x24, 0x02, 0xc5, 0x06, 0x45, 0x06, 0x65, + 0x06, 0xe5, 0x0f, 0x27, 0x26, 0x07, 0x6f, 0x60, + 0xab, 0x2f, 0x0d, 0x0f, 0xa0, 0xe5, 0x2c, 0x76, + 0xe0, 0x00, 0x27, 0xe5, 0x2a, 0xe7, 0x08, 0x26, + 0xe0, 0x00, 0x36, 0xe9, 0x02, 0xa0, 0xe6, 0x0a, + 0xa5, 0x56, 0x05, 0x16, 0x25, 0x06, 0xe9, 0x02, + 0xe5, 0x14, 0xe6, 0x00, 0x36, 0xe5, 0x0f, 0xe6, + 0x03, 0x27, 0xe0, 0x03, 0x16, 0xe5, 0x15, 0x40, + 0x46, 0x07, 0xe5, 0x27, 0x06, 0x27, 0x66, 0x27, + 0x26, 0x47, 0xf6, 0x05, 0x00, 0x04, 0xe9, 0x02, + 0x60, 0x36, 0x85, 0x06, 0x04, 0xe5, 0x01, 0xe9, + 0x02, 0x85, 0x00, 0xe5, 0x21, 0xa6, 0x27, 0x26, + 0x27, 0x26, 0xe0, 0x01, 0x45, 0x06, 0xe5, 0x00, + 0x06, 0x07, 0x20, 0xe9, 0x02, 0x20, 0x76, 0xe5, + 0x08, 0x04, 0xa5, 0x4f, 0x05, 0x07, 0x06, 0x07, + 0xe5, 0x2a, 0x06, 0x05, 0x46, 0x25, 0x26, 0x85, + 0x26, 0x05, 0x06, 0x05, 0xe0, 0x10, 0x25, 0x04, + 0x36, 0xe5, 0x03, 0x07, 0x26, 0x27, 0x36, 0x05, + 0x24, 0x07, 0x06, 0xe0, 0x02, 0xa5, 0x20, 0xa5, + 0x20, 0xa5, 0xe0, 0x01, 0xc5, 0x00, 0xc5, 0x00, + 0xe2, 0x23, 0x0e, 0x64, 0xe2, 0x00, 0xe0, 0x00, + 0xe2, 0x48, 0xe5, 0x1b, 0x27, 0x06, 0x27, 0x06, + 0x27, 0x16, 0x07, 0x06, 0x20, 0xe9, 0x02, 0xa0, + 0xe5, 0xab, 0x1c, 0xe0, 0x04, 0xe5, 0x0f, 0x60, + 0xe5, 0x29, 0x60, 0xfc, 0x87, 0x78, 0xfd, 0x98, + 0x78, 0xe5, 0x80, 0xe6, 0x20, 0xe5, 0x62, 0xe0, + 0x1e, 0xc2, 0xe0, 0x04, 0x82, 0x80, 0x05, 0x06, + 0xe5, 0x02, 0x0c, 0xe5, 0x05, 0x00, 0x85, 0x00, + 0x05, 0x00, 0x25, 0x00, 0x25, 0x00, 0xe5, 0x64, + 0xee, 0x08, 0xe0, 0x09, 0xe5, 0x80, 0xe3, 0x13, + 0x12, 0xe0, 0x08, 0xe5, 0x38, 0x20, 0xe5, 0x2e, + 0xe0, 0x20, 0xe5, 0x04, 0x0d, 0x0f, 0x20, 0xe6, + 0x08, 0xd6, 0x12, 0x13, 0x16, 0xa0, 0xe6, 0x08, + 0x16, 0x31, 0x30, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, - 0x13, 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x36, - 0x12, 0x13, 0x76, 0x50, 0x56, 0x00, 0x76, 0x11, - 0x12, 0x13, 0x12, 0x13, 0x12, 0x13, 0x56, 0x0c, - 0x11, 0x4c, 0x00, 0x16, 0x0d, 0x36, 0x60, 0x85, - 0x00, 0xe5, 0x7f, 0x20, 0x1b, 0x00, 0x56, 0x0d, - 0x56, 0x12, 0x13, 0x16, 0x0c, 0x16, 0x11, 0x36, - 0xe9, 0x02, 0x36, 0x4c, 0x36, 0xe1, 0x12, 0x12, - 0x16, 0x13, 0x0e, 0x10, 0x0e, 0xe2, 0x12, 0x12, - 0x0c, 0x13, 0x0c, 0x12, 0x13, 0x16, 0x12, 0x13, - 0x36, 0xe5, 0x02, 0x04, 0xe5, 0x25, 0x24, 0xe5, - 0x17, 0x40, 0xa5, 0x20, 0xa5, 0x20, 0xa5, 0x20, - 0x45, 0x40, 0x2d, 0x0c, 0x0e, 0x0f, 0x2d, 0x00, - 0x0f, 0x6c, 0x2f, 0xe0, 0x02, 0x5b, 0x2f, 0x20, - 0xe5, 0x04, 0x00, 0xe5, 0x12, 0x00, 0xe5, 0x0b, - 0x00, 0x25, 0x00, 0xe5, 0x07, 0x20, 0xe5, 0x06, - 0xe0, 0x1a, 0xe5, 0x73, 0x80, 0x56, 0x60, 0xeb, - 0x25, 0x40, 0xef, 0x01, 0xea, 0x2d, 0x6b, 0xef, - 0x09, 0x2b, 0x4f, 0x00, 0xef, 0x04, 0x60, 0x0f, - 0xe0, 0x27, 0xef, 0x25, 0x06, 0xe0, 0x7a, 0xe5, - 0x15, 0x40, 0xe5, 0x29, 0xe0, 0x07, 0x06, 0xeb, - 0x13, 0x60, 0xe5, 0x18, 0x6b, 0xe0, 0x01, 0xe5, - 0x0c, 0x0a, 0xe5, 0x00, 0x0a, 0x80, 0xe5, 0x1e, - 0x86, 0x80, 0xe5, 0x16, 0x00, 0x16, 0xe5, 0x1c, - 0x60, 0xe5, 0x00, 0x16, 0x8a, 0xe0, 0x22, 0xe1, - 0x20, 0xe2, 0x20, 0xe5, 0x46, 0x20, 0xe9, 0x02, - 0xa0, 0xe1, 0x1c, 0x60, 0xe2, 0x1c, 0x60, 0xe5, - 0x20, 0xe0, 0x00, 0xe5, 0x2c, 0xe0, 0x03, 0x16, - 0xe0, 0x80, 0x08, 0xe5, 0x80, 0xaf, 0xe0, 0x01, - 0xe5, 0x0e, 0xe0, 0x02, 0xe5, 0x00, 0xe0, 0x80, - 0x10, 0xa5, 0x20, 0x05, 0x00, 0xe5, 0x24, 0x00, - 0x25, 0x40, 0x05, 0x20, 0xe5, 0x0f, 0x00, 0x16, - 0xeb, 0x00, 0xe5, 0x0f, 0x2f, 0xcb, 0xe5, 0x17, - 0xe0, 0x00, 0xeb, 0x01, 0xe0, 0x28, 0xe5, 0x0b, - 0x00, 0x25, 0x80, 0x8b, 0xe5, 0x0e, 0xab, 0x40, - 0x16, 0xe5, 0x12, 0x80, 0x16, 0xe0, 0x38, 0xe5, - 0x30, 0x60, 0x2b, 0x25, 0xeb, 0x08, 0x20, 0xeb, - 0x26, 0x05, 0x46, 0x00, 0x26, 0x80, 0x66, 0x65, - 0x00, 0x45, 0x00, 0xe5, 0x15, 0x20, 0x46, 0x60, - 0x06, 0xeb, 0x01, 0xc0, 0xf6, 0x01, 0xc0, 0xe5, - 0x15, 0x2b, 0x16, 0xe5, 0x15, 0x4b, 0xe0, 0x18, - 0xe5, 0x00, 0x0f, 0xe5, 0x14, 0x26, 0x60, 0x8b, - 0xd6, 0xe0, 0x01, 0xe5, 0x2e, 0x40, 0xd6, 0xe5, - 0x0e, 0x20, 0xeb, 0x00, 0xe5, 0x0b, 0x80, 0xeb, - 0x00, 0xe5, 0x0a, 0xc0, 0x76, 0xe0, 0x04, 0xcb, - 0xe0, 0x48, 0xe5, 0x41, 0xe0, 0x2f, 0xe1, 0x2b, - 0xe0, 0x05, 0xe2, 0x2b, 0xc0, 0xab, 0xe5, 0x1c, - 0x66, 0xe0, 0x00, 0xe9, 0x02, 0xe0, 0x80, 0x9e, - 0xeb, 0x17, 0xe0, 0x79, 0xe5, 0x15, 0xeb, 0x02, - 0x05, 0xe0, 0x00, 0xe5, 0x0e, 0xe6, 0x03, 0x6b, - 0x96, 0xe0, 0x80, 0x1e, 0x07, 0x06, 0x07, 0xe5, - 0x2d, 0xe6, 0x07, 0xd6, 0x60, 0xeb, 0x0c, 0xe9, - 0x02, 0xe0, 0x07, 0x46, 0x07, 0xe5, 0x25, 0x47, - 0x66, 0x27, 0x26, 0x36, 0x1b, 0x76, 0xe0, 0x03, - 0x1b, 0x20, 0xe5, 0x11, 0xc0, 0xe9, 0x02, 0xa0, - 0x46, 0xe5, 0x1c, 0x86, 0x07, 0xe6, 0x00, 0x00, - 0xe9, 0x02, 0x76, 0x05, 0x27, 0xe0, 0x01, 0xe5, - 0x1b, 0x06, 0x36, 0x05, 0xe0, 0x01, 0x26, 0x07, - 0xe5, 0x28, 0x47, 0xe6, 0x01, 0x27, 0x65, 0x76, - 0x66, 0x16, 0x20, 0xe9, 0x02, 0x05, 0x16, 0x05, - 0x56, 0x00, 0xeb, 0x0c, 0xe0, 0x03, 0xe5, 0x0a, - 0x00, 0xe5, 0x11, 0x47, 0x46, 0x27, 0x06, 0x07, - 0x26, 0xb6, 0x06, 0xe0, 0x39, 0xc5, 0x00, 0x05, - 0x00, 0x65, 0x00, 0xe5, 0x07, 0x00, 0xe5, 0x02, - 0x16, 0xa0, 0xe5, 0x27, 0x06, 0x47, 0xe6, 0x00, - 0x80, 0xe9, 0x02, 0xa0, 0x26, 0x27, 0x00, 0xe5, - 0x00, 0x20, 0x25, 0x20, 0xe5, 0x0e, 0x00, 0xc5, - 0x00, 0x25, 0x00, 0x85, 0x00, 0x26, 0x05, 0x27, - 0x06, 0x67, 0x20, 0x27, 0x20, 0x47, 0x20, 0x05, - 0xa0, 0x07, 0x80, 0x85, 0x27, 0x20, 0xc6, 0x40, - 0x86, 0xe0, 0x80, 0x03, 0xe5, 0x2d, 0x47, 0xe6, - 0x00, 0x27, 0x46, 0x07, 0x06, 0x65, 0x96, 0xe9, - 0x02, 0x00, 0x16, 0x00, 0x16, 0x06, 0xe0, 0x19, + 0x13, 0x12, 0x13, 0x36, 0x12, 0x13, 0x76, 0x50, + 0x56, 0x00, 0x76, 0x11, 0x12, 0x13, 0x12, 0x13, + 0x12, 0x13, 0x56, 0x0c, 0x11, 0x4c, 0x00, 0x16, + 0x0d, 0x36, 0x60, 0x85, 0x00, 0xe5, 0x7f, 0x20, + 0x1b, 0x00, 0x56, 0x0d, 0x56, 0x12, 0x13, 0x16, + 0x0c, 0x16, 0x11, 0x36, 0xe9, 0x02, 0x36, 0x4c, + 0x36, 0xe1, 0x12, 0x12, 0x16, 0x13, 0x0e, 0x10, + 0x0e, 0xe2, 0x12, 0x12, 0x0c, 0x13, 0x0c, 0x12, + 0x13, 0x16, 0x12, 0x13, 0x36, 0xe5, 0x02, 0x04, + 0xe5, 0x25, 0x24, 0xe5, 0x17, 0x40, 0xa5, 0x20, + 0xa5, 0x20, 0xa5, 0x20, 0x45, 0x40, 0x2d, 0x0c, + 0x0e, 0x0f, 0x2d, 0x00, 0x0f, 0x6c, 0x2f, 0xe0, + 0x02, 0x5b, 0x2f, 0x20, 0xe5, 0x04, 0x00, 0xe5, + 0x12, 0x00, 0xe5, 0x0b, 0x00, 0x25, 0x00, 0xe5, + 0x07, 0x20, 0xe5, 0x06, 0xe0, 0x1a, 0xe5, 0x73, + 0x80, 0x56, 0x60, 0xeb, 0x25, 0x40, 0xef, 0x01, + 0xea, 0x2d, 0x6b, 0xef, 0x09, 0x2b, 0x4f, 0x00, + 0xef, 0x04, 0x60, 0x0f, 0xe0, 0x27, 0xef, 0x25, + 0x06, 0xe0, 0x7a, 0xe5, 0x15, 0x40, 0xe5, 0x29, + 0xe0, 0x07, 0x06, 0xeb, 0x13, 0x60, 0xe5, 0x18, + 0x6b, 0xe0, 0x01, 0xe5, 0x0c, 0x0a, 0xe5, 0x00, + 0x0a, 0x80, 0xe5, 0x1e, 0x86, 0x80, 0xe5, 0x16, + 0x00, 0x16, 0xe5, 0x1c, 0x60, 0xe5, 0x00, 0x16, + 0x8a, 0xe0, 0x22, 0xe1, 0x20, 0xe2, 0x20, 0xe5, + 0x46, 0x20, 0xe9, 0x02, 0xa0, 0xe1, 0x1c, 0x60, + 0xe2, 0x1c, 0x60, 0xe5, 0x20, 0xe0, 0x00, 0xe5, + 0x2c, 0xe0, 0x03, 0x16, 0xe0, 0x80, 0x08, 0xe5, + 0x80, 0xaf, 0xe0, 0x01, 0xe5, 0x0e, 0xe0, 0x02, + 0xe5, 0x00, 0xe0, 0x80, 0x10, 0xa5, 0x20, 0x05, + 0x00, 0xe5, 0x24, 0x00, 0x25, 0x40, 0x05, 0x20, + 0xe5, 0x0f, 0x00, 0x16, 0xeb, 0x00, 0xe5, 0x0f, + 0x2f, 0xcb, 0xe5, 0x17, 0xe0, 0x00, 0xeb, 0x01, + 0xe0, 0x28, 0xe5, 0x0b, 0x00, 0x25, 0x80, 0x8b, + 0xe5, 0x0e, 0xab, 0x40, 0x16, 0xe5, 0x12, 0x80, + 0x16, 0xe0, 0x38, 0xe5, 0x30, 0x60, 0x2b, 0x25, + 0xeb, 0x08, 0x20, 0xeb, 0x26, 0x05, 0x46, 0x00, + 0x26, 0x80, 0x66, 0x65, 0x00, 0x45, 0x00, 0xe5, + 0x15, 0x20, 0x46, 0x60, 0x06, 0xeb, 0x01, 0xc0, + 0xf6, 0x01, 0xc0, 0xe5, 0x15, 0x2b, 0x16, 0xe5, + 0x15, 0x4b, 0xe0, 0x18, 0xe5, 0x00, 0x0f, 0xe5, + 0x14, 0x26, 0x60, 0x8b, 0xd6, 0xe0, 0x01, 0xe5, + 0x2e, 0x40, 0xd6, 0xe5, 0x0e, 0x20, 0xeb, 0x00, + 0xe5, 0x0b, 0x80, 0xeb, 0x00, 0xe5, 0x0a, 0xc0, + 0x76, 0xe0, 0x04, 0xcb, 0xe0, 0x48, 0xe5, 0x41, + 0xe0, 0x2f, 0xe1, 0x2b, 0xe0, 0x05, 0xe2, 0x2b, + 0xc0, 0xab, 0xe5, 0x1c, 0x66, 0xe0, 0x00, 0xe9, + 0x02, 0xe0, 0x80, 0x9e, 0xeb, 0x17, 0xe0, 0x79, + 0xe5, 0x15, 0xeb, 0x02, 0x05, 0xe0, 0x00, 0xe5, + 0x0e, 0xe6, 0x03, 0x6b, 0x96, 0xe0, 0x7e, 0xe5, + 0x0f, 0xe0, 0x01, 0x07, 0x06, 0x07, 0xe5, 0x2d, + 0xe6, 0x07, 0xd6, 0x60, 0xeb, 0x0c, 0xe9, 0x02, + 0xe0, 0x07, 0x46, 0x07, 0xe5, 0x25, 0x47, 0x66, + 0x27, 0x26, 0x36, 0x1b, 0x76, 0xe0, 0x03, 0x1b, + 0x20, 0xe5, 0x11, 0xc0, 0xe9, 0x02, 0xa0, 0x46, + 0xe5, 0x1c, 0x86, 0x07, 0xe6, 0x00, 0x00, 0xe9, + 0x02, 0x76, 0x05, 0x27, 0xe0, 0x01, 0xe5, 0x1b, + 0x06, 0x36, 0x05, 0xe0, 0x01, 0x26, 0x07, 0xe5, + 0x28, 0x47, 0xe6, 0x01, 0x27, 0x65, 0x76, 0x66, + 0x16, 0x20, 0xe9, 0x02, 0x05, 0x16, 0x05, 0x56, + 0x00, 0xeb, 0x0c, 0xe0, 0x03, 0xe5, 0x0a, 0x00, + 0xe5, 0x11, 0x47, 0x46, 0x27, 0x06, 0x07, 0x26, + 0xb6, 0x06, 0xe0, 0x39, 0xc5, 0x00, 0x05, 0x00, + 0x65, 0x00, 0xe5, 0x07, 0x00, 0xe5, 0x02, 0x16, + 0xa0, 0xe5, 0x27, 0x06, 0x47, 0xe6, 0x00, 0x80, + 0xe9, 0x02, 0xa0, 0x26, 0x27, 0x00, 0xe5, 0x00, + 0x20, 0x25, 0x20, 0xe5, 0x0e, 0x00, 0xc5, 0x00, + 0x25, 0x00, 0x85, 0x00, 0x26, 0x05, 0x27, 0x06, + 0x67, 0x20, 0x27, 0x20, 0x47, 0x20, 0x05, 0xa0, + 0x07, 0x80, 0x85, 0x27, 0x20, 0xc6, 0x40, 0x86, + 0xe0, 0x80, 0x03, 0xe5, 0x2d, 0x47, 0xe6, 0x00, + 0x27, 0x46, 0x07, 0x06, 0x65, 0x96, 0xe9, 0x02, + 0x00, 0x16, 0x00, 0x16, 0x06, 0x05, 0xe0, 0x18, 0xe5, 0x28, 0x47, 0xa6, 0x07, 0x06, 0x67, 0x26, 0x07, 0x26, 0x25, 0x16, 0x05, 0xe0, 0x00, 0xe9, 0x02, 0xe0, 0x80, 0x1e, 0xe5, 0x27, 0x47, 0x66, @@ -2607,99 +2617,108 @@ static const uint8_t unicode_gc_table[3655] = { 0x27, 0x06, 0x07, 0x26, 0x56, 0x05, 0xe0, 0x03, 0xe9, 0x02, 0xa0, 0xf6, 0x05, 0xe0, 0x0b, 0xe5, 0x23, 0x06, 0x07, 0x06, 0x27, 0xa6, 0x07, 0x06, - 0xe0, 0x00, 0xe9, 0x02, 0xe0, 0x2e, 0xe5, 0x13, + 0x05, 0xc0, 0xe9, 0x02, 0xe0, 0x2e, 0xe5, 0x13, 0x20, 0x46, 0x27, 0x66, 0x07, 0x86, 0x60, 0xe9, 0x02, 0x2b, 0x56, 0x0f, 0xe0, 0x80, 0x38, 0xe5, 0x24, 0x47, 0xe6, 0x01, 0x07, 0x26, 0x16, 0xe0, 0x5c, 0xe1, 0x18, 0xe2, 0x18, 0xe9, 0x02, 0xeb, - 0x01, 0xe0, 0x04, 0x05, 0xe0, 0x80, 0x78, 0x05, - 0xe6, 0x02, 0xe5, 0x20, 0xa6, 0x07, 0x05, 0x66, - 0xf6, 0x00, 0x06, 0xe0, 0x00, 0x05, 0xa6, 0x27, - 0x46, 0xe5, 0x20, 0x20, 0x65, 0xe6, 0x05, 0x07, - 0x26, 0x56, 0x05, 0x96, 0xe0, 0x15, 0xe5, 0x31, - 0xe0, 0x80, 0x7f, 0xe5, 0x01, 0x00, 0xe5, 0x1d, - 0x07, 0xc6, 0x00, 0xa6, 0x07, 0x06, 0x05, 0x96, - 0xe0, 0x02, 0xe9, 0x02, 0xeb, 0x0b, 0x40, 0x36, - 0xe5, 0x16, 0x20, 0xe6, 0x0e, 0x00, 0x07, 0xc6, - 0x07, 0x26, 0x07, 0x26, 0xe0, 0x41, 0xc5, 0x00, - 0x25, 0x00, 0xe5, 0x1e, 0xa6, 0x40, 0x06, 0x00, - 0x26, 0x00, 0xc6, 0x05, 0x06, 0xe0, 0x00, 0xe9, - 0x02, 0xa0, 0xa5, 0x00, 0x25, 0x00, 0xe5, 0x18, - 0x87, 0x00, 0x26, 0x00, 0x27, 0x06, 0x07, 0x06, - 0x05, 0xc0, 0xe9, 0x02, 0xe0, 0x80, 0xae, 0xe5, - 0x0b, 0x26, 0x27, 0x36, 0xe0, 0x80, 0x7f, 0xe5, - 0x83, 0x12, 0xe0, 0x5e, 0xea, 0x67, 0x00, 0x96, - 0xe0, 0x03, 0xe5, 0x80, 0x3c, 0xe0, 0x8a, 0x34, - 0xe5, 0x83, 0xa7, 0xe0, 0x8f, 0x49, 0xe5, 0x81, - 0xbf, 0xe0, 0xa1, 0x31, 0xe5, 0x81, 0xb1, 0xc0, - 0xe5, 0x17, 0x00, 0xe9, 0x02, 0x60, 0x36, 0xe0, - 0x58, 0xe5, 0x16, 0x20, 0x86, 0x16, 0xe0, 0x02, - 0xe5, 0x28, 0xc6, 0x96, 0x6f, 0x64, 0x16, 0x0f, - 0xe0, 0x02, 0xe9, 0x02, 0x00, 0xcb, 0x00, 0xe5, - 0x0d, 0x80, 0xe5, 0x0b, 0xe0, 0x82, 0x28, 0xe1, - 0x18, 0xe2, 0x18, 0xeb, 0x0f, 0x76, 0xe0, 0x5d, - 0xe5, 0x3d, 0xe0, 0x03, 0x05, 0xe7, 0x26, 0xe0, - 0x08, 0x66, 0xe4, 0x05, 0xe0, 0x38, 0x24, 0xe0, - 0x16, 0xe5, 0x97, 0x6a, 0xe0, 0x06, 0xe5, 0x82, - 0x6b, 0xe0, 0xa4, 0x85, 0xe5, 0x80, 0x97, 0xe0, - 0x49, 0xe5, 0x81, 0x04, 0xe0, 0x88, 0x7c, 0xe5, - 0x63, 0x80, 0xe5, 0x05, 0x40, 0xe5, 0x01, 0xc0, - 0xe5, 0x02, 0x20, 0x0f, 0x26, 0x16, 0x7b, 0xe0, - 0x92, 0xd4, 0xef, 0x80, 0x6e, 0xe0, 0x02, 0xef, - 0x1f, 0x20, 0xef, 0x34, 0x27, 0x46, 0x4f, 0xa7, - 0xfb, 0x00, 0xe6, 0x00, 0x2f, 0xc6, 0xef, 0x16, - 0x66, 0xef, 0x33, 0xe0, 0x0f, 0xef, 0x3a, 0x46, - 0x0f, 0xe0, 0x80, 0x12, 0xeb, 0x0c, 0xe0, 0x04, - 0xef, 0x4f, 0xe0, 0x01, 0xeb, 0x11, 0xe0, 0x7f, - 0xe1, 0x12, 0xe2, 0x12, 0xe1, 0x12, 0xc2, 0x00, - 0xe2, 0x0a, 0xe1, 0x12, 0xe2, 0x12, 0x01, 0x00, - 0x21, 0x20, 0x01, 0x20, 0x21, 0x20, 0x61, 0x00, - 0xe1, 0x00, 0x62, 0x00, 0x02, 0x00, 0xc2, 0x00, - 0xe2, 0x03, 0xe1, 0x12, 0xe2, 0x12, 0x21, 0x00, - 0x61, 0x20, 0xe1, 0x00, 0x00, 0xc1, 0x00, 0xe2, - 0x12, 0x21, 0x00, 0x61, 0x00, 0x81, 0x00, 0x01, - 0x40, 0xc1, 0x00, 0xe2, 0x12, 0xe1, 0x12, 0xe2, - 0x12, 0xe1, 0x12, 0xe2, 0x12, 0xe1, 0x12, 0xe2, - 0x12, 0xe1, 0x12, 0xe2, 0x12, 0xe1, 0x12, 0xe2, - 0x12, 0xe1, 0x12, 0xe2, 0x14, 0x20, 0xe1, 0x11, + 0x01, 0xe0, 0x04, 0x05, 0xe0, 0x80, 0x18, 0xe5, + 0x00, 0x20, 0xe5, 0x1f, 0x47, 0x66, 0x20, 0x26, + 0x67, 0x06, 0x05, 0x16, 0x05, 0x07, 0xe0, 0x13, + 0x05, 0xe6, 0x02, 0xe5, 0x20, 0xa6, 0x07, 0x05, + 0x66, 0xf6, 0x00, 0x06, 0xe0, 0x00, 0x05, 0xa6, + 0x27, 0x46, 0xe5, 0x26, 0xe6, 0x05, 0x07, 0x26, + 0x56, 0x05, 0x96, 0xe0, 0x15, 0xe5, 0x31, 0xe0, + 0x80, 0x7f, 0xe5, 0x01, 0x00, 0xe5, 0x1d, 0x07, + 0xc6, 0x00, 0xa6, 0x07, 0x06, 0x05, 0x96, 0xe0, + 0x02, 0xe9, 0x02, 0xeb, 0x0b, 0x40, 0x36, 0xe5, + 0x16, 0x20, 0xe6, 0x0e, 0x00, 0x07, 0xc6, 0x07, + 0x26, 0x07, 0x26, 0xe0, 0x41, 0xc5, 0x00, 0x25, + 0x00, 0xe5, 0x1e, 0xa6, 0x40, 0x06, 0x00, 0x26, + 0x00, 0xc6, 0x05, 0x06, 0xe0, 0x00, 0xe9, 0x02, + 0xa0, 0xa5, 0x00, 0x25, 0x00, 0xe5, 0x18, 0x87, + 0x00, 0x26, 0x00, 0x27, 0x06, 0x07, 0x06, 0x05, + 0xc0, 0xe9, 0x02, 0xe0, 0x80, 0xae, 0xe5, 0x0b, + 0x26, 0x27, 0x36, 0xe0, 0x80, 0x3f, 0xeb, 0x0d, + 0xef, 0x00, 0x6d, 0xef, 0x09, 0xe0, 0x05, 0x16, + 0xe5, 0x83, 0x12, 0xe0, 0x5e, 0xea, 0x67, 0x00, + 0x96, 0xe0, 0x03, 0xe5, 0x80, 0x3c, 0xe0, 0x8a, + 0x34, 0xe5, 0x83, 0xa7, 0x00, 0xfb, 0x01, 0xe0, + 0x8f, 0x3f, 0xe5, 0x81, 0xbf, 0xe0, 0xa1, 0x31, + 0xe5, 0x81, 0xb1, 0xc0, 0xe5, 0x17, 0x00, 0xe9, + 0x02, 0x60, 0x36, 0xe0, 0x58, 0xe5, 0x16, 0x20, + 0x86, 0x16, 0xe0, 0x02, 0xe5, 0x28, 0xc6, 0x96, + 0x6f, 0x64, 0x16, 0x0f, 0xe0, 0x02, 0xe9, 0x02, + 0x00, 0xcb, 0x00, 0xe5, 0x0d, 0x80, 0xe5, 0x0b, + 0xe0, 0x82, 0x28, 0xe1, 0x18, 0xe2, 0x18, 0xeb, + 0x0f, 0x76, 0xe0, 0x5d, 0xe5, 0x43, 0x60, 0x06, + 0x05, 0xe7, 0x2f, 0xc0, 0x66, 0xe4, 0x05, 0xe0, + 0x38, 0x24, 0x16, 0x04, 0xe0, 0x14, 0xe5, 0x97, + 0x70, 0xe0, 0x00, 0xe5, 0x82, 0x6b, 0xe0, 0xa4, + 0x85, 0xe5, 0x80, 0x97, 0xe0, 0x29, 0x45, 0xe0, + 0x09, 0x65, 0xe0, 0x00, 0xe5, 0x81, 0x04, 0xe0, + 0x88, 0x7c, 0xe5, 0x63, 0x80, 0xe5, 0x05, 0x40, + 0xe5, 0x01, 0xc0, 0xe5, 0x02, 0x20, 0x0f, 0x26, + 0x16, 0x7b, 0xe0, 0x92, 0xd4, 0xef, 0x80, 0x6e, + 0xe0, 0x02, 0xef, 0x1f, 0x20, 0xef, 0x34, 0x27, + 0x46, 0x4f, 0xa7, 0xfb, 0x00, 0xe6, 0x00, 0x2f, + 0xc6, 0xef, 0x16, 0x66, 0xef, 0x33, 0xe0, 0x0f, + 0xef, 0x3a, 0x46, 0x0f, 0xe0, 0x80, 0x12, 0xeb, + 0x0c, 0xe0, 0x04, 0xef, 0x4f, 0xe0, 0x01, 0xeb, + 0x11, 0xe0, 0x7f, 0xe1, 0x12, 0xe2, 0x12, 0xe1, + 0x12, 0xc2, 0x00, 0xe2, 0x0a, 0xe1, 0x12, 0xe2, + 0x12, 0x01, 0x00, 0x21, 0x20, 0x01, 0x20, 0x21, + 0x20, 0x61, 0x00, 0xe1, 0x00, 0x62, 0x00, 0x02, + 0x00, 0xc2, 0x00, 0xe2, 0x03, 0xe1, 0x12, 0xe2, + 0x12, 0x21, 0x00, 0x61, 0x20, 0xe1, 0x00, 0x00, + 0xc1, 0x00, 0xe2, 0x12, 0x21, 0x00, 0x61, 0x00, + 0x81, 0x00, 0x01, 0x40, 0xc1, 0x00, 0xe2, 0x12, + 0xe1, 0x12, 0xe2, 0x12, 0xe1, 0x12, 0xe2, 0x12, + 0xe1, 0x12, 0xe2, 0x12, 0xe1, 0x12, 0xe2, 0x12, + 0xe1, 0x12, 0xe2, 0x12, 0xe1, 0x12, 0xe2, 0x14, + 0x20, 0xe1, 0x11, 0x0c, 0xe2, 0x11, 0x0c, 0xa2, + 0xe1, 0x11, 0x0c, 0xe2, 0x11, 0x0c, 0xa2, 0xe1, + 0x11, 0x0c, 0xe2, 0x11, 0x0c, 0xa2, 0xe1, 0x11, 0x0c, 0xe2, 0x11, 0x0c, 0xa2, 0xe1, 0x11, 0x0c, - 0xe2, 0x11, 0x0c, 0xa2, 0xe1, 0x11, 0x0c, 0xe2, - 0x11, 0x0c, 0xa2, 0xe1, 0x11, 0x0c, 0xe2, 0x11, - 0x0c, 0xa2, 0xe1, 0x11, 0x0c, 0xe2, 0x11, 0x0c, - 0xa2, 0x3f, 0x20, 0xe9, 0x2a, 0xef, 0x81, 0x78, - 0xe6, 0x2f, 0x6f, 0xe6, 0x2a, 0xef, 0x00, 0x06, - 0xef, 0x06, 0x06, 0x2f, 0x96, 0xe0, 0x07, 0x86, - 0x00, 0xe6, 0x07, 0xe0, 0x84, 0xc8, 0xc6, 0x00, - 0xe6, 0x09, 0x20, 0xc6, 0x00, 0x26, 0x00, 0x86, - 0xe0, 0x87, 0x4d, 0xe5, 0x80, 0x3d, 0x20, 0xeb, - 0x01, 0xc6, 0xe0, 0x21, 0xe1, 0x1a, 0xe2, 0x1a, - 0xc6, 0x80, 0xe9, 0x02, 0x60, 0x36, 0xe0, 0x82, - 0x89, 0xeb, 0x33, 0x0f, 0x4b, 0x0d, 0x6b, 0xe0, - 0x80, 0xc3, 0x65, 0x00, 0xe5, 0x13, 0x00, 0x25, - 0x00, 0x05, 0x20, 0x05, 0x00, 0xe5, 0x02, 0x00, - 0x65, 0x00, 0x05, 0x00, 0x05, 0xa0, 0x05, 0x60, - 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x45, 0x00, - 0x25, 0x00, 0x05, 0x20, 0x05, 0x00, 0x05, 0x00, - 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x25, 0x00, - 0x05, 0x20, 0x65, 0x00, 0xc5, 0x00, 0x65, 0x00, - 0x65, 0x00, 0x05, 0x00, 0xe5, 0x02, 0x00, 0xe5, - 0x09, 0x80, 0x45, 0x00, 0x85, 0x00, 0xe5, 0x09, - 0xe0, 0x2c, 0x2c, 0xe0, 0x80, 0x86, 0xef, 0x24, - 0x60, 0xef, 0x5c, 0xe0, 0x04, 0xef, 0x07, 0x20, - 0xef, 0x07, 0x00, 0xef, 0x07, 0x00, 0xef, 0x1d, - 0xe0, 0x02, 0xeb, 0x05, 0x40, 0xef, 0x54, 0x60, - 0xef, 0x35, 0xe0, 0x31, 0xef, 0x15, 0xe0, 0x05, - 0xef, 0x24, 0x60, 0xef, 0x01, 0xc0, 0x2f, 0xe0, - 0x06, 0xaf, 0xe0, 0x80, 0x12, 0xef, 0x80, 0x73, - 0x8e, 0xef, 0x82, 0x4d, 0xe0, 0x03, 0xef, 0x05, - 0x40, 0xef, 0x02, 0xa0, 0xef, 0x6c, 0xe0, 0x04, - 0xef, 0x51, 0xe0, 0x1f, 0xef, 0x04, 0x60, 0xef, - 0x30, 0xe0, 0x00, 0xef, 0x02, 0xa0, 0xef, 0x20, - 0xe0, 0x00, 0xef, 0x16, 0xe0, 0x4a, 0xef, 0x04, - 0x60, 0xef, 0x27, 0x00, 0xef, 0x29, 0x20, 0x6f, - 0x40, 0x0f, 0x00, 0xef, 0x1f, 0xe0, 0x05, 0xef, - 0x02, 0xa0, 0x4f, 0xe0, 0x05, 0xef, 0x28, 0xe0, - 0x58, 0xef, 0x06, 0xe0, 0x85, 0x0a, 0xe5, 0xc0, + 0xe2, 0x11, 0x0c, 0xa2, 0x3f, 0x20, 0xe9, 0x2a, + 0xef, 0x81, 0x78, 0xe6, 0x2f, 0x6f, 0xe6, 0x2a, + 0xef, 0x00, 0x06, 0xef, 0x06, 0x06, 0x2f, 0x96, + 0xe0, 0x07, 0x86, 0x00, 0xe6, 0x07, 0xe0, 0x84, + 0xc8, 0xc6, 0x00, 0xe6, 0x09, 0x20, 0xc6, 0x00, + 0x26, 0x00, 0x86, 0xe0, 0x80, 0x4d, 0xe5, 0x25, + 0x40, 0xc6, 0xc4, 0x20, 0xe9, 0x02, 0x60, 0x05, + 0x0f, 0xe0, 0x80, 0xe8, 0xe5, 0x24, 0x66, 0xe9, + 0x02, 0x80, 0x0d, 0xe0, 0x84, 0x78, 0xe5, 0x80, + 0x3d, 0x20, 0xeb, 0x01, 0xc6, 0xe0, 0x21, 0xe1, + 0x1a, 0xe2, 0x1a, 0xc6, 0x04, 0x60, 0xe9, 0x02, + 0x60, 0x36, 0xe0, 0x82, 0x89, 0xeb, 0x33, 0x0f, + 0x4b, 0x0d, 0x6b, 0xe0, 0x44, 0xeb, 0x25, 0x0f, + 0xeb, 0x07, 0xe0, 0x80, 0x3a, 0x65, 0x00, 0xe5, + 0x13, 0x00, 0x25, 0x00, 0x05, 0x20, 0x05, 0x00, + 0xe5, 0x02, 0x00, 0x65, 0x00, 0x05, 0x00, 0x05, + 0xa0, 0x05, 0x60, 0x05, 0x00, 0x05, 0x00, 0x05, + 0x00, 0x45, 0x00, 0x25, 0x00, 0x05, 0x20, 0x05, + 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, + 0x00, 0x25, 0x00, 0x05, 0x20, 0x65, 0x00, 0xc5, + 0x00, 0x65, 0x00, 0x65, 0x00, 0x05, 0x00, 0xe5, + 0x02, 0x00, 0xe5, 0x09, 0x80, 0x45, 0x00, 0x85, + 0x00, 0xe5, 0x09, 0xe0, 0x2c, 0x2c, 0xe0, 0x80, + 0x86, 0xef, 0x24, 0x60, 0xef, 0x5c, 0xe0, 0x04, + 0xef, 0x07, 0x20, 0xef, 0x07, 0x00, 0xef, 0x07, + 0x00, 0xef, 0x1d, 0xe0, 0x02, 0xeb, 0x05, 0x40, + 0xef, 0x55, 0x40, 0xef, 0x35, 0xe0, 0x31, 0xef, + 0x15, 0xe0, 0x05, 0xef, 0x24, 0x60, 0xef, 0x01, + 0xc0, 0x2f, 0xe0, 0x06, 0xaf, 0xe0, 0x80, 0x12, + 0xef, 0x80, 0x73, 0x8e, 0xef, 0x82, 0x4e, 0xe0, + 0x02, 0xef, 0x05, 0x40, 0xef, 0x03, 0x80, 0xef, + 0x6c, 0xe0, 0x04, 0xef, 0x51, 0xc0, 0xef, 0x04, + 0xe0, 0x0c, 0xef, 0x04, 0x60, 0xef, 0x30, 0xe0, + 0x00, 0xef, 0x02, 0xa0, 0xef, 0x20, 0xe0, 0x00, + 0xef, 0x16, 0xe0, 0x4a, 0xef, 0x04, 0x00, 0xef, + 0x5d, 0x00, 0x6f, 0x40, 0xef, 0x21, 0x20, 0xaf, + 0x40, 0xef, 0x15, 0x20, 0xef, 0x7f, 0xe0, 0x04, + 0xef, 0x06, 0x20, 0x6f, 0x60, 0x4f, 0x80, 0x4f, + 0xe0, 0x05, 0xaf, 0xe0, 0x84, 0xe2, 0xe5, 0xc0, 0x66, 0x4f, 0xe0, 0x21, 0xe5, 0x8f, 0xad, 0xe0, 0x03, 0xe5, 0x80, 0x56, 0x20, 0xe5, 0x95, 0xfa, 0xe0, 0x06, 0xe5, 0x9c, 0xa9, 0xe0, 0x8b, 0x97, @@ -2745,6 +2764,7 @@ typedef enum { UNICODE_SCRIPT_Duployan, UNICODE_SCRIPT_Egyptian_Hieroglyphs, UNICODE_SCRIPT_Elbasan, + UNICODE_SCRIPT_Elymaic, UNICODE_SCRIPT_Ethiopic, UNICODE_SCRIPT_Georgian, UNICODE_SCRIPT_Glagolitic, @@ -2802,10 +2822,12 @@ typedef enum { UNICODE_SCRIPT_Multani, UNICODE_SCRIPT_Myanmar, UNICODE_SCRIPT_Nabataean, + UNICODE_SCRIPT_Nandinagari, UNICODE_SCRIPT_New_Tai_Lue, UNICODE_SCRIPT_Newa, UNICODE_SCRIPT_Nko, UNICODE_SCRIPT_Nushu, + UNICODE_SCRIPT_Nyiakeng_Puachue_Hmong, UNICODE_SCRIPT_Ogham, UNICODE_SCRIPT_Ol_Chiki, UNICODE_SCRIPT_Old_Hungarian, @@ -2856,6 +2878,7 @@ typedef enum { UNICODE_SCRIPT_Tirhuta, UNICODE_SCRIPT_Ugaritic, UNICODE_SCRIPT_Vai, + UNICODE_SCRIPT_Wancho, UNICODE_SCRIPT_Warang_Citi, UNICODE_SCRIPT_Yi, UNICODE_SCRIPT_Zanabazar_Square, @@ -2897,6 +2920,7 @@ static const char unicode_script_name_table[] = "Duployan,Dupl" "\0" "Egyptian_Hieroglyphs,Egyp" "\0" "Elbasan,Elba" "\0" + "Elymaic,Elym" "\0" "Ethiopic,Ethi" "\0" "Georgian,Geor" "\0" "Glagolitic,Glag" "\0" @@ -2954,10 +2978,12 @@ static const char unicode_script_name_table[] = "Multani,Mult" "\0" "Myanmar,Mymr" "\0" "Nabataean,Nbat" "\0" + "Nandinagari,Nand" "\0" "New_Tai_Lue,Talu" "\0" "Newa,Newa" "\0" "Nko,Nkoo" "\0" "Nushu,Nshu" "\0" + "Nyiakeng_Puachue_Hmong,Hmnp" "\0" "Ogham,Ogam" "\0" "Ol_Chiki,Olck" "\0" "Old_Hungarian,Hung" "\0" @@ -3008,296 +3034,301 @@ static const char unicode_script_name_table[] = "Tirhuta,Tirh" "\0" "Ugaritic,Ugar" "\0" "Vai,Vaii" "\0" + "Wancho,Wcho" "\0" "Warang_Citi,Wara" "\0" "Yi,Yiii" "\0" "Zanabazar_Square,Zanb" "\0" ; -static const uint8_t unicode_script_table[2522] = { - 0xc0, 0x18, 0x99, 0x41, 0x85, 0x18, 0x99, 0x41, - 0xae, 0x18, 0x80, 0x41, 0x8e, 0x18, 0x80, 0x41, - 0x84, 0x18, 0x96, 0x41, 0x80, 0x18, 0x9e, 0x41, - 0x80, 0x18, 0xe1, 0x60, 0x41, 0xa6, 0x18, 0x84, - 0x41, 0x84, 0x18, 0x81, 0x0d, 0x93, 0x18, 0xe0, - 0x0f, 0x34, 0x83, 0x28, 0x80, 0x18, 0x82, 0x28, - 0x01, 0x83, 0x28, 0x80, 0x18, 0x80, 0x28, 0x03, - 0x80, 0x28, 0x80, 0x18, 0x80, 0x28, 0x80, 0x18, - 0x82, 0x28, 0x00, 0x80, 0x28, 0x00, 0x93, 0x28, - 0x00, 0xbe, 0x28, 0x8d, 0x19, 0x8f, 0x28, 0xe0, - 0x24, 0x1c, 0x81, 0x34, 0xe0, 0x48, 0x1c, 0x00, +static const uint8_t unicode_script_table[2565] = { + 0xc0, 0x18, 0x99, 0x42, 0x85, 0x18, 0x99, 0x42, + 0xae, 0x18, 0x80, 0x42, 0x8e, 0x18, 0x80, 0x42, + 0x84, 0x18, 0x96, 0x42, 0x80, 0x18, 0x9e, 0x42, + 0x80, 0x18, 0xe1, 0x60, 0x42, 0xa6, 0x18, 0x84, + 0x42, 0x84, 0x18, 0x81, 0x0d, 0x93, 0x18, 0xe0, + 0x0f, 0x35, 0x83, 0x29, 0x80, 0x18, 0x82, 0x29, + 0x01, 0x83, 0x29, 0x80, 0x18, 0x80, 0x29, 0x03, + 0x80, 0x29, 0x80, 0x18, 0x80, 0x29, 0x80, 0x18, + 0x82, 0x29, 0x00, 0x80, 0x29, 0x00, 0x93, 0x29, + 0x00, 0xbe, 0x29, 0x8d, 0x19, 0x8f, 0x29, 0xe0, + 0x24, 0x1c, 0x81, 0x35, 0xe0, 0x48, 0x1c, 0x00, 0xa5, 0x05, 0x01, 0xaf, 0x05, 0x80, 0x18, 0x80, - 0x05, 0x01, 0x82, 0x05, 0x00, 0xb6, 0x31, 0x07, - 0x9a, 0x31, 0x03, 0x85, 0x31, 0x0a, 0x84, 0x04, + 0x05, 0x01, 0x82, 0x05, 0x00, 0xb6, 0x32, 0x07, + 0x9a, 0x32, 0x03, 0x85, 0x32, 0x0a, 0x84, 0x04, 0x80, 0x18, 0x85, 0x04, 0x80, 0x18, 0x8d, 0x04, 0x80, 0x18, 0x80, 0x04, 0x00, 0x80, 0x04, 0x80, 0x18, 0x9f, 0x04, 0x80, 0x18, 0x89, 0x04, 0x8a, - 0x34, 0x99, 0x04, 0x80, 0x34, 0xe0, 0x0b, 0x04, - 0x80, 0x18, 0xa1, 0x04, 0x8d, 0x81, 0x00, 0xbb, - 0x81, 0x01, 0x82, 0x81, 0xaf, 0x04, 0xb1, 0x8b, - 0x0d, 0xba, 0x5e, 0x01, 0x82, 0x5e, 0xad, 0x75, - 0x01, 0x8e, 0x75, 0x00, 0x9b, 0x4c, 0x01, 0x80, - 0x4c, 0x00, 0x8a, 0x81, 0x34, 0x94, 0x04, 0x00, + 0x35, 0x99, 0x04, 0x80, 0x35, 0xe0, 0x0b, 0x04, + 0x80, 0x18, 0xa1, 0x04, 0x8d, 0x84, 0x00, 0xbb, + 0x84, 0x01, 0x82, 0x84, 0xaf, 0x04, 0xb1, 0x8e, + 0x0d, 0xba, 0x60, 0x01, 0x82, 0x60, 0xad, 0x78, + 0x01, 0x8e, 0x78, 0x00, 0x9b, 0x4d, 0x01, 0x80, + 0x4d, 0x00, 0x8a, 0x84, 0x34, 0x94, 0x04, 0x00, 0x87, 0x04, 0x14, 0x8e, 0x04, 0x80, 0x18, 0x9c, - 0x04, 0xd0, 0x1e, 0x81, 0x34, 0x90, 0x1e, 0x81, + 0x04, 0xd0, 0x1e, 0x83, 0x35, 0x8e, 0x1e, 0x81, 0x18, 0x99, 0x1e, 0x83, 0x0b, 0x00, 0x87, 0x0b, 0x01, 0x81, 0x0b, 0x01, 0x95, 0x0b, 0x00, 0x86, 0x0b, 0x00, 0x80, 0x0b, 0x02, 0x83, 0x0b, 0x01, 0x88, 0x0b, 0x01, 0x81, 0x0b, 0x01, 0x83, 0x0b, 0x07, 0x80, 0x0b, 0x03, 0x81, 0x0b, 0x00, 0x84, - 0x0b, 0x01, 0x98, 0x0b, 0x01, 0x82, 0x2b, 0x00, - 0x85, 0x2b, 0x03, 0x81, 0x2b, 0x01, 0x95, 0x2b, - 0x00, 0x86, 0x2b, 0x00, 0x81, 0x2b, 0x00, 0x81, - 0x2b, 0x00, 0x81, 0x2b, 0x01, 0x80, 0x2b, 0x00, - 0x84, 0x2b, 0x03, 0x81, 0x2b, 0x01, 0x82, 0x2b, - 0x02, 0x80, 0x2b, 0x06, 0x83, 0x2b, 0x00, 0x80, - 0x2b, 0x06, 0x90, 0x2b, 0x09, 0x82, 0x29, 0x00, - 0x88, 0x29, 0x00, 0x82, 0x29, 0x00, 0x95, 0x29, - 0x00, 0x86, 0x29, 0x00, 0x81, 0x29, 0x00, 0x84, - 0x29, 0x01, 0x89, 0x29, 0x00, 0x82, 0x29, 0x00, - 0x82, 0x29, 0x01, 0x80, 0x29, 0x0e, 0x83, 0x29, - 0x01, 0x8b, 0x29, 0x06, 0x86, 0x29, 0x00, 0x82, - 0x6a, 0x00, 0x87, 0x6a, 0x01, 0x81, 0x6a, 0x01, - 0x95, 0x6a, 0x00, 0x86, 0x6a, 0x00, 0x81, 0x6a, - 0x00, 0x84, 0x6a, 0x01, 0x88, 0x6a, 0x01, 0x81, - 0x6a, 0x01, 0x82, 0x6a, 0x07, 0x81, 0x6a, 0x03, - 0x81, 0x6a, 0x00, 0x84, 0x6a, 0x01, 0x91, 0x6a, - 0x09, 0x81, 0x88, 0x00, 0x85, 0x88, 0x02, 0x82, - 0x88, 0x00, 0x83, 0x88, 0x02, 0x81, 0x88, 0x00, - 0x80, 0x88, 0x00, 0x81, 0x88, 0x02, 0x81, 0x88, - 0x02, 0x82, 0x88, 0x02, 0x8b, 0x88, 0x03, 0x84, - 0x88, 0x02, 0x82, 0x88, 0x00, 0x83, 0x88, 0x01, - 0x80, 0x88, 0x05, 0x80, 0x88, 0x0d, 0x94, 0x88, - 0x04, 0x8c, 0x8a, 0x00, 0x82, 0x8a, 0x00, 0x96, - 0x8a, 0x00, 0x8f, 0x8a, 0x02, 0x87, 0x8a, 0x00, - 0x82, 0x8a, 0x00, 0x83, 0x8a, 0x06, 0x81, 0x8a, - 0x00, 0x82, 0x8a, 0x04, 0x83, 0x8a, 0x01, 0x89, - 0x8a, 0x07, 0x87, 0x8a, 0x8c, 0x39, 0x00, 0x82, - 0x39, 0x00, 0x96, 0x39, 0x00, 0x89, 0x39, 0x00, - 0x84, 0x39, 0x01, 0x88, 0x39, 0x00, 0x82, 0x39, - 0x00, 0x83, 0x39, 0x06, 0x81, 0x39, 0x06, 0x80, - 0x39, 0x00, 0x83, 0x39, 0x01, 0x89, 0x39, 0x00, - 0x81, 0x39, 0x0c, 0x83, 0x4b, 0x00, 0x87, 0x4b, - 0x00, 0x82, 0x4b, 0x00, 0xb2, 0x4b, 0x00, 0x82, - 0x4b, 0x00, 0x85, 0x4b, 0x03, 0x8f, 0x4b, 0x01, - 0x99, 0x4b, 0x01, 0x81, 0x7b, 0x00, 0x91, 0x7b, - 0x02, 0x97, 0x7b, 0x00, 0x88, 0x7b, 0x00, 0x80, - 0x7b, 0x01, 0x86, 0x7b, 0x02, 0x80, 0x7b, 0x03, - 0x85, 0x7b, 0x00, 0x80, 0x7b, 0x00, 0x87, 0x7b, - 0x05, 0x89, 0x7b, 0x01, 0x82, 0x7b, 0x0b, 0xb9, - 0x8c, 0x03, 0x80, 0x18, 0x9b, 0x8c, 0x24, 0x81, - 0x40, 0x00, 0x80, 0x40, 0x01, 0x81, 0x40, 0x00, - 0x80, 0x40, 0x01, 0x80, 0x40, 0x05, 0x83, 0x40, - 0x00, 0x86, 0x40, 0x00, 0x82, 0x40, 0x00, 0x80, - 0x40, 0x00, 0x80, 0x40, 0x01, 0x81, 0x40, 0x00, - 0x8c, 0x40, 0x00, 0x82, 0x40, 0x01, 0x84, 0x40, - 0x00, 0x80, 0x40, 0x00, 0x85, 0x40, 0x01, 0x89, - 0x40, 0x01, 0x83, 0x40, 0x1f, 0xc7, 0x8d, 0x00, - 0xa3, 0x8d, 0x03, 0xa6, 0x8d, 0x00, 0xa3, 0x8d, - 0x00, 0x8e, 0x8d, 0x00, 0x86, 0x8d, 0x83, 0x18, - 0x81, 0x8d, 0x24, 0xe0, 0x3f, 0x5a, 0xa5, 0x24, - 0x00, 0x80, 0x24, 0x04, 0x80, 0x24, 0x01, 0xaa, - 0x24, 0x80, 0x18, 0x83, 0x24, 0xe0, 0x9f, 0x2d, - 0xc8, 0x23, 0x00, 0x83, 0x23, 0x01, 0x86, 0x23, - 0x00, 0x80, 0x23, 0x00, 0x83, 0x23, 0x01, 0xa8, - 0x23, 0x00, 0x83, 0x23, 0x01, 0xa0, 0x23, 0x00, - 0x83, 0x23, 0x01, 0x86, 0x23, 0x00, 0x80, 0x23, - 0x00, 0x83, 0x23, 0x01, 0x8e, 0x23, 0x00, 0xb8, - 0x23, 0x00, 0x83, 0x23, 0x01, 0xc2, 0x23, 0x01, - 0x9f, 0x23, 0x02, 0x99, 0x23, 0x05, 0xd5, 0x17, - 0x01, 0x85, 0x17, 0x01, 0xe2, 0x1f, 0x12, 0x9c, - 0x60, 0x02, 0xca, 0x74, 0x82, 0x18, 0x8a, 0x74, - 0x06, 0x8c, 0x82, 0x00, 0x86, 0x82, 0x0a, 0x94, - 0x2f, 0x81, 0x18, 0x08, 0x93, 0x11, 0x0b, 0x8c, - 0x83, 0x00, 0x82, 0x83, 0x00, 0x81, 0x83, 0x0b, - 0xdd, 0x3d, 0x01, 0x89, 0x3d, 0x05, 0x89, 0x3d, - 0x05, 0x81, 0x57, 0x81, 0x18, 0x80, 0x57, 0x80, - 0x18, 0x88, 0x57, 0x00, 0x89, 0x57, 0x05, 0xd8, - 0x57, 0x06, 0xaa, 0x57, 0x04, 0xc5, 0x12, 0x09, - 0x9e, 0x43, 0x00, 0x8b, 0x43, 0x03, 0x8b, 0x43, - 0x03, 0x80, 0x43, 0x02, 0x8b, 0x43, 0x9d, 0x84, - 0x01, 0x84, 0x84, 0x0a, 0xab, 0x5c, 0x03, 0x99, - 0x5c, 0x05, 0x8a, 0x5c, 0x02, 0x81, 0x5c, 0x9f, - 0x3d, 0x9b, 0x10, 0x01, 0x81, 0x10, 0xbe, 0x85, - 0x00, 0x9c, 0x85, 0x01, 0x8a, 0x85, 0x05, 0x89, - 0x85, 0x05, 0x8d, 0x85, 0x01, 0x8e, 0x34, 0x40, - 0xcb, 0x07, 0x03, 0xac, 0x07, 0x02, 0xbf, 0x7f, - 0xb3, 0x0a, 0x07, 0x83, 0x0a, 0xb7, 0x42, 0x02, - 0x8e, 0x42, 0x02, 0x82, 0x42, 0xaf, 0x61, 0x88, - 0x1c, 0x06, 0xaa, 0x24, 0x01, 0x82, 0x24, 0x87, - 0x7f, 0x07, 0x82, 0x34, 0x80, 0x18, 0x8c, 0x34, - 0x80, 0x18, 0x86, 0x34, 0x83, 0x18, 0x80, 0x34, - 0x85, 0x18, 0x80, 0x34, 0x82, 0x18, 0x81, 0x34, - 0x05, 0xa5, 0x41, 0x84, 0x28, 0x80, 0x1c, 0xb0, - 0x41, 0x84, 0x28, 0x83, 0x41, 0x84, 0x28, 0x8c, - 0x41, 0x80, 0x1c, 0xc5, 0x41, 0x80, 0x28, 0xb9, - 0x34, 0x00, 0x84, 0x34, 0xe0, 0x9f, 0x41, 0x95, - 0x28, 0x01, 0x85, 0x28, 0x01, 0xa5, 0x28, 0x01, - 0x85, 0x28, 0x01, 0x87, 0x28, 0x00, 0x80, 0x28, - 0x00, 0x80, 0x28, 0x00, 0x80, 0x28, 0x00, 0x9e, - 0x28, 0x01, 0xb4, 0x28, 0x00, 0x8e, 0x28, 0x00, - 0x8d, 0x28, 0x01, 0x85, 0x28, 0x00, 0x92, 0x28, - 0x01, 0x82, 0x28, 0x00, 0x88, 0x28, 0x00, 0x8b, - 0x18, 0x81, 0x34, 0xd6, 0x18, 0x00, 0x8a, 0x18, - 0x80, 0x41, 0x01, 0x8a, 0x18, 0x80, 0x41, 0x8e, - 0x18, 0x00, 0x8c, 0x41, 0x02, 0x9f, 0x18, 0x0f, - 0xa0, 0x34, 0x0e, 0xa5, 0x18, 0x80, 0x28, 0x82, - 0x18, 0x81, 0x41, 0x85, 0x18, 0x80, 0x41, 0x9a, - 0x18, 0x80, 0x41, 0x90, 0x18, 0xa8, 0x41, 0x82, - 0x18, 0x03, 0xe2, 0x36, 0x18, 0x18, 0x8a, 0x18, - 0x14, 0xe3, 0x3f, 0x18, 0xe0, 0x9f, 0x0f, 0xe2, - 0x13, 0x18, 0x01, 0x9f, 0x18, 0x01, 0xb0, 0x18, - 0x00, 0xb4, 0x18, 0x00, 0xae, 0x25, 0x00, 0xae, - 0x25, 0x00, 0x9f, 0x41, 0xe0, 0x13, 0x19, 0x04, - 0x86, 0x19, 0xa5, 0x24, 0x00, 0x80, 0x24, 0x04, - 0x80, 0x24, 0x01, 0xb7, 0x8e, 0x06, 0x81, 0x8e, - 0x0d, 0x80, 0x8e, 0x96, 0x23, 0x08, 0x86, 0x23, - 0x00, 0x86, 0x23, 0x00, 0x86, 0x23, 0x00, 0x86, - 0x23, 0x00, 0x86, 0x23, 0x00, 0x86, 0x23, 0x00, - 0x86, 0x23, 0x00, 0x86, 0x23, 0x00, 0x9f, 0x1c, - 0xce, 0x18, 0x30, 0x99, 0x2c, 0x00, 0xd8, 0x2c, - 0x0b, 0xe0, 0x75, 0x2c, 0x19, 0x8b, 0x18, 0x03, - 0x84, 0x18, 0x80, 0x2c, 0x80, 0x18, 0x80, 0x2c, - 0x98, 0x18, 0x88, 0x2c, 0x83, 0x34, 0x81, 0x2d, - 0x87, 0x18, 0x83, 0x2c, 0x83, 0x18, 0x00, 0xd5, - 0x32, 0x01, 0x81, 0x34, 0x81, 0x18, 0x82, 0x32, - 0x80, 0x18, 0xd9, 0x3a, 0x81, 0x18, 0x82, 0x3a, - 0x04, 0xaa, 0x0d, 0x00, 0xdd, 0x2d, 0x00, 0x8f, - 0x18, 0x9a, 0x0d, 0x04, 0xa3, 0x18, 0x0b, 0x8f, - 0x3a, 0x9e, 0x2d, 0x00, 0xbf, 0x18, 0x9e, 0x2d, - 0xd0, 0x18, 0xae, 0x3a, 0x00, 0xd7, 0x3a, 0xe0, - 0x47, 0x18, 0xf0, 0x09, 0x55, 0x2c, 0x09, 0xbf, - 0x18, 0xf0, 0x41, 0x8f, 0x2c, 0x0f, 0xe4, 0x2c, - 0x93, 0x02, 0xb6, 0x93, 0x08, 0xaf, 0x46, 0xe0, - 0xcb, 0x91, 0x13, 0xdf, 0x1c, 0xd7, 0x08, 0x07, - 0xa1, 0x18, 0xe0, 0x05, 0x41, 0x82, 0x18, 0xae, - 0x41, 0x3c, 0x88, 0x41, 0xab, 0x80, 0x03, 0x89, - 0x18, 0x05, 0xb7, 0x70, 0x07, 0xc5, 0x76, 0x07, - 0x8b, 0x76, 0x05, 0x9f, 0x1e, 0xad, 0x3b, 0x80, - 0x18, 0x80, 0x3b, 0xa3, 0x73, 0x0a, 0x80, 0x73, - 0x9c, 0x2d, 0x02, 0xcd, 0x37, 0x00, 0x80, 0x18, - 0x89, 0x37, 0x03, 0x81, 0x37, 0x9e, 0x5a, 0x00, - 0xb6, 0x16, 0x08, 0x8d, 0x16, 0x01, 0x89, 0x16, - 0x01, 0x83, 0x16, 0x9f, 0x5a, 0xc2, 0x86, 0x17, - 0x84, 0x86, 0x96, 0x51, 0x09, 0x85, 0x23, 0x01, - 0x85, 0x23, 0x01, 0x85, 0x23, 0x08, 0x86, 0x23, - 0x00, 0x86, 0x23, 0x00, 0xaa, 0x41, 0x80, 0x18, - 0x88, 0x41, 0x80, 0x28, 0x09, 0xcf, 0x17, 0xad, - 0x51, 0x01, 0x89, 0x51, 0x05, 0xf0, 0x1b, 0x43, - 0x2d, 0x0b, 0x96, 0x2d, 0x03, 0xb0, 0x2d, 0x70, - 0x10, 0xa3, 0xe1, 0x0d, 0x2c, 0x01, 0xe0, 0x09, - 0x2c, 0x25, 0x86, 0x41, 0x0b, 0x84, 0x05, 0x04, - 0x99, 0x31, 0x00, 0x84, 0x31, 0x00, 0x80, 0x31, - 0x00, 0x81, 0x31, 0x00, 0x81, 0x31, 0x00, 0x89, - 0x31, 0xe0, 0x11, 0x04, 0x10, 0xe1, 0x0a, 0x04, + 0x0b, 0x01, 0x98, 0x0b, 0x01, 0x82, 0x2c, 0x00, + 0x85, 0x2c, 0x03, 0x81, 0x2c, 0x01, 0x95, 0x2c, + 0x00, 0x86, 0x2c, 0x00, 0x81, 0x2c, 0x00, 0x81, + 0x2c, 0x00, 0x81, 0x2c, 0x01, 0x80, 0x2c, 0x00, + 0x84, 0x2c, 0x03, 0x81, 0x2c, 0x01, 0x82, 0x2c, + 0x02, 0x80, 0x2c, 0x06, 0x83, 0x2c, 0x00, 0x80, + 0x2c, 0x06, 0x90, 0x2c, 0x09, 0x82, 0x2a, 0x00, + 0x88, 0x2a, 0x00, 0x82, 0x2a, 0x00, 0x95, 0x2a, + 0x00, 0x86, 0x2a, 0x00, 0x81, 0x2a, 0x00, 0x84, + 0x2a, 0x01, 0x89, 0x2a, 0x00, 0x82, 0x2a, 0x00, + 0x82, 0x2a, 0x01, 0x80, 0x2a, 0x0e, 0x83, 0x2a, + 0x01, 0x8b, 0x2a, 0x06, 0x86, 0x2a, 0x00, 0x82, + 0x6d, 0x00, 0x87, 0x6d, 0x01, 0x81, 0x6d, 0x01, + 0x95, 0x6d, 0x00, 0x86, 0x6d, 0x00, 0x81, 0x6d, + 0x00, 0x84, 0x6d, 0x01, 0x88, 0x6d, 0x01, 0x81, + 0x6d, 0x01, 0x82, 0x6d, 0x07, 0x81, 0x6d, 0x03, + 0x81, 0x6d, 0x00, 0x84, 0x6d, 0x01, 0x91, 0x6d, + 0x09, 0x81, 0x8b, 0x00, 0x85, 0x8b, 0x02, 0x82, + 0x8b, 0x00, 0x83, 0x8b, 0x02, 0x81, 0x8b, 0x00, + 0x80, 0x8b, 0x00, 0x81, 0x8b, 0x02, 0x81, 0x8b, + 0x02, 0x82, 0x8b, 0x02, 0x8b, 0x8b, 0x03, 0x84, + 0x8b, 0x02, 0x82, 0x8b, 0x00, 0x83, 0x8b, 0x01, + 0x80, 0x8b, 0x05, 0x80, 0x8b, 0x0d, 0x94, 0x8b, + 0x04, 0x8c, 0x8d, 0x00, 0x82, 0x8d, 0x00, 0x96, + 0x8d, 0x00, 0x8f, 0x8d, 0x02, 0x87, 0x8d, 0x00, + 0x82, 0x8d, 0x00, 0x83, 0x8d, 0x06, 0x81, 0x8d, + 0x00, 0x82, 0x8d, 0x04, 0x83, 0x8d, 0x01, 0x89, + 0x8d, 0x06, 0x88, 0x8d, 0x8c, 0x3a, 0x00, 0x82, + 0x3a, 0x00, 0x96, 0x3a, 0x00, 0x89, 0x3a, 0x00, + 0x84, 0x3a, 0x01, 0x88, 0x3a, 0x00, 0x82, 0x3a, + 0x00, 0x83, 0x3a, 0x06, 0x81, 0x3a, 0x06, 0x80, + 0x3a, 0x00, 0x83, 0x3a, 0x01, 0x89, 0x3a, 0x00, + 0x81, 0x3a, 0x0c, 0x83, 0x4c, 0x00, 0x87, 0x4c, + 0x00, 0x82, 0x4c, 0x00, 0xb2, 0x4c, 0x00, 0x82, + 0x4c, 0x00, 0x85, 0x4c, 0x03, 0x8f, 0x4c, 0x01, + 0x99, 0x4c, 0x01, 0x81, 0x7e, 0x00, 0x91, 0x7e, + 0x02, 0x97, 0x7e, 0x00, 0x88, 0x7e, 0x00, 0x80, + 0x7e, 0x01, 0x86, 0x7e, 0x02, 0x80, 0x7e, 0x03, + 0x85, 0x7e, 0x00, 0x80, 0x7e, 0x00, 0x87, 0x7e, + 0x05, 0x89, 0x7e, 0x01, 0x82, 0x7e, 0x0b, 0xb9, + 0x8f, 0x03, 0x80, 0x18, 0x9b, 0x8f, 0x24, 0x81, + 0x41, 0x00, 0x80, 0x41, 0x00, 0x84, 0x41, 0x00, + 0x97, 0x41, 0x00, 0x80, 0x41, 0x00, 0x96, 0x41, + 0x01, 0x84, 0x41, 0x00, 0x80, 0x41, 0x00, 0x85, + 0x41, 0x01, 0x89, 0x41, 0x01, 0x83, 0x41, 0x1f, + 0xc7, 0x90, 0x00, 0xa3, 0x90, 0x03, 0xa6, 0x90, + 0x00, 0xa3, 0x90, 0x00, 0x8e, 0x90, 0x00, 0x86, + 0x90, 0x83, 0x18, 0x81, 0x90, 0x24, 0xe0, 0x3f, + 0x5b, 0xa5, 0x25, 0x00, 0x80, 0x25, 0x04, 0x80, + 0x25, 0x01, 0xaa, 0x25, 0x80, 0x18, 0x83, 0x25, + 0xe0, 0x9f, 0x2e, 0xc8, 0x24, 0x00, 0x83, 0x24, + 0x01, 0x86, 0x24, 0x00, 0x80, 0x24, 0x00, 0x83, + 0x24, 0x01, 0xa8, 0x24, 0x00, 0x83, 0x24, 0x01, + 0xa0, 0x24, 0x00, 0x83, 0x24, 0x01, 0x86, 0x24, + 0x00, 0x80, 0x24, 0x00, 0x83, 0x24, 0x01, 0x8e, + 0x24, 0x00, 0xb8, 0x24, 0x00, 0x83, 0x24, 0x01, + 0xc2, 0x24, 0x01, 0x9f, 0x24, 0x02, 0x99, 0x24, + 0x05, 0xd5, 0x17, 0x01, 0x85, 0x17, 0x01, 0xe2, + 0x1f, 0x12, 0x9c, 0x63, 0x02, 0xca, 0x77, 0x82, + 0x18, 0x8a, 0x77, 0x06, 0x8c, 0x85, 0x00, 0x86, + 0x85, 0x0a, 0x94, 0x30, 0x81, 0x18, 0x08, 0x93, + 0x11, 0x0b, 0x8c, 0x86, 0x00, 0x82, 0x86, 0x00, + 0x81, 0x86, 0x0b, 0xdd, 0x3e, 0x01, 0x89, 0x3e, + 0x05, 0x89, 0x3e, 0x05, 0x81, 0x58, 0x81, 0x18, + 0x80, 0x58, 0x80, 0x18, 0x88, 0x58, 0x00, 0x89, + 0x58, 0x05, 0xd8, 0x58, 0x06, 0xaa, 0x58, 0x04, + 0xc5, 0x12, 0x09, 0x9e, 0x44, 0x00, 0x8b, 0x44, + 0x03, 0x8b, 0x44, 0x03, 0x80, 0x44, 0x02, 0x8b, + 0x44, 0x9d, 0x87, 0x01, 0x84, 0x87, 0x0a, 0xab, + 0x5e, 0x03, 0x99, 0x5e, 0x05, 0x8a, 0x5e, 0x02, + 0x81, 0x5e, 0x9f, 0x3e, 0x9b, 0x10, 0x01, 0x81, + 0x10, 0xbe, 0x88, 0x00, 0x9c, 0x88, 0x01, 0x8a, + 0x88, 0x05, 0x89, 0x88, 0x05, 0x8d, 0x88, 0x01, + 0x8e, 0x35, 0x40, 0xcb, 0x07, 0x03, 0xac, 0x07, + 0x02, 0xbf, 0x82, 0xb3, 0x0a, 0x07, 0x83, 0x0a, + 0xb7, 0x43, 0x02, 0x8e, 0x43, 0x02, 0x82, 0x43, + 0xaf, 0x64, 0x88, 0x1c, 0x06, 0xaa, 0x25, 0x01, + 0x82, 0x25, 0x87, 0x82, 0x07, 0x82, 0x35, 0x80, + 0x18, 0x8c, 0x35, 0x80, 0x18, 0x86, 0x35, 0x83, + 0x18, 0x80, 0x35, 0x85, 0x18, 0x80, 0x35, 0x82, + 0x18, 0x81, 0x35, 0x80, 0x18, 0x04, 0xa5, 0x42, + 0x84, 0x29, 0x80, 0x1c, 0xb0, 0x42, 0x84, 0x29, + 0x83, 0x42, 0x84, 0x29, 0x8c, 0x42, 0x80, 0x1c, + 0xc5, 0x42, 0x80, 0x29, 0xb9, 0x35, 0x00, 0x84, + 0x35, 0xe0, 0x9f, 0x42, 0x95, 0x29, 0x01, 0x85, + 0x29, 0x01, 0xa5, 0x29, 0x01, 0x85, 0x29, 0x01, + 0x87, 0x29, 0x00, 0x80, 0x29, 0x00, 0x80, 0x29, + 0x00, 0x80, 0x29, 0x00, 0x9e, 0x29, 0x01, 0xb4, + 0x29, 0x00, 0x8e, 0x29, 0x00, 0x8d, 0x29, 0x01, + 0x85, 0x29, 0x00, 0x92, 0x29, 0x01, 0x82, 0x29, + 0x00, 0x88, 0x29, 0x00, 0x8b, 0x18, 0x81, 0x35, + 0xd6, 0x18, 0x00, 0x8a, 0x18, 0x80, 0x42, 0x01, + 0x8a, 0x18, 0x80, 0x42, 0x8e, 0x18, 0x00, 0x8c, + 0x42, 0x02, 0x9f, 0x18, 0x0f, 0xa0, 0x35, 0x0e, + 0xa5, 0x18, 0x80, 0x29, 0x82, 0x18, 0x81, 0x42, + 0x85, 0x18, 0x80, 0x42, 0x9a, 0x18, 0x80, 0x42, + 0x90, 0x18, 0xa8, 0x42, 0x82, 0x18, 0x03, 0xe2, + 0x36, 0x18, 0x18, 0x8a, 0x18, 0x14, 0xe3, 0x3f, + 0x18, 0xe0, 0x9f, 0x0f, 0xe2, 0x13, 0x18, 0x01, + 0x9f, 0x18, 0x01, 0xe0, 0x07, 0x18, 0xae, 0x26, + 0x00, 0xae, 0x26, 0x00, 0x9f, 0x42, 0xe0, 0x13, + 0x19, 0x04, 0x86, 0x19, 0xa5, 0x25, 0x00, 0x80, + 0x25, 0x04, 0x80, 0x25, 0x01, 0xb7, 0x91, 0x06, + 0x81, 0x91, 0x0d, 0x80, 0x91, 0x96, 0x24, 0x08, + 0x86, 0x24, 0x00, 0x86, 0x24, 0x00, 0x86, 0x24, + 0x00, 0x86, 0x24, 0x00, 0x86, 0x24, 0x00, 0x86, + 0x24, 0x00, 0x86, 0x24, 0x00, 0x86, 0x24, 0x00, + 0x9f, 0x1c, 0xcf, 0x18, 0x2f, 0x99, 0x2d, 0x00, + 0xd8, 0x2d, 0x0b, 0xe0, 0x75, 0x2d, 0x19, 0x8b, + 0x18, 0x03, 0x84, 0x18, 0x80, 0x2d, 0x80, 0x18, + 0x80, 0x2d, 0x98, 0x18, 0x88, 0x2d, 0x83, 0x35, + 0x81, 0x2e, 0x87, 0x18, 0x83, 0x2d, 0x83, 0x18, + 0x00, 0xd5, 0x33, 0x01, 0x81, 0x35, 0x81, 0x18, + 0x82, 0x33, 0x80, 0x18, 0xd9, 0x3b, 0x81, 0x18, + 0x82, 0x3b, 0x04, 0xaa, 0x0d, 0x00, 0xdd, 0x2e, + 0x00, 0x8f, 0x18, 0x9a, 0x0d, 0x04, 0xa3, 0x18, + 0x0b, 0x8f, 0x3b, 0x9e, 0x2e, 0x00, 0xbf, 0x18, + 0x9e, 0x2e, 0xd0, 0x18, 0xae, 0x3b, 0x80, 0x18, + 0xd7, 0x3b, 0xe0, 0x47, 0x18, 0xf0, 0x09, 0x55, + 0x2d, 0x09, 0xbf, 0x18, 0xf0, 0x41, 0x8f, 0x2d, + 0x0f, 0xe4, 0x2c, 0x97, 0x02, 0xb6, 0x97, 0x08, + 0xaf, 0x47, 0xe0, 0xcb, 0x94, 0x13, 0xdf, 0x1c, + 0xd7, 0x08, 0x07, 0xa1, 0x18, 0xe0, 0x05, 0x42, + 0x82, 0x18, 0xb4, 0x42, 0x01, 0x84, 0x42, 0x2f, + 0x88, 0x42, 0xab, 0x83, 0x03, 0x89, 0x18, 0x05, + 0xb7, 0x73, 0x07, 0xc5, 0x79, 0x07, 0x8b, 0x79, + 0x05, 0x9f, 0x1e, 0xad, 0x3c, 0x80, 0x18, 0x80, + 0x3c, 0xa3, 0x76, 0x0a, 0x80, 0x76, 0x9c, 0x2e, + 0x02, 0xcd, 0x38, 0x00, 0x80, 0x18, 0x89, 0x38, + 0x03, 0x81, 0x38, 0x9e, 0x5b, 0x00, 0xb6, 0x16, + 0x08, 0x8d, 0x16, 0x01, 0x89, 0x16, 0x01, 0x83, + 0x16, 0x9f, 0x5b, 0xc2, 0x89, 0x17, 0x84, 0x89, + 0x96, 0x52, 0x09, 0x85, 0x24, 0x01, 0x85, 0x24, + 0x01, 0x85, 0x24, 0x08, 0x86, 0x24, 0x00, 0x86, + 0x24, 0x00, 0xaa, 0x42, 0x80, 0x18, 0x88, 0x42, + 0x80, 0x29, 0x81, 0x42, 0x07, 0xcf, 0x17, 0xad, + 0x52, 0x01, 0x89, 0x52, 0x05, 0xf0, 0x1b, 0x43, + 0x2e, 0x0b, 0x96, 0x2e, 0x03, 0xb0, 0x2e, 0x70, + 0x10, 0xa3, 0xe1, 0x0d, 0x2d, 0x01, 0xe0, 0x09, + 0x2d, 0x25, 0x86, 0x42, 0x0b, 0x84, 0x05, 0x04, + 0x99, 0x32, 0x00, 0x84, 0x32, 0x00, 0x80, 0x32, + 0x00, 0x81, 0x32, 0x00, 0x81, 0x32, 0x00, 0x89, + 0x32, 0xe0, 0x11, 0x04, 0x10, 0xe1, 0x0a, 0x04, 0x81, 0x18, 0x0f, 0xbf, 0x04, 0x01, 0xb5, 0x04, - 0x27, 0x8d, 0x04, 0x01, 0x8f, 0x34, 0x89, 0x18, - 0x05, 0x8d, 0x34, 0x81, 0x1c, 0xa2, 0x18, 0x00, + 0x27, 0x8d, 0x04, 0x01, 0x8f, 0x35, 0x89, 0x18, + 0x05, 0x8d, 0x35, 0x81, 0x1c, 0xa2, 0x18, 0x00, 0x92, 0x18, 0x00, 0x83, 0x18, 0x03, 0x84, 0x04, 0x00, 0xe0, 0x26, 0x04, 0x01, 0x80, 0x18, 0x00, - 0x9f, 0x18, 0x99, 0x41, 0x85, 0x18, 0x99, 0x41, - 0x8a, 0x18, 0x89, 0x3a, 0x80, 0x18, 0xac, 0x3a, - 0x81, 0x18, 0x9e, 0x2d, 0x02, 0x85, 0x2d, 0x01, - 0x85, 0x2d, 0x01, 0x85, 0x2d, 0x01, 0x82, 0x2d, + 0x9f, 0x18, 0x99, 0x42, 0x85, 0x18, 0x99, 0x42, + 0x8a, 0x18, 0x89, 0x3b, 0x80, 0x18, 0xac, 0x3b, + 0x81, 0x18, 0x9e, 0x2e, 0x02, 0x85, 0x2e, 0x01, + 0x85, 0x2e, 0x01, 0x85, 0x2e, 0x01, 0x82, 0x2e, 0x02, 0x86, 0x18, 0x00, 0x86, 0x18, 0x09, 0x84, - 0x18, 0x01, 0x8b, 0x45, 0x00, 0x99, 0x45, 0x00, - 0x92, 0x45, 0x00, 0x81, 0x45, 0x00, 0x8e, 0x45, - 0x01, 0x8d, 0x45, 0x21, 0xe0, 0x1a, 0x45, 0x04, + 0x18, 0x01, 0x8b, 0x46, 0x00, 0x99, 0x46, 0x00, + 0x92, 0x46, 0x00, 0x81, 0x46, 0x00, 0x8e, 0x46, + 0x01, 0x8d, 0x46, 0x21, 0xe0, 0x1a, 0x46, 0x04, 0x82, 0x18, 0x03, 0xac, 0x18, 0x02, 0x88, 0x18, - 0xce, 0x28, 0x00, 0x8b, 0x18, 0x03, 0x80, 0x28, - 0x2e, 0xac, 0x18, 0x80, 0x34, 0x60, 0x21, 0x9c, - 0x47, 0x02, 0xb0, 0x13, 0x0e, 0x80, 0x34, 0x9a, - 0x18, 0x03, 0xa3, 0x63, 0x08, 0x82, 0x63, 0x9a, - 0x26, 0x04, 0xaa, 0x65, 0x04, 0x9d, 0x90, 0x00, - 0x80, 0x90, 0xa3, 0x66, 0x03, 0x8d, 0x66, 0x29, - 0xcf, 0x1d, 0xaf, 0x78, 0x9d, 0x6c, 0x01, 0x89, - 0x6c, 0x05, 0xa3, 0x6b, 0x03, 0xa3, 0x6b, 0x03, + 0xce, 0x29, 0x00, 0x8b, 0x18, 0x03, 0x80, 0x29, + 0x2e, 0xac, 0x18, 0x80, 0x35, 0x60, 0x21, 0x9c, + 0x48, 0x02, 0xb0, 0x13, 0x0e, 0x80, 0x35, 0x9a, + 0x18, 0x03, 0xa3, 0x66, 0x08, 0x82, 0x66, 0x9a, + 0x27, 0x04, 0xaa, 0x68, 0x04, 0x9d, 0x93, 0x00, + 0x80, 0x93, 0xa3, 0x69, 0x03, 0x8d, 0x69, 0x29, + 0xcf, 0x1d, 0xaf, 0x7b, 0x9d, 0x6f, 0x01, 0x89, + 0x6f, 0x05, 0xa3, 0x6e, 0x03, 0xa3, 0x6e, 0x03, 0xa7, 0x22, 0x07, 0xb3, 0x14, 0x0a, 0x80, 0x14, - 0x60, 0x2f, 0xe0, 0xd6, 0x44, 0x08, 0x95, 0x44, - 0x09, 0x87, 0x44, 0x60, 0x37, 0x85, 0x1b, 0x01, + 0x60, 0x2f, 0xe0, 0xd6, 0x45, 0x08, 0x95, 0x45, + 0x09, 0x87, 0x45, 0x60, 0x37, 0x85, 0x1b, 0x01, 0x80, 0x1b, 0x00, 0xab, 0x1b, 0x00, 0x81, 0x1b, - 0x02, 0x80, 0x1b, 0x01, 0x80, 0x1b, 0x95, 0x33, - 0x00, 0x88, 0x33, 0x9f, 0x6e, 0x9e, 0x5b, 0x07, - 0x88, 0x5b, 0x2f, 0x92, 0x30, 0x00, 0x81, 0x30, - 0x04, 0x84, 0x30, 0x9b, 0x71, 0x02, 0x80, 0x71, - 0x99, 0x48, 0x04, 0x80, 0x48, 0x3f, 0x9f, 0x54, - 0x97, 0x53, 0x03, 0x93, 0x53, 0x01, 0xad, 0x53, - 0x83, 0x3c, 0x00, 0x81, 0x3c, 0x04, 0x87, 0x3c, - 0x00, 0x82, 0x3c, 0x00, 0x9c, 0x3c, 0x01, 0x82, - 0x3c, 0x03, 0x89, 0x3c, 0x06, 0x88, 0x3c, 0x06, - 0x9f, 0x68, 0x9f, 0x64, 0x1f, 0xa6, 0x4d, 0x03, - 0x8b, 0x4d, 0x08, 0xb5, 0x06, 0x02, 0x86, 0x06, - 0x95, 0x36, 0x01, 0x87, 0x36, 0x92, 0x35, 0x04, - 0x87, 0x35, 0x91, 0x72, 0x06, 0x83, 0x72, 0x0b, - 0x86, 0x72, 0x4f, 0xc8, 0x69, 0x36, 0xb2, 0x62, - 0x0c, 0xb2, 0x62, 0x06, 0x85, 0x62, 0xa7, 0x2e, - 0x07, 0x89, 0x2e, 0x60, 0xc5, 0x9e, 0x04, 0x60, - 0x20, 0xa7, 0x67, 0x07, 0xa9, 0x7c, 0x60, 0x45, - 0xcd, 0x0e, 0x03, 0x9d, 0x0e, 0x0e, 0x80, 0x0e, - 0xc1, 0x38, 0x0a, 0x80, 0x38, 0x01, 0x98, 0x7d, - 0x06, 0x89, 0x7d, 0x05, 0xb4, 0x15, 0x00, 0x90, - 0x15, 0x08, 0xa6, 0x4a, 0x08, 0xcd, 0x77, 0x01, - 0x8f, 0x77, 0x00, 0x93, 0x7b, 0x0a, 0x91, 0x3e, - 0x00, 0xab, 0x3e, 0x40, 0x86, 0x59, 0x00, 0x80, - 0x59, 0x00, 0x83, 0x59, 0x00, 0x8e, 0x59, 0x00, - 0x8a, 0x59, 0x05, 0xba, 0x3f, 0x04, 0x89, 0x3f, - 0x05, 0x83, 0x27, 0x00, 0x87, 0x27, 0x01, 0x81, - 0x27, 0x01, 0x95, 0x27, 0x00, 0x86, 0x27, 0x00, - 0x81, 0x27, 0x00, 0x84, 0x27, 0x00, 0x80, 0x34, - 0x88, 0x27, 0x01, 0x81, 0x27, 0x01, 0x82, 0x27, - 0x01, 0x80, 0x27, 0x05, 0x80, 0x27, 0x04, 0x86, - 0x27, 0x01, 0x86, 0x27, 0x02, 0x84, 0x27, 0x60, - 0x2a, 0xd9, 0x5d, 0x00, 0x80, 0x5d, 0x00, 0x81, - 0x5d, 0x20, 0xc7, 0x8f, 0x07, 0x89, 0x8f, 0x60, - 0x45, 0xb5, 0x79, 0x01, 0xa5, 0x79, 0x21, 0xc4, - 0x56, 0x0a, 0x89, 0x56, 0x05, 0x8c, 0x57, 0x12, - 0xb7, 0x87, 0x07, 0x89, 0x87, 0x35, 0x9a, 0x02, - 0x01, 0x8e, 0x02, 0x03, 0x8f, 0x02, 0x60, 0x5f, - 0xbb, 0x1f, 0x60, 0x03, 0xd2, 0x92, 0x0b, 0x80, - 0x92, 0x60, 0x9f, 0xc7, 0x94, 0x07, 0xb3, 0x7e, - 0x01, 0x9c, 0x7e, 0x1c, 0xb8, 0x6f, 0x60, 0xa6, - 0x88, 0x0c, 0x00, 0xac, 0x0c, 0x00, 0x8d, 0x0c, - 0x09, 0x9c, 0x0c, 0x02, 0x9f, 0x4e, 0x01, 0x95, - 0x4e, 0x00, 0x8d, 0x4e, 0x48, 0x86, 0x4f, 0x00, - 0x81, 0x4f, 0x00, 0xab, 0x4f, 0x02, 0x80, 0x4f, - 0x00, 0x81, 0x4f, 0x00, 0x88, 0x4f, 0x07, 0x89, - 0x4f, 0x05, 0x85, 0x2a, 0x00, 0x81, 0x2a, 0x00, - 0xa4, 0x2a, 0x00, 0x81, 0x2a, 0x00, 0x85, 0x2a, - 0x06, 0x89, 0x2a, 0x60, 0xd5, 0x98, 0x49, 0x60, - 0xa6, 0xe3, 0x39, 0x1a, 0x60, 0x05, 0xe0, 0x0e, - 0x1a, 0x00, 0x84, 0x1a, 0x0a, 0xe0, 0x63, 0x1a, - 0x6a, 0x5b, 0xe3, 0xce, 0x21, 0x6f, 0x70, 0xe1, - 0xe6, 0x03, 0x70, 0x11, 0x58, 0xe1, 0xd8, 0x08, - 0x06, 0x9e, 0x58, 0x00, 0x89, 0x58, 0x03, 0x81, - 0x58, 0x5f, 0x9d, 0x09, 0x01, 0x85, 0x09, 0x09, - 0xc5, 0x6d, 0x09, 0x89, 0x6d, 0x00, 0x86, 0x6d, - 0x00, 0x94, 0x6d, 0x04, 0x92, 0x6d, 0x62, 0x4f, - 0xda, 0x50, 0x60, 0x04, 0xc4, 0x55, 0x0a, 0xae, - 0x55, 0x0f, 0x90, 0x55, 0x3f, 0x80, 0x89, 0x80, - 0x5f, 0x1d, 0xf0, 0x07, 0x91, 0x89, 0x0d, 0xe2, - 0x92, 0x89, 0x70, 0x14, 0xac, 0x80, 0x3a, 0xe0, - 0xbd, 0x32, 0x50, 0xe1, 0x2b, 0x5f, 0x68, 0xa3, - 0xe0, 0x0a, 0x20, 0x04, 0x8c, 0x20, 0x02, 0x88, - 0x20, 0x06, 0x89, 0x20, 0x01, 0x83, 0x20, 0x83, - 0x18, 0x70, 0x02, 0xfb, 0xe0, 0x95, 0x18, 0x09, - 0xa6, 0x18, 0x01, 0xbd, 0x18, 0x82, 0x34, 0x90, - 0x18, 0x87, 0x34, 0x81, 0x18, 0x86, 0x34, 0x9d, - 0x18, 0x83, 0x34, 0xba, 0x18, 0x16, 0xc5, 0x28, - 0x60, 0x39, 0x93, 0x18, 0x0b, 0xd6, 0x18, 0x08, - 0x98, 0x18, 0x60, 0x26, 0xd4, 0x18, 0x00, 0xc6, - 0x18, 0x00, 0x81, 0x18, 0x01, 0x80, 0x18, 0x01, - 0x81, 0x18, 0x01, 0x83, 0x18, 0x00, 0x8b, 0x18, - 0x00, 0x80, 0x18, 0x00, 0x86, 0x18, 0x00, 0xc0, - 0x18, 0x00, 0x83, 0x18, 0x01, 0x87, 0x18, 0x00, - 0x86, 0x18, 0x00, 0x9b, 0x18, 0x00, 0x83, 0x18, - 0x00, 0x84, 0x18, 0x00, 0x80, 0x18, 0x02, 0x86, - 0x18, 0x00, 0xe0, 0xf3, 0x18, 0x01, 0xe0, 0xc3, - 0x18, 0x01, 0xb1, 0x18, 0xe2, 0x2b, 0x7a, 0x0e, - 0x84, 0x7a, 0x00, 0x8e, 0x7a, 0x64, 0xef, 0x86, - 0x25, 0x00, 0x90, 0x25, 0x01, 0x86, 0x25, 0x00, - 0x81, 0x25, 0x00, 0x84, 0x25, 0x67, 0x74, 0xe0, - 0x64, 0x52, 0x01, 0x8f, 0x52, 0x28, 0xca, 0x01, - 0x04, 0x89, 0x01, 0x03, 0x81, 0x01, 0x62, 0xb0, - 0xc3, 0x18, 0x60, 0xea, 0x83, 0x04, 0x00, 0x9a, + 0x02, 0x80, 0x1b, 0x01, 0x80, 0x1b, 0x95, 0x34, + 0x00, 0x88, 0x34, 0x9f, 0x71, 0x9e, 0x5c, 0x07, + 0x88, 0x5c, 0x2f, 0x92, 0x31, 0x00, 0x81, 0x31, + 0x04, 0x84, 0x31, 0x9b, 0x74, 0x02, 0x80, 0x74, + 0x99, 0x49, 0x04, 0x80, 0x49, 0x3f, 0x9f, 0x55, + 0x97, 0x54, 0x03, 0x93, 0x54, 0x01, 0xad, 0x54, + 0x83, 0x3d, 0x00, 0x81, 0x3d, 0x04, 0x87, 0x3d, + 0x00, 0x82, 0x3d, 0x00, 0x9c, 0x3d, 0x01, 0x82, + 0x3d, 0x03, 0x89, 0x3d, 0x06, 0x88, 0x3d, 0x06, + 0x9f, 0x6b, 0x9f, 0x67, 0x1f, 0xa6, 0x4e, 0x03, + 0x8b, 0x4e, 0x08, 0xb5, 0x06, 0x02, 0x86, 0x06, + 0x95, 0x37, 0x01, 0x87, 0x37, 0x92, 0x36, 0x04, + 0x87, 0x36, 0x91, 0x75, 0x06, 0x83, 0x75, 0x0b, + 0x86, 0x75, 0x4f, 0xc8, 0x6c, 0x36, 0xb2, 0x65, + 0x0c, 0xb2, 0x65, 0x06, 0x85, 0x65, 0xa7, 0x2f, + 0x07, 0x89, 0x2f, 0x60, 0xc5, 0x9e, 0x04, 0x60, + 0x20, 0xa7, 0x6a, 0x07, 0xa9, 0x7f, 0x60, 0x25, + 0x96, 0x23, 0x08, 0xcd, 0x0e, 0x03, 0x9d, 0x0e, + 0x0e, 0x80, 0x0e, 0xc1, 0x39, 0x0a, 0x80, 0x39, + 0x01, 0x98, 0x80, 0x06, 0x89, 0x80, 0x05, 0xb4, + 0x15, 0x00, 0x90, 0x15, 0x08, 0xa6, 0x4b, 0x08, + 0xcd, 0x7a, 0x01, 0x8f, 0x7a, 0x00, 0x93, 0x7e, + 0x0a, 0x91, 0x3f, 0x00, 0xab, 0x3f, 0x40, 0x86, + 0x5a, 0x00, 0x80, 0x5a, 0x00, 0x83, 0x5a, 0x00, + 0x8e, 0x5a, 0x00, 0x8a, 0x5a, 0x05, 0xba, 0x40, + 0x04, 0x89, 0x40, 0x05, 0x83, 0x28, 0x00, 0x87, + 0x28, 0x01, 0x81, 0x28, 0x01, 0x95, 0x28, 0x00, + 0x86, 0x28, 0x00, 0x81, 0x28, 0x00, 0x84, 0x28, + 0x00, 0x80, 0x35, 0x88, 0x28, 0x01, 0x81, 0x28, + 0x01, 0x82, 0x28, 0x01, 0x80, 0x28, 0x05, 0x80, + 0x28, 0x04, 0x86, 0x28, 0x01, 0x86, 0x28, 0x02, + 0x84, 0x28, 0x60, 0x2a, 0xd9, 0x5f, 0x00, 0x80, + 0x5f, 0x00, 0x82, 0x5f, 0x1f, 0xc7, 0x92, 0x07, + 0x89, 0x92, 0x60, 0x45, 0xb5, 0x7c, 0x01, 0xa5, + 0x7c, 0x21, 0xc4, 0x57, 0x0a, 0x89, 0x57, 0x05, + 0x8c, 0x58, 0x12, 0xb8, 0x8a, 0x06, 0x89, 0x8a, + 0x35, 0x9a, 0x02, 0x01, 0x8e, 0x02, 0x03, 0x8f, + 0x02, 0x60, 0x5f, 0xbb, 0x1f, 0x60, 0x03, 0xd2, + 0x96, 0x0b, 0x80, 0x96, 0x60, 0x3f, 0x87, 0x5d, + 0x01, 0xad, 0x5d, 0x01, 0x8a, 0x5d, 0x1a, 0xc7, + 0x98, 0x07, 0xd2, 0x81, 0x1c, 0xb8, 0x72, 0x60, + 0xa6, 0x88, 0x0c, 0x00, 0xac, 0x0c, 0x00, 0x8d, + 0x0c, 0x09, 0x9c, 0x0c, 0x02, 0x9f, 0x4f, 0x01, + 0x95, 0x4f, 0x00, 0x8d, 0x4f, 0x48, 0x86, 0x50, + 0x00, 0x81, 0x50, 0x00, 0xab, 0x50, 0x02, 0x80, + 0x50, 0x00, 0x81, 0x50, 0x00, 0x88, 0x50, 0x07, + 0x89, 0x50, 0x05, 0x85, 0x2b, 0x00, 0x81, 0x2b, + 0x00, 0xa4, 0x2b, 0x00, 0x81, 0x2b, 0x00, 0x85, + 0x2b, 0x06, 0x89, 0x2b, 0x60, 0xd5, 0x98, 0x4a, + 0x60, 0x66, 0xb1, 0x8b, 0x0c, 0x80, 0x8b, 0xe3, + 0x39, 0x1a, 0x60, 0x05, 0xe0, 0x0e, 0x1a, 0x00, + 0x84, 0x1a, 0x0a, 0xe0, 0x63, 0x1a, 0x6a, 0x5b, + 0xe3, 0xce, 0x21, 0x00, 0x88, 0x21, 0x6f, 0x66, + 0xe1, 0xe6, 0x03, 0x70, 0x11, 0x58, 0xe1, 0xd8, + 0x08, 0x06, 0x9e, 0x59, 0x00, 0x89, 0x59, 0x03, + 0x81, 0x59, 0x5f, 0x9d, 0x09, 0x01, 0x85, 0x09, + 0x09, 0xc5, 0x70, 0x09, 0x89, 0x70, 0x00, 0x86, + 0x70, 0x00, 0x94, 0x70, 0x04, 0x92, 0x70, 0x62, + 0x4f, 0xda, 0x51, 0x60, 0x04, 0xca, 0x56, 0x03, + 0xb8, 0x56, 0x06, 0x90, 0x56, 0x3f, 0x80, 0x8c, + 0x80, 0x61, 0x81, 0x18, 0x1b, 0xf0, 0x07, 0x97, + 0x8c, 0x07, 0xe2, 0x92, 0x8c, 0x70, 0x14, 0xac, + 0x80, 0x3b, 0xe0, 0xbd, 0x33, 0x30, 0x82, 0x33, + 0x10, 0x83, 0x3b, 0x07, 0xe1, 0x2b, 0x61, 0x68, + 0xa3, 0xe0, 0x0a, 0x20, 0x04, 0x8c, 0x20, 0x02, + 0x88, 0x20, 0x06, 0x89, 0x20, 0x01, 0x83, 0x20, + 0x83, 0x18, 0x70, 0x02, 0xfb, 0xe0, 0x95, 0x18, + 0x09, 0xa6, 0x18, 0x01, 0xbd, 0x18, 0x82, 0x35, + 0x90, 0x18, 0x87, 0x35, 0x81, 0x18, 0x86, 0x35, + 0x9d, 0x18, 0x83, 0x35, 0xba, 0x18, 0x16, 0xc5, + 0x29, 0x60, 0x39, 0x93, 0x18, 0x0b, 0xd6, 0x18, + 0x08, 0x98, 0x18, 0x60, 0x26, 0xd4, 0x18, 0x00, + 0xc6, 0x18, 0x00, 0x81, 0x18, 0x01, 0x80, 0x18, + 0x01, 0x81, 0x18, 0x01, 0x83, 0x18, 0x00, 0x8b, + 0x18, 0x00, 0x80, 0x18, 0x00, 0x86, 0x18, 0x00, + 0xc0, 0x18, 0x00, 0x83, 0x18, 0x01, 0x87, 0x18, + 0x00, 0x86, 0x18, 0x00, 0x9b, 0x18, 0x00, 0x83, + 0x18, 0x00, 0x84, 0x18, 0x00, 0x80, 0x18, 0x02, + 0x86, 0x18, 0x00, 0xe0, 0xf3, 0x18, 0x01, 0xe0, + 0xc3, 0x18, 0x01, 0xb1, 0x18, 0xe2, 0x2b, 0x7d, + 0x0e, 0x84, 0x7d, 0x00, 0x8e, 0x7d, 0x64, 0xef, + 0x86, 0x26, 0x00, 0x90, 0x26, 0x01, 0x86, 0x26, + 0x00, 0x81, 0x26, 0x00, 0x84, 0x26, 0x60, 0x74, + 0xac, 0x62, 0x02, 0x8d, 0x62, 0x01, 0x89, 0x62, + 0x03, 0x81, 0x62, 0x61, 0x0f, 0xb9, 0x95, 0x04, + 0x80, 0x95, 0x64, 0x9f, 0xe0, 0x64, 0x53, 0x01, + 0x8f, 0x53, 0x28, 0xcb, 0x01, 0x03, 0x89, 0x01, + 0x03, 0x81, 0x01, 0x62, 0xb0, 0xc3, 0x18, 0x4b, + 0xbc, 0x18, 0x60, 0x61, 0x83, 0x04, 0x00, 0x9a, 0x04, 0x00, 0x81, 0x04, 0x00, 0x80, 0x04, 0x01, 0x80, 0x04, 0x00, 0x89, 0x04, 0x00, 0x83, 0x04, 0x00, 0x80, 0x04, 0x00, 0x80, 0x04, 0x05, 0x80, @@ -3313,118 +3344,126 @@ static const uint8_t unicode_script_table[2522] = { 0x04, 0x60, 0xad, 0xab, 0x18, 0x03, 0xe0, 0x03, 0x18, 0x0b, 0x8e, 0x18, 0x01, 0x8e, 0x18, 0x00, 0x8e, 0x18, 0x00, 0xa4, 0x18, 0x09, 0x8c, 0x18, - 0x02, 0xdb, 0x18, 0x03, 0xbc, 0x18, 0x38, 0x99, - 0x18, 0x80, 0x32, 0x81, 0x18, 0x0c, 0xab, 0x18, + 0x02, 0xdc, 0x18, 0x02, 0xbc, 0x18, 0x38, 0x99, + 0x18, 0x80, 0x33, 0x81, 0x18, 0x0c, 0xab, 0x18, 0x03, 0x88, 0x18, 0x06, 0x81, 0x18, 0x0d, 0x85, - 0x18, 0x60, 0x39, 0xe3, 0x74, 0x18, 0x0a, 0x8c, - 0x18, 0x02, 0x89, 0x18, 0x05, 0xe0, 0x13, 0x18, - 0x0b, 0xd8, 0x18, 0x26, 0x8b, 0x18, 0x03, 0xb7, - 0x18, 0x07, 0x89, 0x18, 0x05, 0xa7, 0x18, 0x07, - 0x9d, 0x18, 0x51, 0x8b, 0x18, 0x03, 0xae, 0x18, - 0x00, 0xb0, 0x18, 0x01, 0x83, 0x18, 0x02, 0x80, - 0x18, 0x00, 0xa6, 0x18, 0x0c, 0x89, 0x18, 0x05, - 0x82, 0x18, 0x0c, 0xaf, 0x18, 0x5f, 0x8d, 0x18, - 0x65, 0x31, 0xf0, 0x96, 0x76, 0x2c, 0x28, 0xef, - 0xd4, 0x2c, 0x0a, 0xe0, 0x7d, 0x2c, 0x01, 0xf0, - 0x06, 0x21, 0x2c, 0x0d, 0xf0, 0x0c, 0xd0, 0x2c, - 0x6b, 0xbe, 0xe1, 0xbd, 0x2c, 0x7a, 0xf5, 0x82, - 0x80, 0x18, 0x1d, 0xdf, 0x18, 0x60, 0x1f, 0xe0, - 0x8f, 0x34, + 0x18, 0x60, 0x39, 0xe3, 0x75, 0x18, 0x09, 0x8c, + 0x18, 0x02, 0x8a, 0x18, 0x04, 0xe0, 0x13, 0x18, + 0x0b, 0xd8, 0x18, 0x06, 0x8b, 0x18, 0x13, 0x8b, + 0x18, 0x03, 0xb7, 0x18, 0x07, 0x89, 0x18, 0x05, + 0xa7, 0x18, 0x07, 0x9d, 0x18, 0x51, 0x8b, 0x18, + 0x00, 0xe0, 0x04, 0x18, 0x00, 0x83, 0x18, 0x02, + 0xa8, 0x18, 0x01, 0x85, 0x18, 0x02, 0x9c, 0x18, + 0x01, 0xe0, 0x26, 0x18, 0x0b, 0x8d, 0x18, 0x01, + 0x83, 0x18, 0x03, 0x82, 0x18, 0x04, 0x82, 0x18, + 0x0c, 0x85, 0x18, 0x65, 0x09, 0xf0, 0x96, 0x76, + 0x2d, 0x28, 0xef, 0xd4, 0x2d, 0x0a, 0xe0, 0x7d, + 0x2d, 0x01, 0xf0, 0x06, 0x21, 0x2d, 0x0d, 0xf0, + 0x0c, 0xd0, 0x2d, 0x6b, 0xbe, 0xe1, 0xbd, 0x2d, + 0x7a, 0xf5, 0x82, 0x80, 0x18, 0x1d, 0xdf, 0x18, + 0x60, 0x1f, 0xe0, 0x8f, 0x35, }; -static const uint8_t unicode_script_ext_table[735] = { - 0x82, 0xc1, 0x00, 0x00, 0x01, 0x28, 0x01, 0x00, - 0x00, 0x01, 0x28, 0x1c, 0x00, 0x0c, 0x01, 0x41, - 0x80, 0x92, 0x00, 0x00, 0x02, 0x1c, 0x65, 0x00, - 0x02, 0x1c, 0x25, 0x01, 0x02, 0x1c, 0x41, 0x00, - 0x02, 0x1c, 0x25, 0x80, 0x80, 0x00, 0x00, 0x02, - 0x05, 0x24, 0x80, 0x01, 0x00, 0x00, 0x04, 0x04, - 0x2e, 0x81, 0x8b, 0x0d, 0x00, 0x00, 0x04, 0x04, - 0x2e, 0x81, 0x8b, 0x00, 0x03, 0x04, 0x81, 0x8b, - 0x01, 0x00, 0x00, 0x04, 0x04, 0x2e, 0x81, 0x8b, - 0x1f, 0x00, 0x00, 0x08, 0x01, 0x04, 0x4c, 0x4d, - 0x72, 0x2e, 0x7c, 0x81, 0x09, 0x00, 0x0a, 0x02, - 0x04, 0x81, 0x09, 0x00, 0x09, 0x02, 0x04, 0x8b, - 0x05, 0x00, 0x00, 0x02, 0x04, 0x81, 0x62, 0x00, - 0x00, 0x02, 0x04, 0x2e, 0x81, 0xfb, 0x00, 0x00, - 0x0d, 0x0b, 0x1e, 0x27, 0x29, 0x2b, 0x39, 0x41, - 0x4b, 0x6a, 0x77, 0x88, 0x8a, 0x8f, 0x00, 0x0c, - 0x0b, 0x1e, 0x27, 0x29, 0x2b, 0x39, 0x41, 0x4b, - 0x6a, 0x88, 0x8a, 0x8f, 0x10, 0x00, 0x00, 0x12, - 0x0b, 0x1e, 0x1f, 0x2a, 0x27, 0x29, 0x2b, 0x39, - 0x4a, 0x4b, 0x6a, 0x3f, 0x7b, 0x80, 0x87, 0x88, - 0x8a, 0x8f, 0x00, 0x13, 0x0b, 0x1e, 0x1f, 0x2a, - 0x27, 0x29, 0x2b, 0x39, 0x43, 0x4a, 0x4b, 0x6a, - 0x3f, 0x7b, 0x80, 0x87, 0x88, 0x8a, 0x8f, 0x09, - 0x04, 0x1e, 0x1f, 0x38, 0x4a, 0x75, 0x00, 0x09, - 0x03, 0x0b, 0x15, 0x80, 0x75, 0x00, 0x09, 0x02, - 0x2b, 0x59, 0x75, 0x00, 0x09, 0x02, 0x29, 0x3e, - 0x80, 0x75, 0x00, 0x0d, 0x02, 0x27, 0x88, 0x83, - 0xcb, 0x00, 0x09, 0x03, 0x15, 0x5a, 0x84, 0x80, - 0x30, 0x00, 0x00, 0x02, 0x24, 0x41, 0x85, 0xb8, - 0x00, 0x01, 0x04, 0x11, 0x2f, 0x83, 0x82, 0x80, - 0x4a, 0x00, 0x01, 0x02, 0x57, 0x70, 0x00, 0x00, - 0x00, 0x02, 0x57, 0x70, 0x84, 0x49, 0x00, 0x00, - 0x04, 0x0b, 0x1e, 0x27, 0x39, 0x00, 0x01, 0x1e, - 0x00, 0x04, 0x0b, 0x1e, 0x27, 0x39, 0x00, 0x02, - 0x1e, 0x27, 0x00, 0x01, 0x1e, 0x01, 0x02, 0x0b, - 0x1e, 0x00, 0x02, 0x1e, 0x77, 0x00, 0x02, 0x0b, - 0x1e, 0x00, 0x02, 0x1e, 0x77, 0x00, 0x06, 0x1e, - 0x39, 0x4b, 0x6a, 0x88, 0x8a, 0x00, 0x01, 0x1e, - 0x01, 0x02, 0x1e, 0x77, 0x01, 0x01, 0x1e, 0x00, - 0x02, 0x1e, 0x77, 0x00, 0x02, 0x0b, 0x1e, 0x07, - 0x01, 0x1e, 0x00, 0x02, 0x0b, 0x1e, 0x01, 0x01, - 0x1e, 0x00, 0x02, 0x0b, 0x1e, 0x03, 0x01, 0x1e, - 0x01, 0x02, 0x1e, 0x27, 0x00, 0x03, 0x1e, 0x27, - 0x39, 0x01, 0x02, 0x0b, 0x1e, 0x00, 0x01, 0x0b, - 0x01, 0x02, 0x1e, 0x27, 0x80, 0x45, 0x00, 0x01, - 0x01, 0x28, 0x82, 0xad, 0x00, 0x00, 0x03, 0x1e, - 0x27, 0x41, 0x8c, 0xd1, 0x00, 0x00, 0x02, 0x1c, - 0x25, 0x81, 0x3c, 0x00, 0x01, 0x06, 0x0d, 0x2d, - 0x2c, 0x32, 0x3a, 0x93, 0x00, 0x05, 0x0d, 0x2d, - 0x2c, 0x32, 0x3a, 0x01, 0x00, 0x00, 0x01, 0x2c, - 0x00, 0x00, 0x09, 0x06, 0x0d, 0x2d, 0x2c, 0x32, - 0x3a, 0x93, 0x00, 0x00, 0x00, 0x05, 0x0d, 0x2d, - 0x2c, 0x32, 0x3a, 0x07, 0x06, 0x0d, 0x2d, 0x2c, - 0x32, 0x3a, 0x93, 0x03, 0x05, 0x0d, 0x2d, 0x2c, - 0x32, 0x3a, 0x09, 0x00, 0x03, 0x02, 0x0d, 0x2c, - 0x01, 0x00, 0x00, 0x05, 0x0d, 0x2d, 0x2c, 0x32, - 0x3a, 0x04, 0x02, 0x32, 0x3a, 0x00, 0x00, 0x00, - 0x05, 0x0d, 0x2d, 0x2c, 0x32, 0x3a, 0x03, 0x00, - 0x01, 0x03, 0x2c, 0x32, 0x3a, 0x01, 0x01, 0x2c, - 0x58, 0x00, 0x03, 0x02, 0x32, 0x3a, 0x02, 0x00, - 0x00, 0x02, 0x32, 0x3a, 0x59, 0x00, 0x00, 0x06, - 0x0d, 0x2d, 0x2c, 0x32, 0x3a, 0x93, 0x00, 0x02, - 0x32, 0x3a, 0x80, 0x12, 0x00, 0x0f, 0x01, 0x2c, - 0x1f, 0x00, 0x23, 0x01, 0x2c, 0x3b, 0x00, 0x27, - 0x01, 0x2c, 0x37, 0x00, 0x30, 0x01, 0x2c, 0x0e, - 0x00, 0x0b, 0x01, 0x2c, 0x80, 0x0b, 0x00, 0x18, - 0x01, 0x2c, 0x09, 0x00, 0x04, 0x01, 0x2c, 0x5f, - 0x00, 0x1e, 0x01, 0x2c, 0xc0, 0x31, 0xef, 0x00, - 0x00, 0x02, 0x1c, 0x25, 0x81, 0x3f, 0x00, 0x02, - 0x0d, 0x1e, 0x1f, 0x29, 0x2b, 0x3e, 0x39, 0x38, - 0x4a, 0x4b, 0x56, 0x3f, 0x87, 0x8f, 0x02, 0x0c, - 0x1e, 0x1f, 0x29, 0x2b, 0x3e, 0x39, 0x38, 0x4a, - 0x56, 0x3f, 0x87, 0x8f, 0x03, 0x0b, 0x1e, 0x1f, - 0x29, 0x2b, 0x3e, 0x38, 0x4a, 0x56, 0x3f, 0x87, - 0x8f, 0x80, 0x36, 0x00, 0x00, 0x02, 0x0b, 0x1e, - 0x00, 0x00, 0x00, 0x02, 0x1e, 0x88, 0x39, 0x00, - 0x00, 0x03, 0x3b, 0x41, 0x5a, 0x80, 0x1f, 0x00, - 0x00, 0x02, 0x10, 0x37, 0xc0, 0x13, 0xa1, 0x00, - 0x00, 0x02, 0x04, 0x8b, 0x09, 0x00, 0x00, 0x02, - 0x04, 0x8b, 0x46, 0x00, 0x01, 0x05, 0x0d, 0x2d, - 0x2c, 0x32, 0x3a, 0x80, 0x99, 0x00, 0x04, 0x06, - 0x0d, 0x2d, 0x2c, 0x32, 0x3a, 0x93, 0x09, 0x00, - 0x00, 0x02, 0x32, 0x3a, 0x2c, 0x00, 0x01, 0x02, - 0x32, 0x3a, 0x80, 0xdf, 0x00, 0x02, 0x02, 0x1b, - 0x45, 0x03, 0x00, 0x2c, 0x03, 0x1b, 0x44, 0x45, - 0x02, 0x00, 0x08, 0x02, 0x1b, 0x45, 0x81, 0x1f, - 0x00, 0x1b, 0x02, 0x04, 0x19, 0x8f, 0x84, 0x00, - 0x00, 0x02, 0x27, 0x88, 0x00, 0x00, 0x00, 0x02, - 0x27, 0x88, 0x36, 0x00, 0x01, 0x02, 0x27, 0x88, - 0xc0, 0x68, 0xe2, 0x00, 0x03, 0x01, 0x20, 0x96, - 0x3b, 0x00, 0x11, 0x01, 0x2c, 0x9e, 0x5d, 0x00, - 0x01, 0x01, 0x2c, 0xce, 0xcd, 0x2d, 0x00, +static const uint8_t unicode_script_ext_table[789] = { + 0x82, 0xc1, 0x00, 0x00, 0x01, 0x29, 0x01, 0x00, + 0x00, 0x01, 0x29, 0x1c, 0x00, 0x0c, 0x01, 0x42, + 0x80, 0x92, 0x00, 0x00, 0x02, 0x1c, 0x68, 0x00, + 0x02, 0x1c, 0x26, 0x01, 0x02, 0x1c, 0x42, 0x00, + 0x02, 0x1c, 0x26, 0x80, 0x80, 0x00, 0x00, 0x02, + 0x05, 0x25, 0x80, 0x01, 0x00, 0x00, 0x04, 0x04, + 0x2f, 0x84, 0x8e, 0x0d, 0x00, 0x00, 0x04, 0x04, + 0x2f, 0x84, 0x8e, 0x00, 0x03, 0x04, 0x84, 0x8e, + 0x01, 0x00, 0x00, 0x04, 0x04, 0x2f, 0x84, 0x8e, + 0x1f, 0x00, 0x00, 0x08, 0x01, 0x04, 0x4d, 0x4e, + 0x75, 0x2f, 0x7f, 0x84, 0x09, 0x00, 0x0a, 0x02, + 0x04, 0x84, 0x09, 0x00, 0x09, 0x02, 0x04, 0x8e, + 0x05, 0x00, 0x00, 0x02, 0x04, 0x84, 0x62, 0x00, + 0x00, 0x02, 0x04, 0x2f, 0x81, 0xfb, 0x00, 0x00, + 0x0d, 0x0b, 0x1e, 0x28, 0x2a, 0x2c, 0x3a, 0x42, + 0x4c, 0x6d, 0x7a, 0x8b, 0x8d, 0x92, 0x00, 0x0c, + 0x0b, 0x1e, 0x28, 0x2a, 0x2c, 0x3a, 0x42, 0x4c, + 0x6d, 0x8b, 0x8d, 0x92, 0x10, 0x00, 0x00, 0x14, + 0x0b, 0x1e, 0x1f, 0x2b, 0x50, 0x28, 0x2a, 0x2c, + 0x3a, 0x4b, 0x4c, 0x5d, 0x6d, 0x40, 0x7e, 0x83, + 0x8a, 0x8b, 0x8d, 0x92, 0x00, 0x15, 0x0b, 0x1e, + 0x1f, 0x2b, 0x50, 0x28, 0x2a, 0x2c, 0x3a, 0x44, + 0x4b, 0x4c, 0x5d, 0x6d, 0x40, 0x7e, 0x83, 0x8a, + 0x8b, 0x8d, 0x92, 0x09, 0x04, 0x1e, 0x1f, 0x39, + 0x4b, 0x75, 0x00, 0x09, 0x03, 0x0b, 0x15, 0x83, + 0x75, 0x00, 0x09, 0x02, 0x2c, 0x5a, 0x75, 0x00, + 0x09, 0x02, 0x2a, 0x3f, 0x80, 0x75, 0x00, 0x0d, + 0x02, 0x28, 0x8b, 0x80, 0x71, 0x00, 0x09, 0x02, + 0x3a, 0x5d, 0x82, 0xcf, 0x00, 0x09, 0x03, 0x15, + 0x5b, 0x87, 0x80, 0x30, 0x00, 0x00, 0x02, 0x25, + 0x42, 0x85, 0xb8, 0x00, 0x01, 0x04, 0x11, 0x30, + 0x86, 0x85, 0x80, 0x4a, 0x00, 0x01, 0x02, 0x58, + 0x73, 0x00, 0x00, 0x00, 0x02, 0x58, 0x73, 0x84, + 0x49, 0x00, 0x00, 0x04, 0x0b, 0x1e, 0x28, 0x3a, + 0x00, 0x01, 0x1e, 0x00, 0x04, 0x0b, 0x1e, 0x28, + 0x3a, 0x00, 0x02, 0x1e, 0x28, 0x00, 0x01, 0x1e, + 0x01, 0x02, 0x0b, 0x1e, 0x00, 0x02, 0x1e, 0x7a, + 0x00, 0x02, 0x0b, 0x1e, 0x00, 0x02, 0x1e, 0x7a, + 0x00, 0x06, 0x1e, 0x3a, 0x4c, 0x6d, 0x8b, 0x8d, + 0x00, 0x01, 0x1e, 0x01, 0x02, 0x1e, 0x7a, 0x01, + 0x01, 0x1e, 0x00, 0x02, 0x1e, 0x7a, 0x00, 0x02, + 0x0b, 0x1e, 0x06, 0x01, 0x1e, 0x00, 0x02, 0x1e, + 0x5d, 0x00, 0x02, 0x0b, 0x1e, 0x01, 0x01, 0x1e, + 0x00, 0x02, 0x0b, 0x1e, 0x03, 0x01, 0x1e, 0x00, + 0x08, 0x0b, 0x1e, 0x28, 0x3a, 0x5d, 0x6d, 0x8d, + 0x92, 0x00, 0x02, 0x1e, 0x28, 0x00, 0x03, 0x1e, + 0x28, 0x3a, 0x01, 0x02, 0x0b, 0x1e, 0x00, 0x01, + 0x0b, 0x01, 0x02, 0x1e, 0x28, 0x00, 0x01, 0x5d, + 0x80, 0x44, 0x00, 0x01, 0x01, 0x29, 0x81, 0xec, + 0x00, 0x00, 0x02, 0x42, 0x58, 0x80, 0x3f, 0x00, + 0x00, 0x03, 0x1e, 0x28, 0x42, 0x8c, 0xd1, 0x00, + 0x00, 0x02, 0x1c, 0x26, 0x81, 0x3c, 0x00, 0x01, + 0x06, 0x0d, 0x2e, 0x2d, 0x33, 0x3b, 0x97, 0x00, + 0x05, 0x0d, 0x2e, 0x2d, 0x33, 0x3b, 0x01, 0x00, + 0x00, 0x01, 0x2d, 0x00, 0x00, 0x09, 0x06, 0x0d, + 0x2e, 0x2d, 0x33, 0x3b, 0x97, 0x00, 0x00, 0x00, + 0x05, 0x0d, 0x2e, 0x2d, 0x33, 0x3b, 0x07, 0x06, + 0x0d, 0x2e, 0x2d, 0x33, 0x3b, 0x97, 0x03, 0x05, + 0x0d, 0x2e, 0x2d, 0x33, 0x3b, 0x09, 0x00, 0x03, + 0x02, 0x0d, 0x2d, 0x01, 0x00, 0x00, 0x05, 0x0d, + 0x2e, 0x2d, 0x33, 0x3b, 0x04, 0x02, 0x33, 0x3b, + 0x00, 0x00, 0x00, 0x05, 0x0d, 0x2e, 0x2d, 0x33, + 0x3b, 0x03, 0x00, 0x01, 0x03, 0x2d, 0x33, 0x3b, + 0x01, 0x01, 0x2d, 0x58, 0x00, 0x03, 0x02, 0x33, + 0x3b, 0x02, 0x00, 0x00, 0x02, 0x33, 0x3b, 0x59, + 0x00, 0x00, 0x06, 0x0d, 0x2e, 0x2d, 0x33, 0x3b, + 0x97, 0x00, 0x02, 0x33, 0x3b, 0x80, 0x12, 0x00, + 0x0f, 0x01, 0x2d, 0x1f, 0x00, 0x23, 0x01, 0x2d, + 0x3b, 0x00, 0x27, 0x01, 0x2d, 0x37, 0x00, 0x30, + 0x01, 0x2d, 0x0e, 0x00, 0x0b, 0x01, 0x2d, 0x32, + 0x00, 0x00, 0x01, 0x2d, 0x57, 0x00, 0x18, 0x01, + 0x2d, 0x09, 0x00, 0x04, 0x01, 0x2d, 0x5f, 0x00, + 0x1e, 0x01, 0x2d, 0xc0, 0x31, 0xef, 0x00, 0x00, + 0x02, 0x1c, 0x26, 0x81, 0x3f, 0x00, 0x02, 0x0e, + 0x1e, 0x1f, 0x2a, 0x2c, 0x3f, 0x3a, 0x39, 0x4b, + 0x4c, 0x57, 0x5d, 0x40, 0x8a, 0x92, 0x02, 0x0d, + 0x1e, 0x1f, 0x2a, 0x2c, 0x3f, 0x3a, 0x39, 0x4b, + 0x57, 0x5d, 0x40, 0x8a, 0x92, 0x03, 0x0b, 0x1e, + 0x1f, 0x2a, 0x2c, 0x3f, 0x39, 0x4b, 0x57, 0x40, + 0x8a, 0x92, 0x80, 0x36, 0x00, 0x00, 0x02, 0x0b, + 0x1e, 0x00, 0x00, 0x00, 0x02, 0x1e, 0x8b, 0x39, + 0x00, 0x00, 0x03, 0x3c, 0x42, 0x5b, 0x80, 0x1f, + 0x00, 0x00, 0x02, 0x10, 0x38, 0xc0, 0x13, 0xa1, + 0x00, 0x00, 0x02, 0x04, 0x8e, 0x09, 0x00, 0x00, + 0x02, 0x04, 0x8e, 0x46, 0x00, 0x01, 0x05, 0x0d, + 0x2e, 0x2d, 0x33, 0x3b, 0x80, 0x99, 0x00, 0x04, + 0x06, 0x0d, 0x2e, 0x2d, 0x33, 0x3b, 0x97, 0x09, + 0x00, 0x00, 0x02, 0x33, 0x3b, 0x2c, 0x00, 0x01, + 0x02, 0x33, 0x3b, 0x80, 0xdf, 0x00, 0x02, 0x02, + 0x1b, 0x46, 0x03, 0x00, 0x2c, 0x03, 0x1b, 0x45, + 0x46, 0x02, 0x00, 0x08, 0x02, 0x1b, 0x46, 0x81, + 0x1f, 0x00, 0x1b, 0x02, 0x04, 0x19, 0x8f, 0x84, + 0x00, 0x00, 0x02, 0x28, 0x8b, 0x00, 0x00, 0x00, + 0x02, 0x28, 0x8b, 0x36, 0x00, 0x01, 0x02, 0x28, + 0x8b, 0x8c, 0x12, 0x00, 0x01, 0x02, 0x28, 0x8b, + 0x00, 0x00, 0x00, 0x02, 0x28, 0x8b, 0xc0, 0x5c, + 0x4b, 0x00, 0x03, 0x01, 0x20, 0x96, 0x3b, 0x00, + 0x11, 0x01, 0x2d, 0x9e, 0x5d, 0x00, 0x01, 0x01, + 0x2d, 0xce, 0xcd, 0x2d, 0x00, }; static const uint8_t unicode_prop_Hyphen_table[28] = { @@ -3462,7 +3501,7 @@ static const uint8_t unicode_prop_Other_Math_table[200] = { 0x80, 0x89, 0x80, 0x90, 0x22, 0x04, 0x80, 0x90, }; -static const uint8_t unicode_prop_Other_Alphabetic_table[389] = { +static const uint8_t unicode_prop_Other_Alphabetic_table[396] = { 0x43, 0x44, 0x80, 0x42, 0x69, 0x8d, 0x00, 0x01, 0x01, 0x00, 0xc7, 0x8a, 0xaf, 0x8c, 0x06, 0x8f, 0x80, 0xe4, 0x33, 0x19, 0x0b, 0x80, 0xa2, 0x80, @@ -3482,36 +3521,37 @@ static const uint8_t unicode_prop_Other_Alphabetic_table[389] = { 0x81, 0xbc, 0x01, 0x86, 0x91, 0x80, 0xe2, 0x01, 0x28, 0x81, 0x8f, 0x80, 0x40, 0xa2, 0x90, 0x8a, 0x8a, 0x80, 0xa3, 0xed, 0x8b, 0x00, 0x0b, 0x96, - 0x1b, 0x10, 0x03, 0x0f, 0x83, 0x8c, 0x84, 0x94, - 0x81, 0x42, 0xc0, 0x80, 0x43, 0xb1, 0x81, 0x9d, - 0x81, 0x9d, 0x81, 0x9d, 0x81, 0xc1, 0x92, 0x40, - 0xbb, 0x81, 0xa1, 0x80, 0xf5, 0x8b, 0x83, 0x88, - 0x40, 0xdd, 0x84, 0xb8, 0x89, 0x81, 0x93, 0x40, - 0x8a, 0x84, 0xaf, 0x8e, 0xbb, 0x82, 0x9d, 0x88, - 0x09, 0xb8, 0x8a, 0xb1, 0x91, 0x40, 0xbb, 0x81, - 0x40, 0xf2, 0x8d, 0x46, 0xc0, 0xb3, 0x48, 0xf5, - 0x9f, 0x60, 0x78, 0x73, 0x87, 0xa1, 0x81, 0x41, - 0x82, 0x84, 0xd7, 0x81, 0xb1, 0x8f, 0x00, 0xdf, - 0x84, 0x9b, 0x8b, 0xac, 0x83, 0xaf, 0x8b, 0xe8, - 0x8d, 0x8b, 0x07, 0x81, 0xe1, 0x00, 0x11, 0x0c, - 0x80, 0xab, 0x24, 0x80, 0x40, 0xec, 0x87, 0x60, - 0x4f, 0x32, 0x80, 0x48, 0x56, 0x84, 0x46, 0x85, - 0x10, 0x0c, 0x83, 0x43, 0x13, 0x83, 0x42, 0xd7, - 0x82, 0xb4, 0x8d, 0xbb, 0x80, 0xac, 0x88, 0xc6, - 0x82, 0xa3, 0x8b, 0x91, 0x81, 0xb8, 0x82, 0xaf, - 0x8c, 0xeb, 0x88, 0x08, 0x28, 0x40, 0x9f, 0x89, - 0x96, 0x83, 0xb9, 0x31, 0x09, 0x81, 0x89, 0x80, - 0x89, 0x81, 0x40, 0xd0, 0x8c, 0x02, 0xe9, 0x91, - 0x40, 0xec, 0x31, 0x86, 0x9c, 0x81, 0xd1, 0x8e, - 0x00, 0xe9, 0x8a, 0xe6, 0x8d, 0x41, 0x00, 0x8c, - 0x41, 0xc7, 0x89, 0xa9, 0x20, 0x83, 0x91, 0x8a, + 0x1b, 0x10, 0x11, 0x32, 0x83, 0x8c, 0x8b, 0x00, + 0x89, 0x83, 0x46, 0x73, 0x81, 0x9d, 0x81, 0x9d, + 0x81, 0x9d, 0x81, 0xc1, 0x92, 0x40, 0xbb, 0x81, + 0xa1, 0x80, 0xf5, 0x8b, 0x83, 0x88, 0x40, 0xdd, + 0x84, 0xb8, 0x89, 0x81, 0x93, 0x40, 0x8a, 0x84, + 0xaf, 0x8e, 0xbb, 0x82, 0x9d, 0x88, 0x09, 0xb8, + 0x8a, 0xb1, 0x92, 0x41, 0xaf, 0x8d, 0x46, 0xc0, + 0xb3, 0x48, 0xf5, 0x9f, 0x60, 0x78, 0x73, 0x87, + 0xa1, 0x81, 0x41, 0x61, 0x07, 0x80, 0x96, 0x84, + 0xd7, 0x81, 0xb1, 0x8f, 0x00, 0xb8, 0x80, 0xa5, + 0x84, 0x9b, 0x8b, 0xac, 0x83, 0xaf, 0x8b, 0xa4, + 0x80, 0xc2, 0x8d, 0x8b, 0x07, 0x81, 0xac, 0x82, + 0xb1, 0x00, 0x11, 0x0c, 0x80, 0xab, 0x24, 0x80, + 0x40, 0xec, 0x87, 0x60, 0x4f, 0x32, 0x80, 0x48, + 0x56, 0x84, 0x46, 0x85, 0x10, 0x0c, 0x83, 0x43, + 0x13, 0x83, 0x42, 0xd7, 0x82, 0xb4, 0x8d, 0xbb, + 0x80, 0xac, 0x88, 0xc6, 0x82, 0xa3, 0x8b, 0x91, + 0x81, 0xb8, 0x82, 0xaf, 0x8c, 0xeb, 0x88, 0x08, + 0x28, 0x40, 0x9f, 0x89, 0x96, 0x83, 0xb9, 0x31, + 0x09, 0x81, 0x89, 0x80, 0x89, 0x81, 0x40, 0xd0, + 0x8c, 0x02, 0xe9, 0x91, 0x40, 0xec, 0x31, 0x86, + 0x9c, 0x81, 0xd1, 0x8e, 0x00, 0xe9, 0x8a, 0xe6, + 0x8d, 0x41, 0x00, 0x8c, 0x41, 0x97, 0x31, 0x2b, + 0x80, 0x9b, 0x89, 0xa9, 0x20, 0x83, 0x91, 0x8a, 0xad, 0x8d, 0x41, 0x96, 0x38, 0x86, 0xd2, 0x95, 0x80, 0x8d, 0xf9, 0x2a, 0x00, 0x08, 0x10, 0x02, 0x80, 0xc1, 0x20, 0x08, 0x83, 0x41, 0x5b, 0x83, - 0x60, 0x4c, 0x38, 0x86, 0x44, 0x19, 0xad, 0x60, - 0x4d, 0x1e, 0x80, 0x60, 0x23, 0x60, 0x30, 0x90, - 0x0e, 0x01, 0x04, 0x49, 0x1b, 0x80, 0x47, 0xe7, - 0x99, 0x85, 0x99, 0x85, 0x99, + 0x60, 0x50, 0x57, 0x00, 0xb6, 0x33, 0x60, 0x4d, + 0x0a, 0x80, 0x60, 0x23, 0x60, 0x30, 0x90, 0x0e, + 0x01, 0x04, 0x49, 0x1b, 0x80, 0x47, 0xe7, 0x99, + 0x85, 0x99, 0x85, 0x99, }; static const uint8_t unicode_prop_Other_Lowercase_table[51] = { @@ -3529,15 +3569,15 @@ static const uint8_t unicode_prop_Other_Uppercase_table[15] = { 0xcc, 0x5f, 0x99, 0x85, 0x99, 0x85, 0x99, }; -static const uint8_t unicode_prop_Other_Grapheme_Extend_table[59] = { +static const uint8_t unicode_prop_Other_Grapheme_Extend_table[62] = { 0x49, 0xbd, 0x80, 0x97, 0x80, 0x41, 0x65, 0x80, 0x97, 0x80, 0xe5, 0x80, 0x97, 0x80, 0x40, 0xe9, 0x80, 0x91, 0x81, 0xe6, 0x80, 0x97, 0x80, 0xf6, - 0x80, 0x8e, 0x80, 0x52, 0x2b, 0x80, 0x50, 0x20, - 0x81, 0x60, 0xcf, 0x6d, 0x81, 0x53, 0x9d, 0x80, - 0x97, 0x80, 0x41, 0x57, 0x80, 0x8b, 0x80, 0x40, - 0xf0, 0x80, 0x60, 0xbb, 0xb4, 0x07, 0x84, 0x6c, - 0x2e, 0xac, 0xdf, + 0x80, 0x8e, 0x80, 0x4d, 0x54, 0x80, 0x44, 0xd5, + 0x80, 0x50, 0x20, 0x81, 0x60, 0xcf, 0x6d, 0x81, + 0x53, 0x9d, 0x80, 0x97, 0x80, 0x41, 0x57, 0x80, + 0x8b, 0x80, 0x40, 0xf0, 0x80, 0x60, 0xbb, 0xb4, + 0x07, 0x84, 0x6c, 0x2e, 0xac, 0xdf, }; static const uint8_t unicode_prop_Other_Default_Ignorable_Code_Point_table[32] = { @@ -3590,7 +3630,7 @@ static const uint8_t unicode_prop_Changes_When_Casefolded1_table[33] = { 0x84, }; -static const uint8_t unicode_prop_Changes_When_NFKC_Casefolded1_table[438] = { +static const uint8_t unicode_prop_Changes_When_NFKC_Casefolded1_table[436] = { 0x40, 0x9f, 0x06, 0x00, 0x01, 0x00, 0x01, 0x12, 0x10, 0x82, 0x9f, 0x80, 0xcf, 0x01, 0x80, 0x8b, 0x07, 0x80, 0xfb, 0x01, 0x01, 0x80, 0xa5, 0x80, @@ -3621,31 +3661,31 @@ static const uint8_t unicode_prop_Changes_When_NFKC_Casefolded1_table[438] = { 0x80, 0x41, 0x2e, 0x80, 0xd2, 0x80, 0x8b, 0x40, 0xd5, 0xa9, 0x80, 0xb4, 0x00, 0x82, 0xdf, 0x09, 0x80, 0xde, 0x80, 0xb0, 0xdd, 0x82, 0x8d, 0xdf, - 0x9e, 0x80, 0xa7, 0x87, 0xae, 0x80, 0xfe, 0x80, - 0x40, 0xff, 0x60, 0x72, 0x9b, 0x81, 0x40, 0xd1, - 0x80, 0x40, 0x86, 0x81, 0x43, 0x61, 0x83, 0x60, - 0x4d, 0x9f, 0x41, 0x0d, 0x08, 0x00, 0x81, 0x89, - 0x00, 0x00, 0x09, 0x82, 0xc3, 0x81, 0xe9, 0xa5, - 0x86, 0x8b, 0x24, 0x00, 0x97, 0x04, 0x00, 0x01, - 0x01, 0x80, 0xeb, 0xa0, 0x41, 0x6a, 0x91, 0xbf, - 0x81, 0xb5, 0xa7, 0x8c, 0x82, 0x99, 0x95, 0x94, - 0x81, 0x8b, 0x80, 0x92, 0x03, 0x1a, 0x00, 0x80, - 0x40, 0x86, 0x08, 0x80, 0x9f, 0x99, 0x40, 0x83, - 0x15, 0x0d, 0x0d, 0x0a, 0x16, 0x06, 0x80, 0x88, - 0x60, 0xbc, 0xa6, 0x83, 0x54, 0xb9, 0x86, 0x8d, - 0x87, 0xbf, 0x85, 0x42, 0x3e, 0xd4, 0x80, 0xc6, - 0x01, 0x08, 0x09, 0x0b, 0x80, 0x8b, 0x00, 0x06, - 0x80, 0xc0, 0x03, 0x0f, 0x06, 0x80, 0x9b, 0x03, - 0x04, 0x00, 0x16, 0x80, 0x41, 0x53, 0x81, 0x41, - 0x23, 0x81, 0xb1, 0x55, 0xff, 0x18, 0x9a, 0x01, - 0x00, 0x08, 0x80, 0x89, 0x03, 0x00, 0x00, 0x28, - 0x18, 0x00, 0x00, 0x02, 0x01, 0x00, 0x08, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x0b, 0x06, 0x03, - 0x03, 0x00, 0x80, 0x89, 0x80, 0x90, 0x22, 0x04, - 0x80, 0x90, 0x42, 0x43, 0x8a, 0x84, 0x9e, 0x80, - 0x9f, 0x99, 0x81, 0xa3, 0x80, 0xee, 0x82, 0x8c, - 0xab, 0x83, 0x88, 0x31, 0x61, 0x05, 0xad, 0x42, - 0x1d, 0x6b, 0x05, 0xe1, 0x4f, 0xff, + 0x9e, 0x80, 0xa7, 0x87, 0xae, 0x80, 0x41, 0x7f, + 0x60, 0x72, 0x9b, 0x81, 0x40, 0xd1, 0x80, 0x40, + 0x86, 0x81, 0x43, 0x61, 0x83, 0x60, 0x4d, 0x9f, + 0x41, 0x0d, 0x08, 0x00, 0x81, 0x89, 0x00, 0x00, + 0x09, 0x82, 0xc3, 0x81, 0xe9, 0xa5, 0x86, 0x8b, + 0x24, 0x00, 0x97, 0x04, 0x00, 0x01, 0x01, 0x80, + 0xeb, 0xa0, 0x41, 0x6a, 0x91, 0xbf, 0x81, 0xb5, + 0xa7, 0x8c, 0x82, 0x99, 0x95, 0x94, 0x81, 0x8b, + 0x80, 0x92, 0x03, 0x1a, 0x00, 0x80, 0x40, 0x86, + 0x08, 0x80, 0x9f, 0x99, 0x40, 0x83, 0x15, 0x0d, + 0x0d, 0x0a, 0x16, 0x06, 0x80, 0x88, 0x60, 0xbc, + 0xa6, 0x83, 0x54, 0xb9, 0x86, 0x8d, 0x87, 0xbf, + 0x85, 0x42, 0x3e, 0xd4, 0x80, 0xc6, 0x01, 0x08, + 0x09, 0x0b, 0x80, 0x8b, 0x00, 0x06, 0x80, 0xc0, + 0x03, 0x0f, 0x06, 0x80, 0x9b, 0x03, 0x04, 0x00, + 0x16, 0x80, 0x41, 0x53, 0x81, 0x41, 0x23, 0x81, + 0xb1, 0x55, 0xff, 0x18, 0x9a, 0x01, 0x00, 0x08, + 0x80, 0x89, 0x03, 0x00, 0x00, 0x28, 0x18, 0x00, + 0x00, 0x02, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x0b, 0x06, 0x03, 0x03, 0x00, + 0x80, 0x89, 0x80, 0x90, 0x22, 0x04, 0x80, 0x90, + 0x42, 0x43, 0x8a, 0x84, 0x9e, 0x80, 0x9f, 0x99, + 0x82, 0xa2, 0x80, 0xee, 0x82, 0x8c, 0xab, 0x83, + 0x88, 0x31, 0x61, 0x05, 0xad, 0x42, 0x1d, 0x6b, + 0x05, 0xe1, 0x4f, 0xff, }; static const uint8_t unicode_prop_ASCII_Hex_Digit_table[5] = { @@ -3673,7 +3713,7 @@ static const uint8_t unicode_prop_Deprecated_table[23] = { 0x42, 0xb8, 0x81, 0x6d, 0xdc, 0xd5, 0x80, }; -static const uint8_t unicode_prop_Diacritic_table[332] = { +static const uint8_t unicode_prop_Diacritic_table[350] = { 0xdd, 0x00, 0x80, 0xc6, 0x05, 0x03, 0x01, 0x81, 0x41, 0xf6, 0x40, 0x9e, 0x07, 0x25, 0x90, 0x0b, 0x80, 0x88, 0x81, 0x40, 0xfc, 0x84, 0x40, 0xd0, @@ -3685,10 +3725,11 @@ static const uint8_t unicode_prop_Diacritic_table[332] = { 0x80, 0x8f, 0x80, 0xed, 0x80, 0x8f, 0x80, 0xae, 0x82, 0xbb, 0x80, 0x8f, 0x80, 0xfe, 0x80, 0xfe, 0x80, 0xed, 0x80, 0x8f, 0x80, 0xec, 0x81, 0x8f, - 0x80, 0xfb, 0x80, 0xfb, 0x28, 0x80, 0xf8, 0x84, - 0xca, 0x81, 0x9a, 0x00, 0x00, 0x03, 0x81, 0xc1, - 0x10, 0x81, 0xbd, 0x80, 0xef, 0x00, 0x81, 0xcb, - 0x30, 0x80, 0x89, 0x81, 0x47, 0x2c, 0x8a, 0x88, + 0x80, 0xfb, 0x80, 0xfb, 0x28, 0x80, 0xea, 0x80, + 0x8c, 0x84, 0xca, 0x81, 0x9a, 0x00, 0x00, 0x03, + 0x81, 0xc1, 0x10, 0x81, 0xbd, 0x80, 0xef, 0x00, + 0x81, 0xa7, 0x0b, 0x84, 0x98, 0x30, 0x80, 0x89, + 0x81, 0x42, 0xc0, 0x82, 0x44, 0x68, 0x8a, 0x88, 0x80, 0x41, 0x5a, 0x82, 0x41, 0x38, 0x39, 0x80, 0xaf, 0x8d, 0xf5, 0x80, 0x8e, 0x80, 0xa5, 0x88, 0xb5, 0x81, 0x40, 0x89, 0x81, 0xbf, 0x85, 0xd1, @@ -3697,8 +3738,8 @@ static const uint8_t unicode_prop_Diacritic_table[332] = { 0x82, 0x8c, 0x82, 0x8c, 0x82, 0x8c, 0x81, 0x4c, 0xef, 0x82, 0x41, 0x3c, 0x80, 0x41, 0xf9, 0x85, 0xe8, 0x83, 0xde, 0x80, 0x60, 0x75, 0x71, 0x80, - 0x8b, 0x08, 0x80, 0x9b, 0x81, 0xd1, 0x81, 0xa4, - 0x8a, 0xe5, 0x80, 0xee, 0x81, 0x40, 0xc9, 0x80, + 0x8b, 0x08, 0x80, 0x9b, 0x81, 0xd1, 0x81, 0x8d, + 0xa1, 0xe5, 0x82, 0xec, 0x81, 0x40, 0xc9, 0x80, 0x9a, 0x91, 0xb8, 0x83, 0xa3, 0x80, 0xde, 0x80, 0x8b, 0x80, 0xa3, 0x80, 0x40, 0x94, 0x82, 0xc0, 0x83, 0xb2, 0x80, 0xe3, 0x84, 0x40, 0x8b, 0x81, @@ -3710,15 +3751,16 @@ static const uint8_t unicode_prop_Diacritic_table[332] = { 0xe7, 0x81, 0x40, 0xb1, 0x81, 0xd0, 0x80, 0x8f, 0x80, 0x97, 0x32, 0x84, 0x40, 0xcc, 0x02, 0x80, 0xfa, 0x81, 0x40, 0xfa, 0x81, 0xfd, 0x80, 0xf5, - 0x81, 0xf2, 0x80, 0x41, 0x0c, 0x81, 0x41, 0xf8, - 0x80, 0x91, 0x80, 0xd0, 0x80, 0x41, 0xa4, 0x80, - 0x41, 0x01, 0x00, 0x81, 0xd0, 0x80, 0x60, 0x4d, - 0x57, 0x84, 0x44, 0x99, 0x90, 0x60, 0x61, 0xc6, - 0x12, 0x2f, 0x39, 0x86, 0x9d, 0x83, 0x57, 0x21, - 0x86, 0xec, 0x10, 0x82, + 0x81, 0xf2, 0x80, 0x41, 0x0c, 0x81, 0x41, 0xa4, + 0x80, 0xd2, 0x80, 0x91, 0x80, 0xd0, 0x80, 0x41, + 0xa4, 0x80, 0x41, 0x01, 0x00, 0x81, 0xd0, 0x80, + 0x60, 0x4d, 0x57, 0x84, 0xba, 0x86, 0x44, 0x57, + 0x90, 0x60, 0x61, 0xc6, 0x12, 0x2f, 0x39, 0x86, + 0x9d, 0x83, 0x4f, 0x81, 0x86, 0x41, 0xb4, 0x83, + 0x45, 0xdf, 0x86, 0xec, 0x10, 0x82, }; -static const uint8_t unicode_prop_Extender_table[82] = { +static const uint8_t unicode_prop_Extender_table[86] = { 0x40, 0xb6, 0x80, 0x42, 0x17, 0x81, 0x43, 0x6d, 0x80, 0x41, 0xb8, 0x80, 0x46, 0x4a, 0x80, 0xfe, 0x80, 0x49, 0x42, 0x80, 0xb7, 0x80, 0x42, 0x62, @@ -3728,8 +3770,8 @@ static const uint8_t unicode_prop_Extender_table[82] = { 0x80, 0x95, 0x80, 0x40, 0x88, 0x80, 0xeb, 0x80, 0x94, 0x81, 0x60, 0x54, 0x7a, 0x80, 0x53, 0xeb, 0x80, 0x42, 0x67, 0x82, 0x44, 0xce, 0x80, 0x60, - 0x50, 0xa8, 0x81, 0x44, 0x9b, 0x81, 0x60, 0x79, - 0x61, 0x82, + 0x50, 0xa8, 0x81, 0x44, 0x9b, 0x08, 0x80, 0x60, + 0x71, 0x57, 0x81, 0x48, 0x05, 0x82, }; static const uint8_t unicode_prop_Hex_Digit_table[12] = { @@ -3749,7 +3791,7 @@ static const uint8_t unicode_prop_Ideographic_table[58] = { 0x60, 0x30, 0x05, 0x81, 0x98, 0x88, 0x8d, 0x82, 0x43, 0xc4, 0x59, 0xb5, 0xc9, 0x60, 0x51, 0xef, 0x60, 0x59, 0x0f, 0x41, 0x6d, 0x81, 0xe9, 0x60, - 0x75, 0x25, 0x57, 0xf1, 0x8d, 0x42, 0xf2, 0x60, + 0x75, 0x25, 0x57, 0xf7, 0x87, 0x42, 0xf2, 0x60, 0x26, 0x7c, 0x41, 0x8b, 0x60, 0x4d, 0x03, 0x60, 0xa6, 0xd6, 0xa8, 0x50, 0x34, 0x8a, 0x40, 0xdd, 0x81, 0x56, 0x81, 0x8d, 0x5d, 0x30, 0x4c, 0x1e, @@ -3854,12 +3896,12 @@ static const uint8_t unicode_prop_Terminal_Punctuation_table[237] = { 0x80, 0xaa, 0x8a, 0x00, 0x40, 0xea, 0x81, 0xb5, 0x8e, 0x9e, 0x80, 0x41, 0x04, 0x81, 0x44, 0xf3, 0x81, 0x40, 0xab, 0x03, 0x85, 0x41, 0x36, 0x81, - 0x43, 0x14, 0x87, 0x43, 0x03, 0x81, 0xfb, 0x82, + 0x43, 0x14, 0x87, 0x43, 0x04, 0x80, 0xfb, 0x82, 0xc6, 0x81, 0x40, 0x9c, 0x12, 0x80, 0xa6, 0x19, 0x81, 0x41, 0x39, 0x81, 0x41, 0x61, 0x83, 0x40, 0xad, 0x08, 0x82, 0x40, 0xda, 0x84, 0xbd, 0x81, 0x43, 0xbb, 0x81, 0x88, 0x82, 0x4d, 0xe3, 0x80, - 0x8c, 0x03, 0x80, 0x89, 0x00, 0x80, 0x41, 0xb1, + 0x8c, 0x03, 0x80, 0x89, 0x00, 0x81, 0x41, 0xb0, 0x81, 0x60, 0x74, 0xfa, 0x81, 0x41, 0x0c, 0x82, 0x40, 0xe2, 0x84, 0x41, 0x7d, 0x81, 0xd5, 0x81, 0xde, 0x80, 0x40, 0x96, 0x82, 0x40, 0x92, 0x82, @@ -3924,7 +3966,7 @@ static const uint8_t unicode_prop_Bidi_Mirrored_table[171] = { 0x80, 0xb8, 0x80, }; -static const uint8_t unicode_prop_Emoji_table[227] = { +static const uint8_t unicode_prop_Emoji_table[236] = { 0xa2, 0x05, 0x04, 0x89, 0xee, 0x03, 0x80, 0x5f, 0x8c, 0x80, 0x8b, 0x80, 0x40, 0xd7, 0x80, 0x95, 0x80, 0xd9, 0x85, 0x8e, 0x81, 0x41, 0x6e, 0x81, @@ -3950,10 +3992,11 @@ static const uint8_t unicode_prop_Emoji_table[227] = { 0x8a, 0x28, 0x97, 0x31, 0x0f, 0x8b, 0x01, 0x19, 0x03, 0x81, 0x8c, 0x09, 0x07, 0x81, 0x88, 0x04, 0x82, 0x8b, 0x17, 0x11, 0x00, 0x03, 0x05, 0x02, - 0x05, 0xd5, 0xaf, 0xc5, 0x27, 0x8c, 0x2a, 0x00, - 0x0a, 0x01, 0x86, 0x42, 0x15, 0xaa, 0x02, 0x05, - 0x80, 0xa9, 0x0b, 0x10, 0x80, 0xa6, 0x8c, 0x89, - 0x2a, 0x8c, 0xaf, + 0x05, 0xd5, 0xaf, 0xc5, 0x27, 0x08, 0x89, 0x2a, + 0x00, 0x0a, 0x01, 0x87, 0x40, 0xe4, 0x8b, 0x41, + 0x20, 0xad, 0x80, 0x89, 0x80, 0xaa, 0x03, 0x82, + 0xa8, 0x0d, 0x82, 0x9c, 0x81, 0xb2, 0xef, 0x1b, + 0x14, 0x82, 0x8c, 0x85, }; static const uint8_t unicode_prop_Emoji_Component_table[28] = { @@ -3967,18 +4010,18 @@ static const uint8_t unicode_prop_Emoji_Modifier_table[4] = { 0x61, 0xf3, 0xfa, 0x84, }; -static const uint8_t unicode_prop_Emoji_Modifier_Base_table[61] = { +static const uint8_t unicode_prop_Emoji_Modifier_Base_table[63] = { 0x60, 0x26, 0x1c, 0x80, 0x40, 0xda, 0x80, 0x8f, 0x83, 0x61, 0xcc, 0x76, 0x80, 0xbb, 0x11, 0x01, - 0x82, 0xf4, 0x09, 0x8a, 0x94, 0x1b, 0x00, 0x88, - 0x10, 0x1a, 0x02, 0xa1, 0x80, 0x40, 0xc8, 0x0b, + 0x82, 0xf4, 0x09, 0x8a, 0x94, 0x92, 0x10, 0x1a, + 0x02, 0x30, 0x00, 0x97, 0x80, 0x40, 0xc8, 0x0b, 0x80, 0x94, 0x03, 0x81, 0x40, 0xad, 0x12, 0x84, 0xd2, 0x80, 0x8f, 0x82, 0x88, 0x80, 0x8a, 0x80, - 0x42, 0x4a, 0x20, 0x0d, 0x80, 0x88, 0x89, 0x11, - 0xf5, 0x08, 0x81, 0x96, 0x8c, + 0x42, 0x41, 0x07, 0x3d, 0x80, 0x88, 0x89, 0x0a, + 0xf5, 0x08, 0x08, 0x80, 0x90, 0x10, 0x8c, }; -static const uint8_t unicode_prop_Emoji_Presentation_table[134] = { +static const uint8_t unicode_prop_Emoji_Presentation_table[143] = { 0x60, 0x23, 0x19, 0x81, 0x40, 0xcc, 0x1a, 0x01, 0x80, 0x42, 0x08, 0x81, 0x94, 0x81, 0xb1, 0x8b, 0xaa, 0x80, 0x92, 0x80, 0x8c, 0x07, 0x81, 0x90, @@ -3993,9 +4036,10 @@ static const uint8_t unicode_prop_Emoji_Presentation_table[134] = { 0x1c, 0x8b, 0x90, 0x10, 0x82, 0xc6, 0x00, 0x80, 0x40, 0xba, 0x81, 0xbe, 0x8c, 0x18, 0x97, 0x91, 0x80, 0x99, 0x81, 0x8c, 0x80, 0xd5, 0xd4, 0xaf, - 0xc5, 0x28, 0x12, 0x97, 0x0e, 0x85, 0x42, 0x15, - 0xaa, 0x02, 0x05, 0x80, 0xa9, 0x0b, 0x10, 0x80, - 0xa6, 0x8c, 0x89, 0x2a, 0x8c, 0xaf, + 0xc5, 0x28, 0x12, 0x08, 0x94, 0x0e, 0x86, 0x40, + 0xe4, 0x8b, 0x41, 0x20, 0xad, 0x80, 0x89, 0x80, + 0xaa, 0x03, 0x82, 0xa8, 0x0d, 0x82, 0x9c, 0x81, + 0xb2, 0xef, 0x1b, 0x14, 0x82, 0x8c, 0x85, }; static const uint8_t unicode_prop_Extended_Pictographic_table[152] = { diff --git a/quickjs/quickjs-atom.h b/quickjs/quickjs-atom.h index 6f5b7ee9a9..8ec55ee2fe 100644 --- a/quickjs/quickjs-atom.h +++ b/quickjs/quickjs-atom.h @@ -266,9 +266,7 @@ DEF(Symbol_operatorNeg, "Symbol.operatorNeg") DEF(Symbol_operatorNot, "Symbol.operatorNot") DEF(Symbol_operatorInc, "Symbol.operatorInc") DEF(Symbol_operatorDec, "Symbol.operatorDec") -DEF(Symbol_operatorMathDiv, "Symbol.operatorMathDiv") DEF(Symbol_operatorMathMod, "Symbol.operatorMathMod") -DEF(Symbol_operatorMathPow, "Symbol.operatorMathPow") #endif #endif /* DEF */ diff --git a/quickjs/quickjs-libc.c b/quickjs/quickjs-libc.c index 4d248b60fe..268ef0472e 100644 --- a/quickjs/quickjs-libc.c +++ b/quickjs/quickjs-libc.c @@ -487,6 +487,7 @@ static JSValue js_evalScript(JSContext *ctx, JSValueConst this_val, JS_SetInterruptHandler(JS_GetRuntime(ctx), interrupt_handler, NULL); } ret = JS_Eval(ctx, str, len, "", JS_EVAL_TYPE_GLOBAL); + JS_FreeCString(ctx, str); if (--eval_script_recurse == 0) { /* remove the interrupt handler */ JS_SetInterruptHandler(JS_GetRuntime(ctx), NULL, NULL); @@ -1409,20 +1410,20 @@ static JSValue js_os_setTimeout(JSContext *ctx, JSValueConst this_val, JSOSTimer *th; JSValue obj; - if (JS_ToInt64(ctx, &delay, argv[0])) - return JS_EXCEPTION; - func = argv[1]; + func = argv[0]; if (!JS_IsFunction(ctx, func)) return JS_ThrowTypeError(ctx, "not a function"); + if (JS_ToInt64(ctx, &delay, argv[1])) + return JS_EXCEPTION; obj = JS_NewObjectClass(ctx, js_os_timer_class_id); if (JS_IsException(obj)) return obj; th = js_mallocz(ctx, sizeof(*th)); - th->has_object = TRUE; if (!th) { JS_FreeValue(ctx, obj); return JS_EXCEPTION; } + th->has_object = TRUE; th->timeout = get_time_ms() + delay; th->func = JS_DupValue(ctx, func); list_add_tail(&th->link, &os_timers); @@ -1448,8 +1449,12 @@ static JSClassDef js_os_timer_class = { static void call_handler(JSContext *ctx, JSValueConst func) { - JSValue ret; - ret = JS_Call(ctx, func, JS_UNDEFINED, 0, NULL); + JSValue ret, func1; + /* 'func' might be destroyed when calling itself (if it frees the + handler), so must take extra care */ + func1 = JS_DupValue(ctx, func); + ret = JS_Call(ctx, func1, JS_UNDEFINED, 0, NULL); + JS_FreeValue(ctx, func1); if (JS_IsException(ret)) js_std_dump_error(ctx); JS_FreeValue(ctx, ret); diff --git a/quickjs/quickjs.c b/quickjs/quickjs.c index 9606455cca..8ee82f4525 100644 --- a/quickjs/quickjs.c +++ b/quickjs/quickjs.c @@ -2649,8 +2649,9 @@ JSValue JS_AtomToString(JSContext *ctx, JSAtom atom) return __JS_AtomToValue(ctx, atom, TRUE); } -/* return TRUE if the atom is a uint32 and return its value */ -static BOOL JS_AtomGetUint32(JSContext *ctx, uint32_t *pval, JSAtom atom) +/* return TRUE if the atom is an array index (i.e. 0 <= index <= + 2^32-2 and return its value */ +static BOOL JS_AtomIsArrayIndex(JSContext *ctx, uint32_t *pval, JSAtom atom) { if (__JS_AtomIsTaggedInt(atom)) { *pval = __JS_AtomToUInt32(atom); @@ -2663,71 +2664,7 @@ static BOOL JS_AtomGetUint32(JSContext *ctx, uint32_t *pval, JSAtom atom) assert(atom < rt->atom_size); p = rt->atom_array[atom]; if (p->atom_type == JS_ATOM_TYPE_STRING && - is_num_string(&val, p)) { - *pval = val; - return TRUE; - } else { - *pval = 0; - return FALSE; - } - } -} - -/* return TRUE if the string is a number n with 0 <= n <= 2^53-1 */ -static inline BOOL is_integer_index_string(uint64_t *pval, const JSString *p) -{ - uint64_t n; - int c, i, len; - - len = p->len; - if (len == 0 || len > 16) - return FALSE; - if (p->is_wide_char) - c = p->u.str16[0]; - else - c = p->u.str8[0]; - if (is_num(c)) { - if (c == '0') { - if (len != 1) - return FALSE; - n = 0; - } else { - n = c - '0'; - for(i = 1; i < len; i++) { - if (p->is_wide_char) - c = p->u.str16[i]; - else - c = p->u.str8[i]; - if (!is_num(c)) - return FALSE; - n = n * 10 + (c - '0'); - if (n >= ((uint64_t)1 << 53)) - return FALSE; - } - } - *pval = n; - return TRUE; - } else { - return FALSE; - } -} - -/* return TRUE if the atom is an integer index (i.e. 0 <= index <= - 2^53-1 and return its value */ -static BOOL JS_AtomIsIntegerIndex(JSContext *ctx, uint64_t *pval, JSAtom atom) -{ - if (__JS_AtomIsTaggedInt(atom)) { - *pval = __JS_AtomToUInt32(atom); - return TRUE; - } else { - JSRuntime *rt = ctx->rt; - JSAtomStruct *p; - uint64_t val; - - assert(atom < rt->atom_size); - p = rt->atom_array[atom]; - if (p->atom_type == JS_ATOM_TYPE_STRING && - is_integer_index_string(&val, p)) { + is_num_string(&val, p) && val != -1) { *pval = val; return TRUE; } else { @@ -3236,6 +3173,26 @@ static int string_get(const JSString *p, int idx) { return p->is_wide_char ? p->u.str16[idx] : p->u.str8[idx]; } +static int string_getc(const JSString *p, int *pidx) +{ + int idx, c, c1; + idx = *pidx; + if (p->is_wide_char) { + c = p->u.str16[idx++]; + if (c >= 0xd800 && c < 0xdc00 && idx < p->len) { + c1 = p->u.str16[idx]; + if (c1 >= 0xdc00 && c1 < 0xe000) { + c = (((c & 0x3ff) << 10) | (c1 & 0x3ff)) + 0x10000; + idx++; + } + } + } else { + c = p->u.str8[idx++]; + } + *pidx = idx; + return c; +} + static int string_buffer_write8(StringBuffer *s, const uint8_t *p, int len) { int i; @@ -6472,11 +6429,11 @@ static int num_keys_cmp(const void *p1, const void *p2, void *opaque) JSContext *ctx = opaque; JSAtom atom1 = ((const JSPropertyEnum *)p1)->atom; JSAtom atom2 = ((const JSPropertyEnum *)p2)->atom; - uint64_t v1, v2; + uint32_t v1, v2; BOOL atom1_is_integer, atom2_is_integer; - atom1_is_integer = JS_AtomIsIntegerIndex(ctx, &v1, atom1); - atom2_is_integer = JS_AtomIsIntegerIndex(ctx, &v2, atom2); + atom1_is_integer = JS_AtomIsArrayIndex(ctx, &v1, atom1); + atom2_is_integer = JS_AtomIsArrayIndex(ctx, &v2, atom2); assert(atom1_is_integer && atom2_is_integer); if (v1 < v2) return -1; @@ -6515,7 +6472,7 @@ static int __exception JS_GetOwnPropertyNames(JSContext *ctx, JSPropertyEnum **p uint32_t num_keys_count, str_keys_count, sym_keys_count, atom_count; uint32_t num_index, str_index, sym_index, exotic_count; BOOL is_enumerable, is_string, num_sorted; - uint64_t num_key; + uint32_t num_key; /* clear pointer for consistency in case of failure */ *ptab = NULL; @@ -6545,7 +6502,7 @@ static int __exception JS_GetOwnPropertyNames(JSContext *ctx, JSPropertyEnum **p return -1; } } - if (JS_AtomIsIntegerIndex(ctx, &num_key, atom)) { + if (JS_AtomIsArrayIndex(ctx, &num_key, atom)) { num_keys_count++; } else if (is_string) { str_keys_count++; @@ -6597,7 +6554,7 @@ static int __exception JS_GetOwnPropertyNames(JSContext *ctx, JSPropertyEnum **p tab_exotic[i].is_enumerable = is_enumerable; } if (!(flags & JS_GPN_ENUM_ONLY) || is_enumerable) { - if (JS_AtomIsIntegerIndex(ctx, &num_key, atom)) { + if (JS_AtomIsArrayIndex(ctx, &num_key, atom)) { num_keys_count++; } else if (is_string) { str_keys_count++; @@ -6634,7 +6591,7 @@ static int __exception JS_GetOwnPropertyNames(JSContext *ctx, JSPropertyEnum **p is_string = JS_AtomIsString(ctx, atom); if ((!(flags & JS_GPN_ENUM_ONLY) || is_enumerable) && ((flags >> is_string) & 1) != 0) { - if (JS_AtomIsIntegerIndex(ctx, &num_key, atom)) { + if (JS_AtomIsArrayIndex(ctx, &num_key, atom)) { j = num_index++; num_sorted = FALSE; } else if (is_string) { @@ -6668,7 +6625,7 @@ static int __exception JS_GetOwnPropertyNames(JSContext *ctx, JSPropertyEnum **p is_string = JS_AtomIsString(ctx, atom); if ((!(flags & JS_GPN_ENUM_ONLY) || is_enumerable) && ((flags >> is_string) & 1) != 0) { - if (JS_AtomIsIntegerIndex(ctx, &num_key, atom)) { + if (JS_AtomIsArrayIndex(ctx, &num_key, atom)) { j = num_index++; num_sorted = FALSE; } else if (is_string) { @@ -7146,7 +7103,7 @@ static int delete_property(JSContext *ctx, JSObject *p, JSAtom atom) if (p->is_exotic) { if (p->fast_array) { uint32_t idx; - if (JS_AtomGetUint32(ctx, &idx, atom) && + if (JS_AtomIsArrayIndex(ctx, &idx, atom) && idx < p->u.array.count) { if (p->class_id == JS_CLASS_ARRAY || p->class_id == JS_CLASS_ARGUMENTS) { @@ -7256,8 +7213,7 @@ static int set_array_length(JSContext *ctx, JSObject *p, JSProperty *prop, for(i = 0, pr = get_shape_prop(sh); i < sh->prop_count; i++, pr++) { if (pr->atom != JS_ATOM_NULL && - JS_AtomGetUint32(ctx, &idx, pr->atom) && - idx != 0xffffffff) { + JS_AtomIsArrayIndex(ctx, &idx, pr->atom)) { if (idx >= cur_len && !(pr->flags & JS_PROP_CONFIGURABLE)) { cur_len = idx + 1; @@ -7268,8 +7224,7 @@ static int set_array_length(JSContext *ctx, JSObject *p, JSProperty *prop, for(i = 0, pr = get_shape_prop(sh); i < sh->prop_count; i++, pr++) { if (pr->atom != JS_ATOM_NULL && - JS_AtomGetUint32(ctx, &idx, pr->atom) && - idx != 0xffffffff) { + JS_AtomIsArrayIndex(ctx, &idx, pr->atom)) { if (idx >= cur_len) { /* remove the property */ delete_property(ctx, p, pr->atom); @@ -7861,14 +7816,14 @@ static int JS_CreateProperty(JSContext *ctx, JSObject *p, } else { goto convert_to_array; } - } else if (JS_AtomGetUint32(ctx, &idx, prop) && idx != 0xffffffff) { + } else if (JS_AtomIsArrayIndex(ctx, &idx, prop)) { /* convert the fast array to normal array */ convert_to_array: if (convert_fast_array_to_array(ctx, p)) return -1; goto generic_array; } - } else if (JS_AtomGetUint32(ctx, &idx, prop) && idx != 0xffffffff) { + } else if (JS_AtomIsArrayIndex(ctx, &idx, prop)) { JSProperty *plen; JSShapeProperty *pslen; generic_array: @@ -9081,11 +9036,11 @@ static JSValue js_atod(JSContext *ctx, const char *str, const char **pp, radix == 0 && (flags & ATOD_ACCEPT_BIN_OCT)) { p += 2; radix = 2; - } else if ((p[1] >= '0' && p[1] <= '7') && + } else if ((p[1] >= '0' && p[1] <= '9') && radix == 0 && (flags & ATOD_ACCEPT_LEGACY_OCTAL)) { int i; - for (i = 2; (p[i] >= '0' && p[i] <= '7') || - (p[i] == sep && is_digit((uint8_t)p[i + 1])); i++) + sep = 256; + for (i = 1; (p[i] >= '0' && p[i] <= '7'); i++) continue; if (p[i] == '8' || p[i] == '9') goto no_prefix; @@ -10400,8 +10355,8 @@ static JSValue JS_ToQuotedString(JSContext *ctx, JSValueConst val1) if (string_buffer_putc8(b, '\"')) goto fail; - for(i = 0; i < p->len; i++) { - c = string_get(p, i); + for(i = 0; i < p->len; ) { + c = string_getc(p, &i); switch(c) { case '\t': c = 't'; @@ -10427,12 +10382,12 @@ static JSValue JS_ToQuotedString(JSContext *ctx, JSValueConst val1) goto fail; break; default: - if (c < 32) { + if (c < 32 || (c >= 0xd800 && c < 0xe000)) { snprintf(buf, sizeof(buf), "\\u%04x", c); if (string_buffer_puts8(b, buf)) goto fail; } else { - if (string_buffer_putc16(b, c)) + if (string_buffer_putc(b, c)) goto fail; } break; @@ -10465,12 +10420,19 @@ static __attribute__((unused)) void JS_DumpObject(JSRuntime *rt, JSObject *p) BOOL is_first = TRUE; /* XXX: should encode atoms with special characters */ - printf("%14p %4d %3d%c %14p %10s ", + sh = p->shape; /* the shape can be NULL while freeing an object */ + printf("%14p %4d ", (void *)p, - p->header.ref_count, - p->shape->header.ref_count, - " *"[p->shape->is_hashed], - (void *)p->shape->proto, + p->header.ref_count); + if (sh) { + printf("%3d%c %14p ", + sh->header.ref_count, + " *"[sh->is_hashed], + (void *)sh->proto); + } else { + printf("%3s %14s ", "-", "-"); + } + printf("%10s ", JS_AtomGetStrRT(rt, atom_buf, sizeof(atom_buf), rt->class_array[p->class_id].class_name)); if (p->is_exotic && p->fast_array) { printf("[ "); @@ -10495,31 +10457,32 @@ static __attribute__((unused)) void JS_DumpObject(JSRuntime *rt, JSObject *p) printf(" ] "); } - printf("{ "); - sh = p->shape; - for(i = 0, prs = get_shape_prop(sh); i < sh->prop_count; i++, prs++) { - if (prs->atom != JS_ATOM_NULL) { - pr = &p->prop[i]; - if (!is_first) - printf(", "); - printf("%s: ", - JS_AtomGetStrRT(rt, atom_buf, sizeof(atom_buf), prs->atom)); - if ((prs->flags & JS_PROP_TMASK) == JS_PROP_GETSET) { - printf("[getset %p %p]", (void *)pr->u.getset.getter, - (void *)pr->u.getset.setter); - } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) { - printf("[varref %p]", (void *)pr->u.var_ref); - } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) { - printf("[autoinit %p %p]", (void *)pr->u.init.init_func, - (void *)pr->u.init.opaque); - } else { - JS_DumpValueShort(rt, pr->u.value); + if (sh) { + printf("{ "); + for(i = 0, prs = get_shape_prop(sh); i < sh->prop_count; i++, prs++) { + if (prs->atom != JS_ATOM_NULL) { + pr = &p->prop[i]; + if (!is_first) + printf(", "); + printf("%s: ", + JS_AtomGetStrRT(rt, atom_buf, sizeof(atom_buf), prs->atom)); + if ((prs->flags & JS_PROP_TMASK) == JS_PROP_GETSET) { + printf("[getset %p %p]", (void *)pr->u.getset.getter, + (void *)pr->u.getset.setter); + } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) { + printf("[varref %p]", (void *)pr->u.var_ref); + } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) { + printf("[autoinit %p %p]", (void *)pr->u.init.init_func, + (void *)pr->u.init.opaque); + } else { + JS_DumpValueShort(rt, pr->u.value); + } + is_first = FALSE; } - is_first = FALSE; } + printf(" }"); } - printf(" }"); - + if (js_class_has_bytecode(p->class_id)) { JSFunctionBytecode *b = p->u.func.function_bytecode; JSVarRef **var_refs; @@ -10974,23 +10937,19 @@ static __exception int js_call_binary_op_fallback(JSContext *ctx, op_name = JS_ATOM_Symbol_operatorMul; break; case OP_div: + case OP_math_div: op_name = JS_ATOM_Symbol_operatorDiv; break; case OP_mod: op_name = JS_ATOM_Symbol_operatorMod; break; case OP_pow: + case OP_math_pow: op_name = JS_ATOM_Symbol_operatorPow; break; - case OP_math_div: - op_name = JS_ATOM_Symbol_operatorMathDiv; - break; case OP_math_mod: op_name = JS_ATOM_Symbol_operatorMathMod; break; - case OP_math_pow: - op_name = JS_ATOM_Symbol_operatorMathPow; - break; case OP_shl: op_name = JS_ATOM_Symbol_operatorShl; break; @@ -11517,7 +11476,8 @@ static no_inline __exception int js_binary_arith_slow(JSContext *ctx, JSValue *s BF_RNDZ) & BF_ST_INVALID_OP; bf_delete(rem); } else { - bf_div(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags); + bf_div(r, a, b, 53, bf_set_exp_bits(11) | + BF_RNDN | BF_FLAG_SUBNORMAL); goto float64_result; } break; @@ -11541,50 +11501,44 @@ static no_inline __exception int js_binary_arith_slow(JSContext *ctx, JSValue *s if (b->sign) { if (is_legacy) { ret = BF_ST_INVALID_OP; - } else { - bf_set_ui(r, 1); - if (bf_cmpu(a, r) <= 0) { - goto do_int_pow; - } else if (op == OP_math_pow) { - op_fallback: - bf_delete(r); - if (a == &a_s) - bf_delete(a); - if (b == &b_s) - bf_delete(b); - op_fallback2: - ret = js_call_binary_op_fallback(ctx, &res, op1, op2, op); - JS_FreeValue(ctx, op1); - JS_FreeValue(ctx, op2); - if (ret < 0) { - goto exception; - } else if (ret == 0) { - JS_ThrowTypeError(ctx, "operator must be defined for exact division or power"); - goto exception; - } - sp[-2] = res; - return 0; - } else { - double dr; - bf_pow(r, a, b, 53, bf_set_exp_bits(11) | - BF_RNDN | BF_FLAG_SUBNORMAL); - float64_result: - bf_get_float64(r, &dr, BF_RNDN); - bf_delete(r); - if (a == &a_s) - bf_delete(a); - if (b == &b_s) - bf_delete(b); - JS_FreeValue(ctx, op1); - JS_FreeValue(ctx, op2); - sp[-2] = __JS_NewFloat64(ctx, dr); - return 0; + } else if (op == OP_math_pow) { + op_fallback: + bf_delete(r); + if (a == &a_s) + bf_delete(a); + if (b == &b_s) + bf_delete(b); + op_fallback2: + ret = js_call_binary_op_fallback(ctx, &res, op1, op2, op); + JS_FreeValue(ctx, op1); + JS_FreeValue(ctx, op2); + if (ret < 0) { + goto exception; + } else if (ret == 0) { + JS_ThrowTypeError(ctx, "operator must be defined for exact division or power"); + goto exception; } + sp[-2] = res; + return 0; + } else { + double dr; + bf_pow(r, a, b, 53, bf_set_exp_bits(11) | + BF_RNDN | BF_FLAG_SUBNORMAL); + float64_result: + bf_get_float64(r, &dr, BF_RNDN); + bf_delete(r); + if (a == &a_s) + bf_delete(a); + if (b == &b_s) + bf_delete(b); + JS_FreeValue(ctx, op1); + JS_FreeValue(ctx, op2); + sp[-2] = __JS_NewFloat64(ctx, dr); + return 0; } } else { - do_int_pow: ret = bf_pow(r, a, b, BF_PREC_INF, BF_RNDZ | BF_POW_JS_QUICKS) & - (BF_ST_OVERFLOW | BF_ST_DIVIDE_ZERO); + BF_ST_OVERFLOW; } break; default: @@ -13155,7 +13109,7 @@ static int js_arguments_define_own_property(JSContext *ctx, uint32_t idx; p = JS_VALUE_GET_OBJ(this_obj); /* convert to normal array when redefining an existing numeric field */ - if (p->fast_array && JS_AtomGetUint32(ctx, &idx, prop) && + if (p->fast_array && JS_AtomIsArrayIndex(ctx, &idx, prop) && idx < p->u.array.count) { if (convert_fast_array_to_array(ctx, p)) return -1; @@ -13736,6 +13690,18 @@ static JSValue js_array_iterator_next(JSContext *ctx, JSValueConst this_val, static JSValue js_create_array_iterator(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic); +static BOOL js_is_fast_array(JSContext *ctx, JSValueConst obj) +{ + /* Try and handle fast arrays explicitly */ + if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) { + JSObject *p = JS_VALUE_GET_OBJ(obj); + if (p->class_id == JS_CLASS_ARRAY && p->fast_array) { + return TRUE; + } + } + return FALSE; +} + /* Access an Array's internal JSValue array if available */ static BOOL js_get_fast_array(JSContext *ctx, JSValueConst obj, JSValue **arrpp, uint32_t *countp) @@ -14132,7 +14098,7 @@ static int js_op_define_class(JSContext *ctx, JSValue *sp, return -1; } -static void close_var_refs(JSContext *ctx, JSStackFrame *sf) +static void close_var_refs(JSRuntime *rt, JSStackFrame *sf) { struct list_head *el, *el1; JSVarRef *var_ref; @@ -14142,9 +14108,9 @@ static void close_var_refs(JSContext *ctx, JSStackFrame *sf) var_ref = list_entry(el, JSVarRef, link); var_idx = var_ref->var_idx; if (var_ref->is_arg) - var_ref->value = JS_DupValue(ctx, sf->arg_buf[var_idx]); + var_ref->value = JS_DupValueRT(rt, sf->arg_buf[var_idx]); else - var_ref->value = JS_DupValue(ctx, sf->var_buf[var_idx]); + var_ref->value = JS_DupValueRT(rt, sf->var_buf[var_idx]); var_ref->pvalue = &var_ref->value; var_ref->link.prev = NULL; /* the reference is no longer to a local variable */ @@ -14205,6 +14171,9 @@ static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj, arg_buf = argv; arg_count = p->u.cfunc.length; + /* better to always check stack overflow */ + if (js_check_stack_overflow(ctx, sizeof(arg_buf[0]) * arg_count)) + return JS_ThrowStackOverflow(ctx); if (unlikely(argc < arg_count)) { /* ensure that at least argc_count arguments are readable */ @@ -14317,6 +14286,8 @@ static JSValue js_call_bound_function(JSContext *ctx, JSValueConst func_obj, p = JS_VALUE_GET_OBJ(func_obj); bf = p->u.bound_function; arg_count = bf->argc + argc; + if (js_check_stack_overflow(ctx, sizeof(JSValue) * arg_count)) + return JS_ThrowStackOverflow(ctx); arg_buf = alloca(sizeof(JSValue) * arg_count); for(i = 0; i < bf->argc; i++) { arg_buf[i] = bf->argv[i]; @@ -16011,8 +15982,14 @@ static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj, var_buf[idx] = JS_NewInt32(ctx, r); sp--; } else if (JS_VALUE_GET_TAG(ops[0]) == JS_TAG_STRING) { - ops[0] = JS_ConcatString(ctx, ops[0], ops[1]); sp--; + ops[1] = JS_ToPrimitiveFree(ctx, ops[1], HINT_NONE); + if (JS_IsException(ops[1])) { + goto exception; + } + /* XXX: should not modify the variable in case of + exception */ + ops[0] = JS_ConcatString(ctx, ops[0], ops[1]); if (JS_IsException(ops[0])) { var_buf[idx] = JS_UNDEFINED; goto exception; @@ -16020,11 +15997,17 @@ static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj, var_buf[idx] = ops[0]; } else { add_loc_slow: + /* XXX: should not modify the variable in case of + exception */ + sp--; + /* In case of exception, js_add_slow frees ops[0] + and ops[1]. */ /* XXX: change API */ - if (js_add_slow(ctx, ops + 2)) + if (js_add_slow(ctx, ops + 2)) { + var_buf[idx] = JS_UNDEFINED; goto exception; + } var_buf[idx] = ops[0]; - sp--; } } BREAK; @@ -16739,7 +16722,7 @@ static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj, done: if (unlikely(!list_empty(&sf->var_ref_list))) { /* variable references reference the stack: must close them */ - close_var_refs(ctx, sf); + close_var_refs(ctx->rt, sf); } /* free the local variables and stack */ for(pval = local_buf; pval < sp; pval++) { @@ -16957,6 +16940,10 @@ static void async_func_free(JSRuntime *rt, JSAsyncFunctionState *s) JSValue *sp; sf = &s->frame; + + /* close the closure variables. */ + close_var_refs(rt, sf); + if (sf->arg_buf) { /* cannot free the function if it is running */ assert(sf->cur_sp != NULL); @@ -16969,13 +16956,6 @@ static void async_func_free(JSRuntime *rt, JSAsyncFunctionState *s) JS_FreeValueRT(rt, s->this_val); } -/* close the closure variables */ -static void async_func_detach(JSContext *ctx, JSAsyncFunctionState *s) -{ - JSStackFrame *sf = &s->frame; - close_var_refs(ctx, sf); -} - static JSValue async_func_resume(JSContext *ctx, JSAsyncFunctionState *s) { JSValue func_obj; @@ -17022,11 +17002,7 @@ static void js_generator_finalizer(JSRuntime *rt, JSValue obj) static void free_generator_stack(JSContext *ctx, JSGeneratorData *s) { - if (s->state != JS_GENERATOR_STATE_COMPLETED) { - /* detach the closures variables */ - async_func_detach(ctx, &s->func_state); - free_generator_stack_rt(ctx->rt, s); - } + free_generator_stack_rt(ctx->rt, s); } static void js_generator_mark(JSRuntime *rt, JSValueConst val, @@ -17245,8 +17221,6 @@ static void js_async_function_terminate(JSRuntime *rt, JSContext *ctx, JSAsyncFunctionData *s) { if (s->is_active) { - if (ctx) - async_func_detach(ctx, &s->func_state); async_func_free(rt, &s->func_state); s->is_active = FALSE; } @@ -17624,7 +17598,6 @@ static void js_async_generator_complete(JSContext *ctx, { if (s->state != JS_ASYNC_GENERATOR_STATE_COMPLETED) { s->state = JS_ASYNC_GENERATOR_STATE_COMPLETED; - async_func_detach(ctx, &s->func_state); async_func_free(ctx->rt, &s->func_state); } } @@ -18324,20 +18297,6 @@ int __attribute__((format(printf, 2, 3))) js_parse_error(JSParseState *s, const return -1; } -int __attribute__((format(printf, 3, 4))) js_parse_error1(JSParseState *s, JSErrorEnum error_num, - const char *fmt, ...) -{ - JSContext *ctx = s->ctx; - va_list ap; - - va_start(ap, fmt); - JS_ThrowError(ctx, error_num, fmt, ap); - va_end(ap); - - build_backtrace(ctx, ctx->current_exception, s->filename, s->line_num, NULL); - return -1; -} - static int js_parse_expect(JSParseState *s, int tok) { if (s->token.val != tok) { @@ -18574,6 +18533,7 @@ static inline BOOL token_is_pseudo_keyword(JSParseState *s, JSAtom atom) { !s->token.u.ident.has_escape; } +#if 0 /* return TRUE if a regexp literal is allowed after this token */ static BOOL is_regexp_allowed(JSParseState *s) { @@ -18597,6 +18557,7 @@ static BOOL is_regexp_allowed(JSParseState *s) return TRUE; } } +#endif static __exception int js_parse_regexp(JSParseState *s) { @@ -18770,9 +18731,21 @@ static __exception int next_token(JSParseState *s) p += 2; break; } - if (*p == '\n') + if (*p == '\n') { s->line_num++; - p++; + s->got_lf = TRUE; /* considered as LF for ASI */ + p++; + } else if (*p == '\r') { + s->got_lf = TRUE; /* considered as LF for ASI */ + p++; + } else if (*p >= 0x80) { + c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p); + if (c == CP_LS || c == CP_PS) { + s->got_lf = TRUE; /* considered as LF for ASI */ + } + } else { + p++; + } } goto redo; } else if (p[1] == '/') { @@ -18794,12 +18767,16 @@ static __exception int next_token(JSParseState *s) } } goto redo; - } else if (is_regexp_allowed(s)) { + } +#if 0 + else if (is_regexp_allowed(s)) { s->buf_ptr = p; if (js_parse_regexp(s)) goto fail; p = s->buf_ptr; - } else if (p[1] == '=') { + } +#endif + else if (p[1] == '=') { p += 2; s->token.val = TOK_DIV_ASSIGN; } else { @@ -19208,7 +19185,9 @@ static __exception int next_token(JSParseState *s) /* and are not JSONWhitespace */ goto def_token; } else { - goto line_terminator; + /* XXX: should avoid incrementing line_number, but + needed to handle HTML comments */ + goto line_terminator; } default: if (lre_is_space(c)) { @@ -20161,6 +20140,8 @@ static __exception int js_parse_seek_token(JSParseState *s, const JSParsePos *sp #define SKIP_HAS_ELLIPSIS (1 << 1) /* XXX: improve speed with early bailout */ +/* XXX: no longer works if regexps are present. Could use previous + regexp parsing heuristics to handle most cases */ static int js_parse_skip_parens_token(JSParseState *s, int *pbits, BOOL no_line_terminator) { char state[256]; @@ -20169,7 +20150,7 @@ static int js_parse_skip_parens_token(JSParseState *s, int *pbits, BOOL no_line_ int tok = TOK_EOF; int bits = 0; - /* protect fom underflow */ + /* protect from underflow */ state[level++] = 0; js_parse_get_pos(s, &pos); @@ -20382,7 +20363,8 @@ static __exception int js_parse_class_default_ctor(JSParseState *s, const char *str; int ret, line_num; JSParseFunctionEnum func_type; - + const uint8_t *saved_buf_end; + js_parse_get_pos(s, &pos); if (has_super) { str = "(...a){super(...a);}"; @@ -20392,13 +20374,16 @@ static __exception int js_parse_class_default_ctor(JSParseState *s, func_type = JS_PARSE_FUNC_CLASS_CONSTRUCTOR; } line_num = s->token.line_num; + saved_buf_end = s->buf_end; s->buf_ptr = (uint8_t *)str; + s->buf_end = (uint8_t *)(str + strlen(str)); ret = next_token(s); if (!ret) { ret = js_parse_function_decl2(s, func_type, JS_FUNC_NORMAL, JS_ATOM_NULL, (uint8_t *)str, line_num, JS_PARSE_EXPORT_NONE, pfd); } + s->buf_end = saved_buf_end; ret |= js_parse_seek_token(s, &pos); return ret; } @@ -20832,12 +20817,11 @@ static __exception int get_lvalue(JSParseState *s, int *popcode, int *pscope, if (tok == TOK_FOR) { return js_parse_error(s, "invalid for in/of left hand-side"); } else if (tok == TOK_INC || tok == TOK_DEC) { - /* Firefox issues a SyntaxError for this */ - return js_parse_error1(s, JS_REFERENCE_ERROR, "invalid increment/decrement operand"); + return js_parse_error(s, "invalid increment/decrement operand"); } else if (tok == '[' || tok == '{') { return js_parse_error(s, "invalid destructuring target"); } else { - return js_parse_error1(s, JS_REFERENCE_ERROR, "invalid assignment left-hand side"); + return js_parse_error(s, "invalid assignment left-hand side"); } } /* remove the last opcode */ @@ -21054,7 +21038,8 @@ static JSAtom js_parse_destructing_var(JSParseState *s, int tok, int is_arg) } static int js_parse_destructing_element(JSParseState *s, int tok, int is_arg, - int hasval, int has_ellipsis) + int hasval, int has_ellipsis, + BOOL allow_initializer) { int label_parse, label_assign, label_done, label_lvalue, depth_lvalue; int start_addr, assign_addr; @@ -21167,7 +21152,7 @@ static int js_parse_destructing_element(JSParseState *s, int tok, int is_arg, emit_op(s, OP_get_field2); emit_u32(s, prop_name); } - if (js_parse_destructing_element(s, tok, is_arg, TRUE, -1)) + if (js_parse_destructing_element(s, tok, is_arg, TRUE, -1, TRUE)) return -1; if (s->token.val == '}') break; @@ -21391,7 +21376,7 @@ static int js_parse_destructing_element(JSParseState *s, int tok, int is_arg, emit_u8(s, 0); emit_op(s, OP_drop); } - if (js_parse_destructing_element(s, tok, is_arg, TRUE, skip_bits & SKIP_HAS_ELLIPSIS)) + if (js_parse_destructing_element(s, tok, is_arg, TRUE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE)) return -1; } else { var_name = JS_ATOM_NULL; @@ -21482,7 +21467,7 @@ static int js_parse_destructing_element(JSParseState *s, int tok, int is_arg, } else { return js_parse_error(s, "invalid assignment syntax"); } - if (s->token.val == '=') { + if (s->token.val == '=' && allow_initializer) { label_done = emit_goto(s, OP_goto, -1); if (next_token(s)) return -1; @@ -21576,12 +21561,21 @@ static __exception int js_parse_postfix_expr(JSParseState *s, BOOL accept_lparen if (next_token(s)) return -1; break; - case TOK_REGEXP: + + case TOK_DIV_ASSIGN: + s->buf_ptr -= 2; + goto parse_regexp; + case '/': + s->buf_ptr--; + parse_regexp: { JSValue str; int ret; if (!s->ctx->compile_regexp) return js_parse_error(s, "RegExp are not supported"); + /* the previous token is '/' or '/=', so no need to free */ + if (js_parse_regexp(s)) + return -1; ret = emit_push_const(s, s->token.u.regexp.body, 0); str = s->ctx->compile_regexp(s->ctx, s->token.u.regexp.body, s->token.u.regexp.flags); @@ -21699,7 +21693,7 @@ static __exception int js_parse_postfix_expr(JSParseState *s, BOOL accept_lparen { int skip_bits; if (js_parse_skip_parens_token(s, &skip_bits, FALSE) == '=') { - if (js_parse_destructing_element(s, 0, 0, FALSE, skip_bits & SKIP_HAS_ELLIPSIS)) + if (js_parse_destructing_element(s, 0, 0, FALSE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE)) return -1; } else { if (s->token.val == '{') { @@ -22219,7 +22213,6 @@ static __exception int js_parse_unary(JSParseState *s, int exponentiation_flag) if (exponentiation_flag) { #ifdef CONFIG_BIGNUM if (s->token.val == TOK_POW || s->token.val == TOK_MATH_POW) { - int val = s->token.val; /* Extended exponentiation syntax rules: we extend the ES7 grammar in order to have more intuitive semantics: -2**2 evaluates to -4. */ @@ -22233,10 +22226,10 @@ static __exception int js_parse_unary(JSParseState *s, int exponentiation_flag) return -1; if (js_parse_unary(s, 1)) return -1; - if (val == TOK_POW) - emit_op(s, OP_pow); - else + if (s->cur_func->js_mode & JS_MODE_MATH) emit_op(s, OP_math_pow); + else + emit_op(s, OP_pow); } #else if (s->token.val == TOK_POW) { @@ -22641,7 +22634,7 @@ static __exception int js_parse_assign_expr(JSParseState *s, BOOL in_accepted) OP_mul, OP_div, OP_mod, OP_add, OP_sub, OP_shl, OP_sar, OP_shr, OP_and, OP_xor, OP_or, #ifdef CONFIG_BIGNUM - OP_math_pow, + OP_pow, #endif OP_pow, }; @@ -22652,6 +22645,8 @@ static __exception int js_parse_assign_expr(JSParseState *s, BOOL in_accepted) op = OP_math_div; else if (op == OP_mod) op = OP_math_mod; + else if (op == OP_pow) + op = OP_math_pow; } #endif emit_op(s, op); @@ -22945,7 +22940,7 @@ static __exception int js_parse_var(JSParseState *s, BOOL in_accepted, int tok, if ((s->token.val == '[' || s->token.val == '{') && js_parse_skip_parens_token(s, &skip_bits, FALSE) == '=') { emit_op(s, OP_undefined); - if (js_parse_destructing_element(s, tok, 0, TRUE, skip_bits & SKIP_HAS_ELLIPSIS)) + if (js_parse_destructing_element(s, tok, 0, TRUE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE)) return -1; } else { return js_parse_error(s, "variable name expected"); @@ -23027,13 +23022,14 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name, JSContext *ctx = s->ctx; JSFunctionDef *fd = s->cur_func; JSAtom var_name; - BOOL has_initializer, is_for_of; + BOOL has_initializer, is_for_of, has_destructuring; int tok, tok1, opcode, scope, block_scope_level; int label_next, label_expr, label_cont, label_body, label_break; int pos_next, pos_expr; BlockEnv break_entry; has_initializer = FALSE; + has_destructuring = FALSE; is_for_of = FALSE; block_scope_level = fd->scope_level; label_cont = new_label(s); @@ -23073,8 +23069,9 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name, if (!(s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved)) { if (s->token.val == '[' || s->token.val == '{') { - if (js_parse_destructing_element(s, tok, 0, TRUE, -1)) + if (js_parse_destructing_element(s, tok, 0, TRUE, -1, FALSE)) return -1; + has_destructuring = TRUE; } else { return js_parse_error(s, "variable name expected"); } @@ -23101,7 +23098,7 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name, int skip_bits; if ((s->token.val == '[' || s->token.val == '{') && ((tok1 = js_parse_skip_parens_token(s, &skip_bits, FALSE)) == TOK_IN || tok1 == TOK_OF)) { - if (js_parse_destructing_element(s, 0, 0, TRUE, skip_bits & SKIP_HAS_ELLIPSIS)) + if (js_parse_destructing_element(s, 0, 0, TRUE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE)) return -1; } else { int lvalue_label; @@ -23173,7 +23170,8 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name, if (is_async) return js_parse_error(s, "'for await' loop should be used with 'of'"); if (has_initializer && - (tok != TOK_VAR || (fd->js_mode & JS_MODE_STRICT))) { + (tok != TOK_VAR || (fd->js_mode & JS_MODE_STRICT) || + has_destructuring)) { initializer_error: return js_parse_error(s, "a declaration in the head of a for-%s loop can't have an initializer", is_for_of ? "of" : "in"); @@ -23798,7 +23796,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s, if (!(s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved)) { if (s->token.val == '[' || s->token.val == '{') { /* XXX: TOK_LET is not completely correct */ - if (js_parse_destructing_element(s, TOK_LET, 0, TRUE, -1)) + if (js_parse_destructing_element(s, TOK_LET, 0, TRUE, -1, TRUE)) goto fail; } else { js_parse_error(s, "identifier expected"); @@ -28070,18 +28068,28 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s) } } goto no_change; +#endif case OP_push_atom_value: if (OPTIMIZE) { JSAtom atom = get_u32(bc_buf + pos + 1); + /* remove push/drop pairs generated by the parser */ + if (code_match(&cc, pos_next, OP_drop, -1)) { + JS_FreeAtom(ctx, atom); + if (cc.line_num >= 0) line_num = cc.line_num; + pos_next = cc.pos; + break; + } +#if SHORT_OPCODES if (atom == JS_ATOM_empty_string) { JS_FreeAtom(ctx, atom); add_pc2line_info(s, bc_out.size, line_num); dbuf_putc(&bc_out, OP_push_empty_string); break; } +#endif } goto no_change; -#endif + case OP_to_propkey: case OP_to_propkey2: if (OPTIMIZE) { @@ -29074,7 +29082,8 @@ static int js_parse_function_check_names(JSParseState *s, JSFunctionDef *fd, if ((fd->js_mode & JS_MODE_STRICT) || !fd->has_simple_parameter_list || (fd->func_type == JS_PARSE_FUNC_METHOD && fd->func_kind == JS_FUNC_ASYNC) - || fd->func_type == JS_PARSE_FUNC_ARROW) { + || fd->func_type == JS_PARSE_FUNC_ARROW + || fd->func_type == JS_PARSE_FUNC_METHOD) { for (idx = 0; idx < fd->arg_count; idx++) { name = fd->args[idx].var_name; if (name != JS_ATOM_NULL) { @@ -29296,7 +29305,7 @@ static __exception int js_parse_function_decl2(JSParseState *s, emit_op(s, OP_get_arg); emit_u16(s, idx); } - if (js_parse_destructing_element(s, TOK_VAR, 1, TRUE, -1)) + if (js_parse_destructing_element(s, TOK_VAR, 1, TRUE, -1, TRUE)) goto fail; /* Close var object: necessary if direct eval call occurred in the assignment expression or if any @@ -29553,11 +29562,10 @@ static __exception int js_parse_function_decl2(JSParseState *s, } } else { if (!s->cur_func->is_global_var) { - /* define_var should not fail since there is no scope chain - XXX: maybe pass a different token to ensure no failure? - */ int var_idx = define_var(s, s->cur_func, func_name, TOK_VAR); + if (var_idx < 0) + goto fail; /* the variable will be assigned at the top of the function */ if (!add_hoisted_def(ctx, s->cur_func, idx, JS_ATOM_NULL, var_idx, FALSE)) goto fail; @@ -34374,11 +34382,13 @@ static JSValue js_array_slice(JSContext *ctx, JSValueConst this_val, k = start; final = start + count; n = 0; + /* The fast array test on arr ensures that + JS_CreateDataPropertyUint32() won't modify obj in case arr is + an exotic object */ /* Special case fast arrays */ - if (js_get_fast_array(ctx, obj, &arrp, &count32)) { + if (js_get_fast_array(ctx, obj, &arrp, &count32) && + js_is_fast_array(ctx, arr)) { /* XXX: should share code with fast array constructor */ - /* XXX: this may crash if the new array has a custom property - handler that modifies the original array */ for (; k < final && k < count32; k++, n++) { if (JS_CreateDataPropertyUint32(ctx, arr, n, JS_DupValue(ctx, arrp[k]), JS_PROP_THROW) < 0) goto exception; @@ -34712,7 +34722,7 @@ static JSValue js_array_sort(JSContext *ctx, JSValueConst this_val, return obj; exception: - for (n = 0; n < pos; n++) { + for (; n < pos; n++) { JS_FreeValue(ctx, array[n].val); if (array[n].str) JS_FreeValue(ctx, JS_MKPTR(JS_TAG_STRING, array[n].str)); @@ -35813,26 +35823,6 @@ static JSValue js_string_charAt(JSContext *ctx, JSValueConst this_val, return ret; } -static int string_getc(JSString *p, int *pidx) -{ - int idx, c, c1; - idx = *pidx; - if (p->is_wide_char) { - c = p->u.str16[idx++]; - if (c >= 0xd800 && c < 0xdc00 && idx < p->len) { - c1 = p->u.str16[idx]; - if (c1 >= 0xdc00 && c1 < 0xe000) { - c = (((c & 0x3ff) << 10) | (c1 & 0x3ff)) + 0x10000; - idx++; - } - } - } else { - c = p->u.str8[idx++]; - } - *pidx = idx; - return c; -} - static JSValue js_string_codePointAt(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { @@ -39180,7 +39170,10 @@ static JSValue json_parse_value(JSParseState *s) { int v; v = JS_VALUE_GET_INT(val); - val = JS_NewInt64(ctx, -(int64_t)v); + if (v == 0 && !is_bignum_mode(s->ctx)) + val = __JS_NewFloat64(ctx, -0.0); + else + val = JS_NewInt64(ctx, -(int64_t)v); } break; } @@ -41202,15 +41195,13 @@ static void delete_weak_ref(JSRuntime *rt, JSMapRecord *mr) *pmr = mr1->next_weak_ref; } -static void map_delete_record(JSRuntime *rt, JSMapState *s, JSMapRecord *mr, - BOOL from_reset_weak) +static void map_delete_record(JSRuntime *rt, JSMapState *s, JSMapRecord *mr) { if (mr->empty) return; list_del(&mr->hash_link); if (s->is_weak) { - if (!from_reset_weak) - delete_weak_ref(rt, mr); + delete_weak_ref(rt, mr); } else { JS_FreeValueRT(rt, mr->key); } @@ -41240,12 +41231,26 @@ static void map_decref_record(JSRuntime *rt, JSMapRecord *mr) static void reset_weak_ref(JSRuntime *rt, JSObject *p) { JSMapRecord *mr, *mr_next; - mr = p->first_weak_ref; - while (mr != NULL) { + JSMapState *s; + + /* first pass to remove the records from the WeakMap/WeakSet + lists */ + for(mr = p->first_weak_ref; mr != NULL; mr = mr->next_weak_ref) { + s = mr->map; + assert(s->is_weak); + assert(!mr->empty); /* no iterator on WeakMap/WeakSet */ + list_del(&mr->hash_link); + list_del(&mr->link); + } + + /* second pass to free the values to avoid modifying the weak + reference list while traversing it. */ + for(mr = p->first_weak_ref; mr != NULL; mr = mr_next) { mr_next = mr->next_weak_ref; - map_delete_record(rt, mr->map, mr, TRUE); - mr = mr_next; + JS_FreeValueRT(rt, mr->value); + js_free_rt(rt, mr); } + p->first_weak_ref = NULL; /* fail safe */ } @@ -41255,13 +41260,11 @@ static JSValue js_map_set(JSContext *ctx, JSValueConst this_val, JSMapState *s = JS_GetOpaque2(ctx, this_val, JS_CLASS_MAP + magic); JSMapRecord *mr; JSValueConst key, value; - BOOL is_weak; if (!s) return JS_EXCEPTION; - is_weak = magic & MAGIC_WEAK; key = map_normalize_key(ctx, argv[0]); - if (is_weak && !JS_IsObject(key)) + if (s->is_weak && !JS_IsObject(key)) return JS_ThrowTypeErrorNotAnObject(ctx); if (magic & MAGIC_SET) value = JS_UNDEFINED; @@ -41323,7 +41326,7 @@ static JSValue js_map_delete(JSContext *ctx, JSValueConst this_val, mr = map_find_record(ctx, s, key); if (!mr) return JS_FALSE; - map_delete_record(ctx->rt, s, mr, FALSE); + map_delete_record(ctx->rt, s, mr); return JS_TRUE; } @@ -41338,7 +41341,7 @@ static JSValue js_map_clear(JSContext *ctx, JSValueConst this_val, return JS_EXCEPTION; list_for_each_safe(el, el1, &s->records) { mr = list_entry(el, JSMapRecord, link); - map_delete_record(ctx->rt, s, mr, FALSE); + map_delete_record(ctx->rt, s, mr); } return JS_UNDEFINED; } @@ -42240,6 +42243,7 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val, JSValue result_promise, resolving_funcs[2], iter, item, next_promise, ret; JSValue next_method = JS_UNDEFINED, values = JS_UNDEFINED; JSValue resolve_element_env = JS_UNDEFINED, resolve_element; + JSValue promise_resolve = JS_UNDEFINED; JSValueConst then_args[2], resolve_element_data[5]; BOOL done; int index, is_zero; @@ -42276,6 +42280,11 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val, JS_PROP_CONFIGURABLE | JS_PROP_ENUMERABLE | JS_PROP_WRITABLE) < 0) goto fail_reject; + promise_resolve = JS_GetProperty(ctx, this_val, JS_ATOM_resolve); + if (JS_IsException(promise_resolve) || + check_function(ctx, promise_resolve)) + goto fail_reject1; + index = 0; for(;;) { /* XXX: conformance: should close the iterator if error on 'done' @@ -42285,8 +42294,8 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val, goto fail_reject; if (done) break; - next_promise = JS_Invoke(ctx, this_val, JS_ATOM_resolve, 1, - (JSValueConst *)&item); + next_promise = JS_Call(ctx, promise_resolve, + this_val, 1, (JSValueConst *)&item); JS_FreeValue(ctx, item); if (JS_IsException(next_promise)) { fail_reject1: @@ -42332,6 +42341,7 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val, } } done: + JS_FreeValue(ctx, promise_resolve); JS_FreeValue(ctx, resolve_element_env); JS_FreeValue(ctx, values); JS_FreeValue(ctx, next_method); @@ -42350,6 +42360,7 @@ static JSValue js_promise_race(JSContext *ctx, JSValueConst this_val, { JSValue result_promise, resolving_funcs[2], iter, item, next_promise, ret; JSValue next_method = JS_UNDEFINED; + JSValue promise_resolve = JS_UNDEFINED; BOOL done; if (!JS_IsObject(this_val)) @@ -42373,6 +42384,11 @@ static JSValue js_promise_race(JSContext *ctx, JSValueConst this_val, if (JS_IsException(next_method)) goto fail_reject; + promise_resolve = JS_GetProperty(ctx, this_val, JS_ATOM_resolve); + if (JS_IsException(promise_resolve) || + check_function(ctx, promise_resolve)) + goto fail_reject1; + for(;;) { /* XXX: conformance: should close the iterator if error on 'done' access, but not on 'value' access */ @@ -42381,8 +42397,8 @@ static JSValue js_promise_race(JSContext *ctx, JSValueConst this_val, goto fail_reject; if (done) break; - next_promise = JS_Invoke(ctx, this_val, JS_ATOM_resolve, 1, - (JSValueConst *)&item); + next_promise = JS_Call(ctx, promise_resolve, + this_val, 1, (JSValueConst *)&item); JS_FreeValue(ctx, item); if (JS_IsException(next_promise)) { fail_reject1: @@ -42396,6 +42412,7 @@ static JSValue js_promise_race(JSContext *ctx, JSValueConst this_val, } } done: + JS_FreeValue(ctx, promise_resolve); JS_FreeValue(ctx, next_method); JS_FreeValue(ctx, iter); JS_FreeValue(ctx, resolving_funcs[0]); @@ -43480,15 +43497,15 @@ static JSValue get_date_string(JSContext *ctx, JSValueConst this_val, switch(fmt) { case 0: pos += snprintf(buf + pos, sizeof(buf) - pos, - "%.3s, %02d %.3s %04d ", + "%.3s, %02d %.3s %0*d ", day_names + wd * 3, d, - month_names + mon * 3, y); + month_names + mon * 3, 4 + (y < 0), y); break; case 1: pos += snprintf(buf + pos, sizeof(buf) - pos, - "%.3s %.3s %02d %04d", + "%.3s %.3s %02d %0*d", day_names + wd * 3, - month_names + mon * 3, d, y); + month_names + mon * 3, d, 4 + (y < 0), y); if (part == 3) { buf[pos++] = ' '; } @@ -43506,7 +43523,7 @@ static JSValue get_date_string(JSContext *ctx, JSValueConst this_val, break; case 3: pos += snprintf(buf + pos, sizeof(buf) - pos, - "%02d/%02d/%04d", mon + 1, d, y); + "%02d/%02d/%0*d", mon + 1, d, 4 + (y < 0), y); if (part == 3) { buf[pos++] = ','; buf[pos++] = ' '; @@ -44889,7 +44906,12 @@ static void JS_AddIntrinsicBasicObjects(JSContext *ctx) add_shape_property(ctx, &ctx->array_shape, NULL, JS_ATOM_length, JS_PROP_WRITABLE | JS_PROP_LENGTH); - assert(ctx->rt->atom_count == JS_ATOM_END); + /* XXX: could test it on first context creation to ensure that no + new atoms are created in JS_AddIntrinsicBasicObjects(). It is + necessary to avoid useless renumbering of atoms after + JS_EvalBinary() if it is done just after + JS_AddIntrinsicBasicObjects(). */ + // assert(ctx->rt->atom_count == JS_ATOM_END); } void JS_AddIntrinsicBaseObjects(JSContext *ctx) @@ -44965,7 +44987,7 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx) { /* initialize Array.prototype[Symbol.unscopables] */ char const unscopables[] = "copyWithin" "\0" "entries" "\0" "fill" "\0" "find" "\0" - "findIndex" "\0" "includes" "\0" "keys" "\0" "values" "\0"; + "findIndex" "\0" "flat" "\0" "flatMap" "\0" "includes" "\0" "keys" "\0" "values" "\0"; const char *p = unscopables; obj1 = JS_NewObjectProto(ctx, JS_NULL); for(p = unscopables; *p; p += strlen(p) + 1) { @@ -47683,9 +47705,9 @@ static JSValue js_atomics_wait(JSContext *ctx, } } -static JSValue js_atomics_wake(JSContext *ctx, - JSValueConst this_obj, - int argc, JSValueConst *argv) +static JSValue js_atomics_notify(JSContext *ctx, + JSValueConst this_obj, + int argc, JSValueConst *argv) { struct list_head *el, *el1, waiter_list; int32_t count, n, *ptr; @@ -47738,7 +47760,7 @@ static const JSCFunctionListEntry js_atomics_funcs[] = { JS_CFUNC_DEF("store", 3, js_atomics_store ), JS_CFUNC_DEF("isLockFree", 1, js_atomics_isLockFree ), JS_CFUNC_DEF("wait", 4, js_atomics_wait ), - JS_CFUNC_DEF("wake", 3, js_atomics_wake ), + JS_CFUNC_DEF("notify", 3, js_atomics_notify ), JS_PROP_STRING_DEF("[Symbol.toStringTag]", "Atomics", JS_PROP_CONFIGURABLE ), }; diff --git a/quickjs/quickjs.h b/quickjs/quickjs.h index ca3636741d..4cb62b5f8a 100644 --- a/quickjs/quickjs.h +++ b/quickjs/quickjs.h @@ -586,6 +586,15 @@ static inline JSValue JS_DupValue(JSContext *ctx, JSValueConst v) return (JSValue)v; } +static inline JSValue JS_DupValueRT(JSRuntime *rt, JSValueConst v) +{ + if (JS_VALUE_HAS_REF_COUNT(v)) { + JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v); + p->ref_count++; + } + return (JSValue)v; +} + int JS_ToBool(JSContext *ctx, JSValueConst val); /* return -1 for JS_EXCEPTION */ int JS_ToInt32(JSContext *ctx, int32_t *pres, JSValueConst val); static int inline JS_ToUint32(JSContext *ctx, uint32_t *pres, JSValueConst val) From 4048b421f08f8ee46ee4052df9fa1a5e635d8d81 Mon Sep 17 00:00:00 2001 From: ftk Date: Mon, 22 Jul 2019 16:22:29 +0000 Subject: [PATCH 004/185] added c++ patch --- quickjs/cplusplus.patch | 54 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 quickjs/cplusplus.patch diff --git a/quickjs/cplusplus.patch b/quickjs/cplusplus.patch new file mode 100644 index 0000000000..159dd92f88 --- /dev/null +++ b/quickjs/cplusplus.patch @@ -0,0 +1,54 @@ +diff --git a/quickjs/quickjs.h b/quickjs/quickjs.h +index 60cd0e7..4cb62b5 100644 +--- a/quickjs/quickjs.h ++++ b/quickjs/quickjs.h +@@ -201,8 +201,13 @@ typedef struct JSValue { + #define JS_VALUE_GET_FLOAT64(v) ((v).u.float64) + #define JS_VALUE_GET_PTR(v) ((v).u.ptr) + ++#ifdef __cplusplus ++#define JS_MKVAL(tag, val) JSValue{ JSValueUnion{.int32 = val}, tag } ++#define JS_MKPTR(tag, p) JSValue{ JSValueUnion{.ptr = p}, tag } ++#else + #define JS_MKVAL(tag, val) (JSValue){ .u.int32 = val, tag } + #define JS_MKPTR(tag, p) (JSValue){ .u.ptr = p, tag } ++#endif + + #define JS_TAG_IS_FLOAT64(tag) ((unsigned)(tag) == JS_TAG_FLOAT64) + +@@ -555,7 +560,7 @@ void __JS_FreeValue(JSContext *ctx, JSValue v); + static inline void JS_FreeValue(JSContext *ctx, JSValue v) + { + if (JS_VALUE_HAS_REF_COUNT(v)) { +- JSRefCountHeader *p = JS_VALUE_GET_PTR(v); ++ JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v); + if (--p->ref_count <= 0) { + __JS_FreeValue(ctx, v); + } +@@ -565,7 +570,7 @@ void __JS_FreeValueRT(JSRuntime *rt, JSValue v); + static inline void JS_FreeValueRT(JSRuntime *rt, JSValue v) + { + if (JS_VALUE_HAS_REF_COUNT(v)) { +- JSRefCountHeader *p = JS_VALUE_GET_PTR(v); ++ JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v); + if (--p->ref_count <= 0) { + __JS_FreeValueRT(rt, v); + } +@@ -575,7 +580,7 @@ static inline void JS_FreeValueRT(JSRuntime *rt, JSValue v) + static inline JSValue JS_DupValue(JSContext *ctx, JSValueConst v) + { + if (JS_VALUE_HAS_REF_COUNT(v)) { +- JSRefCountHeader *p = JS_VALUE_GET_PTR(v); ++ JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v); + p->ref_count++; + } + return (JSValue)v; +@@ -584,7 +589,7 @@ static inline JSValue JS_DupValue(JSContext *ctx, JSValueConst v) + static inline JSValue JS_DupValueRT(JSRuntime *rt, JSValueConst v) + { + if (JS_VALUE_HAS_REF_COUNT(v)) { +- JSRefCountHeader *p = JS_VALUE_GET_PTR(v); ++ JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v); + p->ref_count++; + } + return (JSValue)v; From 497c5be1dae048c007775331cd6e9a0a18bc2037 Mon Sep 17 00:00:00 2001 From: ftk Date: Mon, 22 Jul 2019 16:30:51 +0000 Subject: [PATCH 005/185] basic readme file --- readme.txt | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 readme.txt diff --git a/readme.txt b/readme.txt new file mode 100644 index 0000000000..2b3118454e --- /dev/null +++ b/readme.txt @@ -0,0 +1,19 @@ +QuickJS wrapper for C++. + + +* Status ++ conversions between int32_t, std::string, bool, double and JSValue ++ basic support for classes ++ basic support for modules ++ automatic function wrapping and unwrapping +- exception interop +- tests for memory leaks + +* Installation +QuickJSPP is header-only - C++17 or later is required. QuickJS needs to be compiled. Sample CMake files are provided. + +* Notes +A small patch for C++ support is applied to quickjs.h. + +* License +QuickJSPP is licensed under CC0 (https://creativecommons.org/publicdomain/zero/1.0/). From 53f6b4e0baac0c3232a152fa7342b760043b7d17 Mon Sep 17 00:00:00 2001 From: ftk Date: Tue, 23 Jul 2019 13:42:51 +0000 Subject: [PATCH 006/185] added allocator, fixed memory leaks --- quickjspp.hpp | 143 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 102 insertions(+), 41 deletions(-) diff --git a/quickjspp.hpp b/quickjspp.hpp index fc4c6bd064..cc1c961380 100644 --- a/quickjspp.hpp +++ b/quickjspp.hpp @@ -15,23 +15,57 @@ extern "C" { namespace qjs { + + template + struct allocator + { + JSRuntime * rt; + using value_type = T; + using propagate_on_container_move_assignment = std::true_type; + using propagate_on_container_copy_assignment = std::true_type; + + constexpr allocator(JSRuntime * rt) noexcept : rt{rt} + {} + + allocator(JSContext * ctx) noexcept : rt{JS_GetRuntime(ctx)} + {} + + template + constexpr allocator(const allocator& other) noexcept : rt{other.rt} + {} + + [[nodiscard]] T * allocate(std::size_t n) + { + if(auto p = static_cast(js_malloc_rt(rt, n * sizeof(T)))) return p; + throw std::bad_alloc(); + } + + void deallocate(T * p, std::size_t) noexcept + { js_free_rt(rt, p); } + + template + bool operator == (const allocator& other) const { return rt == other.rt; } + template + bool operator != (const allocator& other) const { return rt != other.rt; } + }; + namespace detail { class exception {}; template struct js_traits { - //static R unwrap(JSContext * ctx, JSValue v); - //static JSValue wrap(JSContext * ctx, R value) + //static R unwrap(JSContext * ctx, JSValueConst v); + //static JSValue wrap(JSContext * ctx, R value); }; // identity template <> struct js_traits { - static JSValue unwrap(JSContext * ctx, JSValue v) noexcept + static JSValue unwrap(JSContext * ctx, JSValueConst v) noexcept { - return v; + return JS_DupValue(ctx, v); } static JSValue wrap(JSContext * ctx, JSValue v) noexcept @@ -103,7 +137,7 @@ namespace qjs { using Base = std::string_view; JSContext * ctx = nullptr; - friend struct js_traits; + friend struct js_traits; js_string(JSContext * ctx, const char * ptr, std::size_t len) : Base(ptr, len), ctx(ctx) {} public: @@ -120,7 +154,7 @@ namespace qjs { }; template <> - struct js_traits + struct js_traits { static js_string unwrap(JSContext * ctx, JSValueConst v) { @@ -131,7 +165,7 @@ namespace qjs { return js_string{ctx, ptr, (std::size_t)plen}; } - static JSValue wrap(JSContext * ctx, js_string str) noexcept + static JSValue wrap(JSContext * ctx, std::string_view str) noexcept { return JS_NewStringLen(ctx, str.data(), (int)str.size()); } @@ -142,7 +176,7 @@ namespace qjs { { static std::string unwrap(JSContext * ctx, JSValueConst v) { - auto str_view = js_traits::unwrap(ctx, v); + auto str_view = js_traits::unwrap(ctx, v); return std::string{str_view.data(), str_view.size()}; } @@ -152,6 +186,30 @@ namespace qjs { } }; + // unwrap and free value + template + T unwrap_free(JSContext * ctx, JSValue val) + { + if constexpr(std::is_same_v) + { + JS_FreeValue(ctx, val); + return js_traits::unwrap(ctx, val); + } + else + { + try + { + T result = js_traits>::unwrap(ctx, val); + JS_FreeValue(ctx, val); + return result; + } + catch(...) + { + JS_FreeValue(ctx, val); + throw; + } + } + } template Tuple unwrap_args_impl(JSContext * ctx, JSValueConst * argv, std::index_sequence) @@ -291,11 +349,12 @@ namespace qjs { // destructor [](JSRuntime * rt, JSValue obj) noexcept { auto pptr = reinterpret_cast *>(JS_GetOpaque(obj, QJSClassId)); - if(!pptr) - { - assert(false && "bad destructor"); - } - delete pptr; + assert(pptr); + //delete pptr; + auto alloc = allocator>{rt}; + using atraits = std::allocator_traits; + atraits::destroy(alloc, pptr); + atraits::deallocate(alloc, pptr, 1); } }; int e = JS_NewClass(JS_GetRuntime(ctx), JS_NewClassID(&QJSClassId), &def); @@ -313,7 +372,12 @@ namespace qjs { { return jsobj; } - auto pptr = new std::shared_ptr(std::move(ptr)); + //auto pptr = new std::shared_ptr(std::move(ptr)); + auto alloc = allocator>{ctx}; + using atraits = std::allocator_traits; + auto pptr = atraits::allocate(alloc, 1); + atraits::construct(alloc, pptr, std::move(ptr)); + JS_SetOpaque(jsobj, pptr); return jsobj; } @@ -336,10 +400,12 @@ namespace qjs { alignas(std::max_align_t) char functor[]; template - static function * create(Functor&& f) + static function * create(JSRuntime * rt, Functor&& f) { - char * data = new char[sizeof(function) + sizeof(Functor)]; - auto fptr = reinterpret_cast(data); + auto fptr = reinterpret_cast(js_malloc_rt(rt, sizeof(function) + sizeof(Functor))); + if(!fptr) + throw std::bad_alloc{}; + new (fptr) function; auto functorptr = reinterpret_cast(fptr->functor); new(functorptr) Functor(std::forward(f)); fptr->destroyer = nullptr; @@ -353,6 +419,8 @@ namespace qjs { return fptr; } }; + static_assert(std::is_trivially_destructible_v); + template <> struct js_traits @@ -364,15 +432,11 @@ namespace qjs { name, // destructor [](JSRuntime * rt, JSValue obj) noexcept { - auto pptr = reinterpret_cast(JS_GetOpaque(obj, QJSClassId)); - if(!pptr) - { - assert(false && "bad destructor"); - } - if(pptr->destroyer) - pptr->destroyer(pptr); - auto cptr = reinterpret_cast(pptr); - delete [] cptr; + auto fptr = reinterpret_cast(JS_GetOpaque(obj, QJSClassId)); + assert(fptr); + if(fptr->destroyer) + fptr->destroyer(fptr); + js_free_rt(rt, fptr); }, nullptr, // mark // call @@ -441,7 +505,7 @@ namespace qjs { template operator Value() const { - return js_traits::unwrap(ctx, js_property_traits::get_property(ctx, this_obj, key)); + return unwrap_free(ctx, js_property_traits::get_property(ctx, this_obj, key)); } template @@ -564,9 +628,10 @@ namespace qjs { JSContext * ctx; const char * name; - std::vector> exports; + using nvp = std::pair; + std::vector> exports; public: - Module(JSContext * ctx, const char * name) : ctx(ctx), name(name) + Module(JSContext * ctx, const char * name) : ctx(ctx), name(name), exports(JS_GetRuntime(ctx)) { m = JS_NewCModule(ctx, name, [](JSContext * ctx, JSModuleDef * m) noexcept { auto context = reinterpret_cast(JS_GetContextOpaque(ctx)); @@ -608,18 +673,18 @@ namespace qjs { //Module(const Module&) = delete; }; - std::vector modules; + std::vector> modules; private: void init() { JS_SetContextOpaque(ctx, this); - detail::js_traits::register_class(ctx, ""); + detail::js_traits::register_class(ctx, "C++ function"); } public: Context(Runtime& rt) : Context(rt.rt) {} - Context(JSRuntime * rt) + Context(JSRuntime * rt) : modules{rt} { ctx = JS_NewContext(rt); if(!ctx) @@ -627,7 +692,7 @@ namespace qjs { init(); } - Context(JSContext * ctx) : ctx{ctx} + Context(JSContext * ctx) : ctx{ctx}, modules{ctx} { init(); } @@ -661,7 +726,7 @@ namespace qjs { detail::js_traits>::register_class(ctx, name, proto); } - Value eval(std::string_view buffer, const char * filename = "eval", unsigned eval_flags = 0) + Value eval(std::string_view buffer, const char * filename = "", unsigned eval_flags = 0) { JSValue v = JS_Eval(ctx, buffer.data(), buffer.size(), filename, eval_flags); //if(JS_IsException(v)) @@ -693,13 +758,9 @@ namespace qjs { const int argc = sizeof...(Args); JSValue argv[argc]; wrap_args(jsfun_obj.ctx, argv, std::forward(args)...); - JSValue result; - //if(JS_IsObject(argv[0])) // constexpr? - // result = JS_Call(ctx, fun_obj, argv[0], argc - 1, const_cast(argv + 1)); - //else - result = JS_Call(jsfun_obj.ctx, jsfun_obj.v, JS_UNDEFINED, argc, const_cast(argv)); + JSValue result = JS_Call(jsfun_obj.ctx, jsfun_obj.v, JS_UNDEFINED, argc, const_cast(argv)); for(int i = 0; i < argc; i++) JS_FreeValue(jsfun_obj.ctx, argv[i]); - return js_traits::unwrap(jsfun_obj.ctx, result); + return unwrap_free(jsfun_obj.ctx, result); }; } @@ -709,7 +770,7 @@ namespace qjs { auto obj = JS_NewObjectClass(ctx, js_traits::QJSClassId); if(JS_IsException(obj)) return JS_EXCEPTION; - auto fptr = function::create(std::forward(functor)); + auto fptr = function::create(JS_GetRuntime(ctx), std::forward(functor)); fptr->invoker = [](function * self, JSContext * ctx, JSValueConst this_value, int argc, JSValueConst * argv) { assert(self); auto f = reinterpret_cast(&self->functor); From 4ba7a7ad577f2290c96d108689a9b4f6e879c977 Mon Sep 17 00:00:00 2001 From: ftk Date: Sun, 28 Jul 2019 15:55:28 +0000 Subject: [PATCH 007/185] class member object support --- main.cpp | 22 ++++++--- quickjspp.hpp | 130 ++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 109 insertions(+), 43 deletions(-) diff --git a/main.cpp b/main.cpp index 1924b1316e..f7e402fe06 100644 --- a/main.cpp +++ b/main.cpp @@ -17,12 +17,12 @@ int32_t f(int32_t x) class test { +public: bool b; int32_t i; double d; std::shared_ptr spt; std::string s; -public: test(int32_t i, TYPES) : i(i) { printf("ctor!\n"); } @@ -67,7 +67,7 @@ int main(int argc, char ** argv) obj["vb"] = true; obj["vd"] = 56.0; obj["vs"] = std::string{"test string"}; - obj.add("lambda", [](int x) -> int { return x * x; }); + obj.add("lambda", [](int x) -> int { return x * x; }); obj.add<&test::fi>("fi"); obj.add<&test::fb>("fb"); @@ -77,6 +77,12 @@ int main(int argc, char ** argv) obj.add<&test::f>("f"); obj.add<&test::fstatic>("fstatic"); + obj.add<&test::i>("i"); + obj.add<&test::b>("b"); + obj.add<&test::d>("d"); + obj.add<&test::s>("s"); + obj.add<&test::spt>("spt"); + context.registerClass("test_class", std::move(obj)); } @@ -110,10 +116,14 @@ int main(int argc, char ** argv) { auto xxx = context.eval("var t = new test.TestSimple(12);" "var q = new test.Test(13, t.vb, t.vi, t.vd, t, t, t.vs, t.vs);" - "q.fb(t.vb, t.vi, t.vd, t, t, t.vs, \"test\");" - "q.fd(t.vb, t.vi, t.vd, t, t, t.vs, \"test\");" - "q.fs(t.vb, t.vi, t.vd, t, t, \"test\", t.vs);" - "q.fspt(t.vb, t.vi, t.vd, t, t, t.vs, \"test\");" + "q.b = true;" + "q.d = 456.789;" + "q.s = \"STRING\";" + "q.spt = t;" + "console.log(q.b === q.fb(t.vb, t.vi, t.vd, t, t, t.vs, \"test\"));" + "console.log(q.d === q.fd(t.vb, t.vi, t.vd, t, t, t.vs, \"test\"));" + "console.log(q.s === q.fs(t.vb, t.vi, t.vd, t, t, \"test\", t.vs));" + "console.log(q.spt === q.fspt(t.vb, t.vi, t.vd, t, t, t.vs, \"test\"));" // false "q.fi(t.vb, t.vi, t.vd, t, t, t.vs, \"test\")"); assert(xxx.cast() == 18); auto yyy = context.eval("q.fi.bind(t)(t.vb, t.vi, t.vd, t, t, t.vs, \"test\")"); diff --git a/quickjspp.hpp b/quickjspp.hpp index cc1c961380..6b25e3f697 100644 --- a/quickjspp.hpp +++ b/quickjspp.hpp @@ -234,7 +234,9 @@ namespace qjs { return JS_UNDEFINED; } else { - return js_traits>::wrap(ctx, std::apply(std::forward(f), unwrap_args(ctx, argv))); + return js_traits>::wrap(ctx, + std::apply(std::forward(f), + unwrap_args(ctx, argv))); } } catch(exception) @@ -243,6 +245,29 @@ namespace qjs { } } + template + JSValue wrap_this_call(JSContext * ctx, Callable&& f, JSValueConst this_value, JSValueConst * argv) noexcept + { + try + { + if constexpr(std::is_same_v) + { + std::apply(std::forward(f), std::tuple_cat(unwrap_args(ctx, &this_value), + unwrap_args(ctx, argv))); + return JS_UNDEFINED; + } else + { + return js_traits>::wrap(ctx, + std::apply(std::forward(f), + std::tuple_cat(unwrap_args(ctx, &this_value), + unwrap_args(ctx, argv)))); + } + } + catch(exception) + { + return JS_EXCEPTION; + } + } template void wrap_args_impl(JSContext * ctx, JSValue * argv, Tuple tuple, std::index_sequence) @@ -255,22 +280,25 @@ namespace qjs { { wrap_args_impl(ctx, argv, std::make_tuple(std::forward(args)...), std::make_index_sequence()); } - // free function - template + template struct fwrapper { const char * name = nullptr; }; - template - struct js_traits> + // free function + template + struct js_traits> { - static JSValue wrap(JSContext * ctx, fwrapper fw) + static JSValue wrap(JSContext * ctx, fwrapper fw) noexcept { return JS_NewCFunction(ctx, [](JSContext * ctx, JSValueConst this_value, int argc, JSValueConst * argv) noexcept -> JSValue { - return wrap_call(ctx, F, argv); + if constexpr(PassThis) + return wrap_this_call(ctx, F, this_value, argv); + else + return wrap_call(ctx, F, argv); }, fw.name, sizeof...(Args)); } @@ -281,31 +309,11 @@ namespace qjs { template struct js_traits> { - static JSValue wrap(JSContext * ctx, fwrapper fw) + static JSValue wrap(JSContext * ctx, fwrapper fw) noexcept { return JS_NewCFunction(ctx, [](JSContext * ctx, JSValueConst this_value, int argc, JSValueConst * argv) noexcept -> JSValue { - //if(argc < sizeof...(Args)) - //return JS_EXCEPTION; - try - { - const auto& this_sp = js_traits>::unwrap(ctx, this_value); - - if constexpr (std::is_same_v) - { - std::apply(F, std::tuple_cat(std::make_tuple(this_sp.get()), - detail::unwrap_args(ctx, argv))); - return JS_UNDEFINED; - } else - return js_traits>::wrap(ctx, - std::apply(F, std::tuple_cat(std::make_tuple(this_sp.get()), - detail::unwrap_args(ctx, - argv))) - ); - } catch(detail::exception) - { - return JS_EXCEPTION; - } + return wrap_this_call, Args...>(ctx, F, this_value, argv); }, fw.name, sizeof...(Args)); } @@ -324,7 +332,7 @@ namespace qjs { template struct js_traits> { - static JSValue wrap(JSContext * ctx, ctor_wrapper cw) + static JSValue wrap(JSContext * ctx, ctor_wrapper cw) noexcept { return JS_NewCFunction2(ctx, [](JSContext * ctx, JSValueConst this_value, int argc, JSValueConst * argv) noexcept -> JSValue { @@ -517,6 +525,28 @@ namespace qjs { } }; + + + // class member variable getter/setter + template + struct get_set + {}; + + template + struct get_set + { + static const R& get(const std::shared_ptr& ptr) + { + return *ptr.*M; + } + + static R& set(const std::shared_ptr& ptr, R value) + { + return *ptr.*M = std::move(value); + } + + }; + } class Value @@ -576,21 +606,44 @@ namespace qjs { } + // add("f", []() {...}); + template + Value& add(const char * name, Function&& f) + { + (*this)[name] = detail::js_traits(f)})>::wrap(ctx, std::forward(f)); + return *this; + } + + // add<&f>("f"); + // add<&T::f>("f"); template - Value& add(const char * name) + std::enable_if_t, Value&> + add(const char * name) { (*this)[name] = detail::fwrapper{name}; return *this; } - template - //std::enable_if_t::value, Value&> - Value& add(const char * name, Function&& f) - { - (*this)[name] = detail::js_traits>::wrap(ctx, std::forward(f)); + // add<&T::member>("member"); + template + std::enable_if_t, Value&> + add(const char * name) + { + auto prop = JS_NewAtom(ctx, name); + using fgetter = detail::fwrapper::get, true>; + using fsetter = detail::fwrapper::set, true>; + int ret = JS_DefinePropertyGetSet(ctx, v, prop, + detail::js_traits::wrap(ctx, fgetter{name}), + detail::js_traits::wrap(ctx, fsetter{name}), + JS_PROP_WRITABLE // ? + ); + JS_FreeAtom(ctx, prop); + if(ret < 0) + throw detail::exception{}; return *this; } + }; @@ -620,6 +673,7 @@ namespace qjs { public: JSContext * ctx; + private: class Module { friend class Context; @@ -670,7 +724,9 @@ namespace qjs { return add(name, detail::js_traits::wrap(ctx, std::move(value))); } - //Module(const Module&) = delete; + Module(const Module&) = delete; + Module(Module&&) = default; + //Module& operator=(Module&&) = default; }; std::vector> modules; From 9680868cb7c4c40f0eeee511f35587c5c22a9615 Mon Sep 17 00:00:00 2001 From: ftk Date: Tue, 30 Jul 2019 15:51:06 +0000 Subject: [PATCH 008/185] update quickjs to 2019-07-28 --- main.cpp | 2 +- quickjs/VERSION | 2 +- quickjs/libbf.c | 5 +- quickjs/libregexp.c | 3 +- quickjs/quickjs-atom.h | 4 + quickjs/quickjs-libc.c | 2 +- quickjs/quickjs-opcode.h | 6 +- quickjs/quickjs.c | 1157 ++++++++++++++++++++++++++++++-------- quickjs/quickjs.h | 3 +- 9 files changed, 932 insertions(+), 252 deletions(-) diff --git a/main.cpp b/main.cpp index f7e402fe06..8618f5af5d 100644 --- a/main.cpp +++ b/main.cpp @@ -142,7 +142,7 @@ int main(int argc, char ** argv) } if(filename) - context.evalFile(filename, JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_SHEBANG); + context.evalFile(filename, JS_EVAL_TYPE_MODULE); JSMemoryUsage mem; JS_ComputeMemoryUsage(rt, &mem); diff --git a/quickjs/VERSION b/quickjs/VERSION index 51e58f773f..6b45bd0759 100644 --- a/quickjs/VERSION +++ b/quickjs/VERSION @@ -1 +1 @@ -2019-07-21 +2019-07-28 diff --git a/quickjs/libbf.c b/quickjs/libbf.c index e848c38d48..de800365fb 100644 --- a/quickjs/libbf.c +++ b/quickjs/libbf.c @@ -2522,11 +2522,12 @@ int bf_atof2(bf_t *r, slimb_t *pexponent, radix == 0 && (flags & BF_ATOF_BIN_OCT)) { p += 2; radix = 2; - } else if ((p[1] >= '0' && p[1] <= '7') && + } else if ((p[1] >= '0' && p[1] <= '9') && radix == 0 && (flags & BF_ATOF_LEGACY_OCTAL)) { int i; /* the separator is not allowed in legacy octal literals */ - for (i = 2; (p[i] >= '0' && p[i] <= '7'); i++) + sep = 256; + for (i = 1; (p[i] >= '0' && p[i] <= '7'); i++) continue; if (p[i] == '8' || p[i] == '9') goto no_prefix; diff --git a/quickjs/libregexp.c b/quickjs/libregexp.c index 61177efab1..ad1e6bf065 100644 --- a/quickjs/libregexp.c +++ b/quickjs/libregexp.c @@ -2511,7 +2511,8 @@ int main(int argc, char **argv) printf("usage: %s regexp input\n", argv[0]); exit(1); } - bc = lre_compile(&len, error_msg, sizeof(error_msg), argv[1], 0, 0, NULL); + bc = lre_compile(&len, error_msg, sizeof(error_msg), argv[1], + strlen(argv[1]), 0, NULL); if (!bc) { fprintf(stderr, "error: %s\n", error_msg); exit(1); diff --git a/quickjs/quickjs-atom.h b/quickjs/quickjs-atom.h index 8ec55ee2fe..b0708aa9be 100644 --- a/quickjs/quickjs-atom.h +++ b/quickjs/quickjs-atom.h @@ -158,6 +158,8 @@ DEF(revoke, "revoke") DEF(async, "async") DEF(exec, "exec") DEF(groups, "groups") +DEF(status, "status") +DEF(reason, "reason") #ifdef CONFIG_BIGNUM DEF(bigint, "bigint") DEF(bigfloat, "bigfloat") @@ -214,6 +216,7 @@ DEF(Map_Iterator, "Map Iterator") DEF(Set_Iterator, "Set Iterator") DEF(Array_Iterator, "Array Iterator") DEF(String_Iterator, "String Iterator") +DEF(RegExp_String_Iterator, "RegExp String Iterator") DEF(Generator, "Generator") DEF(Proxy, "Proxy") DEF(Promise, "Promise") @@ -236,6 +239,7 @@ DEF(InternalError, "InternalError") DEF(Symbol_toPrimitive, "Symbol.toPrimitive") DEF(Symbol_iterator, "Symbol.iterator") DEF(Symbol_match, "Symbol.match") +DEF(Symbol_matchAll, "Symbol.matchAll") DEF(Symbol_replace, "Symbol.replace") DEF(Symbol_search, "Symbol.search") DEF(Symbol_split, "Symbol.split") diff --git a/quickjs/quickjs-libc.c b/quickjs/quickjs-libc.c index 268ef0472e..df6a36ab1c 100644 --- a/quickjs/quickjs-libc.c +++ b/quickjs/quickjs-libc.c @@ -336,7 +336,7 @@ static JSValue js_loadScript(JSContext *ctx, JSValueConst this_val, return JS_EXCEPTION; } ret = JS_Eval(ctx, (char *)buf, buf_len, filename, - JS_EVAL_TYPE_GLOBAL | JS_EVAL_FLAG_SHEBANG); + JS_EVAL_TYPE_GLOBAL); js_free(ctx, buf); JS_FreeCString(ctx, filename); return ret; diff --git a/quickjs/quickjs-opcode.h b/quickjs/quickjs-opcode.h index 44fcc83c7d..d7318682bf 100644 --- a/quickjs/quickjs-opcode.h +++ b/quickjs/quickjs-opcode.h @@ -75,11 +75,8 @@ DEF( push_false, 1, 0, 1, none) DEF( push_true, 1, 0, 1, none) DEF( object, 1, 0, 1, none) DEF( var_object, 1, 0, 1, none) -DEF( this_func, 1, 0, 1, none) /* only used at the start of a function */ -DEF( arguments, 2, 0, 1, none) /* only used at the start of a function */ +DEF( special_object, 2, 0, 1, u8) /* only used at the start of a function */ DEF( rest, 3, 0, 1, u16) /* only used at the start of a function */ -DEF( new_target, 1, 0, 1, none) /* only used at the start of a function */ -DEF( home_object, 1, 0, 1, none) /* only used at the start of a function */ DEF( drop, 1, 1, 0, none) /* a -> */ DEF( nip, 1, 2, 1, none) /* a b -> b */ @@ -120,6 +117,7 @@ DEF( regexp, 1, 2, 1, none) /* create a RegExp object from the pattern a bytecode string */ DEF( get_super_ctor, 1, 1, 1, none) DEF( get_super, 1, 1, 1, none) +DEF( import, 1, 1, 1, none) /* dynamic module import */ DEF( check_var, 5, 0, 1, atom) /* check if a variable exists */ DEF( get_var_undef, 5, 0, 1, atom) /* push undefined if the variable does not exist */ diff --git a/quickjs/quickjs.c b/quickjs/quickjs.c index 8ee82f4525..d3e89b52e1 100644 --- a/quickjs/quickjs.c +++ b/quickjs/quickjs.c @@ -157,6 +157,7 @@ enum { JS_CLASS_SET_ITERATOR, /* u.map_iterator_data */ JS_CLASS_ARRAY_ITERATOR, /* u.array_iterator_data */ JS_CLASS_STRING_ITERATOR, /* u.array_iterator_data */ + JS_CLASS_REGEXP_STRING_ITERATOR, /* u.regexp_string_iterator_data */ JS_CLASS_GENERATOR, /* u.generator_data */ JS_CLASS_PROXY, /* u.proxy_data */ JS_CLASS_PROMISE, /* u.promise_data */ @@ -337,6 +338,7 @@ struct JSContext { JSValue function_proto; JSValue function_ctor; JSValue regexp_ctor; + JSValue promise_ctor; JSValue native_error_proto[JS_NATIVE_ERROR_COUNT]; JSValue iterator_proto; JSValue async_iterator_proto; @@ -567,7 +569,8 @@ typedef struct JSExportEntry { int req_module_idx; /* module for indirect export */ } u; JSExportTypeEnum export_type; - JSAtom local_name; /* not used for local export after compilation */ + JSAtom local_name; /* '*' if export ns from. not used for local + export after compilation */ JSAtom export_name; /* exported variable name */ } JSExportEntry; @@ -605,9 +608,14 @@ struct JSModuleDef { JSValue module_ns; JSValue func_obj; /* only used for JS modules */ JSModuleInitFunc *init_func; /* only used for C modules */ - BOOL resolved; - BOOL instantiated; - BOOL evaluated; + BOOL resolved : 8; + BOOL instantiated : 8; + BOOL evaluated : 8; + BOOL eval_mark : 8; /* temporary use during js_evaluate_module() */ + /* true if evaluation yielded an exception. It is saved in + eval_exception */ + BOOL eval_has_exception : 8; + JSValue eval_exception; }; typedef struct JSJobEntry { @@ -697,6 +705,7 @@ struct JSObject { struct JSMapState *map_state; /* JS_CLASS_MAP..JS_CLASS_WEAKSET */ struct JSMapIteratorData *map_iterator_data; /* JS_CLASS_MAP_ITERATOR, JS_CLASS_SET_ITERATOR */ struct JSArrayIteratorData *array_iterator_data; /* JS_CLASS_ARRAY_ITERATOR, JS_CLASS_STRING_ITERATOR */ + struct JSRegExpStringIteratorData *regexp_string_iterator_data; /* JS_CLASS_REGEXP_STRING_ITERATOR */ struct JSGeneratorData *generator_data; /* JS_CLASS_GENERATOR */ struct JSProxyData *proxy_data; /* JS_CLASS_PROXY */ struct JSPromiseData *promise_data; /* JS_CLASS_PROMISE */ @@ -843,6 +852,9 @@ static void js_map_iterator_mark(JSRuntime *rt, JSValueConst val, static void js_array_iterator_finalizer(JSRuntime *rt, JSValue val); static void js_array_iterator_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); +static void js_regexp_string_iterator_finalizer(JSRuntime *rt, JSValue val); +static void js_regexp_string_iterator_mark(JSRuntime *rt, JSValueConst val, + JS_MarkFunc *mark_func); static void js_generator_finalizer(JSRuntime *rt, JSValue obj); static void js_generator_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); @@ -930,6 +942,7 @@ static JSValue JS_EvalInternal(JSContext *ctx, JSValueConst this_obj, const char *input, size_t input_len, const char *filename, int flags, int scope_idx); static void js_free_module_def(JSContext *ctx, JSModuleDef *m); +static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier); static void free_var_ref(JSRuntime *rt, JSVarRef *var_ref); static JSValue js_new_promise_capability(JSContext *ctx, JSValue *resolving_funcs, @@ -938,6 +951,8 @@ static __exception int perform_promise_then(JSContext *ctx, JSValueConst promise, JSValueConst *resolve_reject, JSValueConst *cap_resolving_funcs); +static JSValue js_promise_resolve(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv, int magic); static int js_string_compare(JSContext *ctx, const JSString *p1, const JSString *p2); static JSValue JS_ToNumber(JSContext *ctx, JSValueConst val); @@ -1193,6 +1208,7 @@ static JSClassShortDef const js_std_class_def[] = { { JS_ATOM_Set_Iterator, js_map_iterator_finalizer, js_map_iterator_mark }, /* JS_CLASS_SET_ITERATOR */ { JS_ATOM_Array_Iterator, js_array_iterator_finalizer, js_array_iterator_mark }, /* JS_CLASS_ARRAY_ITERATOR */ { JS_ATOM_String_Iterator, js_array_iterator_finalizer, js_array_iterator_mark }, /* JS_CLASS_STRING_ITERATOR */ + { JS_ATOM_RegExp_String_Iterator, js_regexp_string_iterator_finalizer, js_regexp_string_iterator_mark }, /* JS_CLASS_STRING_ITERATOR */ { JS_ATOM_Generator, js_generator_finalizer, js_generator_mark }, /* JS_CLASS_GENERATOR */ }; @@ -1748,6 +1764,8 @@ JSContext *JS_NewContextRaw(JSRuntime *rt) #endif for(i = 0; i < rt->class_count; i++) ctx->class_proto[i] = JS_NULL; + ctx->regexp_ctor = JS_NULL; + ctx->promise_ctor = JS_NULL; init_list_head(&ctx->loaded_modules); JS_AddIntrinsicBasicObjects(ctx); @@ -1881,6 +1899,7 @@ void JS_FreeContext(JSContext *ctx) js_free_rt(rt, ctx->class_proto); JS_FreeValue(ctx, ctx->iterator_proto); JS_FreeValue(ctx, ctx->async_iterator_proto); + JS_FreeValue(ctx, ctx->promise_ctor); JS_FreeValue(ctx, ctx->regexp_ctor); JS_FreeValue(ctx, ctx->function_ctor); JS_FreeValue(ctx, ctx->function_proto); @@ -10827,6 +10846,19 @@ static bf_t *JS_ToBigInt(JSContext *ctx, bf_t *buf, JSValueConst val) return JS_ToBigIntFree(ctx, buf, JS_DupValue(ctx, val)); } +static JSValue JS_ToBigIntValueFree(JSContext *ctx, JSValue val) +{ + if (JS_VALUE_GET_TAG(val) == JS_TAG_BIG_INT) { + return val; + } else { + bf_t a_s, *a; + a = JS_ToBigIntFree(ctx, &a_s, val); + if (!a) + return JS_EXCEPTION; + return JS_NewBigInt2(ctx, a, TRUE); + } +} + /* free the bf_t allocated by JS_ToBigInt */ static void JS_FreeBigInt(JSContext *ctx, bf_t *a, bf_t *buf) { @@ -14331,6 +14363,15 @@ static inline __exception int js_poll_interrupts(JSContext *ctx) } } +/* argument of OP_special_object */ +typedef enum { + OP_SPECIAL_OBJECT_ARGUMENTS, + OP_SPECIAL_OBJECT_MAPPED_ARGUMENTS, + OP_SPECIAL_OBJECT_THIS_FUNC, + OP_SPECIAL_OBJECT_NEW_TARGET, + OP_SPECIAL_OBJECT_HOME_OBJECT, +} OPSpecialObjectEnum; + #define FUNC_RET_AWAIT 0 #define FUNC_RET_YIELD 1 #define FUNC_RET_YIELD_STAR 2 @@ -14563,20 +14604,40 @@ static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj, if (unlikely(JS_IsException(sp[-1]))) goto exception; BREAK; - CASE(OP_this_func): - *sp++ = JS_DupValue(ctx, sf->cur_func); - BREAK; - CASE(OP_arguments): + CASE(OP_special_object): { - int mapped = *pc++; - if (mapped) { + int arg = *pc++; + switch(arg) { + case OP_SPECIAL_OBJECT_ARGUMENTS: + *sp++ = js_build_arguments(ctx, argc, (JSValueConst *)argv); + if (unlikely(JS_IsException(sp[-1]))) + goto exception; + break; + case OP_SPECIAL_OBJECT_MAPPED_ARGUMENTS: *sp++ = js_build_mapped_arguments(ctx, argc, (JSValueConst *)argv, sf, min_int(argc, b->arg_count)); - } else { - *sp++ = js_build_arguments(ctx, argc, (JSValueConst *)argv); + if (unlikely(JS_IsException(sp[-1]))) + goto exception; + break; + case OP_SPECIAL_OBJECT_THIS_FUNC: + *sp++ = JS_DupValue(ctx, sf->cur_func); + break; + case OP_SPECIAL_OBJECT_NEW_TARGET: + *sp++ = JS_DupValue(ctx, new_target); + break; + case OP_SPECIAL_OBJECT_HOME_OBJECT: + { + JSObject *p1; + p1 = p->u.func.home_object; + if (unlikely(!p1)) + *sp++ = JS_UNDEFINED; + else + *sp++ = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p1)); + } + break; + default: + abort(); } - if (unlikely(JS_IsException(sp[-1]))) - goto exception; } BREAK; CASE(OP_rest): @@ -14588,19 +14649,6 @@ static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj, goto exception; } BREAK; - CASE(OP_new_target): - *sp++ = JS_DupValue(ctx, new_target); - BREAK; - CASE(OP_home_object): - { - JSObject *p1; - p1 = p->u.func.home_object; - if (unlikely(!p1)) - *sp++ = JS_UNDEFINED; - else - *sp++ = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p1)); - } - BREAK; CASE(OP_drop): JS_FreeValue(ctx, sp[-1]); @@ -14962,6 +15010,17 @@ static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj, } BREAK; + CASE(OP_import): + { + JSValue val; + val = js_dynamic_import(ctx, sp[-1]); + if (JS_IsException(val)) + goto exception; + JS_FreeValue(ctx, sp[-1]); + sp[-1] = val; + } + BREAK; + CASE(OP_check_var): { int ret; @@ -17311,20 +17370,11 @@ static void js_async_function_resume(JSContext *ctx, JSAsyncFunctionData *s) /* await */ JS_FreeValue(ctx, func_ret); /* not used */ - promise = js_new_promise_capability(ctx, resolving_funcs, JS_UNDEFINED); - if (JS_IsException(promise)) - goto fail; - ret2 = JS_Call(ctx, resolving_funcs[0], JS_UNDEFINED, - 1, (JSValueConst *)&value); - JS_FreeValue(ctx, resolving_funcs[0]); - JS_FreeValue(ctx, resolving_funcs[1]); + promise = js_promise_resolve(ctx, ctx->promise_ctor, + 1, (JSValueConst *)&value, 0); JS_FreeValue(ctx, value); - if (JS_IsException(ret2)) { - JS_FreeValue(ctx, promise); + if (JS_IsException(promise)) goto fail; - } - JS_FreeValue(ctx, ret2); - if (js_async_function_resolve_create(ctx, s, resolving_funcs)) { JS_FreeValue(ctx, promise); goto fail; @@ -17387,7 +17437,7 @@ static JSValue js_async_function_call(JSContext *ctx, JSValueConst func_obj, s->resolving_funcs[0] = JS_UNDEFINED; s->resolving_funcs[1] = JS_UNDEFINED; - promise = js_new_promise_capability(ctx, s->resolving_funcs, JS_UNDEFINED); + promise = JS_NewPromiseCapability(ctx, s->resolving_funcs); if (JS_IsException(promise)) goto fail; @@ -17515,21 +17565,13 @@ static int js_async_generator_await(JSContext *ctx, JSAsyncGeneratorData *s, JSValueConst value) { - JSValue promise, resolving_funcs[2], resolving_funcs1[2], ret2; + JSValue promise, resolving_funcs[2], resolving_funcs1[2]; int i, res; - promise = js_new_promise_capability(ctx, resolving_funcs, JS_UNDEFINED); + promise = js_promise_resolve(ctx, ctx->promise_ctor, + 1, &value, 0); if (JS_IsException(promise)) goto fail; - ret2 = JS_Call(ctx, resolving_funcs[0], JS_UNDEFINED, - 1, &value); - JS_FreeValue(ctx, resolving_funcs[0]); - JS_FreeValue(ctx, resolving_funcs[1]); - if (JS_IsException(ret2)) { - JS_FreeValue(ctx, promise); - goto fail; - } - JS_FreeValue(ctx, ret2); if (js_async_generator_resolve_function_create(ctx, JS_MKPTR(JS_TAG_OBJECT, s->generator), resolving_funcs, FALSE)) { @@ -17606,20 +17648,13 @@ static int js_async_generator_completed_return(JSContext *ctx, JSAsyncGeneratorData *s, JSValueConst value) { - JSValue promise, resolving_funcs[2], ret, resolving_funcs1[2]; + JSValue promise, resolving_funcs[2], resolving_funcs1[2]; int res; - promise = js_new_promise_capability(ctx, resolving_funcs, JS_UNDEFINED); + promise = js_promise_resolve(ctx, ctx->promise_ctor, + 1, (JSValueConst *)&value, 0); if (JS_IsException(promise)) return -1; - ret = JS_Call(ctx, resolving_funcs[0], JS_UNDEFINED, 1, &value); - JS_FreeValue(ctx, resolving_funcs[0]); - JS_FreeValue(ctx, resolving_funcs[1]); - if (JS_IsException(ret)) { - JS_FreeValue(ctx, promise); - return -1; - } - JS_FreeValue(ctx, ret); if (js_async_generator_resolve_function_create(ctx, JS_MKPTR(JS_TAG_OBJECT, s->generator), resolving_funcs1, @@ -17781,7 +17816,7 @@ static JSValue js_async_generator_next(JSContext *ctx, JSValueConst this_val, JSValue promise, resolving_funcs[2]; JSAsyncGeneratorRequest *req; - promise = js_new_promise_capability(ctx, resolving_funcs, JS_UNDEFINED); + promise = JS_NewPromiseCapability(ctx, resolving_funcs); if (JS_IsException(promise)) return JS_EXCEPTION; if (!s) { @@ -19222,6 +19257,7 @@ static __exception int next_token(JSParseState *s) } /* only used for ':' and '=>', 'let' or 'function' look-ahead */ +/* XXX: handle all unicode cases */ static int peek_token(JSParseState *s, BOOL no_line_terminator) { const uint8_t *p; @@ -21756,6 +21792,19 @@ static __exception int js_parse_postfix_expr(JSParseState *s, BOOL accept_lparen return js_parse_error(s, "invalid use of 'super'"); } break; + case TOK_IMPORT: + if (!accept_lparen) + return js_parse_error(s, "invalid use of 'import'"); + if (next_token(s)) + return -1; + if (js_parse_expect(s, '(')) + return -1; + if (js_parse_assign_expr(s, TRUE)) + return -1; + if (js_parse_expect(s, ')')) + return -1; + emit_op(s, OP_import); + break; default: return js_parse_error(s, "unexpected token in expression: '%.*s'", (int)(s->buf_ptr - s->token.ptr), s->token.ptr); @@ -22538,6 +22587,7 @@ static __exception int js_parse_assign_expr(JSParseState *s, BOOL in_accepted) label_throw = emit_goto(s, OP_if_true, -1); /* return handling */ + emit_op(s, OP_await); emit_op(s, OP_async_iterator_get); emit_u8(s, 0); label_return1 = emit_goto(s, OP_if_true, -1); @@ -22548,7 +22598,6 @@ static __exception int js_parse_assign_expr(JSParseState *s, BOOL in_accepted) emit_goto(s, OP_if_false, label_yield); emit_label(s, label_return1); - emit_op(s, OP_await); emit_op(s, OP_nip); emit_op(s, OP_nip); emit_op(s, OP_nip); @@ -22586,7 +22635,6 @@ static __exception int js_parse_assign_expr(JSParseState *s, BOOL in_accepted) emit_op(s, OP_await); emit_op(s, OP_yield); label_next = emit_goto(s, OP_if_false, -1); - emit_op(s, OP_await); emit_return(s, TRUE); emit_label(s, label_next); } @@ -22825,8 +22873,11 @@ static void emit_return(JSParseState *s, BOOL hasval) emit_label(s, label_return); emit_op(s, OP_return); } else if (s->cur_func->func_kind != JS_FUNC_NORMAL) { - if (!hasval) + if (!hasval) { emit_op(s, OP_undefined); + } else if (s->cur_func->func_kind == JS_FUNC_ASYNC_GENERATOR) { + emit_op(s, OP_await); + } emit_op(s, OP_return_async); } else { emit_op(s, hasval ? OP_return : OP_return_undef); @@ -23965,7 +24016,6 @@ static __exception int js_parse_statement_or_decl(JSParseState *s, case TOK_ENUM: case TOK_EXPORT: case TOK_EXTENDS: - case TOK_IMPORT: js_unsupported_keyword(s, s->token.u.ident.atom); goto fail; @@ -24006,6 +24056,7 @@ static JSModuleDef *js_new_module_def(JSContext *ctx, JSAtom name) m->module_name = name; m->module_ns = JS_UNDEFINED; m->func_obj = JS_UNDEFINED; + m->eval_exception = JS_UNDEFINED; list_add_tail(&m->link, &ctx->loaded_modules); return m; } @@ -24041,6 +24092,7 @@ static void js_free_module_def(JSContext *ctx, JSModuleDef *m) JS_FreeValue(ctx, m->module_ns); JS_FreeValue(ctx, m->func_obj); + JS_FreeValue(ctx, m->eval_exception); list_del(&m->link); js_free(ctx, m); } @@ -24268,7 +24320,7 @@ static char *js_default_module_normalize_name(JSContext *ctx, /* return NULL in case of exception (e.g. module could not be loaded) */ static JSModuleDef *js_host_resolve_imported_module(JSContext *ctx, - JSModuleDef *base_module, + JSAtom base_module_name, JSAtom module_name1) { JSRuntime *rt = ctx->rt; @@ -24278,7 +24330,7 @@ static JSModuleDef *js_host_resolve_imported_module(JSContext *ctx, const char *base_cname, *cname1; JSAtom module_name; - base_cname = JS_AtomToCString(ctx, base_module->module_name); + base_cname = JS_AtomToCString(ctx, base_module_name); if (!base_cname) return NULL; cname1 = JS_AtomToCString(ctx, module_name1); @@ -24400,10 +24452,18 @@ static JSResolveResultEnum js_resolve_export1(JSContext *ctx, *pme = me; return JS_RESOLVE_RES_FOUND; } else { + /* indirect export */ JSModuleDef *m1; m1 = m->req_module_entries[me->u.req_module_idx].module; - return js_resolve_export1(ctx, pmodule, pme, m1, - me->local_name, s); + if (me->local_name == JS_ATOM__star_) { + /* export ns from */ + *pmodule = m; + *pme = me; + return JS_RESOLVE_RES_FOUND; + } else { + return js_resolve_export1(ctx, pmodule, pme, m1, + me->local_name, s); + } } } else { if (export_name != JS_ATOM_default) { @@ -24498,10 +24558,20 @@ static void js_resolve_export_throw_error(JSContext *ctx, } +typedef enum { + EXPORTED_NAME_AMBIGUOUS, + EXPORTED_NAME_NORMAL, + EXPORTED_NAME_NS, +} ExportedNameEntryEnum; + typedef struct ExportedNameEntry { JSAtom export_name; - JSExportEntry *me; /* NULL if not coming from the module */ - JSVarRef *var_ref; + ExportedNameEntryEnum export_type; + union { + JSExportEntry *me; /* using when the list is built */ + JSVarRef *var_ref; /* EXPORTED_NAME_NORMAL */ + JSModuleDef *module; /* for EXPORTED_NAME_NS */ + } u; } ExportedNameEntry; typedef struct GetExportNamesState { @@ -24554,12 +24624,12 @@ static __exception int get_exported_names(JSContext *ctx, en->export_name = me->export_name; /* avoid a second lookup for simple module exports */ if (from_star || me->export_type != JS_EXPORT_TYPE_LOCAL) - en->me = NULL; + en->u.me = NULL; else - en->me = me; + en->u.me = me; } else { en = &s->exported_names[j]; - en->me = NULL; + en->u.me = NULL; } } for(i = 0; i < m->star_export_entries_count; i++) { @@ -24605,6 +24675,23 @@ static int exported_names_cmp(const void *p1, const void *p2, void *opaque) return ret; } +static JSValue js_get_module_ns(JSContext *ctx, JSModuleDef *m); + +static int js_module_ns_autoinit(JSContext *ctx, JSObject *p, JSAtom atom, + void *opaque) +{ + JSModuleDef *m = opaque; + JSValue val, this_val = JS_MKPTR(JS_TAG_OBJECT, p); + + val = js_get_module_ns(ctx, m); + if (JS_IsException(val)) + return -1; + if (JS_DefinePropertyValue(ctx, this_val, atom, val, + JS_PROP_ENUMERABLE | JS_PROP_WRITABLE) < 0) + return -1; + return 0; +} + static JSValue js_build_module_ns(JSContext *ctx, JSModuleDef *m) { JSValue obj; @@ -24631,8 +24718,8 @@ static JSValue js_build_module_ns(JSContext *ctx, JSModuleDef *m) JSExportEntry *res_me; JSModuleDef *res_m; - if (en->me) { - res_me = en->me; /* fast case: no resolution needed */ + if (en->u.me) { + res_me = en->u.me; /* fast case: no resolution needed */ res_m = m; res = JS_RESOLVE_RES_FOUND; } else { @@ -24644,14 +24731,20 @@ static JSValue js_build_module_ns(JSContext *ctx, JSModuleDef *m) js_resolve_export_throw_error(ctx, res, m, en->export_name); goto fail; } - en->var_ref = NULL; + en->export_type = EXPORTED_NAME_AMBIGUOUS; } else { - if (res_me->u.local.var_ref) { - en->var_ref = res_me->u.local.var_ref; + if (res_me->local_name == JS_ATOM__star_) { + en->export_type = EXPORTED_NAME_NS; + en->u.module = res_m->req_module_entries[res_me->u.req_module_idx].module; } else { - JSObject *p1 = JS_VALUE_GET_OBJ(res_m->func_obj); - p1 = JS_VALUE_GET_OBJ(res_m->func_obj); - en->var_ref = p1->u.func.var_refs[res_me->u.local.var_idx]; + en->export_type = EXPORTED_NAME_NORMAL; + if (res_me->u.local.var_ref) { + en->u.var_ref = res_me->u.local.var_ref; + } else { + JSObject *p1 = JS_VALUE_GET_OBJ(res_m->func_obj); + p1 = JS_VALUE_GET_OBJ(res_m->func_obj); + en->u.var_ref = p1->u.func.var_refs[res_me->u.local.var_idx]; + } } } } @@ -24662,15 +24755,29 @@ static JSValue js_build_module_ns(JSContext *ctx, JSModuleDef *m) for(i = 0; i < s->exported_names_count; i++) { ExportedNameEntry *en = &s->exported_names[i]; - JSVarRef *var_ref = en->var_ref; - if (var_ref != NULL) { - pr = add_property(ctx, p, en->export_name, - JS_PROP_ENUMERABLE | JS_PROP_WRITABLE | - JS_PROP_VARREF); - if (!pr) + switch(en->export_type) { + case EXPORTED_NAME_NORMAL: + { + JSVarRef *var_ref = en->u.var_ref; + pr = add_property(ctx, p, en->export_name, + JS_PROP_ENUMERABLE | JS_PROP_WRITABLE | + JS_PROP_VARREF); + if (!pr) + goto fail; + var_ref->header.ref_count++; + pr->u.var_ref = var_ref; + } + break; + case EXPORTED_NAME_NS: + /* the exported namespace must be created on demand */ + if (JS_DefineAutoInitProperty(ctx, obj, + en->export_name, + js_module_ns_autoinit, + en->u.module, JS_PROP_ENUMERABLE | JS_PROP_WRITABLE) < 0) goto fail; - var_ref->header.ref_count++; - pr->u.var_ref = var_ref; + break; + default: + break; } } @@ -24688,6 +24795,18 @@ static JSValue js_build_module_ns(JSContext *ctx, JSModuleDef *m) return JS_EXCEPTION; } +static JSValue js_get_module_ns(JSContext *ctx, JSModuleDef *m) +{ + if (JS_IsUndefined(m->module_ns)) { + JSValue val; + val = js_build_module_ns(ctx, m); + if (JS_IsException(val)) + return JS_EXCEPTION; + m->module_ns = val; + } + return JS_DupValue(ctx, m->module_ns); +} + /* Load all the required modules for module 'm' */ static int js_resolve_module(JSContext *ctx, JSModuleDef *m) { @@ -24706,7 +24825,8 @@ static int js_resolve_module(JSContext *ctx, JSModuleDef *m) /* resolve each requested module */ for(i = 0; i < m->req_module_entries_count; i++) { JSReqModuleEntry *rme = &m->req_module_entries[i]; - m1 = js_host_resolve_imported_module(ctx, m, rme->module_name); + m1 = js_host_resolve_imported_module(ctx, m->module_name, + rme->module_name); if (!m1) return -1; rme->module = m1; @@ -24836,7 +24956,8 @@ static int js_instantiate_module(JSContext *ctx, JSModuleDef *m) /* check the indirect exports */ for(i = 0; i < m->export_entries_count; i++) { JSExportEntry *me = &m->export_entries[i]; - if (me->export_type == JS_EXPORT_TYPE_INDIRECT) { + if (me->export_type == JS_EXPORT_TYPE_INDIRECT && + me->local_name != JS_ATOM__star_) { JSResolveResultEnum ret; JSExportEntry *res_me; JSModuleDef *res_m, *m1; @@ -24867,20 +24988,21 @@ static int js_instantiate_module(JSContext *ctx, JSModuleDef *m) for(i = 0; i < m->import_entries_count; i++) { mi = &m->import_entries[i]; +#ifdef DUMP_MODULE_RESOLVE + printf("import var_idx=%d name=", mi->var_idx); + print_atom(ctx, mi->import_name); + printf(": "); +#endif m1 = m->req_module_entries[mi->req_module_idx].module; if (mi->import_name == JS_ATOM__star_) { + JSValue val; /* name space import */ - if (JS_IsUndefined(m1->module_ns)) { - JSValue val; - val = js_build_module_ns(ctx, m1); - if (JS_IsException(val)) - goto fail; - m1->module_ns = val; - } - set_value(ctx, &var_refs[mi->var_idx]->value, - JS_DupValue(ctx, m1->module_ns)); + val = js_get_module_ns(ctx, m1); + if (JS_IsException(val)) + goto fail; + set_value(ctx, &var_refs[mi->var_idx]->value, val); #ifdef DUMP_MODULE_RESOLVE - printf("import %d: namespace\n", mi->var_idx); + printf("namespace\n"); #endif } else { JSResolveResultEnum ret; @@ -24894,16 +25016,36 @@ static int js_instantiate_module(JSContext *ctx, JSModuleDef *m) js_resolve_export_throw_error(ctx, ret, m1, mi->import_name); goto fail; } - var_ref = res_me->u.local.var_ref; - if (!var_ref) { - p1 = JS_VALUE_GET_OBJ(res_m->func_obj); - var_ref = p1->u.func.var_refs[res_me->u.local.var_idx]; - } - var_ref->header.ref_count++; - var_refs[mi->var_idx] = var_ref; + if (res_me->local_name == JS_ATOM__star_) { + JSValue val; + JSModuleDef *m2; + /* name space import from */ + m2 = res_m->req_module_entries[res_me->u.req_module_idx].module; + val = js_get_module_ns(ctx, m2); + if (JS_IsException(val)) + goto fail; + var_ref = js_create_module_var(ctx, TRUE); + if (!var_ref) { + JS_FreeValue(ctx, val); + goto fail; + } + set_value(ctx, &var_ref->value, val); + var_refs[mi->var_idx] = var_ref; #ifdef DUMP_MODULE_RESOLVE - printf("import %d: %p\n", mi->var_idx, var_ref); + printf("namespace from\n"); #endif + } else { + var_ref = res_me->u.local.var_ref; + if (!var_ref) { + p1 = JS_VALUE_GET_OBJ(res_m->func_obj); + var_ref = p1->u.func.var_refs[res_me->u.local.var_idx]; + } + var_ref->header.ref_count++; + var_refs[mi->var_idx] = var_ref; +#ifdef DUMP_MODULE_RESOLVE + printf("local export (var_ref=%p)\n", var_ref); +#endif + } } } @@ -24928,6 +25070,85 @@ static int js_instantiate_module(JSContext *ctx, JSModuleDef *m) return -1; } +static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier) +{ + JSStackFrame *sf; + JSFunctionBytecode *b; + JSObject *p; + JSModuleDef *m; + JSAtom basename, filename; + JSValue promise, resolving_funcs[2]; + JSValue specifierString, ret, func_obj, err, ns; + + promise = JS_NewPromiseCapability(ctx, resolving_funcs); + if (JS_IsException(promise)) + return promise; + + /* XXX: currently we just use the filename of the englobing + function. It does not work for eval(). Need to add a + ScriptOrModule info in JSFunctionBytecode */ + sf = ctx->current_stack_frame; + assert(sf != NULL); + assert(JS_VALUE_GET_TAG(sf->cur_func) == JS_TAG_OBJECT); + p = JS_VALUE_GET_OBJ(sf->cur_func); + assert(js_class_has_bytecode(p->class_id)); + b = p->u.func.function_bytecode; + if (!b->has_debug) { + JS_ThrowTypeError(ctx, "no function filename for import()"); + goto exception; + } + basename = b->debug.filename; + + specifierString = JS_ToString(ctx, specifier); + if (JS_IsException(specifierString)) + goto exception; + filename = js_value_to_atom(ctx, specifierString); + JS_FreeValue(ctx, specifierString); + if (filename == JS_ATOM_NULL) + goto exception; + + m = js_host_resolve_imported_module(ctx, basename, filename); + JS_FreeAtom(ctx, filename); + if (!m) { + goto exception; + } + + if (js_resolve_module(ctx, m) < 0) { + js_free_modules(ctx, JS_FREE_MODULE_NOT_RESOLVED); + goto exception; + } + + /* Evaluate the module code */ + func_obj = JS_DupValue(ctx, JS_MKPTR(JS_TAG_MODULE, m)); + ret = JS_EvalFunction(ctx, func_obj, ctx->global_obj); + if (JS_IsException(ret)) + goto exception; + JS_FreeValue(ctx, ret); + + /* return the module namespace */ + ns = js_get_module_ns(ctx, m); + if (JS_IsException(ret)) + goto exception; + + ret = JS_Call(ctx, resolving_funcs[0], JS_UNDEFINED, + 1, (JSValueConst *)&ns); + JS_FreeValue(ctx, ret); /* XXX: what to do if exception ? */ + JS_FreeValue(ctx, ns); + JS_FreeValue(ctx, resolving_funcs[0]); + JS_FreeValue(ctx, resolving_funcs[1]); + return promise; + + exception: + err = JS_GetException(ctx); + ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED, + 1, (JSValueConst *)&err); + JS_FreeValue(ctx, ret); /* XXX: what to do if exception ? */ + JS_FreeValue(ctx, err); + JS_FreeValue(ctx, resolving_funcs[0]); + JS_FreeValue(ctx, resolving_funcs[1]); + return promise; +} + /* Run the function of the module and of all its requested modules. */ static JSValue js_evaluate_module(JSContext *ctx, JSModuleDef *m) @@ -24936,17 +25157,32 @@ static JSValue js_evaluate_module(JSContext *ctx, JSModuleDef *m) int i; JSValue ret_val; - if (m->evaluated) - return JS_UNDEFINED; - m->evaluated = TRUE; + if (m->eval_mark) + return JS_UNDEFINED; /* avoid cycles */ + + if (m->evaluated) { + /* if the module was already evaluated, rethrow the exception + it raised */ + if (m->eval_has_exception) { + return JS_Throw(ctx, JS_DupValue(ctx, m->eval_exception)); + } else { + return JS_UNDEFINED; + } + } + + m->eval_mark = TRUE; for(i = 0; i < m->req_module_entries_count; i++) { JSReqModuleEntry *rme = &m->req_module_entries[i]; - m1 = rme->module; /* already resolved */ - ret_val = js_evaluate_module(ctx, m1); - if (JS_IsException(ret_val)) - return ret_val; - JS_FreeValue(ctx, ret_val); + m1 = rme->module; + if (!m1->eval_mark) { + ret_val = js_evaluate_module(ctx, m1); + if (JS_IsException(ret_val)) { + m->eval_mark = FALSE; + return ret_val; + } + JS_FreeValue(ctx, ret_val); + } } if (m->init_func) { @@ -24959,6 +25195,13 @@ static JSValue js_evaluate_module(JSContext *ctx, JSModuleDef *m) ret_val = JS_CallFree(ctx, m->func_obj, JS_UNDEFINED, 0, NULL); m->func_obj = JS_UNDEFINED; } + if (JS_IsException(ret_val)) { + /* save the thrown exception value */ + m->eval_has_exception = TRUE; + m->eval_exception = JS_DupValue(ctx, ctx->current_exception); + } + m->eval_mark = FALSE; + m->evaluated = TRUE; return ret_val; } @@ -25035,6 +25278,7 @@ static __exception int js_parse_export(JSParseState *s) if (next_token(s)) { fail: JS_FreeAtom(ctx, local_name); + fail1: JS_FreeAtom(ctx, export_name); return -1; } @@ -25070,15 +25314,41 @@ static __exception int js_parse_export(JSParseState *s) } break; case '*': - module_name = js_parse_from_clause(s); - if (module_name == JS_ATOM_NULL) - return -1; - idx = add_req_module_entry(ctx, m, module_name); - JS_FreeAtom(ctx, module_name); - if (idx < 0) - return -1; - if (add_star_export_entry(ctx, m, idx) < 0) - return -1; + if (token_is_pseudo_keyword(s, JS_ATOM_as)) { + /* export ns from */ + if (next_token(s)) + return -1; + if (!token_is_ident(s->token.val)) { + js_parse_error(s, "identifier expected"); + return -1; + } + export_name = JS_DupAtom(ctx, s->token.u.ident.atom); + if (next_token(s)) + goto fail1; + module_name = js_parse_from_clause(s); + if (module_name == JS_ATOM_NULL) + goto fail1; + idx = add_req_module_entry(ctx, m, module_name); + JS_FreeAtom(ctx, module_name); + if (idx < 0) + goto fail1; + me = add_export_entry(s, m, JS_ATOM__star_, export_name, + JS_EXPORT_TYPE_INDIRECT); + JS_FreeAtom(ctx, export_name); + if (!me) + return -1; + me->u.req_module_idx = idx; + } else { + module_name = js_parse_from_clause(s); + if (module_name == JS_ATOM_NULL) + return -1; + idx = add_req_module_entry(ctx, m, module_name); + JS_FreeAtom(ctx, module_name); + if (idx < 0) + return -1; + if (add_star_export_entry(ctx, m, idx) < 0) + return -1; + } break; case TOK_DEFAULT: if (s->token.val == TOK_CLASS) { @@ -25285,7 +25555,10 @@ static __exception int js_parse_source_element(JSParseState *s) } else if (s->token.val == TOK_EXPORT && fd->module) { if (js_parse_export(s)) return -1; - } else if (s->token.val == TOK_IMPORT && fd->module) { + } else if (s->token.val == TOK_IMPORT && fd->module && + peek_token(s, FALSE) != '(') { + /* the peek_token is needed to avoid confusion with ImportCall + (dynamic import) */ if (js_parse_import(s)) return -1; } else { @@ -27651,17 +27924,20 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s) /* initialize the 'home_object' variable if needed */ if (s->home_object_var_idx >= 0) { - dbuf_putc(&bc_out, OP_home_object); + dbuf_putc(&bc_out, OP_special_object); + dbuf_putc(&bc_out, OP_SPECIAL_OBJECT_HOME_OBJECT); put_short_code(&bc_out, OP_put_loc, s->home_object_var_idx); } /* initialize the 'this.active_func' variable if needed */ if (s->this_active_func_var_idx >= 0) { - dbuf_putc(&bc_out, OP_this_func); + dbuf_putc(&bc_out, OP_special_object); + dbuf_putc(&bc_out, OP_SPECIAL_OBJECT_THIS_FUNC); put_short_code(&bc_out, OP_put_loc, s->this_active_func_var_idx); } /* initialize the 'new.target' variable if needed */ if (s->new_target_var_idx >= 0) { - dbuf_putc(&bc_out, OP_new_target); + dbuf_putc(&bc_out, OP_special_object); + dbuf_putc(&bc_out, OP_SPECIAL_OBJECT_NEW_TARGET); put_short_code(&bc_out, OP_put_loc, s->new_target_var_idx); } /* initialize the 'this' variable if needed. In a derived class @@ -27678,17 +27954,18 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s) /* initialize the 'arguments' variable if needed */ if (s->arguments_var_idx >= 0) { if ((s->js_mode & JS_MODE_STRICT) || !s->has_simple_parameter_list) { - dbuf_putc(&bc_out, OP_arguments); - dbuf_putc(&bc_out, 0); + dbuf_putc(&bc_out, OP_special_object); + dbuf_putc(&bc_out, OP_SPECIAL_OBJECT_ARGUMENTS); } else { - dbuf_putc(&bc_out, OP_arguments); - dbuf_putc(&bc_out, 1); + dbuf_putc(&bc_out, OP_special_object); + dbuf_putc(&bc_out, OP_SPECIAL_OBJECT_MAPPED_ARGUMENTS); } put_short_code(&bc_out, OP_put_loc, s->arguments_var_idx); } /* initialize a reference to the current function if needed */ if (s->func_var_idx >= 0) { - dbuf_putc(&bc_out, OP_this_func); + dbuf_putc(&bc_out, OP_special_object); + dbuf_putc(&bc_out, OP_SPECIAL_OBJECT_THIS_FUNC); put_short_code(&bc_out, OP_put_loc, s->func_var_idx); } /* initialize the variable environment object if needed */ @@ -29697,6 +29974,28 @@ JSValue JS_EvalFunction(JSContext *ctx, JSValue fun_obj, JSValueConst this_obj) return JS_EvalFunctionInternal(ctx, fun_obj, this_obj, NULL, NULL); } +static void skip_shebang(JSParseState *s) +{ + const uint8_t *p = s->buf_ptr; + int c; + + if (p[0] == '#' && p[1] == '!') { + p += 2; + while (p < s->buf_end) { + if (*p == '\n' || *p == '\r') { + break; + } else if (*p >= 0x80) { + c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p); + if (c == CP_LS || c == CP_PS) + break; + } else { + p++; + } + } + s->buf_ptr = p; + } +} + /* 'input' must be zero terminated i.e. input[input_len] = '\0'. */ static JSValue __JS_EvalInternal(JSContext *ctx, JSValueConst this_obj, const char *input, size_t input_len, @@ -29712,16 +30011,8 @@ static JSValue __JS_EvalInternal(JSContext *ctx, JSValueConst this_obj, JSModuleDef *m; js_parse_init(ctx, s, input, input_len, filename); + skip_shebang(s); - if (flags & JS_EVAL_FLAG_SHEBANG) { - const uint8_t *p = s->buf_ptr; - if (p[0] == '#' && p[1] == '!') { - p += 2; - while (*p != '\0' && *p != '\n') - p++; - s->buf_ptr = p; - } - } eval_type = flags & JS_EVAL_TYPE_MASK; m = NULL; if (eval_type == JS_EVAL_TYPE_DIRECT) { @@ -32128,20 +32419,6 @@ static JSValue js_object___defineGetter__(JSContext *ctx, JSValueConst this_val, } } -/* Note: corresponds to ECMA spec: CreateDataPropertyOrThrow() */ -static JSValue js_object___setOwnProperty(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - int ret; - ret = JS_DefinePropertyValueValue(ctx, argv[0], JS_DupValue(ctx, argv[1]), - JS_DupValue(ctx, argv[2]), - JS_PROP_C_W_E | JS_PROP_THROW); - if (ret < 0) - return JS_EXCEPTION; - else - return JS_NewBool(ctx, ret); -} - static JSValue js_object_getOwnPropertyDescriptor(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic) { @@ -32605,7 +32882,89 @@ static JSValue js_object_isSealed(JSContext *ctx, JSValueConst this_val, return JS_EXCEPTION; } +static JSValue js_object_fromEntries(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + JSValue obj, iter, next_method = JS_UNDEFINED; + JSValueConst iterable; + BOOL done; + + /* RequireObjectCoercible() not necessary because it is tested in + JS_GetIterator() by JS_GetProperty() */ + iterable = argv[0]; + + obj = JS_NewObject(ctx); + if (JS_IsException(obj)) + return obj; + + iter = JS_GetIterator(ctx, iterable, FALSE); + if (JS_IsException(iter)) + goto fail; + next_method = JS_GetProperty(ctx, iter, JS_ATOM_next); + if (JS_IsException(next_method)) + goto fail; + + for(;;) { + JSValue key, value, item; + item = JS_IteratorNext(ctx, iter, next_method, 0, NULL, &done); + if (JS_IsException(item)) + goto fail; + if (done) { + JS_FreeValue(ctx, item); + break; + } + + key = JS_UNDEFINED; + value = JS_UNDEFINED; + if (!JS_IsObject(item)) { + JS_ThrowTypeErrorNotAnObject(ctx); + goto fail1; + } + key = JS_GetPropertyUint32(ctx, item, 0); + if (JS_IsException(key)) + goto fail1; + value = JS_GetPropertyUint32(ctx, item, 1); + if (JS_IsException(value)) { + JS_FreeValue(ctx, key); + goto fail1; + } + if (JS_DefinePropertyValueValue(ctx, obj, key, value, + JS_PROP_C_W_E | JS_PROP_THROW) < 0) { + fail1: + JS_FreeValue(ctx, item); + goto fail; + } + JS_FreeValue(ctx, item); + } + JS_FreeValue(ctx, next_method); + JS_FreeValue(ctx, iter); + return obj; + fail: + if (JS_IsObject(iter)) { + /* close the iterator object, preserving pending exception */ + JS_IteratorClose(ctx, iter, TRUE); + } + JS_FreeValue(ctx, next_method); + JS_FreeValue(ctx, iter); + JS_FreeValue(ctx, obj); + return JS_EXCEPTION; +} + #if 0 +/* Note: corresponds to ECMA spec: CreateDataPropertyOrThrow() */ +static JSValue js_object___setOwnProperty(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + int ret; + ret = JS_DefinePropertyValueValue(ctx, argv[0], JS_DupValue(ctx, argv[1]), + JS_DupValue(ctx, argv[2]), + JS_PROP_C_W_E | JS_PROP_THROW); + if (ret < 0) + return JS_EXCEPTION; + else + return JS_NewBool(ctx, ret); +} + static JSValue js_object___toObject(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { @@ -32891,13 +33250,14 @@ static const JSCFunctionListEntry js_object_funcs[] = { //JS_CFUNC_DEF("__isObject", 1, js_object___isObject ), //JS_CFUNC_DEF("__isConstructor", 1, js_object___isConstructor ), //JS_CFUNC_DEF("__toObject", 1, js_object___toObject ), - JS_CFUNC_DEF("__setOwnProperty", 3, js_object___setOwnProperty ), + //JS_CFUNC_DEF("__setOwnProperty", 3, js_object___setOwnProperty ), //JS_CFUNC_DEF("__toPrimitive", 2, js_object___toPrimitive ), //JS_CFUNC_DEF("__toPropertyKey", 1, js_object___toPropertyKey ), //JS_CFUNC_DEF("__speciesConstructor", 2, js_object___speciesConstructor ), //JS_CFUNC_DEF("__isSameValueZero", 2, js_object___isSameValueZero ), //JS_CFUNC_DEF("__getObjectData", 1, js_object___getObjectData ), //JS_CFUNC_DEF("__setObjectData", 2, js_object___setObjectData ), + JS_CFUNC_DEF("fromEntries", 1, js_object_fromEntries ), }; static const JSCFunctionListEntry js_object_proto_funcs[] = { @@ -36053,10 +36413,11 @@ static JSValue js_string_includes(JSContext *ctx, JSValueConst this_val, static JSValue js_string_match(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int atom) { - // match(rx) and search(rx) - // atom is JS_ATOM_Symbol_match or JS_ATOM_Symbol_search - JSValueConst O = this_val, regexp = argv[0]; - JSValue matcher, S, rx, result; + // match(rx), search(rx), matchAll(rx) + // atom is JS_ATOM_Symbol_match, JS_ATOM_Symbol_search, or JS_ATOM_Symbol_matchAll + JSValueConst O = this_val, regexp = argv[0], args[2]; + JSValue matcher, S, rx, result, str; + int args_len; if (JS_IsUndefined(O) || JS_IsNull(O)) return JS_ThrowTypeError(ctx, "cannot convert to object"); @@ -36072,8 +36433,19 @@ static JSValue js_string_match(JSContext *ctx, JSValueConst this_val, S = JS_ToString(ctx, O); if (JS_IsException(S)) return JS_EXCEPTION; - rx = JS_CallConstructor(ctx, ctx->regexp_ctor, 1, ®exp); + args_len = 1; + args[0] = regexp; + str = JS_UNDEFINED; + if (atom == JS_ATOM_Symbol_matchAll) { + str = JS_NewString(ctx, "g"); + if (JS_IsException(str)) + goto fail; + args[args_len++] = (JSValueConst)str; + } + rx = JS_CallConstructor(ctx, ctx->regexp_ctor, args_len, args); + JS_FreeValue(ctx, str); if (JS_IsException(rx)) { + fail: JS_FreeValue(ctx, S); return JS_EXCEPTION; } @@ -36997,6 +37369,7 @@ static const JSCFunctionListEntry js_string_proto_funcs[] = { JS_CFUNC_MAGIC_DEF("endsWith", 1, js_string_includes, 2 ), JS_CFUNC_MAGIC_DEF("startsWith", 1, js_string_includes, 1 ), JS_CFUNC_MAGIC_DEF("match", 1, js_string_match, JS_ATOM_Symbol_match ), + JS_CFUNC_MAGIC_DEF("matchAll", 1, js_string_match, JS_ATOM_Symbol_matchAll ), JS_CFUNC_MAGIC_DEF("search", 1, js_string_match, JS_ATOM_Symbol_search ), JS_CFUNC_DEF("split", 2, js_string_split ), JS_CFUNC_DEF("substring", 2, js_string_substring ), @@ -38560,6 +38933,156 @@ static JSValue js_regexp_Symbol_match(JSContext *ctx, JSValueConst this_val, return JS_EXCEPTION; } +typedef struct JSRegExpStringIteratorData { + JSValue iterating_regexp; + JSValue iterated_string; + BOOL global; + BOOL unicode; + BOOL done; +} JSRegExpStringIteratorData; + +static void js_regexp_string_iterator_finalizer(JSRuntime *rt, JSValue val) +{ + JSObject *p = JS_VALUE_GET_OBJ(val); + JSRegExpStringIteratorData *it = p->u.regexp_string_iterator_data; + if (it) { + JS_FreeValueRT(rt, it->iterating_regexp); + JS_FreeValueRT(rt, it->iterated_string); + js_free_rt(rt, it); + } +} + +static void js_regexp_string_iterator_mark(JSRuntime *rt, JSValueConst val, + JS_MarkFunc *mark_func) +{ + JSObject *p = JS_VALUE_GET_OBJ(val); + JSRegExpStringIteratorData *it = p->u.regexp_string_iterator_data; + if (it) { + JS_MarkValue(rt, it->iterating_regexp, mark_func); + JS_MarkValue(rt, it->iterated_string, mark_func); + } +} + +static JSValue js_regexp_string_iterator_next(JSContext *ctx, + JSValueConst this_val, + int argc, JSValueConst *argv, + BOOL *pdone, int magic) +{ + JSRegExpStringIteratorData *it; + JSValueConst R, S; + JSValue matchStr = JS_UNDEFINED, match = JS_UNDEFINED; + JSString *sp; + + it = JS_GetOpaque2(ctx, this_val, JS_CLASS_REGEXP_STRING_ITERATOR); + if (!it) + goto exception; + if (it->done) { + *pdone = TRUE; + return JS_UNDEFINED; + } + R = it->iterating_regexp; + S = it->iterated_string; + match = JS_RegExpExec(ctx, R, S); + if (JS_IsException(match)) + goto exception; + if (JS_IsNull(match)) { + it->done = TRUE; + *pdone = TRUE; + return JS_UNDEFINED; + } else if (it->global) { + matchStr = JS_ToStringFree(ctx, JS_GetPropertyInt64(ctx, match, 0)); + if (JS_IsException(matchStr)) + goto exception; + if (JS_IsEmptyString(matchStr)) { + int64_t thisIndex, nextIndex; + if (JS_ToLengthFree(ctx, &thisIndex, + JS_GetProperty(ctx, R, JS_ATOM_lastIndex)) < 0) + goto exception; + sp = JS_VALUE_GET_STRING(S); + nextIndex = string_advance_index(sp, thisIndex, it->unicode); + if (JS_SetProperty(ctx, R, JS_ATOM_lastIndex, + JS_NewInt32(ctx, nextIndex)) < 0) + goto exception; + } + JS_FreeValue(ctx, matchStr); + } else { + it->done = TRUE; + } + *pdone = FALSE; + return match; + exception: + JS_FreeValue(ctx, match); + JS_FreeValue(ctx, matchStr); + *pdone = FALSE; + return JS_EXCEPTION; +} + +static JSValue js_regexp_Symbol_matchAll(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + // [Symbol.matchAll](str) + JSValueConst R = this_val; + JSValue S, C, flags, matcher, iter; + JSValueConst args[2]; + JSString *strp; + int64_t lastIndex; + JSRegExpStringIteratorData *it; + + if (!JS_IsObject(R)) + return JS_ThrowTypeErrorNotAnObject(ctx); + + C = JS_UNDEFINED; + flags = JS_UNDEFINED; + matcher = JS_UNDEFINED; + iter = JS_UNDEFINED; + + S = JS_ToString(ctx, argv[0]); + if (JS_IsException(S)) + goto exception; + C = JS_SpeciesConstructor(ctx, R, ctx->regexp_ctor); + if (JS_IsException(C)) + goto exception; + flags = JS_ToStringFree(ctx, JS_GetProperty(ctx, R, JS_ATOM_flags)); + if (JS_IsException(flags)) + goto exception; + args[0] = R; + args[1] = flags; + matcher = JS_CallConstructor(ctx, C, 2, args); + if (JS_IsException(matcher)) + goto exception; + if (JS_ToLengthFree(ctx, &lastIndex, + JS_GetProperty(ctx, R, JS_ATOM_lastIndex))) + goto exception; + if (JS_SetProperty(ctx, matcher, JS_ATOM_lastIndex, + JS_NewInt32(ctx, lastIndex)) < 0) + goto exception; + + iter = JS_NewObjectClass(ctx, JS_CLASS_REGEXP_STRING_ITERATOR); + if (JS_IsException(iter)) + goto exception; + it = js_malloc(ctx, sizeof(*it)); + if (!it) + goto exception; + it->iterating_regexp = matcher; + it->iterated_string = S; + strp = JS_VALUE_GET_STRING(flags); + it->global = string_indexof_char(strp, 'g', 0) >= 0; + it->unicode = string_indexof_char(strp, 'u', 0) >= 0; + it->done = FALSE; + JS_SetOpaque(iter, it); + + JS_FreeValue(ctx, C); + JS_FreeValue(ctx, flags); + return iter; + exception: + JS_FreeValue(ctx, S); + JS_FreeValue(ctx, C); + JS_FreeValue(ctx, flags); + JS_FreeValue(ctx, matcher); + JS_FreeValue(ctx, iter); + return JS_EXCEPTION; +} + typedef struct ValueBuffer { JSContext *ctx; JSValue *arr; @@ -39016,12 +39539,18 @@ static const JSCFunctionListEntry js_regexp_proto_funcs[] = { JS_CFUNC_DEF("toString", 0, js_regexp_toString ), JS_CFUNC_DEF("[Symbol.replace]", 2, js_regexp_Symbol_replace ), JS_CFUNC_DEF("[Symbol.match]", 1, js_regexp_Symbol_match ), + JS_CFUNC_DEF("[Symbol.matchAll]", 1, js_regexp_Symbol_matchAll ), JS_CFUNC_DEF("[Symbol.search]", 1, js_regexp_Symbol_search ), JS_CFUNC_DEF("[Symbol.split]", 2, js_regexp_Symbol_split ), //JS_CGETSET_DEF("__source", js_regexp_get___source, NULL ), //JS_CGETSET_DEF("__flags", js_regexp_get___flags, NULL ), }; +static const JSCFunctionListEntry js_regexp_string_iterator_proto_funcs[] = { + JS_ITERATOR_NEXT_DEF("next", 0, js_regexp_string_iterator_next, 0 ), + JS_PROP_STRING_DEF("[Symbol.toStringTag]", "RegExp String Iterator", JS_PROP_CONFIGURABLE ), +}; + void JS_AddIntrinsicRegExpCompiler(JSContext *ctx) { ctx->compile_regexp = js_compile_regexp; @@ -39040,6 +39569,12 @@ void JS_AddIntrinsicRegExp(JSContext *ctx) ctx->class_proto[JS_CLASS_REGEXP]); ctx->regexp_ctor = JS_DupValue(ctx, obj); JS_SetPropertyFunctionList(ctx, obj, js_regexp_funcs, countof(js_regexp_funcs)); + + ctx->class_proto[JS_CLASS_REGEXP_STRING_ITERATOR] = + JS_NewObjectProto(ctx, ctx->iterator_proto); + JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_REGEXP_STRING_ITERATOR], + js_regexp_string_iterator_proto_funcs, + countof(js_regexp_string_iterator_proto_funcs)); } /* JSON */ @@ -42124,6 +42659,11 @@ static JSValue js_new_promise_capability(JSContext *ctx, return JS_EXCEPTION; } +JSValue JS_NewPromiseCapability(JSContext *ctx, JSValue *resolving_funcs) +{ + return js_new_promise_capability(ctx, resolving_funcs, JS_UNDEFINED); +} + static JSValue js_promise_resolve(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic) { @@ -42157,6 +42697,7 @@ static JSValue js_promise_resolve(JSContext *ctx, JSValueConst this_val, return result_promise; } +#if 0 static JSValue js_promise___newPromiseCapability(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) @@ -42181,6 +42722,7 @@ static JSValue js_promise___newPromiseCapability(JSContext *ctx, JS_DefinePropertyValue(ctx, obj, JS_ATOM_reject, resolving_funcs[1], JS_PROP_C_W_E); return obj; } +#endif static __exception int remainingElementsCount_add(JSContext *ctx, JSValueConst resolve_element_env, @@ -42207,22 +42749,47 @@ static JSValue js_promise_all_resolve_element(JSContext *ctx, int magic, JSValue *func_data) { + int is_allSettled = magic & 1; + int is_reject = magic & 2; BOOL alreadyCalled = JS_ToBool(ctx, func_data[0]); JSValueConst values = func_data[2]; JSValueConst resolve = func_data[3]; JSValueConst resolve_element_env = func_data[4]; - JSValue ret; + JSValue ret, obj; int is_zero, index; - + if (JS_ToInt32(ctx, &index, func_data[1])) return JS_EXCEPTION; if (alreadyCalled) return JS_UNDEFINED; func_data[0] = JS_NewBool(ctx, TRUE); + if (is_allSettled) { + JSValue str; + + obj = JS_NewObject(ctx); + if (JS_IsException(obj)) + return JS_EXCEPTION; + str = JS_NewString(ctx, is_reject ? "rejected" : "fulfilled"); + if (JS_IsException(str)) + goto fail1; + if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_status, + str, + JS_PROP_C_W_E) < 0) + goto fail1; + if (JS_DefinePropertyValue(ctx, obj, + is_reject ? JS_ATOM_reason : JS_ATOM_value, + JS_DupValue(ctx, argv[0]), + JS_PROP_C_W_E) < 0) { + fail1: + JS_FreeValue(ctx, obj); + return JS_EXCEPTION; + } + } else { + obj = JS_DupValue(ctx, argv[0]); + } if (JS_DefinePropertyValueUint32(ctx, values, index, - JS_DupValue(ctx, argv[0]), - JS_PROP_CONFIGURABLE | JS_PROP_ENUMERABLE | JS_PROP_WRITABLE) < 0) + obj, JS_PROP_C_W_E) < 0) return JS_EXCEPTION; is_zero = remainingElementsCount_add(ctx, resolve_element_env, -1); @@ -42237,15 +42804,16 @@ static JSValue js_promise_all_resolve_element(JSContext *ctx, return JS_UNDEFINED; } +/* magic = 0: Promise.all 1: Promise.allSettled */ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) + int argc, JSValueConst *argv, int magic) { JSValue result_promise, resolving_funcs[2], iter, item, next_promise, ret; JSValue next_method = JS_UNDEFINED, values = JS_UNDEFINED; - JSValue resolve_element_env = JS_UNDEFINED, resolve_element; + JSValue resolve_element_env = JS_UNDEFINED, resolve_element, reject_element; JSValue promise_resolve = JS_UNDEFINED; JSValueConst then_args[2], resolve_element_data[5]; - BOOL done; + BOOL done, is_allSettled = magic; int index, is_zero; if (!JS_IsObject(this_val)) @@ -42309,22 +42877,36 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val, resolve_element_data[4] = resolve_element_env; resolve_element = JS_NewCFunctionData(ctx, js_promise_all_resolve_element, 1, - 0, 5, resolve_element_data); + is_allSettled, 5, resolve_element_data); if (JS_IsException(resolve_element)) { JS_FreeValue(ctx, next_promise); goto fail_reject1; } + if (is_allSettled) { + reject_element = + JS_NewCFunctionData(ctx, js_promise_all_resolve_element, 1, + is_allSettled | 2, 5, resolve_element_data); + if (JS_IsException(reject_element)) { + JS_FreeValue(ctx, next_promise); + goto fail_reject1; + } + } else { + reject_element = JS_DupValue(ctx, resolving_funcs[1]); + } + if (remainingElementsCount_add(ctx, resolve_element_env, 1) < 0) { JS_FreeValue(ctx, next_promise); JS_FreeValue(ctx, resolve_element); + JS_FreeValue(ctx, reject_element); goto fail_reject1; } then_args[0] = resolve_element; - then_args[1] = resolving_funcs[1]; + then_args[1] = reject_element; ret = JS_InvokeFree(ctx, next_promise, JS_ATOM_then, 2, then_args); JS_FreeValue(ctx, resolve_element); + JS_FreeValue(ctx, reject_element); if (check_exception_free(ctx, ret)) goto fail_reject1; index++; @@ -42605,9 +43187,10 @@ static JSValue js_promise_finally(JSContext *ctx, JSValueConst this_val, static const JSCFunctionListEntry js_promise_funcs[] = { JS_CFUNC_MAGIC_DEF("resolve", 1, js_promise_resolve, 0 ), JS_CFUNC_MAGIC_DEF("reject", 1, js_promise_resolve, 1 ), - JS_CFUNC_DEF("all", 1, js_promise_all ), + JS_CFUNC_MAGIC_DEF("all", 1, js_promise_all, 0 ), + JS_CFUNC_MAGIC_DEF("allSettled", 1, js_promise_all, 1 ), JS_CFUNC_DEF("race", 1, js_promise_race ), - JS_CFUNC_DEF("__newPromiseCapability", 1, js_promise___newPromiseCapability ), + //JS_CFUNC_DEF("__newPromiseCapability", 1, js_promise___newPromiseCapability ), JS_CGETSET_DEF("[Symbol.species]", js_get_this, NULL), }; @@ -42682,7 +43265,7 @@ static void js_async_from_sync_iterator_mark(JSRuntime *rt, JSValueConst val, static JSValue JS_CreateAsyncFromSyncIterator(JSContext *ctx, JSValueConst sync_iter) { - JSValue async_iter, ret, next_method; + JSValue async_iter, next_method; JSAsyncFromSyncIteratorData *s; next_method = JS_GetProperty(ctx, sync_iter, JS_ATOM_next); @@ -42702,10 +43285,7 @@ static JSValue JS_CreateAsyncFromSyncIterator(JSContext *ctx, s->sync_iter = JS_DupValue(ctx, sync_iter); s->next_method = next_method; JS_SetOpaque(async_iter, s); - - ret = JS_GetIterator(ctx, async_iter, TRUE); - JS_FreeValue(ctx, async_iter); - return ret; + return async_iter; } static JSValue js_async_from_sync_iterator_next(JSContext *ctx, JSValueConst this_val, @@ -42717,7 +43297,7 @@ static JSValue js_async_from_sync_iterator_next(JSContext *ctx, JSValueConst thi int done; int is_reject; - promise = js_new_promise_capability(ctx, resolving_funcs, JS_UNDEFINED); + promise = JS_NewPromiseCapability(ctx, resolving_funcs); if (JS_IsException(promise)) return JS_EXCEPTION; s = JS_GetOpaque(this_val, JS_CLASS_ASYNC_FROM_SYNC_ITERATOR); @@ -42772,24 +43352,15 @@ static JSValue js_async_from_sync_iterator_next(JSContext *ctx, JSValueConst thi return promise; } { - JSValue value_wrapper_resolving_funcs[2], value_wrapper_promise; - JSValue resolve_reject[2], ret; + JSValue value_wrapper_promise, resolve_reject[2]; int res; - value_wrapper_promise = - js_new_promise_capability(ctx, value_wrapper_resolving_funcs, JS_UNDEFINED); - if (JS_IsException(value_wrapper_promise)) - goto fail; - - ret = JS_Call(ctx, value_wrapper_resolving_funcs[0], JS_UNDEFINED, 1, - (JSValueConst *)&value); - JS_FreeValue(ctx, value_wrapper_resolving_funcs[0]); - JS_FreeValue(ctx, value_wrapper_resolving_funcs[1]); - if (JS_IsException(ret)) { - JS_FreeValue(ctx, value_wrapper_promise); - goto fail; + value_wrapper_promise = js_promise_resolve(ctx, ctx->promise_ctor, + 1, (JSValueConst *)&value, 0); + if (JS_IsException(value_wrapper_promise)) { + JS_FreeValue(ctx, value); + goto reject; } - JS_FreeValue(ctx, ret); resolve_reject[0] = js_async_from_async_iterator_unwrap_func_create(ctx, value, done); if (JS_IsException(resolve_reject[0])) { @@ -42821,7 +43392,6 @@ static JSValue js_async_from_sync_iterator_next(JSContext *ctx, JSValueConst thi } static const JSCFunctionListEntry js_async_from_sync_iterator_proto_funcs[] = { - JS_PROP_STRING_DEF("[Symbol.toStringTag]", "Async-from-Sync Iterator", JS_PROP_CONFIGURABLE ), JS_CFUNC_MAGIC_DEF("next", 1, js_async_from_sync_iterator_next, GEN_MAGIC_NEXT ), JS_CFUNC_MAGIC_DEF("return", 1, js_async_from_sync_iterator_next, GEN_MAGIC_RETURN ), JS_CFUNC_MAGIC_DEF("throw", 1, js_async_from_sync_iterator_next, GEN_MAGIC_THROW ), @@ -42877,6 +43447,7 @@ void JS_AddIntrinsicPromise(JSContext *ctx) countof(js_promise_proto_funcs)); obj1 = JS_NewCFunction2(ctx, js_promise_constructor, "Promise", 1, JS_CFUNC_constructor, 0); + ctx->promise_ctor = JS_DupValue(ctx, obj1); JS_SetPropertyFunctionList(ctx, obj1, js_promise_funcs, countof(js_promise_funcs)); @@ -47428,7 +47999,7 @@ typedef enum AtomicsOpEnum { static void *js_atomics_get_ptr(JSContext *ctx, int *psize_log2, JSClassID *pclass_id, JSValueConst obj, JSValueConst idx_val, - BOOL is_int32_array) + BOOL is_waitable) { JSObject *p; JSTypedArray *ta; @@ -47441,11 +48012,20 @@ static void *js_atomics_get_ptr(JSContext *ctx, if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) goto fail; p = JS_VALUE_GET_OBJ(obj); - if (is_int32_array) +#ifdef CONFIG_BIGNUM + if (is_waitable) + err = (p->class_id != JS_CLASS_INT32_ARRAY && + p->class_id != JS_CLASS_BIG_INT64_ARRAY); + else + err = !(p->class_id >= JS_CLASS_INT8_ARRAY && + p->class_id <= JS_CLASS_BIG_UINT64_ARRAY); +#else + if (is_waitable) err = (p->class_id != JS_CLASS_INT32_ARRAY); else err = !(p->class_id >= JS_CLASS_INT8_ARRAY && p->class_id <= JS_CLASS_UINT32_ARRAY); +#endif if (err) { fail: JS_ThrowTypeError(ctx, "integer TypedArray expected"); @@ -47478,7 +48058,11 @@ static JSValue js_atomics_op(JSContext *ctx, int argc, JSValueConst *argv, int op) { int size_log2; +#ifdef CONFIG_BIGNUM + uint64_t v, a, rep_val; +#else uint32_t v, a, rep_val; +#endif void *ptr; JSValue ret; JSClassID class_id; @@ -47490,16 +48074,34 @@ static JSValue js_atomics_op(JSContext *ctx, rep_val = 0; if (op == ATOMICS_OP_LOAD) { v = 0; - } else { - if (JS_ToUint32(ctx, &v, argv[2])) - return JS_EXCEPTION; - if (op == ATOMICS_OP_COMPARE_EXCHANGE) { - if (JS_ToUint32(ctx, &rep_val, argv[3])) + } else +#ifdef CONFIG_BIGNUM + if (size_log2 == 3) { + int64_t v64; + if (JS_ToBigInt64(ctx, &v64, argv[2])) return JS_EXCEPTION; - } - } - switch(op | (size_log2 << 3)) { - + v = v64; + if (op == ATOMICS_OP_COMPARE_EXCHANGE) { + if (JS_ToBigInt64(ctx, &v64, argv[3])) + return JS_EXCEPTION; + rep_val = v64; + } + } else +#endif + { + uint32_t v32; + if (JS_ToUint32(ctx, &v32, argv[2])) + return JS_EXCEPTION; + v = v32; + if (op == ATOMICS_OP_COMPARE_EXCHANGE) { + if (JS_ToUint32(ctx, &v32, argv[3])) + return JS_EXCEPTION; + rep_val = v32; + } + } + switch(op | (size_log2 << 3)) { + +#ifdef CONFIG_BIGNUM #define OP(op_name, func_name) \ case ATOMICS_OP_ ## op_name | (0 << 3): \ a = func_name((_Atomic(uint8_t) *)ptr, v); \ @@ -47509,8 +48111,22 @@ static JSValue js_atomics_op(JSContext *ctx, break; \ case ATOMICS_OP_ ## op_name | (2 << 3): \ a = func_name((_Atomic(uint32_t) *)ptr, v); \ + break; \ + case ATOMICS_OP_ ## op_name | (3 << 3): \ + a = func_name((_Atomic(uint64_t) *)ptr, v); \ break; - +#else +#define OP(op_name, func_name) \ + case ATOMICS_OP_ ## op_name | (0 << 3): \ + a = func_name((_Atomic(uint8_t) *)ptr, v); \ + break; \ + case ATOMICS_OP_ ## op_name | (1 << 3): \ + a = func_name((_Atomic(uint16_t) *)ptr, v); \ + break; \ + case ATOMICS_OP_ ## op_name | (2 << 3): \ + a = func_name((_Atomic(uint32_t) *)ptr, v); \ + break; +#endif OP(ADD, atomic_fetch_add) OP(AND, atomic_fetch_and) OP(OR, atomic_fetch_or) @@ -47528,7 +48144,12 @@ static JSValue js_atomics_op(JSContext *ctx, case ATOMICS_OP_LOAD | (2 << 3): a = atomic_load((_Atomic(uint32_t) *)ptr); break; - +#ifdef CONFIG_BIGNUM + case ATOMICS_OP_LOAD | (3 << 3): + a = atomic_load((_Atomic(uint64_t) *)ptr); + break; +#endif + case ATOMICS_OP_COMPARE_EXCHANGE | (0 << 3): { uint8_t v1 = v; @@ -47550,9 +48171,19 @@ static JSValue js_atomics_op(JSContext *ctx, a = v1; } break; +#ifdef CONFIG_BIGNUM + case ATOMICS_OP_COMPARE_EXCHANGE | (3 << 3): + { + uint64_t v1 = v; + atomic_compare_exchange_strong((_Atomic(uint64_t) *)ptr, &v1, rep_val); + a = v1; + } + break; +#endif default: abort(); } + switch(class_id) { case JS_CLASS_INT8_ARRAY: a = (int8_t)a; @@ -47573,6 +48204,14 @@ static JSValue js_atomics_op(JSContext *ctx, case JS_CLASS_UINT32_ARRAY: ret = JS_NewUint32(ctx, a); break; +#ifdef CONFIG_BIGNUM + case JS_CLASS_BIG_INT64_ARRAY: + ret = JS_NewBigInt64(ctx, a); + break; + case JS_CLASS_BIG_UINT64_ARRAY: + ret = JS_NewBigUint64(ctx, a); + break; +#endif default: abort(); } @@ -47584,33 +48223,48 @@ static JSValue js_atomics_store(JSContext *ctx, int argc, JSValueConst *argv) { int size_log2; - uint32_t v; void *ptr; JSValue ret; ptr = js_atomics_get_ptr(ctx, &size_log2, NULL, argv[0], argv[1], FALSE); if (!ptr) return JS_EXCEPTION; - /* XXX: spec, would be simpler to return the written value */ - ret = JS_ToIntegerFree(ctx, JS_DupValue(ctx, argv[2])); - if (JS_IsException(ret)) - return ret; - if (JS_ToUint32(ctx, &v, ret)) { - JS_FreeValue(ctx, ret); - return JS_EXCEPTION; - } - switch(size_log2) { - case 0: - atomic_store((_Atomic(uint8_t) *)ptr, v); - break; - case 1: - atomic_store((_Atomic(uint16_t) *)ptr, v); - break; - case 2: - atomic_store((_Atomic(uint32_t) *)ptr, v); - break; - default: - abort(); +#ifdef CONFIG_BIGNUM + if (size_log2 == 3) { + int64_t v64; + ret = JS_ToBigIntValueFree(ctx, JS_DupValue(ctx, argv[2])); + if (JS_IsException(ret)) + return ret; + if (JS_ToBigInt64(ctx, &v64, ret)) { + JS_FreeValue(ctx, ret); + return JS_EXCEPTION; + } + atomic_store((_Atomic(uint64_t) *)ptr, v64); + } else +#endif + { + uint32_t v; + /* XXX: spec, would be simpler to return the written value */ + ret = JS_ToIntegerFree(ctx, JS_DupValue(ctx, argv[2])); + if (JS_IsException(ret)) + return ret; + if (JS_ToUint32(ctx, &v, ret)) { + JS_FreeValue(ctx, ret); + return JS_EXCEPTION; + } + switch(size_log2) { + case 0: + atomic_store((_Atomic(uint8_t) *)ptr, v); + break; + case 1: + atomic_store((_Atomic(uint16_t) *)ptr, v); + break; + case 2: + atomic_store((_Atomic(uint32_t) *)ptr, v); + break; + default: + abort(); + } } return ret; } @@ -47622,7 +48276,11 @@ static JSValue js_atomics_isLockFree(JSContext *ctx, int v, ret; if (JS_ToInt32Sat(ctx, &v, argv[0])) return JS_EXCEPTION; - ret = (v == 1 || v == 2 || v == 4); + ret = (v == 1 || v == 2 || v == 4 +#ifdef CONFIG_BIGNUM + || v == 8 +#endif + ); return JS_NewBool(ctx, ret); } @@ -47641,18 +48299,29 @@ static JSValue js_atomics_wait(JSContext *ctx, JSValueConst this_obj, int argc, JSValueConst *argv) { - int32_t v, *ptr; + int64_t v; + int32_t v32; + void *ptr; int64_t timeout; struct timespec ts; JSAtomicsWaiter waiter_s, *waiter; - int ret; + int ret, size_log2, res; double d; - ptr = js_atomics_get_ptr(ctx, NULL, NULL, argv[0], argv[1], TRUE); + ptr = js_atomics_get_ptr(ctx, &size_log2, NULL, argv[0], argv[1], TRUE); if (!ptr) return JS_EXCEPTION; - if (JS_ToInt32(ctx, &v, argv[2])) - return JS_EXCEPTION; +#ifdef CONFIG_BIGNUM + if (size_log2 == 3) { + if (JS_ToBigInt64(ctx, &v, argv[2])) + return JS_EXCEPTION; + } else +#endif + { + if (JS_ToInt32(ctx, &v32, argv[2])) + return JS_EXCEPTION; + v = v32; + } if (JS_ToFloat64(ctx, &d, argv[3])) return JS_EXCEPTION; if (isnan(d) || d > INT64_MAX) @@ -47668,7 +48337,12 @@ static JSValue js_atomics_wait(JSContext *ctx, 'ptr' value */ /* XXX: use Linux futexes when available ? */ pthread_mutex_lock(&js_atomics_mutex); - if (*ptr != v) { + if (size_log2 == 3) { + res = *(int64_t *)ptr != v; + } else { + res = *(int32_t *)ptr != v; + } + if (res) { pthread_mutex_unlock(&js_atomics_mutex); return JS_AtomToString(ctx, JS_ATOM_not_equal); } @@ -47710,7 +48384,8 @@ static JSValue js_atomics_notify(JSContext *ctx, int argc, JSValueConst *argv) { struct list_head *el, *el1, waiter_list; - int32_t count, n, *ptr; + int32_t count, n; + void *ptr; JSAtomicsWaiter *waiter; ptr = js_atomics_get_ptr(ctx, NULL, NULL, argv[0], argv[1], TRUE); diff --git a/quickjs/quickjs.h b/quickjs/quickjs.h index 4cb62b5f8a..6b863be360 100644 --- a/quickjs/quickjs.h +++ b/quickjs/quickjs.h @@ -278,7 +278,6 @@ static inline JSValue __JS_NewFloat64(JSContext *ctx, double d) #define JS_EVAL_TYPE_INDIRECT (3 << 0) /* indirect call (internal use) */ #define JS_EVAL_TYPE_MASK (3 << 0) -#define JS_EVAL_FLAG_SHEBANG (1 << 2) /* skip first line beginning with '#!' */ #define JS_EVAL_FLAG_STRICT (1 << 3) /* force 'strict' mode */ #define JS_EVAL_FLAG_STRIP (1 << 4) /* force 'strip' mode */ #define JS_EVAL_FLAG_COMPILE_ONLY (1 << 5) /* internal use */ @@ -704,6 +703,8 @@ JSValue JS_NewArrayBufferCopy(JSContext *ctx, const uint8_t *buf, size_t len); void JS_DetachArrayBuffer(JSContext *ctx, JSValueConst obj); uint8_t *JS_GetArrayBuffer(JSContext *ctx, size_t *psize, JSValueConst obj); +JSValue JS_NewPromiseCapability(JSContext *ctx, JSValue *resolving_funcs); + /* return != 0 if the JS code needs to be interrupted */ typedef int JSInterruptHandler(JSRuntime *rt, void *opaque); void JS_SetInterruptHandler(JSRuntime *rt, JSInterruptHandler *cb, void *opaque); From b4f7f0a49da95e89eab5bcef8c13bdb9d944abbf Mon Sep 17 00:00:00 2001 From: ftk Date: Tue, 30 Jul 2019 16:06:48 +0000 Subject: [PATCH 009/185] support const class member functions --- main.cpp | 12 ++++-------- quickjspp.hpp | 12 ++++++++++++ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/main.cpp b/main.cpp index 8618f5af5d..46445b404d 100644 --- a/main.cpp +++ b/main.cpp @@ -8,10 +8,6 @@ #include #include -int32_t f(int32_t x) -{ - return x * x; -}; #define TYPES bool, int32_t, double, std::shared_ptr, const std::shared_ptr&, std::string, const std::string& @@ -19,7 +15,7 @@ class test { public: bool b; - int32_t i; + mutable int32_t i; double d; std::shared_ptr spt; std::string s; @@ -35,9 +31,9 @@ class test ~test() { printf("dtor!\n"); } - int32_t fi(TYPES) { i++; return i; } - bool fb(TYPES) { i++; return b; } - double fd(TYPES) { i++; return d; } + int32_t fi(TYPES) const { i++; return i; } + bool fb(TYPES) noexcept { i++; return b; } + double fd(TYPES) const noexcept { i++; return d; } const std::shared_ptr& fspt(TYPES) { i++; return spt; } const std::string& fs(TYPES) { i++; return s; } void f(TYPES) { i++; } diff --git a/quickjspp.hpp b/quickjspp.hpp index 6b25e3f697..b7f63da42a 100644 --- a/quickjspp.hpp +++ b/quickjspp.hpp @@ -319,6 +319,18 @@ namespace qjs { } }; + template + struct js_traits> + { + static JSValue wrap(JSContext * ctx, fwrapper fw) noexcept + { + return JS_NewCFunction(ctx, [](JSContext * ctx, JSValueConst this_value, int argc, + JSValueConst * argv) noexcept -> JSValue { + return wrap_this_call, Args...>(ctx, F, this_value, argv); + }, fw.name, sizeof...(Args)); + + } + }; // class constructor From f9b1acfb9bfd250192f6efe5613dead074278ec4 Mon Sep 17 00:00:00 2001 From: ftk Date: Mon, 5 Aug 2019 13:04:42 +0300 Subject: [PATCH 010/185] dont define setter for const class member variable --- main.cpp | 2 +- quickjspp.hpp | 36 ++++++++++++++++++++++++++---------- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/main.cpp b/main.cpp index 46445b404d..002c340f25 100644 --- a/main.cpp +++ b/main.cpp @@ -16,7 +16,7 @@ class test public: bool b; mutable int32_t i; - double d; + const double d = 7.; std::shared_ptr spt; std::string s; diff --git a/quickjspp.hpp b/quickjspp.hpp index b7f63da42a..8ac6cac051 100644 --- a/quickjspp.hpp +++ b/quickjspp.hpp @@ -5,13 +5,15 @@ extern "C" { #include "quickjs/quickjs-libc.h" } -#include -#include -#include -#include +#include +#include +#include #include #include #include +#include +#include +#include namespace qjs { @@ -547,6 +549,8 @@ namespace qjs { template struct get_set { + using is_const = std::is_const; + static const R& get(const std::shared_ptr& ptr) { return *ptr.*M; @@ -643,12 +647,24 @@ namespace qjs { { auto prop = JS_NewAtom(ctx, name); using fgetter = detail::fwrapper::get, true>; - using fsetter = detail::fwrapper::set, true>; - int ret = JS_DefinePropertyGetSet(ctx, v, prop, - detail::js_traits::wrap(ctx, fgetter{name}), - detail::js_traits::wrap(ctx, fsetter{name}), - JS_PROP_WRITABLE // ? - ); + int ret; + if constexpr (detail::get_set::is_const::value) + { + ret = JS_DefinePropertyGetSet(ctx, v, prop, + detail::js_traits::wrap(ctx, fgetter{name}), + JS_UNDEFINED, + 0 // ? + ); + } + else + { + using fsetter = detail::fwrapper::set, true>; + ret = JS_DefinePropertyGetSet(ctx, v, prop, + detail::js_traits::wrap(ctx, fgetter{name}), + detail::js_traits::wrap(ctx, fsetter{name}), + JS_PROP_WRITABLE // ? + ); + } JS_FreeAtom(ctx, prop); if(ret < 0) throw detail::exception{}; From cf61b2c735c53ae440fb59053cdff8372cb2ca0a Mon Sep 17 00:00:00 2001 From: ftk Date: Sat, 10 Aug 2019 13:33:44 +0300 Subject: [PATCH 011/185] fix crash if added module is not loaded --- quickjspp.hpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/quickjspp.hpp b/quickjspp.hpp index 8ac6cac051..aefdc72864 100644 --- a/quickjspp.hpp +++ b/quickjspp.hpp @@ -701,7 +701,7 @@ namespace qjs { public: JSContext * ctx; - private: + //private: class Module { friend class Context; @@ -710,7 +710,7 @@ namespace qjs { JSContext * ctx; const char * name; - using nvp = std::pair; + using nvp = std::pair; std::vector> exports; public: Module(JSContext * ctx, const char * name) : ctx(ctx), name(name), exports(JS_GetRuntime(ctx)) @@ -719,13 +719,13 @@ namespace qjs { auto context = reinterpret_cast(JS_GetContextOpaque(ctx)); if(!context) return -1; - auto it = std::find_if(context->modules.cbegin(), context->modules.cend(), + auto it = std::find_if(context->modules.begin(), context->modules.end(), [m](const Module& module) { return module.m == m; }); if(it == context->modules.end()) return -1; for(const auto& e : it->exports) { - if(JS_SetModuleExport(ctx, m, e.first, e.second) != 0) + if(JS_SetModuleExport(ctx, m, e.first, JS_DupValue(ctx, e.second.v)) != 0) return -1; } return 0; @@ -736,14 +736,17 @@ namespace qjs { Module& add(const char * name, JSValue value) { - exports.push_back({name, value}); + exports.push_back({name, {ctx, value}}); JS_AddModuleExport(ctx, m, name); return *this; } Module& add(const char * name, Value value) { - return add(name, value.release()); + assert(value.ctx == ctx); + exports.push_back({name, std::move(value)}); + JS_AddModuleExport(ctx, m, name); + return *this; } template @@ -785,6 +788,7 @@ namespace qjs { ~Context() { + modules.clear(); JS_FreeContext(ctx); } From f3f4d6a41a1df489dfc24a19391bfad236f99f1e Mon Sep 17 00:00:00 2001 From: ftk Date: Sat, 10 Aug 2019 10:37:54 +0000 Subject: [PATCH 012/185] add class and function register helpers to module --- quickjspp.hpp | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/quickjspp.hpp b/quickjspp.hpp index aefdc72864..cf51a621d2 100644 --- a/quickjspp.hpp +++ b/quickjspp.hpp @@ -758,6 +758,75 @@ namespace qjs { Module(const Module&) = delete; Module(Module&&) = default; //Module& operator=(Module&&) = default; + + + // function wrappers + template + Module& function(const char * name) + { + return add(name, qjs::detail::fwrapper{name}); + } + template + Module& function(const char * name, F&& f) + { + return add(name, detail::js_traits(f)})>::wrap(std::forward(f))); + } + + // class register wrapper + private: + template + class class_registrar + { + const char * name; + qjs::Value prototype; + qjs::Context::Module& module; + qjs::Context& context; + public: + explicit class_registrar(const char * name, qjs::Context::Module& module, qjs::Context& context) : + name(name), + prototype(context.newObject()), + module(module), + context(context) + { + } + + class_registrar(const class_registrar&) = delete; + + template + class_registrar& fun(const char * name, F&& f) + { + prototype.add(name, std::forward(f)); + return *this; + } + + template + class_registrar& fun(const char * name) + { + prototype.add(name); + return *this; + } + + template + class_registrar& constructor(const char * name = nullptr) + { + if(!name) + name = this->name; + module.add(name, qjs::detail::ctor_wrapper{name}); + return *this; + } + + ~class_registrar() + { + context.registerClass(name, std::move(prototype)); + } + }; + public: + template + class_registrar class_(const char * name) + { + return class_registrar{name, *this, *reinterpret_cast(JS_GetContextOpaque(ctx))}; + } + }; std::vector> modules; From 8908c0a474e493ce77b71a5cae465246290d7378 Mon Sep 17 00:00:00 2001 From: ftk Date: Sat, 10 Aug 2019 13:39:17 +0300 Subject: [PATCH 013/185] T * wrappers --- quickjspp.hpp | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/quickjspp.hpp b/quickjspp.hpp index cf51a621d2..e91196022e 100644 --- a/quickjspp.hpp +++ b/quickjspp.hpp @@ -413,6 +413,37 @@ namespace qjs { } }; + // T * - non-owning pointer + template + struct js_traits + { + static JSValue wrap(JSContext * ctx, T * ptr) + { + if(js_traits>::QJSClassId == 0) // not registered + throw exception{}; + auto jsobj = JS_NewObjectClass(ctx, js_traits>::QJSClassId); + if(JS_IsException(jsobj)) + { + return jsobj; + } + //auto pptr = new std::shared_ptr(ptr, [](T *){}); + auto alloc = allocator>{ctx}; + using atraits = std::allocator_traits; + auto pptr = atraits::allocate(alloc, 1); + atraits::construct(alloc, pptr, ptr, [](T *){}); // shared_ptr with empty deleter + + JS_SetOpaque(jsobj, pptr); + return jsobj; + } + + static T * unwrap(JSContext * ctx, JSValueConst v) + { + auto ptr = reinterpret_cast *>(JS_GetOpaque2(ctx, v, js_traits>::QJSClassId)); + if(!ptr) + throw exception{}; + return ptr->get(); + } + }; struct function // std::function replacement From 8d3f0883cfe5d065eb2dea9b9e69a2ffbb431d78 Mon Sep 17 00:00:00 2001 From: ftk Date: Sat, 10 Aug 2019 19:19:57 +0300 Subject: [PATCH 014/185] update glue code --- main.cpp | 92 ++++++++++++++++++++++++++++----------------------- quickjspp.hpp | 14 ++++++++ 2 files changed, 65 insertions(+), 41 deletions(-) diff --git a/main.cpp b/main.cpp index 002c340f25..a0417d3646 100644 --- a/main.cpp +++ b/main.cpp @@ -11,12 +11,24 @@ #define TYPES bool, int32_t, double, std::shared_ptr, const std::shared_ptr&, std::string, const std::string& -class test +class base_test +{ +public: + double base_field; + + double base_method(double x) + { + std::swap(x, base_field); + return x; + } +}; + +class test : public base_test { public: bool b; mutable int32_t i; - const double d = 7.; + double d = 7.; std::shared_ptr spt; std::string s; @@ -44,7 +56,33 @@ class test void f(TYPES) {} - +void qjs_glue(qjs::Context::Module& m) { + m.function<&::f>("f"); // (bool, ::int32_t, double, ::std::shared_ptr, ::std::shared_ptr const &, ::std::string, ::std::string const &) + m.class_<::base_test>("base_test") + // implicit: .constructor<::base_test const &>() + // implicit: .constructor<>() + .fun<&::base_test::base_method>("base_method") // (double) + .fun<&::base_test::base_field>("base_field") // double + ; + + m.class_<::test>("test") + //.base<::base_test>() + .constructor<::int32_t, bool, ::int32_t, double, ::std::shared_ptr, ::std::shared_ptr const &, ::std::string, ::std::string const &>("Test") + .constructor<::int32_t>("TestSimple") + .fun<&::test::fi>("fi") // (bool, ::int32_t, double, ::std::shared_ptr, ::std::shared_ptr const &, ::std::string, ::std::string const &) + .fun<&::test::fb>("fb") // (bool, ::int32_t, double, ::std::shared_ptr, ::std::shared_ptr const &, ::std::string, ::std::string const &) + .fun<&::test::fd>("fd") // (bool, ::int32_t, double, ::std::shared_ptr, ::std::shared_ptr const &, ::std::string, ::std::string const &) + .fun<&::test::fspt>("fspt") // (bool, ::int32_t, double, ::std::shared_ptr, ::std::shared_ptr const&, ::std::string, ::std::string const &) + .fun<&::test::fs>("fs") // (bool, ::int32_t, double, ::std::shared_ptr, ::std::shared_ptr const &, ::std::string, ::std::string const &) + .fun<&::test::f>("f") // (bool, ::int32_t, double, ::std::shared_ptr, ::std::shared_ptr const &, ::std::string, ::std::string const &) + .fun<&::test::fstatic>("fstatic") // (bool, ::int32_t, double, ::std::shared_ptr, ::std::shared_ptrconst &, ::std::string, ::std::string const &) + .fun<&::test::b>("b") // bool + .fun<&::test::i>("i") // ::int32_t + .fun<&::test::d>("d") // double + .fun<&::test::spt>("spt") // ::std::shared_ptr + .fun<&::test::s>("s") // ::std::string + ; +} // qjs_glue int main(int argc, char ** argv) { JSRuntime * rt; @@ -57,38 +95,7 @@ int main(int argc, char ** argv) Context context(runtime); ctx = context.ctx; - { - auto obj = context.newObject(); - obj["vi"] = 54; - obj["vb"] = true; - obj["vd"] = 56.0; - obj["vs"] = std::string{"test string"}; - obj.add("lambda", [](int x) -> int { return x * x; }); - - obj.add<&test::fi>("fi"); - obj.add<&test::fb>("fb"); - obj.add<&test::fd>("fd"); - obj.add<&test::fs>("fs"); - obj.add<&test::fspt>("fspt"); - obj.add<&test::f>("f"); - obj.add<&test::fstatic>("fstatic"); - - obj.add<&test::i>("i"); - obj.add<&test::b>("b"); - obj.add<&test::d>("d"); - obj.add<&test::s>("s"); - obj.add<&test::spt>("spt"); - - context.registerClass("test_class", std::move(obj)); - } - - - context.addModule("test") - //.add("obj", obj) - .add("Test", detail::ctor_wrapper{"Test"}) - .add("TestSimple", detail::ctor_wrapper{"TestSimple"}); - - + qjs_glue(context.addModule("test")); /* loader for ES6 modules */ @@ -109,28 +116,31 @@ int main(int argc, char ** argv) context.eval(str, "", JS_EVAL_TYPE_MODULE); const char * filename = argv[1]; + try { - auto xxx = context.eval("var t = new test.TestSimple(12);" + auto xxx = context.eval("\"use strict\";" + "var t = new test.TestSimple(12);" "var q = new test.Test(13, t.vb, t.vi, t.vd, t, t, t.vs, t.vs);" "q.b = true;" "q.d = 456.789;" "q.s = \"STRING\";" "q.spt = t;" + //"q.base_field = 105.5;" "console.log(q.b === q.fb(t.vb, t.vi, t.vd, t, t, t.vs, \"test\"));" "console.log(q.d === q.fd(t.vb, t.vi, t.vd, t, t, t.vs, \"test\"));" "console.log(q.s === q.fs(t.vb, t.vi, t.vd, t, t, \"test\", t.vs));" + //"console.log(105.5 === q.base_method(5.1));" + //"console.log(5.1 === q.base_field);" "console.log(q.spt === q.fspt(t.vb, t.vi, t.vd, t, t, t.vs, \"test\"));" // false "q.fi(t.vb, t.vi, t.vd, t, t, t.vs, \"test\")"); assert(xxx.cast() == 18); auto yyy = context.eval("q.fi.bind(t)(t.vb, t.vi, t.vd, t, t, t.vs, \"test\")"); assert(yyy.cast() == 13); - } - try - { + auto f = context.eval("q.fi.bind(q)").cast>(); - int xxx = f(false, 1, 0., context.eval("q").cast>(), + int zzz = f(false, 1, 0., context.eval("q").cast>(), context.eval("t").cast>(), "test string", std::string{"test"}); - assert(xxx == 19); + assert(zzz == 19); } catch(detail::exception) { diff --git a/quickjspp.hpp b/quickjspp.hpp index e91196022e..3081eea4b6 100644 --- a/quickjspp.hpp +++ b/quickjspp.hpp @@ -846,6 +846,20 @@ namespace qjs { return *this; } + /* TODO: needs casting to base class + template + class_registrar& base() + { + assert(detail::js_traits>::QJSClassId && "base class is not registered"); + auto base_proto = JS_GetClassProto(context.ctx, detail::js_traits>::QJSClassId); + int err = JS_SetPrototype(context.ctx, prototype.v, base_proto); + JS_FreeValue(context.ctx, base_proto); + if(err < 0) + throw detail::exception{}; + return *this; + } + */ + ~class_registrar() { context.registerClass(name, std::move(prototype)); From 322442258c7b6d88f27faec0db6451dea11262cc Mon Sep 17 00:00:00 2001 From: ftk Date: Sat, 10 Aug 2019 19:21:28 +0300 Subject: [PATCH 015/185] add simple bindings generator based on pygccxml --- binding-generator/generator.py | 120 +++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 binding-generator/generator.py diff --git a/binding-generator/generator.py b/binding-generator/generator.py new file mode 100644 index 0000000000..9bb74721c4 --- /dev/null +++ b/binding-generator/generator.py @@ -0,0 +1,120 @@ + +# python3 generator.py -std=c++1z ../main.cpp +# python3, castxml and pygccxml should be installed + +import os +import sys + +# Find out the file location within the sources tree +this_module_dir_path = os.path.abspath( + os.path.dirname(sys.modules[__name__].__file__)) +# Add pygccxml package to Python path +#sys.path.append(os.path.join(this_module_dir_path, '..', '..')) + + +from pygccxml import parser # nopep8 +from pygccxml import declarations # nopep8 +from pygccxml import utils # nopep8 + +# Find out the xml generator (gccxml or castxml) +generator_path, generator_name = utils.find_xml_generator() + +flags = filter(lambda x: x.startswith("-"), sys.argv[1:]) + +# Configure the xml generator +config = parser.xml_generator_configuration_t( + xml_generator_path=generator_path, + xml_generator=generator_name, + cflags=" ".join(flags), + # start_with_declarations="test", + #compiler="gcc", +) + +# Parsing source file + +filenames = list(filter(lambda x: not x.startswith("-"), sys.argv[1:])) +full_filenames = [os.path.abspath(filename) for filename in filenames ] + +decls = parser.parse(full_filenames, + config, + compilation_mode=parser.COMPILATION_MODE.ALL_AT_ONCE + +) +global_ns = declarations.get_global_namespace(decls) + +write_hdrs = True + +if write_hdrs: + for filename in filenames: + print('#include "%s"' % filename) + + +def get_prefix(member, duplicates): + p = [] + try: + if member.name in duplicates: + p.append("overload") + if member.is_artificial: + p.append("implicit") + if member.access_type != "public": + p.append(member.access_type) + except AttributeError: + pass + if p == []: + duplicates.append(member.name) + return "" + return "// " + ", ".join(p) + ": " + + +def get_arg_types(fn): + return ", ".join([x.decl_string for x in fn.argument_types]) + +def get_addr(fn): + #return "static_cast<" + fn.decl_string + ">(&" + declarations.declaration_utils.full_name(fn) + ")" + return "&" + declarations.declaration_utils.full_name(fn) + + + +write_fn = True + +if write_fn: + print('void qjs_glue(qjs::Context::Module& m) {') + +dump_all = False + +# print free functions +free_dups = [] +for fn in global_ns.free_functions(allow_empty=True): + if not dump_all and not fn.location.file_name in full_filenames: + continue + + print('%sm.function<%s>("%s"); // (%s)' % (get_prefix(fn, free_dups), get_addr(fn), fn.name, get_arg_types(fn))) + + +visited = [] + +def dump_class(class_): + if class_ in visited: + return + visited.append(class_) + duplicates = [] + print('m.class_<%s>("%s")' % (declarations.declaration_utils.full_name(class_), class_.name)) + # print('\tbase classes : ', repr([ + for base in class_.bases: + print('\t//.base<%s>()' % declarations.declaration_utils.full_name(base.related_class)); + for fn in class_.constructors(allow_empty=True): + print('\t%s.constructor<%s>()' % (get_prefix(fn, duplicates), get_arg_types(fn))) + for fn in class_.member_functions(allow_empty=True): + print('\t%s.fun<%s>("%s") // (%s)' % (get_prefix(fn, duplicates), get_addr(fn), fn.name, get_arg_types(fn))) + for fn in class_.variables(allow_empty=True): + print('\t%s.fun<%s>("%s") // %s' % (get_prefix(fn, duplicates), get_addr(fn), fn.name, fn.decl_type.decl_string)) + print(';\n') + +# Print all classes +for class_ in global_ns.classes(): + if not dump_all and not class_.location.file_name in full_filenames: + continue + dump_class(class_) + +if write_fn: + print('} // qjs_glue') From 228130c463cf2679ba35a81f0e5607c2a275b7fa Mon Sep 17 00:00:00 2001 From: ftk Date: Tue, 13 Aug 2019 17:06:34 +0300 Subject: [PATCH 016/185] std::vector support --- main.cpp | 13 +++++++++---- quickjspp.hpp | 31 +++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/main.cpp b/main.cpp index a0417d3646..61f26b0a6f 100644 --- a/main.cpp +++ b/main.cpp @@ -14,11 +14,11 @@ class base_test { public: - double base_field; + std::vector> base_field; - double base_method(double x) + int base_method(int x) { - std::swap(x, base_field); + std::swap(x, base_field[0][0]); return x; } }; @@ -60,7 +60,7 @@ void qjs_glue(qjs::Context::Module& m) { m.function<&::f>("f"); // (bool, ::int32_t, double, ::std::shared_ptr, ::std::shared_ptr const &, ::std::string, ::std::string const &) m.class_<::base_test>("base_test") // implicit: .constructor<::base_test const &>() - // implicit: .constructor<>() + .constructor<>() .fun<&::base_test::base_method>("base_method") // (double) .fun<&::base_test::base_field>("base_field") // double ; @@ -119,6 +119,11 @@ int main(int argc, char ** argv) try { auto xxx = context.eval("\"use strict\";" + "var b = new test.base_test();" + "b.base_field = [[5],[1,2,3,4],[6]];" + "console.log(b.base_field[1][3] === 4);" + "console.log(b.base_method() === 5);" + "var t = new test.TestSimple(12);" "var q = new test.Test(13, t.vb, t.vi, t.vd, t, t, t.vs, t.vs);" "q.b = true;" diff --git a/quickjspp.hpp b/quickjspp.hpp index 3081eea4b6..40fbf35a48 100644 --- a/quickjspp.hpp +++ b/quickjspp.hpp @@ -983,6 +983,37 @@ namespace qjs { } }; + // std::vector <-> Array + template + struct js_traits> + { + static JSValue wrap(JSContext * ctx, const std::vector& arr) + { + auto jsarray = Value{ctx, JS_NewArray(ctx)}; + if(JS_IsException(jsarray.v)) + throw detail::exception{}; + + for(uint32_t i = 0; i < (uint32_t) arr.size(); i++) + jsarray[i] = arr[i]; + + return std::move(jsarray); + } + + static std::vector unwrap(JSContext * ctx, JSValueConst jsarr) + { + if(!JS_IsArray(ctx, jsarr)) + throw exception{}; + Value jsarray {ctx, JS_DupValue(ctx, jsarr)}; + std::vector arr; + int32_t len = jsarray["length"]; + arr.reserve((uint32_t)len); + for(uint32_t i = 0; i < (uint32_t)len; i++) + arr.push_back(jsarray[i]); + return arr; + } + }; + + } } \ No newline at end of file From feaaed01c3beed745c8b145df719a261d0cfd1e7 Mon Sep 17 00:00:00 2001 From: ftk Date: Tue, 13 Aug 2019 17:18:21 +0300 Subject: [PATCH 017/185] updated quickjs to 2019-08-10 --- quickjs/VERSION | 2 +- quickjs/libbf.c | 4 +- quickjs/libbf.h | 8 +- quickjs/quickjs-atom.h | 8 +- quickjs/quickjs-libc.c | 200 +++- quickjs/quickjs-opcode.h | 55 +- quickjs/quickjs.c | 1907 +++++++++++++++++++++++++++++++------- quickjs/quickjs.h | 28 +- quickjspp.hpp | 6 +- 9 files changed, 1824 insertions(+), 394 deletions(-) diff --git a/quickjs/VERSION b/quickjs/VERSION index 6b45bd0759..c88c1f0c71 100644 --- a/quickjs/VERSION +++ b/quickjs/VERSION @@ -1 +1 @@ -2019-07-28 +2019-08-10 diff --git a/quickjs/libbf.c b/quickjs/libbf.c index de800365fb..cbabf9525d 100644 --- a/quickjs/libbf.c +++ b/quickjs/libbf.c @@ -2475,6 +2475,7 @@ int bf_atof2(bf_t *r, slimb_t *pexponent, { const char *p, *p_start; int is_neg, radix_bits, exp_is_neg, ret, digits_per_limb, shift, sep; + int ret_legacy_octal = 0; limb_t cur_limb; slimb_t pos, expn, int_len, digit_count; BOOL has_decpt, is_bin_exp, is_float; @@ -2525,6 +2526,7 @@ int bf_atof2(bf_t *r, slimb_t *pexponent, } else if ((p[1] >= '0' && p[1] <= '9') && radix == 0 && (flags & BF_ATOF_LEGACY_OCTAL)) { int i; + ret_legacy_octal = BF_ATOF_ST_LEGACY_OCTAL; /* the separator is not allowed in legacy octal literals */ sep = 256; for (i = 1; (p[i] >= '0' && p[i] <= '7'); i++) @@ -2745,7 +2747,7 @@ int bf_atof2(bf_t *r, slimb_t *pexponent, done: if (pnext) *pnext = p; - return ret; + return ret | ret_legacy_octal; error: if (!radix_bits) bf_delete(a); diff --git a/quickjs/libbf.h b/quickjs/libbf.h index e73b51d969..e3ea06019b 100644 --- a/quickjs/libbf.h +++ b/quickjs/libbf.h @@ -269,10 +269,12 @@ void bf_logic_and(bf_t *r, const bf_t *a, const bf_t *b); /* only accept decimal floating point if radix = 0 */ #define BF_ATOF_ONLY_DEC_FLOAT (1 << 26) -/* one more return flag: indicate that the parsed number is an integer - (only set when the flags BF_ATOF_INT_PREC_INF or - BF_ATOF_INT_N_SUFFIX are used) */ +/* additional return flags */ +/* indicate that the parsed number is an integer (only set when the + flags BF_ATOF_INT_PREC_INF or BF_ATOF_INT_N_SUFFIX are used) */ #define BF_ATOF_ST_INTEGER (1 << 5) +/* integer parsed as legacy octal */ +#define BF_ATOF_ST_LEGACY_OCTAL (1 << 6) int bf_atof(bf_t *a, const char *str, const char **pnext, int radix, limb_t prec, bf_flags_t flags); diff --git a/quickjs/quickjs-atom.h b/quickjs/quickjs-atom.h index b0708aa9be..6bbc3b2982 100644 --- a/quickjs/quickjs-atom.h +++ b/quickjs/quickjs-atom.h @@ -144,6 +144,11 @@ DEF(raw, "raw") DEF(new_target, "new.target") DEF(this_active_func, "this.active_func") DEF(home_object, "") +DEF(computed_field, "") +DEF(static_computed_field, "") /* must come after computed_fields */ +DEF(class_fields_init, "") +DEF(brand, "") +DEF(hash_constructor, "#constructor") DEF(as, "as") DEF(from, "from") DEF(_default_, "*default*") @@ -234,7 +239,8 @@ DEF(SyntaxError, "SyntaxError") DEF(TypeError, "TypeError") DEF(URIError, "URIError") DEF(InternalError, "InternalError") - +/* private symbols */ +DEF(Private_brand, "") /* symbols */ DEF(Symbol_toPrimitive, "Symbol.toPrimitive") DEF(Symbol_iterator, "Symbol.iterator") diff --git a/quickjs/quickjs-libc.c b/quickjs/quickjs-libc.c index df6a36ab1c..a4a4c1c8d4 100644 --- a/quickjs/quickjs-libc.c +++ b/quickjs/quickjs-libc.c @@ -100,6 +100,7 @@ static JSValue js_printf_internal(JSContext *ctx, const uint8_t *p; char *q; int i, c, len; + size_t fmt_len; int32_t int32_arg; int64_t int64_arg; double double_arg; @@ -112,13 +113,13 @@ static JSValue js_printf_internal(JSContext *ctx, js_std_dbuf_init(ctx, &dbuf); if (argc > 0) { - fmt_str = JS_ToCStringLen(ctx, &len, argv[0], FALSE); + fmt_str = JS_ToCStringLen(ctx, &fmt_len, argv[0]); if (!fmt_str) goto fail; i = 1; fmt = (const uint8_t *)fmt_str; - fmt_end = fmt + len; + fmt_end = fmt + fmt_len; while (fmt < fmt_end) { for (p = fmt; fmt < fmt_end && *fmt != '%'; fmt++) continue; @@ -477,9 +478,9 @@ static JSValue js_evalScript(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { const char *str; - int len; + size_t len; JSValue ret; - str = JS_ToCStringLen(ctx, &len, argv[0], FALSE); + str = JS_ToCStringLen(ctx, &len, argv[0]); if (!str) return JS_EXCEPTION; if (++eval_script_recurse == 1) { @@ -878,6 +879,196 @@ static JSValue js_std_file_putByte(JSContext *ctx, JSValueConst this_val, return JS_NewInt32(ctx, c); } +/* urlGet */ + +#define URL_GET_PROGRAM "curl -s -i" +#define URL_GET_BUF_SIZE 4096 + +static int http_get_header_line(FILE *f, char *buf, size_t buf_size, + DynBuf *dbuf) +{ + int c; + char *p; + + p = buf; + for(;;) { + c = fgetc(f); + if (c < 0) + return -1; + if ((p - buf) < buf_size - 1) + *p++ = c; + if (dbuf) + dbuf_putc(dbuf, c); + if (c == '\n') + break; + } + *p = '\0'; + return 0; +} + +static int http_get_status(const char *buf) +{ + const char *p = buf; + while (*p != ' ' && *p != '\0') + p++; + if (*p != ' ') + return 0; + while (*p == ' ') + p++; + return atoi(p); +} + +static JSValue js_std_urlGet(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + const char *url; + DynBuf cmd_buf; + DynBuf data_buf_s, *data_buf = &data_buf_s; + DynBuf header_buf_s, *header_buf = &header_buf_s; + char *buf; + size_t i, len; + int c, status; + JSValue val, response = JS_UNDEFINED, ret_obj; + JSValueConst options_obj; + FILE *f; + BOOL binary_flag, full_flag; + + url = JS_ToCString(ctx, argv[0]); + if (!url) + return JS_EXCEPTION; + + binary_flag = FALSE; + full_flag = FALSE; + + if (argc >= 2) { + options_obj = argv[1]; + + val = JS_GetPropertyStr(ctx, options_obj, "binary"); + if (JS_IsException(val)) + goto fail_opt; + binary_flag = JS_ToBool(ctx, val); + JS_FreeValue(ctx, val); + + val = JS_GetPropertyStr(ctx, options_obj, "full"); + if (JS_IsException(val)) { + fail_opt: + JS_FreeCString(ctx, url); + return JS_EXCEPTION; + } + full_flag = JS_ToBool(ctx, val); + JS_FreeValue(ctx, val); + } + + + js_std_dbuf_init(ctx, &cmd_buf); + dbuf_printf(&cmd_buf, "%s ''", URL_GET_PROGRAM); + len = strlen(url); + for(i = 0; i < len; i++) { + c = url[i]; + if (c == '\'' || c == '\\') + dbuf_putc(&cmd_buf, '\\'); + dbuf_putc(&cmd_buf, c); + } + JS_FreeCString(ctx, url); + dbuf_putstr(&cmd_buf, "''"); + dbuf_putc(&cmd_buf, '\0'); + if (dbuf_error(&cmd_buf)) { + dbuf_free(&cmd_buf); + return JS_EXCEPTION; + } + // printf("%s\n", (char *)cmd_buf.buf); + f = popen((char *)cmd_buf.buf, "r"); + dbuf_free(&cmd_buf); + if (!f) { + return js_std_throw_errno(ctx, errno); + } + + js_std_dbuf_init(ctx, data_buf); + js_std_dbuf_init(ctx, header_buf); + + buf = js_malloc(ctx, URL_GET_BUF_SIZE); + if (!buf) + goto fail; + + /* get the HTTP status */ + if (http_get_header_line(f, buf, URL_GET_BUF_SIZE, NULL) < 0) + goto bad_header; + status = http_get_status(buf); + if (!full_flag && !(status >= 200 && status <= 299)) { + js_std_throw_errno(ctx, ENOENT); + goto fail; + } + + /* wait until there is an empty line */ + for(;;) { + if (http_get_header_line(f, buf, URL_GET_BUF_SIZE, header_buf) < 0) { + bad_header: + js_std_throw_errno(ctx, EINVAL); + goto fail; + } + if (!strcmp(buf, "\r\n")) + break; + } + if (dbuf_error(header_buf)) + goto fail; + header_buf->size -= 2; /* remove the trailing CRLF */ + + /* download the data */ + for(;;) { + len = fread(buf, 1, URL_GET_BUF_SIZE, f); + if (len == 0) + break; + dbuf_put(data_buf, (uint8_t *)buf, len); + } + js_free(ctx, buf); + buf = NULL; + pclose(f); + f = NULL; + + if (dbuf_error(data_buf)) + goto fail; + if (binary_flag) { + response = JS_NewArrayBufferCopy(ctx, + data_buf->buf, data_buf->size); + } else { + response = JS_NewStringLen(ctx, (char *)data_buf->buf, data_buf->size); + } + dbuf_free(data_buf); + data_buf = NULL; + if (JS_IsException(response)) + goto fail; + + if (full_flag) { + ret_obj = JS_NewObject(ctx); + if (JS_IsException(ret_obj)) + goto fail; + JS_DefinePropertyValueStr(ctx, ret_obj, "response", + response, + JS_PROP_C_W_E); + JS_DefinePropertyValueStr(ctx, ret_obj, "responseHeaders", + JS_NewStringLen(ctx, (char *)header_buf->buf, + header_buf->size), + JS_PROP_C_W_E); + JS_DefinePropertyValueStr(ctx, ret_obj, "status", + JS_NewInt32(ctx, status), + JS_PROP_C_W_E); + } else { + ret_obj = response; + } + dbuf_free(header_buf); + return ret_obj; + fail: + if (f) + pclose(f); + js_free(ctx, buf); + if (data_buf) + dbuf_free(data_buf); + if (header_buf) + dbuf_free(header_buf); + JS_FreeValue(ctx, response); + return JS_EXCEPTION; +} + static JSClassDef js_std_file_class = { "FILE", .finalizer = js_std_file_finalizer, @@ -889,6 +1080,7 @@ static const JSCFunctionListEntry js_std_funcs[] = { JS_CFUNC_DEF("evalScript", 1, js_evalScript ), JS_CFUNC_DEF("loadScript", 1, js_loadScript ), JS_CFUNC_DEF("getenv", 1, js_std_getenv ), + JS_CFUNC_DEF("urlGet", 1, js_std_urlGet ), /* FILE I/O */ JS_CFUNC_DEF("open", 2, js_std_open ), diff --git a/quickjs/quickjs-opcode.h b/quickjs/quickjs-opcode.h index d7318682bf..0ea029eecf 100644 --- a/quickjs/quickjs-opcode.h +++ b/quickjs/quickjs-opcode.h @@ -61,20 +61,20 @@ FMT(label_u16) #define def(id, size, n_pop, n_push, f) DEF(id, size, n_pop, n_push, f) #endif -def(invalid, 1, 0, 0, none) /* never emitted */ +DEF(invalid, 1, 0, 0, none) /* never emitted */ /* push values */ DEF( push_i32, 5, 0, 1, i32) DEF( push_const, 5, 0, 1, const) DEF( fclosure, 5, 0, 1, const) /* must follow push_const */ DEF(push_atom_value, 5, 0, 1, atom) +DEF( private_symbol, 5, 0, 1, atom) DEF( undefined, 1, 0, 1, none) DEF( null, 1, 0, 1, none) DEF( push_this, 1, 0, 1, none) /* only used at the start of a function */ DEF( push_false, 1, 0, 1, none) DEF( push_true, 1, 0, 1, none) DEF( object, 1, 0, 1, none) -DEF( var_object, 1, 0, 1, none) DEF( special_object, 2, 0, 1, u8) /* only used at the start of a function */ DEF( rest, 3, 0, 1, u16) /* only used at the start of a function */ @@ -109,6 +109,8 @@ DEF( return, 1, 1, 0, none) DEF( return_undef, 1, 0, 0, none) DEF(check_ctor_return, 1, 1, 2, none) DEF( check_ctor, 1, 0, 0, none) +DEF( check_brand, 1, 2, 2, none) /* this_obj func -> this_obj func */ +DEF( add_brand, 1, 2, 0, none) /* this_obj home_obj -> */ DEF( return_async, 1, 1, 0, none) DEF( throw, 1, 1, 0, none) DEF( throw_var, 6, 0, 0, atom_u8) @@ -135,6 +137,9 @@ DEF( define_func, 6, 1, 0, atom_u8) DEF( get_field, 5, 1, 1, atom) DEF( get_field2, 5, 1, 2, atom) DEF( put_field, 5, 2, 0, atom) +DEF( get_private_field, 1, 2, 1, none) /* obj prop -> value */ +DEF( put_private_field, 1, 3, 0, none) /* obj value prop -> */ +DEF(define_private_field, 1, 3, 1, none) /* obj prop value -> obj */ DEF( get_array_el, 1, 2, 1, none) DEF( get_array_el2, 1, 2, 2, none) /* obj prop -> obj value */ DEF( put_array_el, 1, 3, 0, none) @@ -144,12 +149,13 @@ DEF( define_field, 5, 2, 1, atom) DEF( set_name, 5, 1, 1, atom) DEF(set_name_computed, 1, 2, 2, none) DEF( set_proto, 1, 2, 1, none) +DEF(set_home_object, 1, 2, 2, none) DEF(define_array_el, 1, 3, 2, none) DEF( append, 1, 3, 2, none) /* append enumerated object, update length */ DEF(copy_data_properties, 2, 3, 3, u8) DEF( define_method, 6, 2, 1, atom_u8) DEF(define_method_computed, 2, 3, 1, u8) /* must come after define_method */ -DEF( define_class, 2, 2, 2, u8) +DEF( define_class, 6, 2, 2, atom_u8) DEF( get_loc, 3, 0, 1, loc) DEF( put_loc, 3, 1, 0, loc) /* must come after get_loc */ @@ -161,7 +167,6 @@ DEF( get_var_ref, 3, 0, 1, var_ref) DEF( put_var_ref, 3, 1, 0, var_ref) /* must come after get_var_ref */ DEF( set_var_ref, 3, 1, 1, var_ref) /* must come after put_var_ref */ DEF(set_loc_uninitialized, 3, 0, 0, loc) -def(set_arg_valid_upto, 3, 0, 0, arg) /* emitted in phase 1, removed in phase 2 */ DEF( get_loc_check, 3, 0, 1, loc) DEF( put_loc_check, 3, 1, 0, loc) /* must come after get_loc_check */ DEF( put_loc_check_init, 3, 1, 0, loc) @@ -169,26 +174,13 @@ DEF(get_var_ref_check, 3, 0, 1, var_ref) DEF(put_var_ref_check, 3, 1, 0, var_ref) /* must come after get_var_ref_check */ DEF(put_var_ref_check_init, 3, 1, 0, var_ref) DEF( close_loc, 3, 0, 0, loc) -def(close_var_object, 1, 0, 0, none) /* emitted in phase 1, removed in phase 2 */ -def( enter_scope, 3, 0, 0, u16) /* emitted in phase 1, removed in phase 2 */ -def( leave_scope, 3, 0, 0, u16) /* emitted in phase 1, removed in phase 2 */ - DEF( if_false, 5, 1, 0, label) DEF( if_true, 5, 1, 0, label) /* must come after if_false */ DEF( goto, 5, 0, 0, label) /* must come after if_true */ -def( label, 5, 0, 0, label) /* emitted in phase 1, removed in phase 3 */ DEF( catch, 5, 0, 1, label) DEF( gosub, 5, 0, 0, label) /* used to execute the finally block */ DEF( ret, 1, 1, 0, none) /* used to return from the finally block */ -def(scope_get_var_undef, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2 */ -def( scope_get_var, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2 */ -def( scope_put_var, 7, 1, 0, atom_u16) /* emitted in phase 1, removed in phase 2 */ -def(scope_delete_var, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2 */ -def( scope_make_ref, 11, 0, 2, atom_label_u16) /* emitted in phase 1, removed in phase 2 */ -def( scope_get_ref, 7, 0, 2, atom_u16) /* emitted in phase 1, removed in phase 2 */ -def(scope_put_var_init, 7, 0, 2, atom_u16) /* emitted in phase 1, removed in phase 2 */ - DEF( to_object, 1, 1, 1, none) //DEF( to_string, 1, 1, 1, none) DEF( to_propkey, 1, 1, 1, none) @@ -206,8 +198,6 @@ DEF( make_arg_ref, 7, 0, 2, atom_u16) DEF(make_var_ref_ref, 7, 0, 2, atom_u16) DEF( make_var_ref, 5, 0, 2, atom) -def( line_num, 5, 0, 0, u32) /* emitted in phase 1, removed in phase 3 */ - DEF( for_in_start, 1, 1, 1, none) DEF( for_of_start, 1, 1, 3, none) DEF(for_await_of_start, 1, 1, 3, none) @@ -270,6 +260,31 @@ DEF( math_div, 1, 2, 1, none) DEF( math_mod, 1, 2, 1, none) DEF( math_pow, 1, 2, 1, none) #endif +/* must be the last non short and non temporary opcode */ +DEF( nop, 1, 0, 0, none) + +/* temporary opcodes: never emitted in the final bytecode */ + +def(set_arg_valid_upto, 3, 0, 0, arg) /* emitted in phase 1, removed in phase 2 */ + +def(close_var_object, 1, 0, 0, none) /* emitted in phase 1, removed in phase 2 */ +def( enter_scope, 3, 0, 0, u16) /* emitted in phase 1, removed in phase 2 */ +def( leave_scope, 3, 0, 0, u16) /* emitted in phase 1, removed in phase 2 */ + +def( label, 5, 0, 0, label) /* emitted in phase 1, removed in phase 3 */ + +def(scope_get_var_undef, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2 */ +def( scope_get_var, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2 */ +def( scope_put_var, 7, 1, 0, atom_u16) /* emitted in phase 1, removed in phase 2 */ +def(scope_delete_var, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2 */ +def( scope_make_ref, 11, 0, 2, atom_label_u16) /* emitted in phase 1, removed in phase 2 */ +def( scope_get_ref, 7, 0, 2, atom_u16) /* emitted in phase 1, removed in phase 2 */ +def(scope_put_var_init, 7, 0, 2, atom_u16) /* emitted in phase 1, removed in phase 2 */ +def(scope_get_private_field, 7, 1, 1, atom_u16) /* obj -> value, emitted in phase 1, removed in phase 2 */ +def(scope_get_private_field2, 7, 1, 2, atom_u16) /* obj -> obj value, emitted in phase 1, removed in phase 2 */ +def(scope_put_private_field, 7, 1, 1, atom_u16) /* obj value ->, emitted in phase 1, removed in phase 2 */ + +def( line_num, 5, 0, 0, u32) /* emitted in phase 1, removed in phase 3 */ #if SHORT_OPCODES DEF( push_minus1, 1, 0, 1, none_int) @@ -345,8 +360,6 @@ DEF( is_null, 1, 1, 1, none) DEF( is_function, 1, 1, 1, none) #endif -DEF( nop, 1, 0, 0, none) /* temporary use during code generation */ - #undef DEF #undef def #endif /* DEF */ diff --git a/quickjs/quickjs.c b/quickjs/quickjs.c index d3e89b52e1..7bb20cb4db 100644 --- a/quickjs/quickjs.c +++ b/quickjs/quickjs.c @@ -70,7 +70,6 @@ #if !defined(EMSCRIPTEN) #define CONFIG_ATOMICS #endif -#define JSON_SUPERSET 1 /* dump object free */ //#define DUMP_FREE @@ -379,14 +378,29 @@ enum { JS_ATOM_TYPE_STRING = 1, JS_ATOM_TYPE_GLOBAL_SYMBOL, JS_ATOM_TYPE_SYMBOL, + JS_ATOM_TYPE_PRIVATE, }; +enum { + JS_ATOM_HASH_SYMBOL, + JS_ATOM_HASH_PRIVATE, +}; + +typedef enum { + JS_ATOM_KIND_STRING, + JS_ATOM_KIND_SYMBOL, + JS_ATOM_KIND_PRIVATE, +} JSAtomKindEnum; + #define JS_ATOM_HASH_MASK ((1 << 30) - 1) struct JSString { JSRefCountHeader header; /* must come first, 32-bit */ uint32_t len : 31; uint8_t is_wide_char : 1; /* 0 = 8 bits, 1 = 16 bits characters */ + /* for JS_ATOM_TYPE_SYMBOL: hash = 0, atom_type = 3, + for JS_ATOM_TYPE_PRIVATE: hash = 1, atom_type = 3 + XXX: could change encoding to have one more bit in hash */ uint32_t hash : 30; uint8_t atom_type : 2; /* != 0 if atom, JS_ATOM_TYPE_x */ uint32_t hash_next; /* atom_index for JS_ATOM_TYPE_SYMBOL */ @@ -404,8 +418,8 @@ typedef struct JSClosureVar { uint8_t is_arg : 1; uint8_t is_const : 1; uint8_t is_lexical : 1; - uint8_t is_catch : 1; - /* 11 bits available */ + uint8_t var_kind : 3; /* see JSVarKindEnum */ + /* 9 bits available */ uint16_t var_idx; /* is_local = TRUE: index to a normal variable of the parent function. otherwise: index to a closure variable of the parent function */ @@ -417,18 +431,29 @@ typedef struct JSVarScope { int first; /* index into fd->vars of the last variable in this scope */ } JSVarScope; +typedef enum { + /* XXX: add more variable kinds here instead of using bit fields */ + JS_VAR_NORMAL, + JS_VAR_CATCH, + JS_VAR_PRIVATE_FIELD, + JS_VAR_PRIVATE_METHOD, + JS_VAR_PRIVATE_GETTER, + JS_VAR_PRIVATE_SETTER, /* must come after JS_VAR_PRIVATE_GETTER */ + JS_VAR_PRIVATE_GETTER_SETTER, /* must come after JS_VAR_PRIVATE_SETTER */ +} JSVarKindEnum; + typedef struct JSVarDef { JSAtom var_name; int scope_level; /* index into fd->scopes of this variable lexical scope */ int scope_next; /* index into fd->vars of the next variable in the * same or enclosing lexical scope */ - uint8_t is_catch : 1; uint8_t is_function : 1; /* only used for debug */ uint8_t is_func_var : 1; /* used for the function self reference */ uint8_t is_const : 1; uint8_t is_lexical : 1; uint8_t is_captured : 1; - int func_pool_idx : 26; /* only used during compilation */ + uint8_t var_kind : 3; /* see JSVarKindEnum */ + int func_pool_idx : 24; /* only used during compilation */ } JSVarDef; /* for the encoding of the pc2line table */ @@ -457,9 +482,10 @@ typedef struct JSFunctionBytecode { uint8_t new_target_allowed : 1; uint8_t super_call_allowed : 1; uint8_t super_allowed : 1; + uint8_t arguments_allowed : 1; uint8_t has_debug : 1; uint8_t read_only_bytecode : 1; - /* XXX: 5 bits available */ + /* XXX: 4 bits available */ uint8_t *byte_code_buf; /* (self pointer) */ int byte_code_len; JSAtom func_name; @@ -513,6 +539,7 @@ typedef struct JSProxyData { JSValue handler; JSValue proto; uint8_t is_func; + uint8_t is_revoked; } JSProxyData; typedef struct JSArrayBuffer { @@ -779,10 +806,23 @@ typedef enum OPCodeFormat { typedef enum OPCodeEnum { #define FMT(f) #define DEF(id, size, n_pop, n_push, f) OP_ ## id, +#define def(id, size, n_pop, n_push, f) +#include "quickjs-opcode.h" +#undef def +#undef DEF +#undef FMT + OP_COUNT, /* excluding temporary opcodes */ + /* temporary opcodes : overlap with the short opcodes */ + OP_TEMP_START = OP_nop + 1, + OP___dummy = OP_TEMP_START - 1, +#define FMT(f) +#define DEF(id, size, n_pop, n_push, f) +#define def(id, size, n_pop, n_push, f) OP_ ## id, #include "quickjs-opcode.h" +#undef def #undef DEF #undef FMT - OP_COUNT, + OP_TEMP_END, } OPCodeEnum; static int JS_InitAtoms(JSRuntime *rt); @@ -898,17 +938,15 @@ static JSProperty *add_property(JSContext *ctx, JSObject *p, JSAtom prop, int prop_flags); #ifdef CONFIG_BIGNUM static void js_float_env_finalizer(JSRuntime *rt, JSValue val); -static JSValue JS_NewBigInt64(JSContext *ctx, int64_t v); -static JSValue JS_NewBigUint64(JSContext *ctx, uint64_t v); static JSValue JS_NewBigFloat(JSContext *ctx, bf_t *a); static JSValue JS_NewBigInt2(JSContext *ctx, bf_t *a, BOOL force_bigint); static JSValue JS_NewBigInt(JSContext *ctx, bf_t *a); static int JS_ToBigInt64Free(JSContext *ctx, int64_t *pres, JSValue val); -static int JS_ToBigInt64(JSContext *ctx, int64_t *pres, JSValueConst val); static bf_t *JS_ToBigFloat(JSContext *ctx, BOOL *pis_float, bf_t *buf, JSValueConst val); #endif JSValue JS_ThrowOutOfMemory(JSContext *ctx); +static JSValue JS_ThrowTypeErrorRevokedProxy(JSContext *ctx); static JSValue js_proxy_call(JSContext *ctx, JSValueConst func_obj, JSValueConst this_obj, int argc, JSValueConst *argv); @@ -961,8 +999,8 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj, static int JS_NumberIsInteger(JSContext *ctx, JSValueConst val); static BOOL JS_NumberIsNegativeOrMinusZero(JSContext *ctx, JSValueConst val); static JSValue JS_ToNumberFree(JSContext *ctx, JSValue val); -static int JS_GetOwnProperty(JSContext *ctx, JSPropertyDescriptor *desc, - JSObject *p, JSAtom prop); +static int JS_GetOwnPropertyInternal(JSContext *ctx, JSPropertyDescriptor *desc, + JSObject *p, JSAtom prop); static void js_free_desc(JSContext *ctx, JSPropertyDescriptor *desc); static void async_func_mark(JSRuntime *rt, JSAsyncFunctionState *s, JS_MarkFunc *mark_func); @@ -976,6 +1014,8 @@ static __exception int js_get_length32(JSContext *ctx, uint32_t *pres, JSValueConst obj); static __exception int js_get_length64(JSContext *ctx, int64_t *pres, JSValueConst obj); +static BOOL js_get_fast_array(JSContext *ctx, JSValueConst obj, + JSValue **arrpp, uint32_t *countp); static JSValue JS_CreateAsyncFromSyncIterator(JSContext *ctx, JSValueConst sync_iter); static void js_c_function_data_finalizer(JSRuntime *rt, JSValue val); @@ -984,6 +1024,8 @@ static void js_c_function_data_mark(JSRuntime *rt, JSValueConst val, static JSValue js_c_function_data_call(JSContext *ctx, JSValueConst func_obj, JSValueConst this_val, int argc, JSValueConst *argv); +static JSAtom js_value_to_atom(JSContext *ctx, JSValueConst val); +static JSAtom js_symbol_to_atom(JSContext *ctx, JSValue val); static const JSClassExoticMethods js_arguments_exotic_methods; static const JSClassExoticMethods js_string_exotic_methods; @@ -1635,9 +1677,15 @@ void JS_FreeRuntime(JSRuntime *rt) printf(")"); break; case JS_ATOM_TYPE_SYMBOL: - printf("Symbol("); - JS_DumpString(rt, p); - printf(")"); + if (p->hash == JS_ATOM_HASH_SYMBOL) { + printf("Symbol("); + JS_DumpString(rt, p); + printf(")"); + } else { + printf("Private("); + JS_DumpString(rt, p); + printf(")"); + } break; } if (rt->rt_info) { @@ -2048,18 +2096,19 @@ static inline BOOL is_num_string(uint32_t *pval, const JSString *p) } /* XXX: could use faster version ? */ -static inline uint32_t hash_string8(const uint8_t *str, int len, uint32_t h) +static inline uint32_t hash_string8(const uint8_t *str, size_t len, uint32_t h) { - int i; + size_t i; for(i = 0; i < len; i++) h = h * 263 + str[i]; return h; } -static inline uint32_t hash_string16(const uint16_t *str, int len, uint32_t h) +static inline uint32_t hash_string16(const uint16_t *str, + size_t len, uint32_t h) { - int i; + size_t i; for(i = 0; i < len; i++) h = h * 263 + str[i]; @@ -2187,7 +2236,9 @@ static int JS_InitAtoms(JSRuntime *rt) p = js_atom_init; for(i = 1; i < JS_ATOM_END; i++) { - if (i >= JS_ATOM_Symbol_toPrimitive) + if (i == JS_ATOM_Private_brand) + atom_type = JS_ATOM_TYPE_PRIVATE; + else if (i >= JS_ATOM_Symbol_toPrimitive) atom_type = JS_ATOM_TYPE_SYMBOL; else atom_type = JS_ATOM_TYPE_STRING; @@ -2223,16 +2274,37 @@ JSAtom JS_DupAtom(JSContext *ctx, JSAtom v) return v; } -static BOOL JS_AtomIsString(JSContext *ctx, JSAtom v) +static JSAtomKindEnum JS_AtomGetKind(JSContext *ctx, JSAtom v) { JSRuntime *rt; JSAtomStruct *p; rt = ctx->rt; if (__JS_AtomIsTaggedInt(v)) - return TRUE; + return JS_ATOM_KIND_STRING; p = rt->atom_array[v]; - return p->atom_type == JS_ATOM_TYPE_STRING; + switch(p->atom_type) { + case JS_ATOM_TYPE_STRING: + return JS_ATOM_KIND_STRING; + case JS_ATOM_TYPE_GLOBAL_SYMBOL: + return JS_ATOM_KIND_SYMBOL; + case JS_ATOM_TYPE_SYMBOL: + switch(p->hash) { + case JS_ATOM_HASH_SYMBOL: + return JS_ATOM_KIND_SYMBOL; + case JS_ATOM_HASH_PRIVATE: + return JS_ATOM_KIND_PRIVATE; + default: + abort(); + } + default: + abort(); + } +} + +static BOOL JS_AtomIsString(JSContext *ctx, JSAtom v) +{ + return JS_AtomGetKind(ctx, v) == JS_ATOM_KIND_STRING; } static JSAtom js_get_atom_index(JSRuntime *rt, JSAtomStruct *p) @@ -2263,7 +2335,7 @@ static JSAtom __JS_NewAtom(JSRuntime *rt, JSString *str, int atom_type) #if 0 printf("__JS_NewAtom: "); JS_DumpString(rt, str); printf("\n"); #endif - if (atom_type != JS_ATOM_TYPE_SYMBOL) { + if (atom_type < JS_ATOM_TYPE_SYMBOL) { /* str is not NULL */ if (str->atom_type == atom_type) { /* str is the atom, return its index */ @@ -2293,7 +2365,12 @@ static JSAtom __JS_NewAtom(JSRuntime *rt, JSString *str, int atom_type) } } else { h1 = 0; /* avoid warning */ - h = 0; /* avoid warning */ + if (atom_type == JS_ATOM_TYPE_SYMBOL) { + h = JS_ATOM_HASH_SYMBOL; + } else { + h = JS_ATOM_HASH_PRIVATE; + atom_type = JS_ATOM_TYPE_SYMBOL; + } } if (rt->atom_free_index == 0) { @@ -2417,7 +2494,7 @@ static JSAtom __JS_NewAtomInit(JSRuntime *rt, const char *str, int len, return __JS_NewAtom(rt, p, atom_type); } -static JSAtom __JS_FindAtom(JSRuntime *rt, const char *str, int len, +static JSAtom __JS_FindAtom(JSRuntime *rt, const char *str, size_t len, int atom_type) { uint32_t h, h1, i; @@ -2511,7 +2588,7 @@ static JSAtom JS_NewAtomStr(JSContext *ctx, JSString *p) return __JS_NewAtom(rt, p, JS_ATOM_TYPE_STRING); } -JSAtom JS_NewAtomLen(JSContext *ctx, const char *str, int len) +JSAtom JS_NewAtomLen(JSContext *ctx, const char *str, size_t len) { JSValue val; @@ -2574,6 +2651,20 @@ static JSValue JS_NewSymbol(JSContext *ctx, JSString *p, int atom_type) return JS_MKPTR(JS_TAG_SYMBOL, rt->atom_array[atom]); } +/* descr must be a non-numeric string atom */ +static JSValue JS_NewSymbolFromAtom(JSContext *ctx, JSAtom descr, + int atom_type) +{ + JSRuntime *rt = ctx->rt; + JSString *p; + + assert(!__JS_AtomIsTaggedInt(descr)); + assert(descr < rt->atom_size); + p = rt->atom_array[descr]; + JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, p)); + return JS_NewSymbol(ctx, p, atom_type); +} + #define ATOM_GET_STR_BUF_SIZE 64 /* Should only be used for debug. */ @@ -2812,7 +2903,9 @@ static BOOL JS_AtomSymbolHasDescription(JSContext *ctx, JSAtom v) if (__JS_AtomIsTaggedInt(v)) return FALSE; p = rt->atom_array[v]; - return (p->atom_type != JS_ATOM_TYPE_STRING && + return (((p->atom_type == JS_ATOM_TYPE_SYMBOL && + p->hash == JS_ATOM_HASH_SYMBOL) || + p->atom_type == JS_ATOM_TYPE_GLOBAL_SYMBOL) && !(p->len == 0 && p->is_wide_char != 0)); } @@ -2868,6 +2961,46 @@ const char *JS_AtomToCString(JSContext *ctx, JSAtom atom) return cstr; } +/* return a string atom containing name concatenated with str1 */ +static JSAtom js_atom_concat_str(JSContext *ctx, JSAtom name, const char *str1) +{ + JSValue str; + JSAtom atom; + const char *cstr; + char *cstr2; + size_t len, len1; + + str = JS_AtomToString(ctx, name); + if (JS_IsException(str)) + return JS_ATOM_NULL; + cstr = JS_ToCStringLen(ctx, &len, str); + if (!cstr) + goto fail; + len1 = strlen(str1); + cstr2 = js_malloc(ctx, len + len1 + 1); + if (!cstr2) + goto fail; + memcpy(cstr2, cstr, len); + memcpy(cstr2 + len, str1, len1); + cstr2[len + len1] = '\0'; + atom = JS_NewAtomLen(ctx, cstr2, len + len1); + js_free(ctx, cstr2); + JS_FreeCString(ctx, cstr); + JS_FreeValue(ctx, str); + return atom; + fail: + JS_FreeCString(ctx, cstr); + JS_FreeValue(ctx, str); + return JS_ATOM_NULL; +} + +static JSAtom js_atom_concat_num(JSContext *ctx, JSAtom name, uint32_t n) +{ + char buf[16]; + snprintf(buf, sizeof(buf), "%u", n); + return js_atom_concat_str(ctx, name, buf); +} + static inline BOOL JS_IsEmptyString(JSValueConst v) { return JS_VALUE_GET_TAG(v) == JS_TAG_STRING && JS_VALUE_GET_STRING(v)->len == 0; @@ -3366,22 +3499,25 @@ static JSValue string_buffer_end(StringBuffer *s) } /* create a string from a UTF-8 buffer */ -JSValue JS_NewStringLen(JSContext *ctx, const char *buf, int buf_len) +JSValue JS_NewStringLen(JSContext *ctx, const char *buf, size_t buf_len) { const uint8_t *p, *p_end, *p_start, *p_next; uint32_t c; StringBuffer b_s, *b = &b_s; - + size_t len1; + p_start = (const uint8_t *)buf; p_end = p_start + buf_len; p = p_start; while (p < p_end && *p < 128) p++; + len1 = p - p_start; + if (len1 > JS_STRING_LEN_MAX) + return JS_ThrowInternalError(ctx, "string too long"); if (p == p_end) { /* ASCII string */ return js_new_string8(ctx, (const uint8_t *)buf, buf_len); } else { - int len1 = p - p_start; if (string_buffer_init(ctx, b, buf_len)) goto fail; string_buffer_write8(b, p_start, len1); @@ -3472,7 +3608,7 @@ JSValue JS_NewAtomString(JSContext *ctx, const char *str) /* return (NULL, 0) if exception. */ /* return pointer into a JSString with a live ref_count */ /* cesu8 determines if non-BMP1 codepoints are encoded as 1 or 2 utf-8 sequences */ -const char *JS_ToCStringLen(JSContext *ctx, int *plen, JSValueConst val1, BOOL cesu8) +const char *JS_ToCStringLen2(JSContext *ctx, size_t *plen, JSValueConst val1, BOOL cesu8) { JSValue val; JSString *str, *str_new; @@ -5851,6 +5987,28 @@ static int find_line_num(JSContext *ctx, JSFunctionBytecode *b, return line_num; } +/* in order to avoid executing arbitrary code during the stack trace + generation, we only look at simple 'name' properties containing a + string. */ +static const char *get_func_name(JSContext *ctx, JSValueConst func) +{ + JSProperty *pr; + JSShapeProperty *prs; + JSValueConst val; + + if (JS_VALUE_GET_TAG(func) != JS_TAG_OBJECT) + return NULL; + prs = find_own_property(&pr, JS_VALUE_GET_OBJ(func), JS_ATOM_name); + if (!prs) + return NULL; + if ((prs->flags & JS_PROP_TMASK) != JS_PROP_NORMAL) + return NULL; + val = pr->u.value; + if (JS_VALUE_GET_TAG(val) != JS_TAG_STRING) + return NULL; + return JS_ToCString(ctx, val); +} + /* if filename != NULL, an additional level is added with the filename and line number information (used for parse error). If 'pc' != NULL, it is used as the cur_pc value for the current stack frame */ @@ -5859,7 +6017,7 @@ static void build_backtrace(JSContext *ctx, JSValueConst error_obj, const uint8_t *cur_pc) { JSStackFrame *sf; - JSValue str, func_name; + JSValue str; DynBuf dbuf; const char *func_name_str; const char *str1; @@ -5879,15 +6037,13 @@ static void build_backtrace(JSContext *ctx, JSValueConst error_obj, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); } for(sf = ctx->current_stack_frame; sf != NULL; sf = sf->prev_frame) { - func_name = JS_GetProperty(ctx, sf->cur_func, JS_ATOM_name); - func_name_str = JS_ToCString(ctx, func_name); + func_name_str = get_func_name(ctx, sf->cur_func); if (!func_name_str || func_name_str[0] == '\0') str1 = ""; else str1 = func_name_str; dbuf_printf(&dbuf, " at %s", str1); JS_FreeCString(ctx, func_name_str); - JS_FreeValue(ctx, func_name); p = JS_VALUE_GET_OBJ(sf->cur_func); if (js_class_has_bytecode(p->class_id)) { @@ -6056,6 +6212,11 @@ static JSValue JS_ThrowTypeErrorNotAnObject(JSContext *ctx) return JS_ThrowTypeError(ctx, "not an object"); } +static JSValue JS_ThrowTypeErrorNotASymbol(JSContext *ctx) +{ + return JS_ThrowTypeError(ctx, "not a symbol"); +} + static JSValue JS_ThrowReferenceErrorNotDefined(JSContext *ctx, JSAtom name) { char buf[ATOM_GET_STR_BUF_SIZE]; @@ -6443,6 +6604,189 @@ JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj, } } +static JSValue JS_ThrowTypeErrorPrivateNotFound(JSContext *ctx, JSAtom atom) +{ + char buf[ATOM_GET_STR_BUF_SIZE]; + return JS_ThrowTypeError(ctx, "private class field %s does not exist", + JS_AtomGetStr(ctx, buf, sizeof(buf), atom)); +} + +/* Private fields can be added even on non extensible objects or + Proxies */ +static int JS_DefinePrivateField(JSContext *ctx, JSValueConst obj, + JSValueConst name, JSValue val) +{ + JSObject *p; + JSShapeProperty *prs; + JSProperty *pr; + JSAtom prop; + + if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)) { + JS_ThrowTypeErrorNotAnObject(ctx); + goto fail; + } + /* safety check */ + if (unlikely(JS_VALUE_GET_TAG(name) != JS_TAG_SYMBOL)) { + JS_ThrowTypeErrorNotASymbol(ctx); + goto fail; + } + prop = js_symbol_to_atom(ctx, (JSValue)name); + p = JS_VALUE_GET_OBJ(obj); + prs = find_own_property(&pr, p, prop); + if (prs) { + char buf[ATOM_GET_STR_BUF_SIZE]; + JS_ThrowTypeError(ctx, "private class field %s already exists", + JS_AtomGetStr(ctx, buf, sizeof(buf), prop)); + goto fail; + } + pr = add_property(ctx, p, prop, JS_PROP_C_W_E); + if (unlikely(!pr)) { + fail: + JS_FreeValue(ctx, val); + return -1; + } + pr->u.value = val; + return 0; +} + +static JSValue JS_GetPrivateField(JSContext *ctx, JSValueConst obj, + JSValueConst name) +{ + JSObject *p; + JSShapeProperty *prs; + JSProperty *pr; + JSAtom prop; + + if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)) + return JS_ThrowTypeErrorNotAnObject(ctx); + /* safety check */ + if (unlikely(JS_VALUE_GET_TAG(name) != JS_TAG_SYMBOL)) + return JS_ThrowTypeErrorNotASymbol(ctx); + prop = js_symbol_to_atom(ctx, (JSValue)name); + p = JS_VALUE_GET_OBJ(obj); + prs = find_own_property(&pr, p, prop); + if (!prs) { + JS_ThrowTypeErrorPrivateNotFound(ctx, prop); + return JS_EXCEPTION; + } + return JS_DupValue(ctx, pr->u.value); +} + +static int JS_SetPrivateField(JSContext *ctx, JSValueConst obj, + JSValueConst name, JSValue val) +{ + JSObject *p; + JSShapeProperty *prs; + JSProperty *pr; + JSAtom prop; + + if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)) { + JS_ThrowTypeErrorNotAnObject(ctx); + goto fail; + } + /* safety check */ + if (unlikely(JS_VALUE_GET_TAG(name) != JS_TAG_SYMBOL)) { + JS_ThrowTypeErrorNotASymbol(ctx); + goto fail; + } + prop = js_symbol_to_atom(ctx, (JSValue)name); + p = JS_VALUE_GET_OBJ(obj); + prs = find_own_property(&pr, p, prop); + if (!prs) { + JS_ThrowTypeErrorPrivateNotFound(ctx, prop); + fail: + JS_FreeValue(ctx, val); + return -1; + } + set_value(ctx, &pr->u.value, val); + return 0; +} + +static int JS_AddBrand(JSContext *ctx, JSValueConst obj, JSValueConst home_obj) +{ + JSObject *p, *p1; + JSShapeProperty *prs; + JSProperty *pr; + JSValue brand; + JSAtom brand_atom; + + if (unlikely(JS_VALUE_GET_TAG(home_obj) != JS_TAG_OBJECT)) { + JS_ThrowTypeErrorNotAnObject(ctx); + return -1; + } + p = JS_VALUE_GET_OBJ(home_obj); + prs = find_own_property(&pr, p, JS_ATOM_Private_brand); + if (!prs) { + brand = JS_NewSymbolFromAtom(ctx, JS_ATOM_brand, JS_ATOM_TYPE_PRIVATE); + if (JS_IsException(brand)) + return -1; + /* if the brand is not present, add it */ + pr = add_property(ctx, p, JS_ATOM_Private_brand, JS_PROP_C_W_E); + if (!pr) { + JS_FreeValue(ctx, brand); + return -1; + } + pr->u.value = JS_DupValue(ctx, brand); + } else { + brand = JS_DupValue(ctx, pr->u.value); + } + brand_atom = js_symbol_to_atom(ctx, brand); + + if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)) { + JS_ThrowTypeErrorNotAnObject(ctx); + JS_FreeAtom(ctx, brand_atom); + return -1; + } + p1 = JS_VALUE_GET_OBJ(obj); + pr = add_property(ctx, p1, brand_atom, JS_PROP_C_W_E); + JS_FreeAtom(ctx, brand_atom); + if (!pr) + return -1; + pr->u.value = JS_UNDEFINED; + return 0; +} + +static int JS_CheckBrand(JSContext *ctx, JSValueConst obj, JSValueConst func) +{ + JSObject *p, *p1, *home_obj; + JSShapeProperty *prs; + JSProperty *pr; + JSValueConst brand; + + /* get the home object of 'func' */ + if (unlikely(JS_VALUE_GET_TAG(func) != JS_TAG_OBJECT)) { + not_obj: + JS_ThrowTypeErrorNotAnObject(ctx); + return -1; + } + p1 = JS_VALUE_GET_OBJ(func); + if (!js_class_has_bytecode(p1->class_id)) + goto not_obj; + home_obj = p1->u.func.home_object; + if (!home_obj) + goto not_obj; + prs = find_own_property(&pr, home_obj, JS_ATOM_Private_brand); + if (!prs) { + JS_ThrowTypeError(ctx, "expecting private field"); + return -1; + } + brand = pr->u.value; + /* safety check */ + if (unlikely(JS_VALUE_GET_TAG(brand) != JS_TAG_SYMBOL)) + goto not_obj; + + /* get the brand array of 'obj' */ + if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)) + goto not_obj; + p = JS_VALUE_GET_OBJ(obj); + prs = find_own_property(&pr, p, js_symbol_to_atom(ctx, (JSValue)brand)); + if (!prs) { + JS_ThrowTypeError(ctx, "invalid brand on object"); + return -1; + } + return 0; +} + static int num_keys_cmp(const void *p1, const void *p2, void *opaque) { JSContext *ctx = opaque; @@ -6472,16 +6816,12 @@ static void js_free_prop_enum(JSContext *ctx, JSPropertyEnum *tab, uint32_t len) } } -#define JS_GPN_SYMBOL_MASK (1 << 0) -#define JS_GPN_STRING_MASK (1 << 1) -/* only include the enumerable properties */ -#define JS_GPN_ENUM_ONLY (1 << 2) -/* set theJSPropertyEnum.is_enumerable field */ -#define JS_GPN_SET_ENUM (1 << 3) - -static int __exception JS_GetOwnPropertyNames(JSContext *ctx, JSPropertyEnum **ptab, - uint32_t *plen, - JSObject *p, int flags) +/* return < 0 in case if exception, 0 if OK. ptab and its atoms must + be freed by the user. */ +static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx, + JSPropertyEnum **ptab, + uint32_t *plen, + JSObject *p, int flags) { int i, j; JSShape *sh; @@ -6490,9 +6830,10 @@ static int __exception JS_GetOwnPropertyNames(JSContext *ctx, JSPropertyEnum **p JSAtom atom; uint32_t num_keys_count, str_keys_count, sym_keys_count, atom_count; uint32_t num_index, str_index, sym_index, exotic_count; - BOOL is_enumerable, is_string, num_sorted; + BOOL is_enumerable, num_sorted; uint32_t num_key; - + JSAtomKindEnum kind; + /* clear pointer for consistency in case of failure */ *ptab = NULL; *plen = 0; @@ -6508,9 +6849,9 @@ static int __exception JS_GetOwnPropertyNames(JSContext *ctx, JSPropertyEnum **p atom = prs->atom; if (atom != JS_ATOM_NULL) { is_enumerable = ((prs->flags & JS_PROP_ENUMERABLE) != 0); - is_string = JS_AtomIsString(ctx, atom); + kind = JS_AtomGetKind(ctx, atom); if ((!(flags & JS_GPN_ENUM_ONLY) || is_enumerable) && - ((flags >> is_string) & 1) != 0) { + ((flags >> kind) & 1) != 0) { /* need to raise an exception in case of the module name space (implicit GetOwnProperty) */ if (unlikely((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) && @@ -6523,7 +6864,7 @@ static int __exception JS_GetOwnPropertyNames(JSContext *ctx, JSPropertyEnum **p } if (JS_AtomIsArrayIndex(ctx, &num_key, atom)) { num_keys_count++; - } else if (is_string) { + } else if (kind == JS_ATOM_KIND_STRING) { str_keys_count++; } else { sym_keys_count++; @@ -6553,14 +6894,14 @@ static int __exception JS_GetOwnPropertyNames(JSContext *ctx, JSPropertyEnum **p return -1; for(i = 0; i < exotic_count; i++) { atom = tab_exotic[i].atom; - is_string = JS_AtomIsString(ctx, atom); - if (((flags >> is_string) & 1) != 0) { + kind = JS_AtomGetKind(ctx, atom); + if (((flags >> kind) & 1) != 0) { is_enumerable = FALSE; if (flags & (JS_GPN_SET_ENUM | JS_GPN_ENUM_ONLY)) { JSPropertyDescriptor desc; int res; /* set the "is_enumerable" field if necessary */ - res = JS_GetOwnProperty(ctx, &desc, p, atom); + res = JS_GetOwnPropertyInternal(ctx, &desc, p, atom); if (res < 0) { js_free_prop_enum(ctx, tab_exotic, exotic_count); return -1; @@ -6575,7 +6916,7 @@ static int __exception JS_GetOwnPropertyNames(JSContext *ctx, JSPropertyEnum **p if (!(flags & JS_GPN_ENUM_ONLY) || is_enumerable) { if (JS_AtomIsArrayIndex(ctx, &num_key, atom)) { num_keys_count++; - } else if (is_string) { + } else if (kind == JS_ATOM_KIND_STRING) { str_keys_count++; } else { sym_keys_count++; @@ -6607,13 +6948,13 @@ static int __exception JS_GetOwnPropertyNames(JSContext *ctx, JSPropertyEnum **p atom = prs->atom; if (atom != JS_ATOM_NULL) { is_enumerable = ((prs->flags & JS_PROP_ENUMERABLE) != 0); - is_string = JS_AtomIsString(ctx, atom); + kind = JS_AtomGetKind(ctx, atom); if ((!(flags & JS_GPN_ENUM_ONLY) || is_enumerable) && - ((flags >> is_string) & 1) != 0) { + ((flags >> kind) & 1) != 0) { if (JS_AtomIsArrayIndex(ctx, &num_key, atom)) { j = num_index++; num_sorted = FALSE; - } else if (is_string) { + } else if (kind == JS_ATOM_KIND_STRING) { j = str_index++; } else { j = sym_index++; @@ -6641,13 +6982,13 @@ static int __exception JS_GetOwnPropertyNames(JSContext *ctx, JSPropertyEnum **p for(i = 0; i < exotic_count; i++) { atom = tab_exotic[i].atom; is_enumerable = tab_exotic[i].is_enumerable; - is_string = JS_AtomIsString(ctx, atom); + kind = JS_AtomGetKind(ctx, atom); if ((!(flags & JS_GPN_ENUM_ONLY) || is_enumerable) && - ((flags >> is_string) & 1) != 0) { + ((flags >> kind) & 1) != 0) { if (JS_AtomIsArrayIndex(ctx, &num_key, atom)) { j = num_index++; num_sorted = FALSE; - } else if (is_string) { + } else if (kind == JS_ATOM_KIND_STRING) { j = str_index++; } else { j = sym_index++; @@ -6675,11 +7016,22 @@ static int __exception JS_GetOwnPropertyNames(JSContext *ctx, JSPropertyEnum **p return 0; } +int JS_GetOwnPropertyNames(JSContext *ctx, JSPropertyEnum **ptab, + uint32_t *plen, JSValueConst obj, int flags) +{ + if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) { + JS_ThrowTypeErrorNotAnObject(ctx); + return -1; + } + return JS_GetOwnPropertyNamesInternal(ctx, ptab, plen, + JS_VALUE_GET_OBJ(obj), flags); +} + /* Return -1 if exception, FALSE if the property does not exist, TRUE if it exists. If TRUE is returned, the property descriptor 'desc' is filled present. */ -static int JS_GetOwnProperty(JSContext *ctx, JSPropertyDescriptor *desc, - JSObject *p, JSAtom prop) +static int JS_GetOwnPropertyInternal(JSContext *ctx, JSPropertyDescriptor *desc, + JSObject *p, JSAtom prop) { JSShapeProperty *prs; JSProperty *pr; @@ -6771,6 +7123,16 @@ static int JS_GetOwnProperty(JSContext *ctx, JSPropertyDescriptor *desc, return FALSE; } +int JS_GetOwnProperty(JSContext *ctx, JSPropertyDescriptor *desc, + JSValueConst obj, JSAtom prop) +{ + if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) { + JS_ThrowTypeErrorNotAnObject(ctx); + return -1; + } + return JS_GetOwnPropertyInternal(ctx, desc, JS_VALUE_GET_OBJ(obj), prop); +} + /* return -1 if exception (Proxy object only) or TRUE/FALSE */ int JS_IsExtensible(JSContext *ctx, JSValueConst obj) { @@ -6814,7 +7176,7 @@ int JS_HasProperty(JSContext *ctx, JSValueConst obj, JSAtom prop) if (em && em->has_property) return em->has_property(ctx, JS_MKPTR(JS_TAG_OBJECT, p), prop); } - ret = JS_GetOwnProperty(ctx, NULL, p, prop); + ret = JS_GetOwnPropertyInternal(ctx, NULL, p, prop); if (ret != 0) return ret; if (p->class_id >= JS_CLASS_UINT8C_ARRAY && @@ -6824,7 +7186,7 @@ int JS_HasProperty(JSContext *ctx, JSValueConst obj, JSAtom prop) if (ret < 0) return -1; /* the detached array test was done in - JS_GetOwnProperty() */ + JS_GetOwnPropertyInternal() */ return FALSE; } } @@ -6835,6 +7197,13 @@ int JS_HasProperty(JSContext *ctx, JSValueConst obj, JSAtom prop) return FALSE; } +/* val must be a symbol */ +static JSAtom js_symbol_to_atom(JSContext *ctx, JSValue val) +{ + JSAtomStruct *p = JS_VALUE_GET_PTR(val); + return js_get_atom_index(ctx->rt, p); +} + /* return JS_ATOM_NULL in case of exception */ static JSAtom js_value_to_atom(JSContext *ctx, JSValueConst val) { @@ -6854,8 +7223,7 @@ static JSAtom js_value_to_atom(JSContext *ctx, JSValueConst val) if (JS_IsException(str)) return JS_ATOM_NULL; if (JS_VALUE_GET_TAG(str) == JS_TAG_SYMBOL) { - JSAtomStruct *p = JS_VALUE_GET_PTR(str); - atom = js_get_atom_index(ctx->rt, p); + atom = js_symbol_to_atom(ctx, str); } else { atom = JS_NewAtomStr(ctx, JS_VALUE_GET_STRING(str)); } @@ -7333,7 +7701,7 @@ static int JS_SetPropertyGeneric(JSContext *ctx, } } - ret = JS_GetOwnProperty(ctx, &desc, p, prop); + ret = JS_GetOwnPropertyInternal(ctx, &desc, p, prop); if (ret < 0) return ret; if (ret) { @@ -7364,7 +7732,7 @@ static int JS_SetPropertyGeneric(JSContext *ctx, p = JS_VALUE_GET_OBJ(this_obj); /* modify the property in this_obj if it already exists */ - ret = JS_GetOwnProperty(ctx, &desc, p, prop); + ret = JS_GetOwnPropertyInternal(ctx, &desc, p, prop); if (ret < 0) return ret; if (ret) { @@ -7478,12 +7846,12 @@ int JS_SetPropertyInternal(JSContext *ctx, JSValueConst this_obj, return JS_SetPropertyValue(ctx, this_obj, JS_NewInt32(ctx, idx), val, flags); else break; - } else if (p->class_id >= JS_CLASS_UINT8C_ARRAY && - p->class_id <= JS_CLASS_FLOAT64_ARRAY) { + } else if (p1->class_id >= JS_CLASS_UINT8C_ARRAY && + p1->class_id <= JS_CLASS_FLOAT64_ARRAY) { goto typed_array_oob; } - } else if (p->class_id >= JS_CLASS_UINT8C_ARRAY && - p->class_id <= JS_CLASS_FLOAT64_ARRAY) { + } else if (p1->class_id >= JS_CLASS_UINT8C_ARRAY && + p1->class_id <= JS_CLASS_FLOAT64_ARRAY) { ret = JS_AtomIsNumericIndex(ctx, prop); if (ret != 0) { if (ret < 0) { @@ -7495,7 +7863,7 @@ int JS_SetPropertyInternal(JSContext *ctx, JSValueConst this_obj, JS_FreeValue(ctx, val); if (JS_IsException(val)) return -1; - if (typed_array_is_detached(ctx, p)) { + if (typed_array_is_detached(ctx, p1)) { JS_ThrowTypeErrorDetachedArrayBuffer(ctx); return -1; } @@ -8598,6 +8966,7 @@ static int JS_SetGlobalVar(JSContext *ctx, JSAtom prop, JSValue val, /* XXX: should handle JS_PROP_AUTOINIT properties? */ if (flag != 1) { if (unlikely(JS_IsUninitialized(pr->u.value))) { + JS_FreeValue(ctx, val); JS_ThrowReferenceErrorUninitialized(ctx, prs->atom); return -1; } @@ -10661,7 +11030,7 @@ static double js_pow(double a, double b) #ifdef CONFIG_BIGNUM -static JSValue JS_NewBigInt64(JSContext *ctx, int64_t v) +JSValue JS_NewBigInt64(JSContext *ctx, int64_t v) { BOOL is_bignum = is_bignum_mode(ctx); if (is_bignum && v == (int32_t)v) { @@ -10674,7 +11043,7 @@ static JSValue JS_NewBigInt64(JSContext *ctx, int64_t v) } } -static JSValue JS_NewBigUint64(JSContext *ctx, uint64_t v) +JSValue JS_NewBigUint64(JSContext *ctx, uint64_t v) { BOOL is_bignum = is_bignum_mode(ctx); if (is_bignum && v == (int32_t)v) { @@ -10846,7 +11215,7 @@ static bf_t *JS_ToBigInt(JSContext *ctx, bf_t *buf, JSValueConst val) return JS_ToBigIntFree(ctx, buf, JS_DupValue(ctx, val)); } -static JSValue JS_ToBigIntValueFree(JSContext *ctx, JSValue val) +static __attribute__((unused)) JSValue JS_ToBigIntValueFree(JSContext *ctx, JSValue val) { if (JS_VALUE_GET_TAG(val) == JS_TAG_BIG_INT) { return val; @@ -10886,7 +11255,7 @@ static int JS_ToBigInt64Free(JSContext *ctx, int64_t *pres, JSValue val) return 0; } -static int JS_ToBigInt64(JSContext *ctx, int64_t *pres, JSValueConst val) +int JS_ToBigInt64(JSContext *ctx, int64_t *pres, JSValueConst val) { return JS_ToBigInt64Free(ctx, pres, JS_DupValue(ctx, val)); } @@ -13316,7 +13685,7 @@ static JSValue build_for_in_iterator(JSContext *ctx, JSValue obj) /* fast path: assume no enumerable properties in the prototype chain */ p1 = p->shape->proto; while (p1 != NULL) { - if (JS_GetOwnPropertyNames(ctx, &tab_atom, &tab_atom_count, p1, + if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count, p1, JS_GPN_STRING_MASK | JS_GPN_ENUM_ONLY)) goto fail; js_free_prop_enum(ctx, tab_atom, tab_atom_count); @@ -13348,7 +13717,7 @@ static JSValue build_for_in_iterator(JSContext *ctx, JSValue obj) it->array_length = p->u.array.count; } else { normal_case: - if (JS_GetOwnPropertyNames(ctx, &tab_atom, &tab_atom_count, p, + if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count, p, JS_GPN_STRING_MASK | JS_GPN_ENUM_ONLY)) goto fail; for(i = 0; i < tab_atom_count; i++) { @@ -13362,7 +13731,7 @@ static JSValue build_for_in_iterator(JSContext *ctx, JSValue obj) /* non enumerable properties hide the enumerables ones in the prototype chain */ while (p != NULL) { - if (JS_GetOwnPropertyNames(ctx, &tab_atom, &tab_atom_count, p, + if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count, p, JS_GPN_STRING_MASK | JS_GPN_SET_ENUM)) goto fail; for(i = 0; i < tab_atom_count; i++) { @@ -13852,7 +14221,7 @@ static __exception int JS_CopyDataProperties(JSContext *ctx, pexcl = JS_VALUE_GET_OBJ(excluded); p = JS_VALUE_GET_OBJ(source); - if (JS_GetOwnPropertyNames(ctx, &tab_atom, &tab_atom_count, p, + if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count, p, JS_GPN_STRING_MASK | JS_GPN_SYMBOL_MASK | JS_GPN_ENUM_ONLY)) return -1; @@ -13861,7 +14230,7 @@ static __exception int JS_CopyDataProperties(JSContext *ctx, for (i = 0; i < tab_atom_count; i++) { if (pexcl) { - ret = JS_GetOwnProperty(ctx, NULL, pexcl, tab_atom[i].atom); + ret = JS_GetOwnPropertyInternal(ctx, NULL, pexcl, tab_atom[i].atom); if (ret) { if (ret < 0) break; @@ -14045,7 +14414,7 @@ static JSValue js_closure(JSContext *ctx, JSValue bfunc, #define JS_DEFINE_CLASS_HAS_HERITAGE (1 << 0) static int js_op_define_class(JSContext *ctx, JSValue *sp, - int class_flags, + JSAtom class_name, int class_flags, JSVarRef **cur_var_refs, JSStackFrame *sf) { @@ -14113,6 +14482,11 @@ static int js_op_define_class(JSContext *ctx, JSValue *sp, set_cycle_flag(ctx, ctor); set_cycle_flag(ctx, proto); + if (class_name != JS_ATOM_NULL) { + if (JS_DefineObjectName(ctx, ctor, class_name, JS_PROP_CONFIGURABLE) < 0) + goto fail; + } + JS_FreeValue(ctx, parent_proto); JS_FreeValue(ctx, parent_class); @@ -14185,6 +14559,12 @@ static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj, p = JS_VALUE_GET_OBJ(func_obj); cproto = p->u.cfunc.cproto; + arg_count = p->u.cfunc.length; + + /* better to always check stack overflow */ + if (js_check_stack_overflow(ctx, sizeof(arg_buf[0]) * arg_count)) + return JS_ThrowStackOverflow(ctx); + prev_sf = ctx->current_stack_frame; sf->prev_frame = prev_sf; ctx->current_stack_frame = sf; @@ -14202,11 +14582,6 @@ static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj, sf->arg_count = argc; arg_buf = argv; - arg_count = p->u.cfunc.length; - /* better to always check stack overflow */ - if (js_check_stack_overflow(ctx, sizeof(arg_buf[0]) * arg_count)) - return JS_ThrowStackOverflow(ctx); - if (unlikely(argc < arg_count)) { /* ensure that at least argc_count arguments are readable */ arg_buf = alloca(sizeof(arg_buf[0]) * arg_count); @@ -14370,6 +14745,7 @@ typedef enum { OP_SPECIAL_OBJECT_THIS_FUNC, OP_SPECIAL_OBJECT_NEW_TARGET, OP_SPECIAL_OBJECT_HOME_OBJECT, + OP_SPECIAL_OBJECT_VAR_OBJECT, } OPSpecialObjectEnum; #define FUNC_RET_AWAIT 0 @@ -14398,9 +14774,13 @@ static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj, #else static const void * const dispatch_table[256] = { #define DEF(id, size, n_pop, n_push, f) && case_OP_ ## id, +#if SHORT_OPCODES +#define def(id, size, n_pop, n_push, f) +#else #define def(id, size, n_pop, n_push, f) && case_default, +#endif #include "quickjs-opcode.h" - [ OP_nop + 1 ... 255 ] = &&case_default + [ OP_COUNT ... 255 ] = &&case_default }; #define SWITCH(pc) goto *dispatch_table[opcode = *pc++]; #define CASE(op) case_ ## op @@ -14599,11 +14979,6 @@ static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj, if (unlikely(JS_IsException(sp[-1]))) goto exception; BREAK; - CASE(OP_var_object): - *sp++ = JS_NewObjectProto(ctx, JS_NULL); - if (unlikely(JS_IsException(sp[-1]))) - goto exception; - BREAK; CASE(OP_special_object): { int arg = *pc++; @@ -14635,6 +15010,11 @@ static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj, *sp++ = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p1)); } break; + case OP_SPECIAL_OBJECT_VAR_OBJECT: + *sp++ = JS_NewObjectProto(ctx, JS_NULL); + if (unlikely(JS_IsException(sp[-1]))) + goto exception; + break; default: abort(); } @@ -14932,7 +15312,18 @@ static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj, goto exception; } BREAK; - + CASE(OP_check_brand): + if (JS_CheckBrand(ctx, sp[-2], sp[-1]) < 0) + goto exception; + BREAK; + CASE(OP_add_brand): + if (JS_AddBrand(ctx, sp[-2], sp[-1]) < 0) + goto exception; + JS_FreeValue(ctx, sp[-2]); + JS_FreeValue(ctx, sp[-1]); + sp -= 2; + BREAK; + CASE(OP_throw): JS_Throw(ctx, *--sp); goto exception; @@ -15725,6 +16116,57 @@ static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj, } BREAK; + CASE(OP_private_symbol): + { + JSAtom atom; + JSValue val; + + atom = get_u32(pc); + pc += 4; + val = JS_NewSymbolFromAtom(ctx, atom, JS_ATOM_TYPE_PRIVATE); + if (JS_IsException(val)) + goto exception; + *sp++ = val; + } + BREAK; + + CASE(OP_get_private_field): + { + JSValue val; + + val = JS_GetPrivateField(ctx, sp[-2], sp[-1]); + JS_FreeValue(ctx, sp[-1]); + JS_FreeValue(ctx, sp[-2]); + sp[-2] = val; + sp--; + if (unlikely(JS_IsException(val))) + goto exception; + } + BREAK; + + CASE(OP_put_private_field): + { + int ret; + ret = JS_SetPrivateField(ctx, sp[-3], sp[-1], sp[-2]); + JS_FreeValue(ctx, sp[-3]); + JS_FreeValue(ctx, sp[-1]); + sp -= 3; + if (unlikely(ret < 0)) + goto exception; + } + BREAK; + + CASE(OP_define_private_field): + { + int ret; + ret = JS_DefinePrivateField(ctx, sp[-3], sp[-2], sp[-1]); + JS_FreeValue(ctx, sp[-2]); + sp -= 2; + if (unlikely(ret < 0)) + goto exception; + } + BREAK; + CASE(OP_define_field): { int ret; @@ -15772,6 +16214,9 @@ static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj, sp--; } BREAK; + CASE(OP_set_home_object): + js_method_set_home_object(ctx, sp[-1], sp[-2]); + BREAK; CASE(OP_define_method): CASE(OP_define_method_computed): { @@ -15835,9 +16280,12 @@ static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj, CASE(OP_define_class): { int class_flags; - - class_flags = *pc++; - if (js_op_define_class(ctx, sp, class_flags, + JSAtom atom; + + atom = get_u32(pc); + class_flags = pc[4]; + pc += 5; + if (js_op_define_class(ctx, sp, atom, class_flags, var_refs, sf) < 0) goto exception; } @@ -15956,12 +16404,12 @@ static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj, atom, sp[-1], sp[-4], JS_PROP_THROW_STRICT); JS_FreeAtom(ctx, atom); - if (ret < 0) - goto exception; JS_FreeValue(ctx, sp[-4]); JS_FreeValue(ctx, sp[-3]); JS_FreeValue(ctx, sp[-2]); sp -= 4; + if (ret < 0) + goto exception; } BREAK; @@ -16736,6 +17184,7 @@ static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj, sp[-1] = JS_FALSE; BREAK; #endif + CASE(OP_invalid): DEFAULT: JS_ThrowInternalError(ctx, "invalid opcode: pc=%u opcode=0x%02x", (int)(pc - b->byte_code_buf - 1), opcode); @@ -16837,8 +17286,8 @@ static JSValue js_create_from_ctor(JSContext *ctx, JSValueConst ctor, /* check if revoked proxy */ { JSProxyData *s = JS_GetOpaque(ctor, JS_CLASS_PROXY); - if (s && JS_IsNull(s->handler)) - return JS_ThrowTypeError(ctx, "revoked proxy"); + if (s && s->is_revoked) + return JS_ThrowTypeErrorRevokedProxy(ctx); } /* XXX: should use the ctor realm instead of 'ctx' */ proto = JS_DupValue(ctx, ctx->class_proto[class_id]); @@ -16957,8 +17406,8 @@ static __exception int async_func_init(JSContext *ctx, JSAsyncFunctionState *s, sf->cur_pc = b->byte_code_buf; arg_buf_len = max_int(b->arg_count, argc); local_count = arg_buf_len + b->var_count + b->stack_size; - sf->arg_buf = js_malloc(ctx, sizeof(JSValue) * local_count); - if (!sf->arg_buf && local_count != 0) + sf->arg_buf = js_malloc(ctx, sizeof(JSValue) * max_int(local_count, 1)); + if (!sf->arg_buf) return -1; sf->cur_func = JS_DupValue(ctx, func_obj); s->this_val = JS_DupValue(ctx, this_obj); @@ -17932,6 +18381,7 @@ enum { TOK_ARROW, TOK_ELLIPSIS, TOK_ERROR, + TOK_PRIVATE_NAME, TOK_EOF, /* keywords: WARNING: same order as atoms */ TOK_NULL, /* must be first */ @@ -18088,6 +18538,7 @@ typedef struct JSFunctionDef { throw a syntax error */ BOOL super_call_allowed; /* true if super() is allowed */ BOOL super_allowed; /* true if super. or super[] is allowed */ + BOOL arguments_allowed; /* true if the 'arguments' identifier is allowed */ BOOL is_derived_class_constructor; BOOL in_function_body; JSFunctionKindEnum func_kind : 8; @@ -18111,7 +18562,8 @@ typedef struct JSFunctionDef { int new_target_var_idx; /* variable containg the 'new.target' value, -1 if none */ int this_active_func_var_idx; /* variable containg the 'this.active_func' value, -1 if none */ int home_object_var_idx; - + BOOL need_home_object; + int scope_level; /* index into fd->scopes if the current lexical scope */ int scope_first; /* index into vd->vars of first lexically scoped variable */ int scope_size; /* allocated size of fd->scopes array */ @@ -18126,7 +18578,8 @@ typedef struct JSFunctionDef { DynBuf byte_code; int last_opcode_pos; /* -1 if no last opcode */ int last_opcode_line_num; - + BOOL use_short_opcodes; /* true if short opcodes are used in byte_code */ + LabelSlot *label_slots; int label_size; /* allocated size for label_slots[] */ int label_count; @@ -18219,7 +18672,7 @@ typedef struct JSOpCode { uint8_t fmt; } JSOpCode; -static const JSOpCode opcode_info[OP_COUNT] = { +static const JSOpCode opcode_info[OP_COUNT + (OP_TEMP_END - OP_TEMP_START)] = { #define FMT(f) #ifdef DUMP_BYTECODE #define DEF(id, size, n_pop, n_push, f) { #id, size, n_pop, n_push, OP_FMT_ ## f }, @@ -18231,6 +18684,18 @@ static const JSOpCode opcode_info[OP_COUNT] = { #undef FMT }; +#if SHORT_OPCODES +/* After the final compilation pass, short opcodes are used. Their + opcodes overlap with the temporary opcodes which cannot appear in + the final bytecode. Their description is after the temporary + opcodes in opcode_info[]. */ +#define short_opcode_info(op) \ + opcode_info[(op) >= OP_TEMP_START ? \ + (op) + (OP_TEMP_END - OP_TEMP_START) : (op)] +#else +#define short_opcode_info(op) opcode_info[op] +#endif + static __exception int next_token(JSParseState *s); static void free_token(JSParseState *s, JSToken *token) @@ -18251,6 +18716,7 @@ static void free_token(JSParseState *s, JSToken *token) break; case TOK_IDENT: case TOK_FIRST_KEYWORD ... TOK_LAST_KEYWORD: + case TOK_PRIVATE_NAME: JS_FreeAtom(s->ctx, token->u.ident.atom); break; default: @@ -18532,15 +18998,6 @@ static __exception int js_parse_string(JSParseState *s, int sep, if (c > 0x10FFFF) goto invalid_utf8; p = p_next; -#ifndef JSON_SUPERSET - /* LS or PS are invalid in Javascript string literals, considered - as line terminators, but allowed in JSON source and template - literals. - ECMA 2019 proposal json-superset removes this restriction. - */ - if ((c == CP_LS || c == CP_PS) && sep != '`' && s->cur_func) - goto invalid_char; -#endif } if (string_buffer_putc(b, c)) goto fail; @@ -18896,6 +19353,53 @@ static __exception int next_token(JSParseState *s) s->token.val = TOK_IDENT; } break; + case '#': + /* private name */ + { + const uint8_t *p1; + p++; + q = buf; + *q++ = '#'; + p1 = p; + c = *p1++; + if (c == '\\' && *p1 == 'u') { + c = lre_parse_escape(&p1, TRUE); + } else if (c >= 128) { + c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p1); + } + if (!lre_js_is_ident_first(c)) { + js_parse_error(s, "invalid first character of private name"); + goto fail; + } + p = p1; + for(;;) { + if (c < 128) { + *q++ = c; + } else { + q += unicode_to_utf8((uint8_t*)q, c); + } + p1 = p; + c = *p1++; + if (c == '\\' && *p1 == 'u') { + c = lre_parse_escape(&p1, TRUE); + ident_has_escape = TRUE; + } else if (c >= 128) { + c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p1); + } + /* XXX: check if c >= 0 and c <= 0x10FFFF */ + if (!lre_js_is_ident_next(c)) + break; + p = p1; + if ((q - buf) >= sizeof(buf) - UTF8_CHAR_LEN_MAX) { + js_parse_error(s, "private name too long"); + goto fail; + } + } + *q = '\0'; + s->token.u.ident.atom = JS_NewAtomLen(s->ctx, buf, q - buf); + s->token.val = TOK_PRIVATE_NAME; + } + break; case '.': if (p[1] == '.' && p[2] == '.') { p += 3; @@ -18961,7 +19465,8 @@ static __exception int next_token(JSParseState *s) is_bigint = FALSE; is_bigfloat = FALSE; if (*p == 'n') { - if (!(res & BF_ATOF_ST_INTEGER)) { + if (!(res & BF_ATOF_ST_INTEGER) || + (res & BF_ATOF_ST_LEGACY_OCTAL)) { bf_delete(r); goto bad_number; } @@ -19552,7 +20057,8 @@ static int find_lexical_decl(JSContext *ctx, JSFunctionDef *fd, JSAtom name, while (scope_idx >= 0) { JSVarDef *vd = &fd->vars[scope_idx]; if (vd->var_name == name && - (vd->is_lexical || (vd->is_catch && check_catch_var))) + (vd->is_lexical || (vd->var_kind == JS_VAR_CATCH && + check_catch_var))) return scope_idx; scope_idx = vd->scope_next; } @@ -19768,7 +20274,7 @@ static int define_var(JSParseState *s, JSFunctionDef *fd, JSAtom name, int tok) if (idx >= 0) { if ((idx < GLOBAL_VAR_OFFSET && (fd->vars[idx].scope_level == fd->scope_level || - (fd->vars[idx].is_catch && (fd->vars[idx].scope_level + 2) == fd->scope_level))) || + (fd->vars[idx].var_kind == JS_VAR_CATCH && (fd->vars[idx].scope_level + 2) == fd->scope_level))) || (idx == GLOBAL_VAR_OFFSET && fd->scope_level == 1)) { /* redefining a scoped var in the same scope: error */ return js_parse_error(s, "invalid redefinition of lexical identifier"); @@ -19827,7 +20333,7 @@ static int define_var(JSParseState *s, JSFunctionDef *fd, JSAtom name, int tok) idx = add_var(ctx, fd, name); if (idx >= 0) { vd = &fd->vars[idx]; - vd->is_catch = 1; + vd->var_kind = JS_VAR_CATCH; vd->scope_level = fd->scope_level; vd->scope_next = fd->scope_first; fd->scopes[fd->scope_level].first = idx; @@ -19877,6 +20383,7 @@ static __exception int js_parse_function_decl(JSParseState *s, JSFunctionKindEnum func_kind, JSAtom func_name, const uint8_t *ptr, int start_line); +static JSFunctionDef *js_parse_function_class_fields_init(JSParseState *s); static __exception int js_parse_function_decl2(JSParseState *s, JSParseFunctionEnum func_type, JSFunctionKindEnum func_kind, @@ -20032,6 +20539,8 @@ static __exception int js_parse_template(JSParseState *s, int call, int *argc) #define PROP_TYPE_ASYNC 5 #define PROP_TYPE_ASYNC_STAR 6 +#define PROP_TYPE_PRIVATE (1 << 4) + static BOOL token_is_ident(int tok) { /* Accept keywords and reserved words as property names */ @@ -20043,11 +20552,13 @@ static BOOL token_is_ident(int tok) /* if the property is an expression, name = JS_ATOM_NULL */ static int __exception js_parse_property_name(JSParseState *s, JSAtom *pname, - BOOL allow_method, BOOL allow_var) + BOOL allow_method, BOOL allow_var, + BOOL allow_private) { + int is_private = 0; JSAtom name; int prop_type; - + prop_type = PROP_TYPE_IDENT; if (allow_method) { if (token_is_pseudo_keyword(s, JS_ATOM_get) @@ -20067,8 +20578,13 @@ static int __exception js_parse_property_name(JSParseState *s, prop_type = PROP_TYPE_STAR; } else if (token_is_pseudo_keyword(s, JS_ATOM_async) && peek_token(s, TRUE) != '\n') { + name = JS_DupAtom(s->ctx, s->token.u.ident.atom); if (next_token(s)) - goto fail; + goto fail1; + if (s->token.val == ':' || s->token.val == ',' || + s->token.val == '}' || s->token.val == '(') + goto done; + JS_FreeAtom(s->ctx, name); if (s->token.val == '*') { if (next_token(s)) goto fail; @@ -20127,6 +20643,11 @@ static int __exception js_parse_property_name(JSParseState *s, if (js_parse_expect(s, ']')) goto fail; name = JS_ATOM_NULL; + } else if (s->token.val == TOK_PRIVATE_NAME && allow_private) { + name = JS_DupAtom(s->ctx, s->token.u.ident.atom); + if (next_token(s)) + goto fail1; + is_private = PROP_TYPE_PRIVATE; } else { goto invalid_prop; } @@ -20139,7 +20660,7 @@ static int __exception js_parse_property_name(JSParseState *s, } done: *pname = name; - return prop_type; + return prop_type | is_private; fail1: JS_FreeAtom(s->ctx, name); fail: @@ -20303,7 +20824,7 @@ static __exception int js_parse_object_literal(JSParseState *s) goto next; } - prop_type = js_parse_property_name(s, &name, TRUE, TRUE); + prop_type = js_parse_property_name(s, &name, TRUE, TRUE, FALSE); if (prop_type < 0) goto fail; @@ -20424,20 +20945,165 @@ static __exception int js_parse_class_default_ctor(JSParseState *s, return ret; } +/* find field in the current scope */ +static int find_private_class_field(JSContext *ctx, JSFunctionDef *fd, + JSAtom name, int scope_level) +{ + int idx; + idx = fd->scopes[scope_level].first; + while (idx != -1) { + if (fd->vars[idx].scope_level != scope_level) + break; + if (fd->vars[idx].var_name == name) + return idx; + idx = fd->vars[idx].scope_next; + } + return -1; +} + +/* add field in the current scope */ +static int add_private_class_field(JSParseState *s, JSFunctionDef *fd, + JSAtom name, JSVarKindEnum var_kind) +{ + JSContext *ctx = s->ctx; + JSVarDef *vd; + int idx; + + idx = add_var(ctx, fd, name); + if (idx < 0) + return idx; + vd = &fd->vars[idx]; + vd->is_lexical = 1; + vd->is_const = 1; + vd->var_kind = var_kind; + vd->scope_level = fd->scope_level; + vd->scope_next = fd->scope_first; + fd->scopes[fd->scope_level].first = idx; + fd->scope_first = idx; + return idx; +} + +/* initialize the class fields, called by the constructor. Note: + super() can be called in an arrow function, so and + can be variable references */ +static void emit_class_field_init(JSParseState *s) +{ + int label_next; + + emit_op(s, OP_scope_get_var); + emit_atom(s, JS_ATOM_class_fields_init); + emit_u16(s, s->cur_func->scope_level); + + /* no need to call the class field initializer if not defined */ + emit_op(s, OP_dup); + label_next = emit_goto(s, OP_if_false, -1); + + emit_op(s, OP_scope_get_var); + emit_atom(s, JS_ATOM_this); + emit_u16(s, 0); + + emit_op(s, OP_swap); + + emit_op(s, OP_call_method); + emit_u16(s, 0); + + emit_label(s, label_next); + emit_op(s, OP_drop); +} + +/* build a private setter function name from the private getter name */ +static JSAtom get_private_setter_name(JSContext *ctx, JSAtom name) +{ + return js_atom_concat_str(ctx, name, ""); +} + +typedef struct { + JSFunctionDef *fields_init_fd; + int computed_fields_count; + BOOL has_brand; + int brand_push_pos; +} ClassFieldsDef; + +static __exception int emit_class_init_start(JSParseState *s, + ClassFieldsDef *cf) +{ + int label_add_brand; + + cf->fields_init_fd = js_parse_function_class_fields_init(s); + if (!cf->fields_init_fd) + return -1; + + s->cur_func = cf->fields_init_fd; + + /* XXX: would be better to add the code only if needed, maybe in a + later pass */ + emit_op(s, OP_push_false); /* will be patched later */ + cf->brand_push_pos = cf->fields_init_fd->last_opcode_pos; + label_add_brand = emit_goto(s, OP_if_false, -1); + + emit_op(s, OP_scope_get_var); + emit_atom(s, JS_ATOM_this); + emit_u16(s, 0); + + emit_op(s, OP_scope_get_var); + emit_atom(s, JS_ATOM_home_object); + emit_u16(s, 0); + + emit_op(s, OP_add_brand); + + emit_label(s, label_add_brand); + + s->cur_func = s->cur_func->parent; + return 0; +} + +static __exception int add_brand(JSParseState *s, ClassFieldsDef *cf) +{ + if (!cf->has_brand) { + /* define the brand field in 'this' of the initializer */ + if (!cf->fields_init_fd) { + if (emit_class_init_start(s, cf)) + return -1; + } + /* patch the start of the function to enable the OP_add_brand code */ + cf->fields_init_fd->byte_code.buf[cf->brand_push_pos] = OP_push_true; + + cf->has_brand = TRUE; + } + return 0; +} + +static void emit_class_init_end(JSParseState *s, ClassFieldsDef *cf) +{ + int cpool_idx; + + s->cur_func = cf->fields_init_fd; + emit_op(s, OP_return_undef); + s->cur_func = s->cur_func->parent; + + cpool_idx = cpool_add(s, JS_NULL); + cf->fields_init_fd->parent_cpool_idx = cpool_idx; + emit_op(s, OP_fclosure); + emit_u32(s, cpool_idx); + emit_op(s, OP_set_home_object); +} + + static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr, JSParseExportEnum export_flag) { JSContext *ctx = s->ctx; JSFunctionDef *fd = s->cur_func; - JSAtom name = JS_ATOM_NULL, class_name = JS_ATOM_NULL; + JSAtom name = JS_ATOM_NULL, class_name = JS_ATOM_NULL, class_name1; JSAtom class_var_name = JS_ATOM_NULL; JSFunctionDef *method_fd, *ctor_fd; int saved_js_mode, class_name_var_idx, prop_type, ctor_cpool_offset; - int class_flags = 0; - BOOL is_static; + int class_flags = 0, i; + BOOL is_static, is_private; const uint8_t *class_start_ptr = s->token.ptr; const uint8_t *start_ptr; - + ClassFieldsDef class_fields[2]; + /* classes are parsed and executed in strict mode */ saved_js_mode = fd->js_mode; fd->js_mode |= JS_MODE_STRICT; @@ -20486,13 +21152,29 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr, if (js_parse_expect(s, '{')) goto fail; + /* this scope contains the private fields */ + push_scope(s); + emit_op(s, OP_push_const); ctor_cpool_offset = fd->byte_code.size; emit_u32(s, 0); /* will be patched at the end of the class parsing */ + if (class_var_name != JS_ATOM_NULL && class_name == JS_ATOM_NULL) + class_name1 = JS_ATOM_default; + else + class_name1 = class_name; + emit_op(s, OP_define_class); + emit_atom(s, class_name1); emit_u8(s, class_flags); + for(i = 0; i < 2; i++) { + ClassFieldsDef *cf = &class_fields[i]; + cf->fields_init_fd = NULL; + cf->computed_fields_count = 0; + cf->has_brand = FALSE; + } + ctor_fd = NULL; while (s->token.val != '}') { if (s->token.val == ';') { @@ -20508,33 +21190,169 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr, if (is_static) emit_op(s, OP_swap); start_ptr = s->token.ptr; - prop_type = js_parse_property_name(s, &name, TRUE, FALSE); + prop_type = js_parse_property_name(s, &name, TRUE, FALSE, TRUE); if (prop_type < 0) goto fail; - + is_private = prop_type & PROP_TYPE_PRIVATE; + prop_type &= ~PROP_TYPE_PRIVATE; + if ((name == JS_ATOM_constructor && !is_static && prop_type != PROP_TYPE_IDENT) || - (name == JS_ATOM_prototype && is_static)) { + (name == JS_ATOM_prototype && is_static) || + name == JS_ATOM_hash_constructor) { js_parse_error(s, "invalid method name"); goto fail; } if (prop_type == PROP_TYPE_GET || prop_type == PROP_TYPE_SET) { BOOL is_set = prop_type - PROP_TYPE_GET; - if (js_parse_function_decl(s, JS_PARSE_FUNC_GETTER + is_set, - JS_FUNC_NORMAL, JS_ATOM_NULL, - start_ptr, s->token.line_num)) + JSFunctionDef *method_fd; + + if (is_private) { + int idx, var_kind; + idx = find_private_class_field(ctx, fd, name, fd->scope_level); + if (idx >= 0) { + var_kind = fd->vars[idx].var_kind; + if (var_kind == JS_VAR_PRIVATE_FIELD || + var_kind == JS_VAR_PRIVATE_METHOD || + var_kind == JS_VAR_PRIVATE_GETTER_SETTER || + var_kind == (JS_VAR_PRIVATE_GETTER + is_set)) { + goto private_field_already_defined; + } + fd->vars[idx].var_kind = JS_VAR_PRIVATE_GETTER_SETTER; + } else { + if (add_private_class_field(s, fd, name, + JS_VAR_PRIVATE_GETTER + is_set) < 0) + goto fail; + } + if (add_brand(s, &class_fields[is_static]) < 0) + goto fail; + } + + if (js_parse_function_decl2(s, JS_PARSE_FUNC_GETTER + is_set, + JS_FUNC_NORMAL, JS_ATOM_NULL, + start_ptr, s->token.line_num, + JS_PARSE_EXPORT_NONE, &method_fd)) goto fail; + if (is_private) { + method_fd->need_home_object = TRUE; /* needed for brand check */ + emit_op(s, OP_set_home_object); + /* XXX: missing function name */ + emit_op(s, OP_scope_put_var_init); + if (is_set) { + JSAtom setter_name; + int ret; + + setter_name = get_private_setter_name(ctx, name); + if (setter_name == JS_ATOM_NULL) + goto fail; + emit_atom(s, setter_name); + ret = add_private_class_field(s, fd, setter_name, + JS_VAR_PRIVATE_SETTER); + JS_FreeAtom(ctx, setter_name); + if (ret < 0) + goto fail; + } else { + emit_atom(s, name); + } + emit_u16(s, s->cur_func->scope_level); + } else { + if (name == JS_ATOM_NULL) { + emit_op(s, OP_define_method_computed); + } else { + emit_op(s, OP_define_method); + emit_atom(s, name); + } + emit_u8(s, OP_DEFINE_METHOD_GETTER + is_set); + } + } else if (prop_type == PROP_TYPE_IDENT && s->token.val != '(') { + ClassFieldsDef *cf = &class_fields[is_static]; + JSAtom field_var_name = JS_ATOM_NULL; + + /* class field */ + + /* XXX: spec: not consistent with method name checks */ + if (name == JS_ATOM_constructor || name == JS_ATOM_prototype) { + js_parse_error(s, "invalid field name"); + goto fail; + } + + if (is_private) { + if (find_private_class_field(ctx, fd, name, + fd->scope_level) >= 0) { + goto private_field_already_defined; + } + if (add_private_class_field(s, fd, name, + JS_VAR_PRIVATE_FIELD) < 0) + goto fail; + emit_op(s, OP_private_symbol); + emit_atom(s, name); + emit_op(s, OP_scope_put_var_init); + emit_atom(s, name); + emit_u16(s, s->cur_func->scope_level); + } + + if (!cf->fields_init_fd) { + if (emit_class_init_start(s, cf)) + goto fail; + } + if (name == JS_ATOM_NULL ) { + /* save the computed field name into a variable */ + field_var_name = js_atom_concat_num(ctx, JS_ATOM_computed_field + is_static, cf->computed_fields_count); + if (field_var_name == JS_ATOM_NULL) + goto fail; + if (define_var(s, fd, field_var_name, TOK_CONST) < 0) { + JS_FreeAtom(ctx, field_var_name); + goto fail; + } + emit_op(s, OP_to_propkey); + emit_op(s, OP_scope_put_var_init); + emit_atom(s, field_var_name); + emit_u16(s, s->cur_func->scope_level); + } + s->cur_func = cf->fields_init_fd; + emit_op(s, OP_scope_get_var); + emit_atom(s, JS_ATOM_this); + emit_u16(s, 0); + if (name == JS_ATOM_NULL) { - emit_op(s, OP_define_method_computed); + emit_op(s, OP_scope_get_var); + emit_atom(s, field_var_name); + emit_u16(s, s->cur_func->scope_level); + cf->computed_fields_count++; + JS_FreeAtom(ctx, field_var_name); + } else if (is_private) { + emit_op(s, OP_scope_get_var); + emit_atom(s, name); + emit_u16(s, s->cur_func->scope_level); + } + + if (s->token.val == '=') { + if (next_token(s)) + goto fail; + if (js_parse_assign_expr(s, TRUE)) + goto fail; } else { - emit_op(s, OP_define_method); + emit_op(s, OP_undefined); + } + if (is_private) { + set_object_name_computed(s); + emit_op(s, OP_define_private_field); + } else if (name == JS_ATOM_NULL) { + set_object_name_computed(s); + emit_op(s, OP_define_array_el); + emit_op(s, OP_drop); + } else { + set_object_name(s, name); + emit_op(s, OP_define_field); emit_atom(s, name); } - emit_u8(s, OP_DEFINE_METHOD_GETTER + is_set); + s->cur_func = s->cur_func->parent; + if (js_parse_expect_semi(s)) + goto fail; } else { JSParseFunctionEnum func_type; JSFunctionKindEnum func_kind; - + func_type = JS_PARSE_FUNC_METHOD; func_kind = JS_FUNC_NORMAL; if (prop_type == PROP_TYPE_STAR) { @@ -20553,11 +21371,32 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr, else func_type = JS_PARSE_FUNC_CLASS_CONSTRUCTOR; } + if (is_private) { + if (add_brand(s, &class_fields[is_static]) < 0) + goto fail; + } if (js_parse_function_decl2(s, func_type, func_kind, JS_ATOM_NULL, start_ptr, s->token.line_num, JS_PARSE_EXPORT_NONE, &method_fd)) goto fail; if (func_type == JS_PARSE_FUNC_DERIVED_CLASS_CONSTRUCTOR || func_type == JS_PARSE_FUNC_CLASS_CONSTRUCTOR) { ctor_fd = method_fd; + } else if (is_private) { + method_fd->need_home_object = TRUE; /* needed for brand check */ + if (find_private_class_field(ctx, fd, name, + fd->scope_level) >= 0) { + private_field_already_defined: + js_parse_error(s, "private class field is already defined"); + goto fail; + } + if (add_private_class_field(s, fd, name, + JS_VAR_PRIVATE_METHOD) < 0) + goto fail; + emit_op(s, OP_set_home_object); + emit_op(s, OP_set_name); + emit_atom(s, name); + emit_op(s, OP_scope_put_var_init); + emit_atom(s, name); + emit_u16(s, s->cur_func->scope_level); } else { if (name == JS_ATOM_NULL) { emit_op(s, OP_define_method_computed); @@ -20579,9 +21418,6 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr, goto fail; } - /* drop the prototype */ - emit_op(s, OP_drop); - if (!ctor_fd) { if (js_parse_class_default_ctor(s, class_flags & JS_DEFINE_CLASS_HAS_HERITAGE, &ctor_fd)) goto fail; @@ -20603,6 +21439,38 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr, if (next_token(s)) goto fail; + /* store the function to initialize the fields to that it can be + referenced by the constructor */ + { + ClassFieldsDef *cf = &class_fields[0]; + int var_idx; + + var_idx = define_var(s, fd, JS_ATOM_class_fields_init, TOK_CONST); + if (var_idx < 0) + goto fail; + if (cf->fields_init_fd) { + emit_class_init_end(s, cf); + } else { + emit_op(s, OP_undefined); + } + emit_op(s, OP_scope_put_var_init); + emit_atom(s, JS_ATOM_class_fields_init); + emit_u16(s, s->cur_func->scope_level); + } + + /* drop the prototype */ + emit_op(s, OP_drop); + + /* initialize the static fields */ + if (class_fields[1].fields_init_fd != NULL) { + ClassFieldsDef *cf = &class_fields[1]; + emit_op(s, OP_dup); + emit_class_init_end(s, cf); + emit_op(s, OP_call_method); + emit_u16(s, 0); + emit_op(s, OP_drop); + } + if (class_name != JS_ATOM_NULL) { /* store the class name in the scoped class name variable (it is independent from the class statement variable @@ -20613,28 +21481,23 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr, emit_u16(s, fd->scope_level); } pop_scope(s); + pop_scope(s); /* the class statements have a block level scope */ if (class_var_name != JS_ATOM_NULL) { - emit_op(s, OP_set_name); - if (class_name == JS_ATOM_NULL) { - /* only happens when export_flag == JS_PARSE_EXPORT_DEFAULT */ - emit_atom(s, JS_ATOM_default); - } else { - emit_atom(s, class_name); - } if (define_var(s, fd, class_var_name, TOK_LET) < 0) goto fail; emit_op(s, OP_scope_put_var_init); emit_atom(s, class_var_name); emit_u16(s, fd->scope_level); } else { - emit_op(s, OP_set_name); - emit_atom(s, class_name); - /* if class_name = JS_ATOM_NULL, it will be set upon storing into - a named variable or property */ - if (class_name != JS_ATOM_NULL) - fd->last_opcode_pos = -1; + if (class_name == JS_ATOM_NULL) { + /* XXX: should be done before calling the initializers. It + could be done with a specific opcode to patch the code + before */ + emit_op(s, OP_set_name); + emit_atom(s, class_name); /* will be patched by assignment */ + } } if (export_flag != JS_PARSE_EXPORT_NONE) { @@ -20842,6 +21705,11 @@ static __exception int get_lvalue(JSParseState *s, int *popcode, int *pscope, name = get_u32(fd->byte_code.buf + fd->last_opcode_pos + 1); depth = 1; break; + case OP_scope_get_private_field: + name = get_u32(fd->byte_code.buf + fd->last_opcode_pos + 1); + scope = get_u16(fd->byte_code.buf + fd->last_opcode_pos + 5); + depth = 1; + break; case OP_get_array_el: depth = 2; break; @@ -20881,6 +21749,11 @@ static __exception int get_lvalue(JSParseState *s, int *popcode, int *pscope, emit_op(s, OP_get_field2); emit_atom(s, name); break; + case OP_scope_get_private_field: + emit_op(s, OP_scope_get_private_field2); + emit_atom(s, name); + emit_u16(s, scope); + break; case OP_get_array_el: /* XXX: replace by a single opcode ? */ emit_op(s, OP_to_propkey2); @@ -20940,6 +21813,15 @@ static void put_lvalue(JSParseState *s, int opcode, int scope, emit_op(s, OP_put_field); emit_u32(s, name); /* name has refcount */ break; + case OP_scope_get_private_field: + if (!special) + emit_op(s, OP_insert2); /* obj v -> v obj v */ + else + emit_op(s, OP_perm3); /* obj v0 v -> v0 obj v */ + emit_op(s, OP_scope_put_private_field); + emit_u32(s, name); /* name has refcount */ + emit_u16(s, scope); + break; case OP_get_array_el: if (!special) emit_op(s, OP_insert3); /* obj prop v -> v obj prop v */ @@ -20968,6 +21850,43 @@ static void put_lvalue(JSParseState *s, int opcode, int scope, } } +static void put_lvalue_nokeep(JSParseState *s, int opcode, int scope, + JSAtom name, int label, int var_tok) +{ + switch(opcode) { + case OP_scope_get_var: /* val -- */ + emit_op(s, (var_tok == TOK_CONST || var_tok == TOK_LET) ? + OP_scope_put_var_init : OP_scope_put_var); + emit_u32(s, name); /* has refcount */ + emit_u16(s, scope); + break; + case OP_get_field: /* obj val -- */ + emit_op(s, OP_put_field); + emit_u32(s, name); /* has refcount */ + break; + case OP_scope_get_private_field: + emit_op(s, OP_scope_put_private_field); + emit_u32(s, name); /* has refcount */ + emit_u16(s, scope); + break; + case OP_get_array_el: /* obj prop val -- */ + emit_op(s, OP_put_array_el); + break; + case OP_get_ref_value: /* obj prop val -- */ + /* XXX: currently this reference is never optimized */ + JS_FreeAtom(s->ctx, name); + emit_label(s, label); + //emit_op(s, OP_nop); /* emit 2 bytes for optimizer */ + emit_op(s, OP_put_ref_value); + break; + case OP_get_super_value: + emit_op(s, OP_put_super_value); + break; + default: + abort(); + } +} + static __exception int js_parse_expr_paren(JSParseState *s) { if (js_parse_expect(s, '(')) @@ -21150,7 +22069,7 @@ static int js_parse_destructing_element(JSParseState *s, int tok, int is_arg, emit_u8(s, 0 | ((depth_lvalue + 1) << 2) | ((depth_lvalue + 2) << 5)); goto set_val; } - prop_type = js_parse_property_name(s, &prop_name, FALSE, TRUE); + prop_type = js_parse_property_name(s, &prop_name, FALSE, TRUE, FALSE); if (prop_type < 0) return -1; var_name = JS_ATOM_NULL; @@ -21161,7 +22080,9 @@ static int js_parse_destructing_element(JSParseState *s, int tok, int is_arg, if (prop_type == PROP_TYPE_IDENT) { if (next_token(s)) goto prop_error; - if (s->token.val == '[' || s->token.val == '{') { + if ((s->token.val == '[' || s->token.val == '{') + && ((tok1 = js_parse_skip_parens_token(s, &skip_bits, FALSE)) == ',' || + tok1 == '=' || tok1 == '}')) { if (prop_name == JS_ATOM_NULL) { /* computed property name on stack */ if (has_ellipsis) { @@ -21330,34 +22251,7 @@ static int js_parse_destructing_element(JSParseState *s, int tok, int is_arg, emit_label(s, label_hasval); } /* store value into lvalue object */ - /* XXX: should use put_lvalue() with tok and no_keep */ - switch(opcode) { - case OP_scope_get_var: /* val -- */ - emit_op(s, (tok == TOK_CONST || tok == TOK_LET) ? - OP_scope_put_var_init : OP_scope_put_var); - emit_u32(s, var_name); /* has refcount */ - emit_u16(s, scope); - break; - case OP_get_field: /* obj val -- */ - emit_op(s, OP_put_field); - emit_u32(s, var_name); /* has refcount */ - break; - case OP_get_array_el: /* obj prop val -- */ - emit_op(s, OP_put_array_el); - break; - case OP_get_ref_value: /* obj prop val -- */ - /* XXX: currently this reference is never optimized */ - JS_FreeAtom(s->ctx, var_name); - emit_label(s, label_lvalue); - //emit_op(s, OP_nop); /* emit 2 bytes for optimizer */ - emit_op(s, OP_put_ref_value); - break; - case OP_get_super_value: - emit_op(s, OP_put_super_value); - break; - default: - abort(); - } + put_lvalue_nokeep(s, opcode, scope, var_name, label_lvalue, tok); if (s->token.val == '}') break; /* accept a trailing comma before the '}' */ @@ -21457,34 +22351,8 @@ static int js_parse_destructing_element(JSParseState *s, int tok, int is_arg, emit_label(s, label_hasval); } /* store value into lvalue object */ - /* XXX: should use put_lvalue() with tok and no_keep */ - switch(opcode) { - case OP_scope_get_var: /* enum_rec val -- enum_rec */ - emit_op(s, (tok == TOK_CONST || tok == TOK_LET) ? - OP_scope_put_var_init : OP_scope_put_var); - emit_u32(s, var_name); /* has refcount */ - emit_u16(s, scope); - break; - case OP_get_field: /* enum_rec obj val -- enum_rec */ - emit_op(s, OP_put_field); - emit_u32(s, var_name); /* has refcount */ - break; - case OP_get_array_el: /* enum_rec obj prop val -- enum_rec */ - emit_op(s, OP_put_array_el); - break; - case OP_get_ref_value: /* enum_rec obj prop val -- enum_rec */ - /* XXX: this reference is not optimized for global vars */ - JS_FreeAtom(s->ctx, var_name); - emit_label(s, label_lvalue); - //emit_op(s, OP_nop); /* emit 2 bytes for optimizer */ - emit_op(s, OP_put_ref_value); - break; - case OP_get_super_value: /* enum_rec this obj prop val -- enum_rec */ - emit_op(s, OP_put_super_value); - break; - default: - abort(); - } + put_lvalue_nokeep(s, opcode, scope, var_name, + label_lvalue, tok); } if (s->token.val == ']') break; @@ -21714,6 +22582,11 @@ static __exception int js_parse_postfix_expr(JSParseState *s, BOOL accept_lparen goto do_get_var; } } else { + if (s->token.u.ident.atom == JS_ATOM_arguments && + !s->cur_func->arguments_allowed) { + js_parse_error(s, "'arguments' identifier is not allowed in class field initializer"); + return -1; + } name = JS_DupAtom(s->ctx, s->token.u.ident.atom); if (next_token(s)) /* update line number before emitting code */ return -1; @@ -21832,6 +22705,10 @@ static __exception int js_parse_postfix_expr(JSParseState *s, BOOL accept_lparen /* keep the object on the stack */ fd->byte_code.buf[fd->last_opcode_pos] = OP_get_field2; break; + case OP_scope_get_private_field: + /* keep the object on the stack */ + fd->byte_code.buf[fd->last_opcode_pos] = OP_scope_get_private_field2; + break; case OP_get_array_el: /* keep the object on the stack */ fd->byte_code.buf[fd->last_opcode_pos] = OP_get_array_el2; @@ -21974,6 +22851,7 @@ static __exception int js_parse_postfix_expr(JSParseState *s, BOOL accept_lparen /* apply function call */ switch(opcode) { case OP_get_field: + case OP_scope_get_private_field: case OP_get_array_el: case OP_scope_get_ref: /* obj func array -> func obj array */ @@ -21998,6 +22876,8 @@ static __exception int js_parse_postfix_expr(JSParseState *s, BOOL accept_lparen emit_op(s, OP_scope_put_var_init); emit_atom(s, JS_ATOM_this); emit_u16(s, 0); + + emit_class_field_init(s); } else if (call_type == FUNC_CALL_NEW) { /* obj func array -> func obj array */ emit_op(s, OP_perm3); @@ -22018,6 +22898,7 @@ static __exception int js_parse_postfix_expr(JSParseState *s, BOOL accept_lparen emit_func_call: switch(opcode) { case OP_get_field: + case OP_scope_get_private_field: case OP_get_array_el: case OP_scope_get_ref: emit_op(s, OP_call_method); @@ -22050,6 +22931,8 @@ static __exception int js_parse_postfix_expr(JSParseState *s, BOOL accept_lparen emit_op(s, OP_scope_put_var_init); emit_atom(s, JS_ATOM_this); emit_u16(s, 0); + + emit_class_field_init(s); } else if (call_type == FUNC_CALL_NEW) { emit_op(s, OP_call_constructor); emit_u16(s, arg_count); @@ -22064,21 +22947,31 @@ static __exception int js_parse_postfix_expr(JSParseState *s, BOOL accept_lparen } else if (s->token.val == '.') { if (next_token(s)) return -1; - if (!token_is_ident(s->token.val)) { - return js_parse_error(s, "expecting field name"); - } - if (get_prev_opcode(fd) == OP_get_super) { - JSValue val; - int ret; - val = JS_AtomToValue(s->ctx, s->token.u.ident.atom); - ret = emit_push_const(s, val, 1); - JS_FreeValue(s->ctx, val); - if (ret) - return -1; - emit_op(s, OP_get_super_value); - } else { - emit_op(s, OP_get_field); + if (s->token.val == TOK_PRIVATE_NAME) { + /* private class field */ + if (get_prev_opcode(fd) == OP_get_super) { + return js_parse_error(s, "private class field forbidden after super"); + } + emit_op(s, OP_scope_get_private_field); emit_atom(s, s->token.u.ident.atom); + emit_u16(s, s->cur_func->scope_level); + } else { + if (!token_is_ident(s->token.val)) { + return js_parse_error(s, "expecting field name"); + } + if (get_prev_opcode(fd) == OP_get_super) { + JSValue val; + int ret; + val = JS_AtomToValue(s->ctx, s->token.u.ident.atom); + ret = emit_push_const(s, val, 1); + JS_FreeValue(s->ctx, val); + if (ret) + return -1; + emit_op(s, OP_get_super_value); + } else { + emit_op(s, OP_get_field); + emit_atom(s, s->token.u.ident.atom); + } } if (next_token(s)) return -1; @@ -22157,6 +23050,8 @@ static __exception int js_parse_delete(JSParseState *s) fd->byte_code.buf[fd->last_opcode_pos] = OP_scope_delete_var; } break; + case OP_scope_get_private_field: + return js_parse_error(s, "cannot delete a private class field"); default: ret_true: emit_op(s, OP_drop); @@ -23152,41 +24047,29 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name, if (js_parse_destructing_element(s, 0, 0, TRUE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE)) return -1; } else { - int lvalue_label; + int lvalue_label, depth; if (js_parse_postfix_expr(s, TRUE)) return -1; - if (get_lvalue(s, &opcode, &scope, &var_name, &lvalue_label, NULL, FALSE, TOK_FOR)) + if (get_lvalue(s, &opcode, &scope, &var_name, &lvalue_label, + &depth, FALSE, TOK_FOR)) return -1; /* swap value and lvalue object and store it into lvalue object */ - /* cannot use put_lvalue() */ - switch(opcode) { - case OP_get_field: - /* enum_rec val obj -- enum_rec */ + /* enum_rec val [depth] -- enum_rec */ + switch(depth) { + case 1: emit_op(s, OP_swap); - emit_op(s, OP_put_field); - emit_u32(s, var_name); /* has refcount */ - break; - case OP_get_array_el: - /* enum_rec val obj prop -- enum_rec obj prop val */ - emit_op(s, OP_rot3l); - /* enum_obj obj prop val -- enum_obj */ - emit_op(s, OP_put_array_el); break; - case OP_get_ref_value: - JS_FreeAtom(s->ctx, var_name); - emit_label(s, lvalue_label); - /* enum_rec val obj prop -- enum_rec obj prop val */ + case 2: emit_op(s, OP_rot3l); - emit_op(s, OP_put_ref_value); break; - case OP_get_super_value: - /* enum_rec val this obj prop -- enum_rec this obj prop val */ + case 3: emit_op(s, OP_rot4l); - emit_op(s, OP_put_super_value); break; default: abort(); } + put_lvalue_nokeep(s, opcode, scope, var_name, lvalue_label, + TOK_FOR /* not used */); } var_name = JS_ATOM_NULL; } @@ -25393,7 +26276,8 @@ static __exception int js_parse_export(JSParseState *s) static int add_closure_var(JSContext *ctx, JSFunctionDef *s, BOOL is_local, BOOL is_arg, int var_idx, JSAtom var_name, - BOOL is_const, BOOL is_lexical, BOOL is_catch); + BOOL is_const, BOOL is_lexical, + JSVarKindEnum var_kind); static int add_import(JSParseState *s, JSModuleDef *m, JSAtom local_name, JSAtom import_name) @@ -25627,16 +26511,23 @@ static JSFunctionDef *js_new_function_def(JSContext *ctx, } static void free_bytecode_atoms(JSRuntime *rt, - const uint8_t *bc_buf, int bc_len) + const uint8_t *bc_buf, int bc_len, + BOOL use_short_opcodes) { int pos, len, op; JSAtom atom; - + const JSOpCode *oi; + pos = 0; while (pos < bc_len) { op = bc_buf[pos]; - len = opcode_info[op].size; - switch(opcode_info[op].fmt) { + if (use_short_opcodes) + oi = &short_opcode_info(op); + else + oi = &opcode_info[op]; + + len = oi->size; + switch(oi->fmt) { case OP_FMT_atom: case OP_FMT_atom_u8: case OP_FMT_atom_u16: @@ -25664,7 +26555,8 @@ static void js_free_function_def(JSContext *ctx, JSFunctionDef *fd) js_free_function_def(ctx, fd1); } - free_bytecode_atoms(ctx->rt, fd->byte_code.buf, fd->byte_code.size); + free_bytecode_atoms(ctx->rt, fd->byte_code.buf, fd->byte_code.size, + fd->use_short_opcodes); dbuf_free(&fd->byte_code); js_free(ctx, fd->jump_slots); js_free(ctx, fd->label_slots); @@ -25749,13 +26641,18 @@ static void dump_byte_code(JSContext *ctx, int pass, const JSOpCode *oi; int pos, pos_next, op, size, idx, addr, line, line1, in_source; uint8_t *bits = js_mallocz(ctx, len * sizeof(*bits)); + BOOL use_short_opcodes = (b != NULL); /* scan for jump targets */ for (pos = 0; pos < len; pos = pos_next) { op = tab[pos]; - pos_next = pos + opcode_info[op].size; + if (use_short_opcodes) + oi = &short_opcode_info(op); + else + oi = &opcode_info[op]; + pos_next = pos + oi->size; if (op < OP_COUNT) { - switch (opcode_info[op].fmt) { + switch (oi->fmt) { #if SHORT_OPCODES case OP_FMT_label8: pos++; @@ -25821,7 +26718,10 @@ static void dump_byte_code(JSContext *ctx, int pass, pos++; continue; } - oi = &opcode_info[op]; + if (use_short_opcodes) + oi = &short_opcode_info(op); + else + oi = &opcode_info[op]; size = oi->size; if (pos + size > len) { printf("truncated opcode (0x%02x)\n", op); @@ -26077,7 +26977,7 @@ static __attribute__((unused)) void js_dump_function_bytecode(JSContext *ctx, JS for(i = 0; i < b->var_count; i++) { JSVarDef *vd = &b->vardefs[b->arg_count + i]; printf("%5d: %s %s", i, - vd->is_catch ? "catch" : + vd->var_kind == JS_VAR_CATCH ? "catch" : vd->is_function ? "function" : vd->is_const ? "const" : vd->is_lexical ? "let" : "var", @@ -26119,7 +27019,8 @@ static __attribute__((unused)) void js_dump_function_bytecode(JSContext *ctx, JS static int add_closure_var(JSContext *ctx, JSFunctionDef *s, BOOL is_local, BOOL is_arg, int var_idx, JSAtom var_name, - BOOL is_const, BOOL is_lexical, BOOL is_catch) + BOOL is_const, BOOL is_lexical, + JSVarKindEnum var_kind) { JSClosureVar *cv; @@ -26148,7 +27049,7 @@ static int add_closure_var(JSContext *ctx, JSFunctionDef *s, cv->is_arg = is_arg; cv->is_const = is_const; cv->is_lexical = is_lexical; - cv->is_catch = is_catch; + cv->var_kind = var_kind; cv->var_idx = var_idx; cv->var_name = JS_DupAtom(ctx, var_name); return s->closure_var_count - 1; @@ -26172,14 +27073,15 @@ static int find_closure_var(JSContext *ctx, JSFunctionDef *s, static int get_closure_var2(JSContext *ctx, JSFunctionDef *s, JSFunctionDef *fd, BOOL is_local, BOOL is_arg, int var_idx, JSAtom var_name, - BOOL is_const, BOOL is_lexical, BOOL is_catch) + BOOL is_const, BOOL is_lexical, + JSVarKindEnum var_kind) { int i; if (fd != s->parent) { var_idx = get_closure_var2(ctx, s->parent, fd, is_local, is_arg, var_idx, var_name, - is_const, is_lexical, is_catch); + is_const, is_lexical, var_kind); if (var_idx < 0) return -1; is_local = FALSE; @@ -26191,17 +27093,18 @@ static int get_closure_var2(JSContext *ctx, JSFunctionDef *s, return i; } return add_closure_var(ctx, s, is_local, is_arg, var_idx, var_name, - is_const, is_lexical, is_catch); + is_const, is_lexical, var_kind); } static int get_closure_var(JSContext *ctx, JSFunctionDef *s, JSFunctionDef *fd, BOOL is_arg, int var_idx, JSAtom var_name, BOOL is_const, BOOL is_lexical, - BOOL is_catch) + JSVarKindEnum var_kind) { return get_closure_var2(ctx, s, fd, TRUE, is_arg, - var_idx, var_name, is_const, is_lexical, is_catch); + var_idx, var_name, is_const, is_lexical, + var_kind); } static int get_with_scope_opcode(int op) @@ -26599,7 +27502,7 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s, break; } else if (vd->var_name == JS_ATOM__with_ && !is_pseudo_var) { vd->is_captured = 1; - idx = get_closure_var(ctx, s, fd, FALSE, idx, vd->var_name, FALSE, FALSE, FALSE); + idx = get_closure_var(ctx, s, fd, FALSE, idx, vd->var_name, FALSE, FALSE, JS_VAR_NORMAL); if (idx >= 0) { dbuf_putc(bc, OP_get_var_ref); dbuf_put_u16(bc, idx); @@ -26645,7 +27548,7 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s, fd->vars[fd->var_object_idx].is_captured = 1; idx = get_closure_var(ctx, s, fd, FALSE, fd->var_object_idx, JS_ATOM__var_, - FALSE, FALSE, FALSE); + FALSE, FALSE, JS_VAR_NORMAL); dbuf_putc(bc, OP_get_var_ref); dbuf_put_u16(bc, idx); dbuf_putc(bc, get_with_scope_opcode(op)); @@ -26675,7 +27578,7 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s, FALSE, cv->is_arg, idx1, cv->var_name, cv->is_const, - cv->is_lexical, cv->is_catch); + cv->is_lexical, cv->var_kind); } else { idx = idx1; } @@ -26687,7 +27590,8 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s, idx = get_closure_var2(ctx, s, fd, FALSE, cv->is_arg, idx1, - cv->var_name, FALSE, FALSE, FALSE); + cv->var_name, FALSE, FALSE, + JS_VAR_NORMAL); } else { idx = idx1; } @@ -26710,7 +27614,7 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s, fd->args[var_idx - ARGUMENT_VAR_OFFSET].is_captured = 1; idx = get_closure_var(ctx, s, fd, TRUE, var_idx - ARGUMENT_VAR_OFFSET, - var_name, FALSE, FALSE, FALSE); + var_name, FALSE, FALSE, JS_VAR_NORMAL); } else { fd->vars[var_idx].is_captured = 1; idx = get_closure_var(ctx, s, fd, @@ -26718,7 +27622,7 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s, var_name, fd->vars[var_idx].is_const, fd->vars[var_idx].is_lexical, - fd->vars[var_idx].is_catch); + fd->vars[var_idx].var_kind); } if (idx >= 0) { has_idx: @@ -26844,6 +27748,190 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s, return pos_next; } +/* search in all scopes */ +static int find_private_class_field_all(JSContext *ctx, JSFunctionDef *fd, + JSAtom name, int scope_level) +{ + int idx; + + idx = fd->scopes[scope_level].first; + while (idx >= 0) { + if (fd->vars[idx].var_name == name) + return idx; + idx = fd->vars[idx].scope_next; + } + return -1; +} + +static void get_loc_or_ref(DynBuf *bc, BOOL is_ref, int idx) +{ + if (is_ref) + dbuf_putc(bc, OP_get_var_ref); + else + dbuf_putc(bc, OP_get_loc); + dbuf_put_u16(bc, idx); + +} + +static int resolve_scope_private_field1(JSContext *ctx, + BOOL *pis_ref, int *pvar_kind, + JSFunctionDef *s, + JSAtom var_name, int scope_level) +{ + int idx, var_kind; + JSFunctionDef *fd; + BOOL is_ref; + + fd = s; + is_ref = FALSE; + for(;;) { + idx = find_private_class_field_all(ctx, fd, var_name, scope_level); + if (idx >= 0) { + var_kind = fd->vars[idx].var_kind; + if (is_ref) { + idx = get_closure_var(ctx, s, fd, FALSE, idx, var_name, + TRUE, TRUE, JS_VAR_NORMAL); + if (idx < 0) + return -1; + } + break; + } + scope_level = fd->parent_scope_level; + if (!fd->parent) { + char buf[ATOM_GET_STR_BUF_SIZE]; + + if (fd->is_eval) { + /* closure of the eval function (top level) */ + for (idx = 0; idx < fd->closure_var_count; idx++) { + JSClosureVar *cv = &fd->closure_var[idx]; + if (cv->var_name == var_name) { + var_kind = cv->var_kind; + is_ref = TRUE; + if (fd != s) { + idx = get_closure_var2(ctx, s, fd, + FALSE, + cv->is_arg, idx, + cv->var_name, cv->is_const, + cv->is_lexical, + cv->var_kind); + if (idx < 0) + return -1; + } + goto done; + } + } + } + /* XXX: no line number info */ + JS_ThrowSyntaxError(ctx, "undefined private field %s", + JS_AtomGetStr(ctx, buf, sizeof(buf), var_name)); + return -1; + } else { + fd = fd->parent; + } + is_ref = TRUE; + } + done: + *pis_ref = is_ref; + *pvar_kind = var_kind; + return idx; +} + +/* return 0 if OK or -1 if the private field could not be resolved */ +static int resolve_scope_private_field(JSContext *ctx, JSFunctionDef *s, + JSAtom var_name, int scope_level, int op, + DynBuf *bc) +{ + int idx, var_kind; + BOOL is_ref; + + idx = resolve_scope_private_field1(ctx, &is_ref, &var_kind, s, + var_name, scope_level); + if (idx < 0) + return -1; + assert(var_kind != JS_VAR_NORMAL); + switch (op) { + case OP_scope_get_private_field: + case OP_scope_get_private_field2: + switch(var_kind) { + case JS_VAR_PRIVATE_FIELD: + if (op == OP_scope_get_private_field2) + dbuf_putc(bc, OP_dup); + get_loc_or_ref(bc, is_ref, idx); + dbuf_putc(bc, OP_get_private_field); + break; + case JS_VAR_PRIVATE_METHOD: + get_loc_or_ref(bc, is_ref, idx); + dbuf_putc(bc, OP_check_brand); + if (op != OP_scope_get_private_field2) + dbuf_putc(bc, OP_nip); + break; + case JS_VAR_PRIVATE_GETTER: + case JS_VAR_PRIVATE_GETTER_SETTER: + if (op == OP_scope_get_private_field2) + dbuf_putc(bc, OP_dup); + get_loc_or_ref(bc, is_ref, idx); + dbuf_putc(bc, OP_check_brand); + dbuf_putc(bc, OP_call_method); + dbuf_put_u16(bc, 0); + break; + case JS_VAR_PRIVATE_SETTER: + /* XXX: add clearer error message */ + dbuf_putc(bc, OP_throw_var); + dbuf_put_u32(bc, JS_DupAtom(ctx, var_name)); + dbuf_putc(bc, JS_THROW_VAR_RO); + break; + default: + abort(); + } + break; + case OP_scope_put_private_field: + switch(var_kind) { + case JS_VAR_PRIVATE_FIELD: + get_loc_or_ref(bc, is_ref, idx); + dbuf_putc(bc, OP_put_private_field); + break; + case JS_VAR_PRIVATE_METHOD: + case JS_VAR_PRIVATE_GETTER: + /* XXX: add clearer error message */ + dbuf_putc(bc, OP_throw_var); + dbuf_put_u32(bc, JS_DupAtom(ctx, var_name)); + dbuf_putc(bc, JS_THROW_VAR_RO); + break; + case JS_VAR_PRIVATE_SETTER: + case JS_VAR_PRIVATE_GETTER_SETTER: + { + JSAtom setter_name = get_private_setter_name(ctx, var_name); + if (setter_name == JS_ATOM_NULL) + return -1; + idx = resolve_scope_private_field1(ctx, &is_ref, + &var_kind, s, + setter_name, scope_level); + JS_FreeAtom(ctx, setter_name); + if (idx < 0) + return -1; + assert(var_kind == JS_VAR_PRIVATE_SETTER); + get_loc_or_ref(bc, is_ref, idx); + dbuf_putc(bc, OP_swap); + /* obj func value */ + dbuf_putc(bc, OP_rot3r); + /* value obj func */ + dbuf_putc(bc, OP_check_brand); + dbuf_putc(bc, OP_rot3l); + /* obj func value */ + dbuf_putc(bc, OP_call_method); + dbuf_put_u16(bc, 1); + } + break; + default: + abort(); + } + break; + default: + abort(); + } + return 0; +} + static void mark_eval_captured_variables(JSContext *ctx, JSFunctionDef *s, int scope_level) { @@ -26928,7 +28016,7 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s) vd = &fd->vars[scope_idx]; vd->is_captured = 1; get_closure_var(ctx, s, fd, FALSE, scope_idx, - vd->var_name, vd->is_const, vd->is_lexical, vd->is_catch); + vd->var_name, vd->is_const, vd->is_lexical, vd->var_kind); scope_idx = vd->scope_next; } /* add unscoped variables */ @@ -26936,7 +28024,8 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s) vd = &fd->args[i]; if (vd->var_name != JS_ATOM_NULL) { get_closure_var(ctx, s, fd, - TRUE, i, vd->var_name, FALSE, FALSE, FALSE); + TRUE, i, vd->var_name, FALSE, FALSE, + JS_VAR_NORMAL); } } for(i = 0; i < fd->var_count; i++) { @@ -26946,7 +28035,8 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s) vd->var_name != JS_ATOM__ret_ && vd->var_name != JS_ATOM_NULL) { get_closure_var(ctx, s, fd, - FALSE, i, vd->var_name, FALSE, FALSE, FALSE); + FALSE, i, vd->var_name, FALSE, FALSE, + JS_VAR_NORMAL); } } if (fd->is_eval) { @@ -26958,7 +28048,7 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s) get_closure_var2(ctx, s, fd, FALSE, cv->is_arg, idx, cv->var_name, cv->is_const, - cv->is_lexical, cv->is_catch); + cv->is_lexical, cv->var_kind); } } } @@ -26990,7 +28080,7 @@ static __exception int add_closure_variables(JSContext *ctx, JSFunctionDef *s, cv->is_arg = FALSE; cv->is_const = vd->is_const; cv->is_lexical = vd->is_lexical; - cv->is_catch = vd->is_catch; + cv->var_kind = vd->var_kind; cv->var_idx = i; cv->var_name = JS_DupAtom(ctx, vd->var_name); } @@ -27004,7 +28094,7 @@ static __exception int add_closure_variables(JSContext *ctx, JSFunctionDef *s, cv->is_arg = TRUE; cv->is_const = FALSE; cv->is_lexical = FALSE; - cv->is_catch = FALSE; + cv->var_kind = JS_VAR_NORMAL; cv->var_idx = i; cv->var_name = JS_DupAtom(ctx, vd->var_name); } @@ -27017,7 +28107,7 @@ static __exception int add_closure_variables(JSContext *ctx, JSFunctionDef *s, cv->is_arg = FALSE; cv->is_const = FALSE; cv->is_lexical = FALSE; - cv->is_catch = FALSE; + cv->var_kind = JS_VAR_NORMAL; cv->var_idx = i; cv->var_name = JS_DupAtom(ctx, vd->var_name); } @@ -27029,7 +28119,7 @@ static __exception int add_closure_variables(JSContext *ctx, JSFunctionDef *s, cv->is_arg = cv0->is_arg; cv->is_const = cv0->is_const; cv->is_lexical = cv0->is_lexical; - cv->is_catch = cv0->is_catch; + cv->var_kind = cv0->var_kind; cv->var_idx = i; cv->var_name = JS_DupAtom(ctx, cv0->var_name); } @@ -27380,7 +28470,7 @@ static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s) if (cv->var_name == hf->var_name) { if (s->eval_type == JS_EVAL_TYPE_DIRECT && (cv->is_lexical || - (cv->is_catch && hf->is_for_of))) { + (cv->var_kind == JS_VAR_CATCH && hf->is_for_of))) { /* Check if a lexical variable is redefined as 'var'. XXX: Could abort compilation here, but for consistency @@ -27456,7 +28546,19 @@ static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s) JS_FreeAtom(ctx, var_name); } break; - + case OP_scope_get_private_field: + case OP_scope_get_private_field2: + case OP_scope_put_private_field: + { + int ret; + var_name = get_u32(bc_buf + pos + 1); + scope = get_u16(bc_buf + pos + 5); + ret = resolve_scope_private_field(ctx, s, var_name, scope, op, &bc_out); + if (ret < 0) + goto fail; + JS_FreeAtom(ctx, var_name); + } + break; case OP_gosub: s->jump_size++; if (OPTIMIZE) { @@ -27668,6 +28770,18 @@ static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s) return -1; } return 0; + fail: + /* continue the copy to keep the atom refcounts consistent */ + /* XXX: find a better solution ? */ + for (; pos < bc_len; pos = pos_next) { + op = bc_buf[pos]; + len = opcode_info[op].size; + pos_next = pos + len; + dbuf_put(&bc_out, bc_buf + pos, len); + } + dbuf_free(&s->byte_code); + s->byte_code = bc_out; + return -1; } /* the pc2line table gives a line number for each PC value */ @@ -27970,7 +29084,8 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s) } /* initialize the variable environment object if needed */ if (s->var_object_idx >= 0) { - dbuf_putc(&bc_out, OP_var_object); + dbuf_putc(&bc_out, OP_special_object); + dbuf_putc(&bc_out, OP_SPECIAL_OBJECT_VAR_OBJECT); put_short_code(&bc_out, OP_put_loc, s->var_object_idx); } @@ -27987,7 +29102,8 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s) add_pc2line_info(s, bc_out.size, line_num); dbuf_putc(&bc_out, OP_close_loc); dbuf_put_u16(&bc_out, s->var_object_idx); - dbuf_putc(&bc_out, OP_var_object); + dbuf_putc(&bc_out, OP_special_object); + dbuf_putc(&bc_out, OP_SPECIAL_OBJECT_VAR_OBJECT); put_short_code(&bc_out, OP_put_loc, s->var_object_idx); } } @@ -28494,10 +29610,13 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s) if (code_match(&cc, pos_next, OP_push_atom_value, OP_add, OP_dup, OP_put_loc, idx, OP_drop, -1)) { if (cc.line_num >= 0) line_num = cc.line_num; add_pc2line_info(s, bc_out.size, line_num); +#if SHORT_OPCODES if (cc.atom == JS_ATOM_empty_string) { JS_FreeAtom(ctx, cc.atom); dbuf_putc(&bc_out, OP_push_empty_string); - } else { + } else +#endif + { dbuf_putc(&bc_out, OP_push_atom_value); dbuf_put_u32(&bc_out, cc.atom); } @@ -28765,12 +29884,14 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s) /* set the new byte code */ dbuf_free(&s->byte_code); s->byte_code = bc_out; + s->use_short_opcodes = TRUE; if (dbuf_error(&s->byte_code)) { JS_ThrowOutOfMemory(ctx); return -1; } return 0; fail: + /* XXX: not safe */ dbuf_free(&bc_out); return -1; } @@ -28822,7 +29943,7 @@ static __exception int compute_stack_size_rec(JSContext *ctx, JS_ThrowInternalError(ctx, "invalid opcode (op=%d, pc=%d)", op, pos); return -1; } - oi = &opcode_info[op]; + oi = &short_opcode_info(op); pos_next = pos + oi->size; if (pos_next > bc_len) { buf_overflow: @@ -29177,10 +30298,12 @@ static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd) b->js_mode = fd->js_mode; b->is_derived_class_constructor = fd->is_derived_class_constructor; b->func_kind = fd->func_kind; - b->need_home_object = (fd->home_object_var_idx >= 0); + b->need_home_object = (fd->home_object_var_idx >= 0 || + fd->need_home_object); b->new_target_allowed = fd->new_target_allowed; b->super_call_allowed = fd->super_call_allowed; b->super_allowed = fd->super_allowed; + b->arguments_allowed = fd->arguments_allowed; #if defined(DUMP_BYTECODE) && (DUMP_BYTECODE & 1) if (!(fd->js_mode & JS_MODE_STRIP)) { @@ -29211,7 +30334,7 @@ static void free_function_bytecode(JSRuntime *rt, JSFunctionBytecode *b) JS_AtomGetStrRT(rt, buf, sizeof(buf), b->func_name)); } #endif - free_bytecode_atoms(rt, b->byte_code_buf, b->byte_code_len); + free_bytecode_atoms(rt, b->byte_code_buf, b->byte_code_len, TRUE); if (b->vardefs) { for(i = 0; i < b->arg_count + b->var_count; i++) { @@ -29383,6 +30506,32 @@ static int js_parse_function_check_names(JSParseState *s, JSFunctionDef *fd, return js_parse_error(s, "duplicate argument names not allowed in this context"); } +/* create a function to initialize class fields */ +static JSFunctionDef *js_parse_function_class_fields_init(JSParseState *s) +{ + JSFunctionDef *fd; + + fd = js_new_function_def(s->ctx, s->cur_func, FALSE, FALSE, + s->filename, 0); + if (!fd) + return NULL; + fd->func_name = JS_ATOM_NULL; + fd->has_prototype = FALSE; + fd->has_home_object = TRUE; + + fd->has_arguments_binding = FALSE; + fd->has_this_binding = TRUE; + fd->is_derived_class_constructor = FALSE; + fd->new_target_allowed = TRUE; + fd->super_call_allowed = FALSE; + fd->super_allowed = fd->has_home_object; + fd->arguments_allowed = FALSE; + + fd->func_kind = JS_FUNC_NORMAL; + fd->func_type = JS_PARSE_FUNC_METHOD; + return fd; +} + /* func_name must be JS_ATOM_NULL for JS_PARSE_FUNC_STATEMENT and JS_PARSE_FUNC_EXPR, JS_PARSE_FUNC_ARROW and JS_PARSE_FUNC_VAR */ static __exception int js_parse_function_decl2(JSParseState *s, @@ -29525,10 +30674,12 @@ static __exception int js_parse_function_decl2(JSParseState *s, fd->new_target_allowed = fd->parent->new_target_allowed; fd->super_call_allowed = fd->parent->super_call_allowed; fd->super_allowed = fd->parent->super_allowed; + fd->arguments_allowed = fd->parent->arguments_allowed; } else { fd->new_target_allowed = TRUE; fd->super_call_allowed = fd->is_derived_class_constructor; fd->super_allowed = fd->has_home_object; + fd->arguments_allowed = TRUE; } /* fd->in_function_body == FALSE prevents yield/await during the parsing @@ -29543,6 +30694,10 @@ static __exception int js_parse_function_decl2(JSParseState *s, emit_op(s, OP_check_ctor); } + if (func_type == JS_PARSE_FUNC_CLASS_CONSTRUCTOR) { + emit_class_field_init(s); + } + /* parse arguments */ fd->has_simple_parameter_list = TRUE; has_opt_arg = FALSE; @@ -30054,10 +31209,12 @@ static JSValue __JS_EvalInternal(JSContext *ctx, JSValueConst this_obj, fd->new_target_allowed = b->new_target_allowed; fd->super_call_allowed = b->super_call_allowed; fd->super_allowed = b->super_allowed; + fd->arguments_allowed = b->arguments_allowed; } else { fd->new_target_allowed = FALSE; fd->super_call_allowed = FALSE; fd->super_allowed = FALSE; + fd->arguments_allowed = TRUE; } fd->js_mode = js_mode; fd->func_name = JS_DupAtom(ctx, JS_ATOM__eval_); @@ -30120,11 +31277,11 @@ static JSValue JS_EvalObject(JSContext *ctx, JSValueConst this_obj, { JSValue ret; const char *str; - int len; + size_t len; if (!JS_IsString(val)) return JS_DupValue(ctx, val); - str = JS_ToCStringLen(ctx, &len, val, FALSE); + str = JS_ToCStringLen(ctx, &len, val); if (!str) return JS_EXCEPTION; ret = JS_EvalInternal(ctx, this_obj, str, len, "", flags, scope_idx); @@ -30354,8 +31511,8 @@ static void bc_byte_swap(uint8_t *bc_buf, int bc_len) pos = 0; while (pos < bc_len) { op = bc_buf[pos]; - len = opcode_info[op].size; - fmt = opcode_info[op].fmt; + len = short_opcode_info(op).size; + fmt = short_opcode_info(op).fmt; switch(fmt) { case OP_FMT_u16: case OP_FMT_i16: @@ -30417,8 +31574,8 @@ static int JS_WriteFunctionBytecode(BCWriterState *s, pos = 0; while (pos < bc_len) { op = bc_buf[pos]; - len = opcode_info[op].size; - switch(opcode_info[op].fmt) { + len = short_opcode_info(op).size; + switch(short_opcode_info(op).fmt) { case OP_FMT_atom: case OP_FMT_atom_u8: case OP_FMT_atom_u16: @@ -30510,6 +31667,7 @@ static int JS_WriteObjectRec(BCWriterState *s, JSValueConst obj) bc_set_flags(&flags, &idx, b->new_target_allowed, 1); bc_set_flags(&flags, &idx, b->super_call_allowed, 1); bc_set_flags(&flags, &idx, b->super_allowed, 1); + bc_set_flags(&flags, &idx, b->arguments_allowed, 1); bc_set_flags(&flags, &idx, b->has_debug, 1); assert(idx <= 16); bc_put_u16(s, flags); @@ -30531,7 +31689,7 @@ static int JS_WriteObjectRec(BCWriterState *s, JSValueConst obj) bc_put_leb128(s, vd->scope_level); bc_put_leb128(s, vd->scope_next + 1); flags = idx = 0; - bc_set_flags(&flags, &idx, vd->is_catch, 1); + bc_set_flags(&flags, &idx, vd->var_kind, 3); bc_set_flags(&flags, &idx, vd->is_function, 1); bc_set_flags(&flags, &idx, vd->is_func_var, 1); bc_set_flags(&flags, &idx, vd->is_const, 1); @@ -30553,7 +31711,7 @@ static int JS_WriteObjectRec(BCWriterState *s, JSValueConst obj) bc_set_flags(&flags, &idx, cv->is_arg, 1); bc_set_flags(&flags, &idx, cv->is_const, 1); bc_set_flags(&flags, &idx, cv->is_lexical, 1); - bc_set_flags(&flags, &idx, cv->is_catch, 1); + bc_set_flags(&flags, &idx, cv->var_kind, 3); assert(idx <= 8); bc_put_u8(s, flags); } @@ -31114,8 +32272,8 @@ static int JS_ReadFunctionBytecode(BCReaderState *s, JSFunctionBytecode *b, pos = 0; while (pos < bc_len) { op = bc_buf[pos]; - len = opcode_info[op].size; - switch(opcode_info[op].fmt) { + len = short_opcode_info(op).size; + switch(short_opcode_info(op).fmt) { case OP_FMT_atom: case OP_FMT_atom_u8: case OP_FMT_atom_u16: @@ -31224,6 +32382,7 @@ static JSValue JS_ReadObjectRec(BCReaderState *s) bc.new_target_allowed = bc_get_flags(v16, &idx, 1); bc.super_call_allowed = bc_get_flags(v16, &idx, 1); bc.super_allowed = bc_get_flags(v16, &idx, 1); + bc.arguments_allowed = bc_get_flags(v16, &idx, 1); bc.has_debug = bc_get_flags(v16, &idx, 1); bc.read_only_bytecode = s->is_rom_data; if (bc_get_u8(s, &v8)) @@ -31295,7 +32454,7 @@ static JSValue JS_ReadObjectRec(BCReaderState *s) if (bc_get_u8(s, &v8)) goto fail; idx = 0; - vd->is_catch = bc_get_flags(v8, &idx, 1); + vd->var_kind = bc_get_flags(v8, &idx, 3); vd->is_function = bc_get_flags(v8, &idx, 1); vd->is_func_var = bc_get_flags(v8, &idx, 1); vd->is_const = bc_get_flags(v8, &idx, 1); @@ -31325,7 +32484,7 @@ static JSValue JS_ReadObjectRec(BCReaderState *s) cv->is_arg = bc_get_flags(v8, &idx, 1); cv->is_const = bc_get_flags(v8, &idx, 1); cv->is_lexical = bc_get_flags(v8, &idx, 1); - cv->is_catch = bc_get_flags(v8, &idx, 1); + cv->var_kind = bc_get_flags(v8, &idx, 3); #ifdef DUMP_READ_OBJECT bc_read_trace(s, "name: "); print_atom(s->ctx, cv->var_name); printf("\n"); #endif @@ -32239,7 +33398,7 @@ static __exception int JS_ObjectDefineProperties(JSContext *ctx, if (JS_IsException(props)) return -1; p = JS_VALUE_GET_OBJ(props); - if (JS_GetOwnPropertyNames(ctx, &atoms, &len, p, JS_GPN_ENUM_ONLY | JS_GPN_STRING_MASK) < 0) + if (JS_GetOwnPropertyNamesInternal(ctx, &atoms, &len, p, JS_GPN_ENUM_ONLY | JS_GPN_STRING_MASK) < 0) goto exception; for(i = 0; i < len; i++) { JS_FreeValue(ctx, desc); @@ -32441,7 +33600,7 @@ static JSValue js_object_getOwnPropertyDescriptor(JSContext *ctx, JSValueConst t return JS_EXCEPTION; ret = JS_UNDEFINED; if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) { - res = JS_GetOwnProperty(ctx, &desc, JS_VALUE_GET_OBJ(obj), atom); + res = JS_GetOwnPropertyInternal(ctx, &desc, JS_VALUE_GET_OBJ(obj), atom); if (res < 0) goto exception; if (res) { @@ -32493,7 +33652,7 @@ static JSValue js_object_getOwnPropertyDescriptors(JSContext *ctx, JSValueConst return JS_EXCEPTION; p = JS_VALUE_GET_OBJ(obj); - if (JS_GetOwnPropertyNames(ctx, &props, &len, p, + if (JS_GetOwnPropertyNamesInternal(ctx, &props, &len, p, JS_GPN_STRING_MASK | JS_GPN_SYMBOL_MASK)) goto exception; r = JS_NewObject(ctx); @@ -32543,7 +33702,7 @@ static JSValue JS_GetOwnPropertyNames2(JSContext *ctx, JSValueConst obj1, if (JS_IsException(obj)) return JS_EXCEPTION; p = JS_VALUE_GET_OBJ(obj); - if (JS_GetOwnPropertyNames(ctx, &atoms, &len, p, flags & ~JS_GPN_ENUM_ONLY)) + if (JS_GetOwnPropertyNamesInternal(ctx, &atoms, &len, p, flags & ~JS_GPN_ENUM_ONLY)) goto exception; r = JS_NewArray(ctx); if (JS_IsException(r)) @@ -32555,7 +33714,7 @@ static JSValue JS_GetOwnPropertyNames2(JSContext *ctx, JSValueConst obj1, int res; /* Check if property is still enumerable */ - res = JS_GetOwnProperty(ctx, &desc, p, atom); + res = JS_GetOwnPropertyInternal(ctx, &desc, p, atom); if (res < 0) goto exception; if (!res) @@ -32688,7 +33847,7 @@ static JSValue js_object_hasOwnProperty(JSContext *ctx, JSValueConst this_val, return obj; } p = JS_VALUE_GET_OBJ(obj); - ret = JS_GetOwnProperty(ctx, NULL, p, atom); + ret = JS_GetOwnPropertyInternal(ctx, NULL, p, atom); JS_FreeAtom(ctx, atom); JS_FreeValue(ctx, obj); if (ret < 0) @@ -32806,7 +33965,7 @@ static JSValue js_object_seal(JSContext *ctx, JSValueConst this_val, p = JS_VALUE_GET_OBJ(obj); flags = JS_GPN_STRING_MASK | JS_GPN_SYMBOL_MASK; - if (JS_GetOwnPropertyNames(ctx, &props, &len, p, flags)) + if (JS_GetOwnPropertyNamesInternal(ctx, &props, &len, p, flags)) return JS_EXCEPTION; for(i = 0; i < len; i++) { @@ -32815,7 +33974,7 @@ static JSValue js_object_seal(JSContext *ctx, JSValueConst this_val, desc_flags = JS_PROP_THROW | JS_PROP_HAS_CONFIGURABLE; if (freeze_flag) { - res = JS_GetOwnProperty(ctx, &desc, p, prop); + res = JS_GetOwnPropertyInternal(ctx, &desc, p, prop); if (res < 0) goto exception; if (res) { @@ -32850,14 +34009,14 @@ static JSValue js_object_isSealed(JSContext *ctx, JSValueConst this_val, p = JS_VALUE_GET_OBJ(obj); flags = JS_GPN_STRING_MASK | JS_GPN_SYMBOL_MASK; - if (JS_GetOwnPropertyNames(ctx, &props, &len, p, flags)) + if (JS_GetOwnPropertyNamesInternal(ctx, &props, &len, p, flags)) return JS_EXCEPTION; for(i = 0; i < len; i++) { JSPropertyDescriptor desc; JSAtom prop = props[i].atom; - res = JS_GetOwnProperty(ctx, &desc, p, prop); + res = JS_GetOwnPropertyInternal(ctx, &desc, p, prop); if (res < 0) goto exception; if (res) { @@ -33166,7 +34325,7 @@ static JSValue js_object_propertyIsEnumerable(JSContext *ctx, JSValueConst this_ if (unlikely(prop == JS_ATOM_NULL)) goto exception; - has_prop = JS_GetOwnProperty(ctx, &desc, JS_VALUE_GET_OBJ(obj), prop); + has_prop = JS_GetOwnPropertyInternal(ctx, &desc, JS_VALUE_GET_OBJ(obj), prop); if (has_prop < 0) goto exception; if (has_prop) { @@ -33199,7 +34358,7 @@ static JSValue js_object___lookupGetter__(JSContext *ctx, JSValueConst this_val, goto exception; for (v = obj;;) { - has_prop = JS_GetOwnProperty(ctx, &desc, JS_VALUE_GET_OBJ(v), prop); + has_prop = JS_GetOwnPropertyInternal(ctx, &desc, JS_VALUE_GET_OBJ(v), prop); if (has_prop < 0) goto exception; if (has_prop) { @@ -36609,6 +37768,7 @@ static JSValue js_string_replace(JSContext *ctx, JSValueConst this_val, pos = string_indexof(sp, searchp, 0); if (pos < 0) { + string_buffer_free(b); JS_FreeValue(ctx, search_str); JS_FreeValue(ctx, replaceValue_str); return str; @@ -37100,7 +38260,7 @@ static int JS_ToUTF32String(JSContext *ctx, uint32_t **pbuf, JSValueConst val1) p = JS_VALUE_GET_STRING(val); len = p->len; /* UTF32 buffer length is len minus the number of correct surrogates pairs */ - buf = js_malloc(ctx, sizeof(buf[0]) * len); + buf = js_malloc(ctx, sizeof(buf[0]) * max_int(len, 1)); if (!buf) { JS_FreeValue(ctx, val); goto fail; @@ -37135,7 +38295,8 @@ static JSValue js_string_normalize(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { const char *form, *p; - int form_len, is_compat, buf_len, out_len; + size_t form_len; + int is_compat, buf_len, out_len; UnicodeNormalizationEnum n_type; JSValue val; uint32_t *buf, *out_buf; @@ -37151,7 +38312,7 @@ static JSValue js_string_normalize(JSContext *ctx, JSValueConst this_val, if (argc == 0 || JS_IsUndefined(argv[0])) { n_type = UNICODE_NFC; } else { - form = JS_ToCStringLen(ctx, &form_len, argv[0], FALSE); + form = JS_ToCStringLen(ctx, &form_len, argv[0]); if (!form) goto fail1; p = form; @@ -38154,13 +39315,14 @@ static JSValue js_compile_regexp(JSContext *ctx, JSValueConst pattern, const char *str; int re_flags, mask; uint8_t *re_bytecode_buf; - int re_bytecode_len, i, len; + size_t i, len; + int re_bytecode_len; JSValue ret; char error_msg[64]; re_flags = 0; if (!JS_IsUndefined(flags)) { - str = JS_ToCStringLen(ctx, &len, flags, FALSE); + str = JS_ToCStringLen(ctx, &len, flags); if (!str) return JS_EXCEPTION; /* XXX: re_flags = LRE_FLAG_OCTAL unless strict mode? */ @@ -38197,7 +39359,7 @@ static JSValue js_compile_regexp(JSContext *ctx, JSValueConst pattern, JS_FreeCString(ctx, str); } - str = JS_ToCStringLen(ctx, &len, pattern, !(re_flags & LRE_FLAG_UTF16)); + str = JS_ToCStringLen2(ctx, &len, pattern, !(re_flags & LRE_FLAG_UTF16)); if (!str) return JS_EXCEPTION; re_bytecode_buf = lre_compile(&re_bytecode_len, error_msg, @@ -39772,7 +40934,6 @@ JSValue JS_ParseJSON(JSContext *ctx, const char *buf, size_t buf_len, return JS_EXCEPTION; } -/* XXX: check stack limit ? */ static JSValue internalize_json_property(JSContext *ctx, JSValueConst holder, JSAtom name, JSValueConst reviver) { @@ -39783,6 +40944,10 @@ static JSValue internalize_json_property(JSContext *ctx, JSValueConst holder, JSAtom prop; JSPropertyEnum *atoms = NULL; + if (js_check_stack_overflow(ctx, 0)) { + return JS_ThrowStackOverflow(ctx); + } + val = JS_GetProperty(ctx, holder, name); if (JS_IsException(val)) return val; @@ -39794,7 +40959,7 @@ static JSValue internalize_json_property(JSContext *ctx, JSValueConst holder, if (js_get_length32(ctx, &len, val)) goto fail; } else { - ret = JS_GetOwnPropertyNames(ctx, &atoms, &len, JS_VALUE_GET_OBJ(val), JS_GPN_ENUM_ONLY | JS_GPN_STRING_MASK); + ret = JS_GetOwnPropertyNamesInternal(ctx, &atoms, &len, JS_VALUE_GET_OBJ(val), JS_GPN_ENUM_ONLY | JS_GPN_STRING_MASK); if (ret < 0) goto fail; } @@ -39844,9 +41009,9 @@ static JSValue js_json_parse(JSContext *ctx, JSValueConst this_val, JSValue obj, root; JSValueConst reviver; const char *str; - int len; + size_t len; - str = JS_ToCStringLen(ctx, &len, argv[0], FALSE); + str = JS_ToCStringLen(ctx, &len, argv[0]); if (!str) return JS_EXCEPTION; obj = JS_ParseJSON(ctx, str, len, ""); @@ -40436,15 +41601,26 @@ static void js_proxy_mark(JSRuntime *rt, JSValueConst val, } } +static JSValue JS_ThrowTypeErrorRevokedProxy(JSContext *ctx) +{ + return JS_ThrowTypeError(ctx, "revoked proxy"); +} + static JSProxyData *get_proxy_method(JSContext *ctx, JSValue *pmethod, JSValueConst obj, JSAtom name) { JSProxyData *s = JS_GetOpaque(obj, JS_CLASS_PROXY); JSValue method; + /* safer to test recursion in all proxy methods */ + if (js_check_stack_overflow(ctx, 0)) { + JS_ThrowStackOverflow(ctx); + return NULL; + } + /* 's' should never be NULL */ - if (JS_IsNull(s->handler)) { - JS_ThrowTypeError(ctx, "revoked proxy"); + if (s->is_revoked) { + JS_ThrowTypeErrorRevokedProxy(ctx); return NULL; } method = JS_GetProperty(ctx, s->handler, name); @@ -40628,7 +41804,7 @@ static int js_proxy_has(JSContext *ctx, JSValueConst obj, JSAtom atom) if (!ret) { JSPropertyDescriptor desc; p = JS_VALUE_GET_OBJ(s->target); - res = JS_GetOwnProperty(ctx, &desc, p, atom); + res = JS_GetOwnPropertyInternal(ctx, &desc, p, atom); if (res < 0) return -1; if (res) { @@ -40655,6 +41831,7 @@ static JSValue js_proxy_get(JSContext *ctx, JSValueConst obj, JSAtom atom, s = get_proxy_method(ctx, &method, obj, JS_ATOM_get); if (!s) return JS_EXCEPTION; + /* Note: recursion is possible thru the prototype of s->target */ if (JS_IsUndefined(method)) return JS_GetPropertyInternal(ctx, s->target, atom, receiver, FALSE); atom_val = JS_AtomToValue(ctx, atom); @@ -40669,7 +41846,7 @@ static JSValue js_proxy_get(JSContext *ctx, JSValueConst obj, JSAtom atom, JS_FreeValue(ctx, atom_val); if (JS_IsException(ret)) return JS_EXCEPTION; - res = JS_GetOwnProperty(ctx, &desc, JS_VALUE_GET_OBJ(s->target), atom); + res = JS_GetOwnPropertyInternal(ctx, &desc, JS_VALUE_GET_OBJ(s->target), atom); if (res < 0) return JS_EXCEPTION; if (res) { @@ -40722,7 +41899,7 @@ static int js_proxy_set(JSContext *ctx, JSValueConst obj, JSAtom atom, ret = JS_ToBoolFree(ctx, ret1); if (ret) { JSPropertyDescriptor desc; - res = JS_GetOwnProperty(ctx, &desc, JS_VALUE_GET_OBJ(s->target), atom); + res = JS_GetOwnPropertyInternal(ctx, &desc, JS_VALUE_GET_OBJ(s->target), atom); if (res < 0) return -1; if (res) { @@ -40801,7 +41978,7 @@ static int js_proxy_get_own_property(JSContext *ctx, JSPropertyDescriptor *pdesc return -1; p = JS_VALUE_GET_OBJ(s->target); if (JS_IsUndefined(method)) { - return JS_GetOwnProperty(ctx, pdesc, p, prop); + return JS_GetOwnPropertyInternal(ctx, pdesc, p, prop); } prop_val = JS_AtomToValue(ctx, prop); if (JS_IsException(prop_val)) { @@ -40818,7 +41995,7 @@ static int js_proxy_get_own_property(JSContext *ctx, JSPropertyDescriptor *pdesc JS_FreeValue(ctx, ret1); goto fail; } - target_res = JS_GetOwnProperty(ctx, &target_desc, p, prop); + target_res = JS_GetOwnPropertyInternal(ctx, &target_desc, p, prop); if (target_res < 0) { JS_FreeValue(ctx, ret1); return -1; @@ -40920,7 +42097,7 @@ static int js_proxy_define_own_property(JSContext *ctx, JSValueConst obj, } } p = JS_VALUE_GET_OBJ(s->target); - res = JS_GetOwnProperty(ctx, &desc, p, prop); + res = JS_GetOwnPropertyInternal(ctx, &desc, p, prop); if (res < 0) return -1; setting_not_configurable = ((flags & (JS_PROP_HAS_CONFIGURABLE | @@ -40989,7 +42166,7 @@ static int js_proxy_delete_property(JSContext *ctx, JSValueConst obj, res = JS_ToBoolFree(ctx, ret); if (res) { JSPropertyDescriptor desc; - res2 = JS_GetOwnProperty(ctx, &desc, JS_VALUE_GET_OBJ(s->target), atom); + res2 = JS_GetOwnPropertyInternal(ctx, &desc, JS_VALUE_GET_OBJ(s->target), atom); if (res2 < 0) return -1; if (res2) { @@ -41032,7 +42209,7 @@ static int js_proxy_get_own_property_names(JSContext *ctx, if (!s) return -1; if (JS_IsUndefined(method)) { - return JS_GetOwnPropertyNames(ctx, ptab, plen, + return JS_GetOwnPropertyNamesInternal(ctx, ptab, plen, JS_VALUE_GET_OBJ(s->target), JS_GPN_STRING_MASK | JS_GPN_SYMBOL_MASK); } @@ -41081,19 +42258,19 @@ static int js_proxy_get_own_property_names(JSContext *ctx, goto fail; /* check if there are non configurable properties */ - if (JS_IsNull(s->handler)) { - JS_ThrowTypeError(ctx, "revoked proxy"); + if (s->is_revoked) { + JS_ThrowTypeErrorRevokedProxy(ctx); goto fail; } - if (JS_GetOwnPropertyNames(ctx, &tab2, &len2, JS_VALUE_GET_OBJ(s->target), + if (JS_GetOwnPropertyNamesInternal(ctx, &tab2, &len2, JS_VALUE_GET_OBJ(s->target), JS_GPN_STRING_MASK | JS_GPN_SYMBOL_MASK)) goto fail; for(i = 0; i < len2; i++) { - if (JS_IsNull(s->handler)) { - JS_ThrowTypeError(ctx, "revoked proxy"); + if (s->is_revoked) { + JS_ThrowTypeErrorRevokedProxy(ctx); goto fail; } - res = JS_GetOwnProperty(ctx, &desc, JS_VALUE_GET_OBJ(s->target), + res = JS_GetOwnPropertyInternal(ctx, &desc, JS_VALUE_GET_OBJ(s->target), tab2[i].atom); if (res < 0) goto fail; @@ -41203,8 +42380,8 @@ static int js_proxy_isArray(JSContext *ctx, JSValueConst obj) JSProxyData *s = JS_GetOpaque(obj, JS_CLASS_PROXY); if (!s) return FALSE; - if (JS_IsNull(s->handler)) { - JS_ThrowTypeError(ctx, "revoked proxy"); + if (s->is_revoked) { + JS_ThrowTypeErrorRevokedProxy(ctx); return -1; } return JS_IsArray(ctx, s->target); @@ -41233,12 +42410,12 @@ static JSValue js_proxy_constructor(JSContext *ctx, JSValueConst this_val, JS_VALUE_GET_TAG(handler) != JS_TAG_OBJECT) return JS_ThrowTypeErrorNotAnObject(ctx); s = JS_GetOpaque(target, JS_CLASS_PROXY); - if (s && JS_IsNull(s->handler)) + if (s && s->is_revoked) goto revoked_proxy; s = JS_GetOpaque(handler, JS_CLASS_PROXY); - if (s && JS_IsNull(s->handler)) { + if (s && s->is_revoked) { revoked_proxy: - return JS_ThrowTypeError(ctx, "revoked proxy"); + return JS_ThrowTypeErrorRevokedProxy(ctx); } obj = JS_NewObjectProtoClass(ctx, JS_NULL, JS_CLASS_PROXY); @@ -41253,6 +42430,7 @@ static JSValue js_proxy_constructor(JSContext *ctx, JSValueConst this_val, s->handler = JS_DupValue(ctx, handler); s->proto = JS_NULL; s->is_func = JS_IsFunction(ctx, target); + s->is_revoked = FALSE; JS_SetOpaque(obj, s); JS_SetConstructorBit(ctx, obj, JS_IsConstructor(ctx, target)); return obj; @@ -41264,10 +42442,9 @@ static JSValue js_proxy_revoke(JSContext *ctx, JSValueConst this_val, { JSProxyData *s = JS_GetOpaque(func_data[0], JS_CLASS_PROXY); if (s) { - /* Note: we keep s->target so that the proxy handlers can still be - executed if the revocation is done inside a Proxy callback */ - JS_FreeValue(ctx, s->handler); - s->handler = JS_NULL; + /* We do not free the handler and target in case they are + referenced as constants in the C call stack */ + s->is_revoked = TRUE; JS_FreeValue(ctx, func_data[0]); func_data[0] = JS_NULL; } @@ -44371,10 +45548,24 @@ static JSValue js_Date_parse(JSContext *ctx, JSValueConst this_val, if (string_get_signed_field(sp, &p, &fields[0])) goto done; - for(i = 1; i < 7; i++) { + for (i = 1; i < 6; i++) { if (string_get_field(sp, &p, &fields[i])) break; } + if (i == 6 && p < sp->len && string_get(sp, p) == '.') { + /* parse milliseconds as a fractional part, round to nearest */ + /* XXX: the spec does not indicate which rounding should be used */ + int mul = 1000, ms = 0; + while (++p < sp->len) { + int c = string_get(sp, p); + if (!(c >= '0' && c <= '9')) + break; + if (mul == 1 && c >= '5') + ms += 1; + ms += (c - '0') * (mul /= 10); + } + fields[6] = ms; + } fields[1] -= 1; /* parse the time zone offset if present: [+-]HH:mm */ @@ -44418,6 +45609,7 @@ static JSValue js_Date_parse(JSContext *ctx, JSValueConst this_val, if (string_get_field(sp, &p, &fields[3 + i])) goto done; } + // XXX: parse optional milliseconds? /* parse the time zone offset if present: [+-]HHmm */ tz = 0; @@ -47234,21 +48426,24 @@ static int js_TA_cmp_generic(const void *a, const void *b, void *opaque) { res = JS_Call(ctx, psc->cmp, JS_UNDEFINED, 2, argv); if (JS_IsException(res)) { psc->exception = 1; - } else - if (validate_typed_array(ctx, psc->arr) < 0) { - JS_FreeValue(ctx, res); - psc->exception = 1; - } else + goto done; + } if (JS_VALUE_GET_TAG(res) == JS_TAG_INT) { int val = JS_VALUE_GET_INT(res); cmp = (val > 0) - (val < 0); } else { double val; - if (JS_ToFloat64Free(ctx, &val, res) < 0) + if (JS_ToFloat64Free(ctx, &val, res) < 0) { psc->exception = 1; - else + goto done; + } else { cmp = (val > 0) - (val < 0); + } } + if (validate_typed_array(ctx, psc->arr) < 0) { + psc->exception = 1; + } + done: JS_FreeValue(ctx, (JSValue)argv[0]); JS_FreeValue(ctx, (JSValue)argv[1]); } diff --git a/quickjs/quickjs.h b/quickjs/quickjs.h index 6b863be360..5936032725 100644 --- a/quickjs/quickjs.h +++ b/quickjs/quickjs.h @@ -374,7 +374,7 @@ void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s); void JS_DumpMemoryUsage(FILE *fp, const JSMemoryUsage *s, JSRuntime *rt); /* atom support */ -JSAtom JS_NewAtomLen(JSContext *ctx, const char *str, int len); +JSAtom JS_NewAtomLen(JSContext *ctx, const char *str, size_t len); JSAtom JS_NewAtom(JSContext *ctx, const char *str); JSAtom JS_NewAtomUInt32(JSContext *ctx, uint32_t n); JSAtom JS_DupAtom(JSContext *ctx, JSAtom v); @@ -466,6 +466,8 @@ static js_force_inline JSValue JS_NewCatchOffset(JSContext *ctx, int32_t val) } JSValue JS_NewInt64(JSContext *ctx, int64_t v); +JSValue JS_NewBigInt64(JSContext *ctx, int64_t v); +JSValue JS_NewBigUint64(JSContext *ctx, uint64_t v); static js_force_inline JSValue JS_NewFloat64(JSContext *ctx, double d) { @@ -603,16 +605,21 @@ static int inline JS_ToUint32(JSContext *ctx, uint32_t *pres, JSValueConst val) int JS_ToInt64(JSContext *ctx, int64_t *pres, JSValueConst val); int JS_ToIndex(JSContext *ctx, uint64_t *plen, JSValueConst val); int JS_ToFloat64(JSContext *ctx, double *pres, JSValueConst val); +int JS_ToBigInt64(JSContext *ctx, int64_t *pres, JSValueConst val); -JSValue JS_NewStringLen(JSContext *ctx, const char *str1, int len1); +JSValue JS_NewStringLen(JSContext *ctx, const char *str1, size_t len1); JSValue JS_NewString(JSContext *ctx, const char *str); JSValue JS_NewAtomString(JSContext *ctx, const char *str); JSValue JS_ToString(JSContext *ctx, JSValueConst val); JSValue JS_ToPropertyKey(JSContext *ctx, JSValueConst val); -const char *JS_ToCStringLen(JSContext *ctx, int *plen, JSValueConst val1, JS_BOOL cesu8); +const char *JS_ToCStringLen2(JSContext *ctx, size_t *plen, JSValueConst val1, JS_BOOL cesu8); +static inline const char *JS_ToCStringLen(JSContext *ctx, size_t *plen, JSValueConst val1) +{ + return JS_ToCStringLen2(ctx, plen, val1, 0); +} static inline const char *JS_ToCString(JSContext *ctx, JSValueConst val1) { - return JS_ToCStringLen(ctx, NULL, val1, 0); + return JS_ToCStringLen2(ctx, NULL, val1, 0); } void JS_FreeCString(JSContext *ctx, const char *ptr); @@ -661,6 +668,19 @@ int JS_DeleteProperty(JSContext *ctx, JSValueConst obj, JSAtom prop, int flags); int JS_SetPrototype(JSContext *ctx, JSValueConst obj, JSValueConst proto_val); JSValueConst JS_GetPrototype(JSContext *ctx, JSValueConst val); +#define JS_GPN_STRING_MASK (1 << 0) +#define JS_GPN_SYMBOL_MASK (1 << 1) +#define JS_GPN_PRIVATE_MASK (1 << 2) +/* only include the enumerable properties */ +#define JS_GPN_ENUM_ONLY (1 << 4) +/* set theJSPropertyEnum.is_enumerable field */ +#define JS_GPN_SET_ENUM (1 << 5) + +int JS_GetOwnPropertyNames(JSContext *ctx, JSPropertyEnum **ptab, + uint32_t *plen, JSValueConst obj, int flags); +int JS_GetOwnProperty(JSContext *ctx, JSPropertyDescriptor *desc, + JSValueConst obj, JSAtom prop); + JSValue JS_ParseJSON(JSContext *ctx, const char *buf, size_t buf_len, const char *filename); JSValue JS_Call(JSContext *ctx, JSValueConst func_obj, JSValueConst this_obj, diff --git a/quickjspp.hpp b/quickjspp.hpp index 40fbf35a48..000a10f587 100644 --- a/quickjspp.hpp +++ b/quickjspp.hpp @@ -160,11 +160,11 @@ namespace qjs { { static js_string unwrap(JSContext * ctx, JSValueConst v) { - int plen; - const char * ptr = JS_ToCStringLen(ctx, &plen, v, 0); + std::size_t plen; + const char * ptr = JS_ToCStringLen(ctx, &plen, v); if(!ptr) throw exception{}; - return js_string{ctx, ptr, (std::size_t)plen}; + return js_string{ctx, ptr, plen}; } static JSValue wrap(JSContext * ctx, std::string_view str) noexcept From e593f9904522d648db3ba7f2c8268738cfdb8ea2 Mon Sep 17 00:00:00 2001 From: ftk Date: Tue, 13 Aug 2019 20:20:24 +0300 Subject: [PATCH 018/185] move exception and traits out of detail namespace --- main.cpp | 2 +- quickjspp.hpp | 1665 +++++++++++++++++++++++++------------------------ 2 files changed, 843 insertions(+), 824 deletions(-) diff --git a/main.cpp b/main.cpp index 61f26b0a6f..186d65ed4f 100644 --- a/main.cpp +++ b/main.cpp @@ -147,7 +147,7 @@ int main(int argc, char ** argv) context.eval("t").cast>(), "test string", std::string{"test"}); assert(zzz == 19); } - catch(detail::exception) + catch(exception) { js_std_dump_error(ctx); } diff --git a/quickjspp.hpp b/quickjspp.hpp index 000a10f587..496302f20f 100644 --- a/quickjspp.hpp +++ b/quickjspp.hpp @@ -18,1002 +18,1021 @@ extern "C" { namespace qjs { - template - struct allocator +template +struct allocator +{ + JSRuntime * rt; + using value_type = T; + using propagate_on_container_move_assignment = std::true_type; + using propagate_on_container_copy_assignment = std::true_type; + + constexpr allocator(JSRuntime * rt) noexcept : rt{rt} + {} + + allocator(JSContext * ctx) noexcept : rt{JS_GetRuntime(ctx)} + {} + + template + constexpr allocator(const allocator& other) noexcept : rt{other.rt} + {} + + [[nodiscard]] T * allocate(std::size_t n) { - JSRuntime * rt; - using value_type = T; - using propagate_on_container_move_assignment = std::true_type; - using propagate_on_container_copy_assignment = std::true_type; + if(auto p = static_cast(js_malloc_rt(rt, n * sizeof(T)))) return p; + throw std::bad_alloc(); + } - constexpr allocator(JSRuntime * rt) noexcept : rt{rt} - {} + void deallocate(T * p, std::size_t) noexcept + { js_free_rt(rt, p); } - allocator(JSContext * ctx) noexcept : rt{JS_GetRuntime(ctx)} - {} + template + bool operator ==(const allocator& other) const + { return rt == other.rt; } - template - constexpr allocator(const allocator& other) noexcept : rt{other.rt} - {} + template + bool operator !=(const allocator& other) const + { return rt != other.rt; } +}; - [[nodiscard]] T * allocate(std::size_t n) - { - if(auto p = static_cast(js_malloc_rt(rt, n * sizeof(T)))) return p; - throw std::bad_alloc(); - } +class exception {}; - void deallocate(T * p, std::size_t) noexcept - { js_free_rt(rt, p); } +template +struct js_traits +{ + //static R unwrap(JSContext * ctx, JSValueConst v); + //static JSValue wrap(JSContext * ctx, R value); +}; - template - bool operator == (const allocator& other) const { return rt == other.rt; } - template - bool operator != (const allocator& other) const { return rt != other.rt; } - }; +// identity +template <> +struct js_traits +{ + static JSValue unwrap(JSContext * ctx, JSValueConst v) noexcept + { + return JS_DupValue(ctx, v); + } - namespace detail { - class exception {}; + static JSValue wrap(JSContext * ctx, JSValue v) noexcept + { + return v; + } +}; - template - struct js_traits - { - //static R unwrap(JSContext * ctx, JSValueConst v); - //static JSValue wrap(JSContext * ctx, R value); - }; +template <> +struct js_traits +{ + static int32_t unwrap(JSContext * ctx, JSValueConst v) + { + int32_t r; + if(JS_ToInt32(ctx, &r, v)) + throw exception{}; + return r; + } - // identity - template <> - struct js_traits - { - static JSValue unwrap(JSContext * ctx, JSValueConst v) noexcept - { - return JS_DupValue(ctx, v); - } + static JSValue wrap(JSContext * ctx, int32_t i) noexcept + { + return JS_NewInt32(ctx, i); + } +}; - static JSValue wrap(JSContext * ctx, JSValue v) noexcept - { - return v; - } - }; +template <> +struct js_traits +{ + static bool unwrap(JSContext * ctx, JSValueConst v) noexcept + { + return JS_ToBool(ctx, v); + } - template <> - struct js_traits - { - static int32_t unwrap(JSContext * ctx, JSValueConst v) - { - int32_t r; - if(JS_ToInt32(ctx, &r, v)) - throw exception{}; - return r; - } + static JSValue wrap(JSContext * ctx, bool i) noexcept + { + return JS_NewBool(ctx, i); + } +}; - static JSValue wrap(JSContext * ctx, int32_t i) noexcept - { - return JS_NewInt32(ctx, i); - } - }; +template <> +struct js_traits +{ + static void unwrap(JSContext * ctx, JSValueConst undefined) + { + if(!JS_IsUndefined(undefined)) + throw exception{}; + } +}; - template <> - struct js_traits - { - static bool unwrap(JSContext * ctx, JSValueConst v) noexcept - { - return JS_ToBool(ctx, v); - } +template <> +struct js_traits +{ + static double unwrap(JSContext * ctx, JSValueConst v) + { + double r; + if(JS_ToFloat64(ctx, &r, v)) + throw exception{}; + return r; + } - static JSValue wrap(JSContext * ctx, bool i) noexcept - { - return JS_NewBool(ctx, i); - } - }; + static JSValue wrap(JSContext * ctx, double i) noexcept + { + return JS_NewFloat64(ctx, i); + } +}; - template <> - struct js_traits - { - static void unwrap(JSContext * ctx, JSValueConst undefined) - { - if(!JS_IsUndefined(undefined)) - throw exception{}; - } - }; +namespace detail { +class js_string : public std::string_view +{ + using Base = std::string_view; + JSContext * ctx = nullptr; - template <> - struct js_traits - { - static double unwrap(JSContext * ctx, JSValueConst v) - { - double r; - if(JS_ToFloat64(ctx, &r, v)) - throw exception{}; - return r; - } + friend struct js_traits; - static JSValue wrap(JSContext * ctx, double i) noexcept - { - return JS_NewFloat64(ctx, i); - } - }; + js_string(JSContext * ctx, const char * ptr, std::size_t len) : Base(ptr, len), ctx(ctx) + {} - class js_string : public std::string_view - { - using Base = std::string_view; - JSContext * ctx = nullptr; +public: - friend struct js_traits; - js_string(JSContext * ctx, const char * ptr, std::size_t len) : Base(ptr, len), ctx(ctx) {} - public: + template + js_string(Args&& ... args) : Base(std::forward(args)...), ctx(nullptr) + {} - template - js_string(Args&&... args) : Base(std::forward(args)...), ctx(nullptr) {} + js_string(const js_string& other) = delete; - js_string(const js_string& other) = delete; + ~js_string() + { + if(ctx) + JS_FreeCString(ctx, this->data()); + } +}; +} // namespace detail - ~js_string() - { - if(ctx) - JS_FreeCString(ctx, this->data()); - } - }; +template <> +struct js_traits +{ + static detail::js_string unwrap(JSContext * ctx, JSValueConst v) + { + std::size_t plen; + const char * ptr = JS_ToCStringLen(ctx, &plen, v); + if(!ptr) + throw exception{}; + return detail::js_string{ctx, ptr, plen}; + } - template <> - struct js_traits - { - static js_string unwrap(JSContext * ctx, JSValueConst v) - { - std::size_t plen; - const char * ptr = JS_ToCStringLen(ctx, &plen, v); - if(!ptr) - throw exception{}; - return js_string{ctx, ptr, plen}; - } + static JSValue wrap(JSContext * ctx, std::string_view str) noexcept + { + return JS_NewStringLen(ctx, str.data(), (int) str.size()); + } +}; - static JSValue wrap(JSContext * ctx, std::string_view str) noexcept - { - return JS_NewStringLen(ctx, str.data(), (int)str.size()); - } - }; +template <> // slower +struct js_traits +{ + static std::string unwrap(JSContext * ctx, JSValueConst v) + { + auto str_view = js_traits::unwrap(ctx, v); + return std::string{str_view.data(), str_view.size()}; + } - template <> // slower - struct js_traits - { - static std::string unwrap(JSContext * ctx, JSValueConst v) - { - auto str_view = js_traits::unwrap(ctx, v); - return std::string{str_view.data(), str_view.size()}; - } + static JSValue wrap(JSContext * ctx, const std::string& str) noexcept + { + return JS_NewStringLen(ctx, str.data(), (int) str.size()); + } +}; - static JSValue wrap(JSContext * ctx, const std::string& str) noexcept - { - return JS_NewStringLen(ctx, str.data(), (int) str.size()); - } - }; +namespace detail { - // unwrap and free value - template - T unwrap_free(JSContext * ctx, JSValue val) +// unwrap and free value +template +T unwrap_free(JSContext * ctx, JSValue val) +{ + if constexpr(std::is_same_v) + { + JS_FreeValue(ctx, val); + return js_traits::unwrap(ctx, val); + } else + { + try { - if constexpr(std::is_same_v) - { - JS_FreeValue(ctx, val); - return js_traits::unwrap(ctx, val); - } - else - { - try - { - T result = js_traits>::unwrap(ctx, val); - JS_FreeValue(ctx, val); - return result; - } - catch(...) - { - JS_FreeValue(ctx, val); - throw; - } - } + T result = js_traits>::unwrap(ctx, val); + JS_FreeValue(ctx, val); + return result; } - - template - Tuple unwrap_args_impl(JSContext * ctx, JSValueConst * argv, std::index_sequence) + catch(...) { - return Tuple{js_traits>>::unwrap(ctx, argv[I])...}; + JS_FreeValue(ctx, val); + throw; } + } +} - template - std::tuple unwrap_args(JSContext * ctx, JSValueConst * argv) - { - return unwrap_args_impl>(ctx, argv, std::make_index_sequence()); - } +template +Tuple unwrap_args_impl(JSContext * ctx, JSValueConst * argv, std::index_sequence) +{ + return Tuple{js_traits>>::unwrap(ctx, argv[I])...}; +} - template - JSValue wrap_call(JSContext * ctx, Callable&& f, JSValueConst * argv) noexcept - { - try - { - if constexpr(std::is_same_v) - { - std::apply(std::forward(f), unwrap_args(ctx, argv)); - return JS_UNDEFINED; - } else - { - return js_traits>::wrap(ctx, - std::apply(std::forward(f), - unwrap_args(ctx, argv))); - } - } - catch(exception) - { - return JS_EXCEPTION; - } - } +template +std::tuple unwrap_args(JSContext * ctx, JSValueConst * argv) +{ + return unwrap_args_impl>(ctx, argv, std::make_index_sequence()); +} - template - JSValue wrap_this_call(JSContext * ctx, Callable&& f, JSValueConst this_value, JSValueConst * argv) noexcept +template +JSValue wrap_call(JSContext * ctx, Callable&& f, JSValueConst * argv) noexcept +{ + try + { + if constexpr(std::is_same_v) { - try - { - if constexpr(std::is_same_v) - { - std::apply(std::forward(f), std::tuple_cat(unwrap_args(ctx, &this_value), - unwrap_args(ctx, argv))); - return JS_UNDEFINED; - } else - { - return js_traits>::wrap(ctx, - std::apply(std::forward(f), - std::tuple_cat(unwrap_args(ctx, &this_value), - unwrap_args(ctx, argv)))); - } - } - catch(exception) - { - return JS_EXCEPTION; - } - } - - template - void wrap_args_impl(JSContext * ctx, JSValue * argv, Tuple tuple, std::index_sequence) + std::apply(std::forward(f), unwrap_args(ctx, argv)); + return JS_UNDEFINED; + } else { - ((argv[I] = js_traits>>::wrap(ctx, std::get(tuple))), ...); + return js_traits>::wrap(ctx, + std::apply(std::forward(f), + unwrap_args(ctx, argv))); } + } + catch(exception) + { + return JS_EXCEPTION; + } +} - template - void wrap_args(JSContext * ctx, JSValue * argv, Args&&... args) +template +JSValue wrap_this_call(JSContext * ctx, Callable&& f, JSValueConst this_value, JSValueConst * argv) noexcept +{ + try + { + if constexpr(std::is_same_v) { - wrap_args_impl(ctx, argv, std::make_tuple(std::forward(args)...), std::make_index_sequence()); - } - - template - struct fwrapper + std::apply(std::forward(f), std::tuple_cat(unwrap_args(ctx, &this_value), + unwrap_args(ctx, argv))); + return JS_UNDEFINED; + } else { - const char * name = nullptr; - }; + return js_traits>::wrap(ctx, + std::apply(std::forward(f), + std::tuple_cat( + unwrap_args(ctx, &this_value), + unwrap_args(ctx, argv)))); + } + } + catch(exception) + { + return JS_EXCEPTION; + } +} - // free function - template - struct js_traits> - { - static JSValue wrap(JSContext * ctx, fwrapper fw) noexcept - { - return JS_NewCFunction(ctx, [](JSContext * ctx, JSValueConst this_value, int argc, - JSValueConst * argv) noexcept -> JSValue { - if constexpr(PassThis) - return wrap_this_call(ctx, F, this_value, argv); - else - return wrap_call(ctx, F, argv); - }, fw.name, sizeof...(Args)); +template +void wrap_args_impl(JSContext * ctx, JSValue * argv, Tuple tuple, std::index_sequence) +{ + ((argv[I] = js_traits>>::wrap(ctx, std::get(tuple))), ...); +} - } - }; +template +void wrap_args(JSContext * ctx, JSValue * argv, Args&& ... args) +{ + wrap_args_impl(ctx, argv, std::make_tuple(std::forward(args)...), + std::make_index_sequence()); +} +} // namespace detail + +template +struct fwrapper +{ + const char * name = nullptr; +}; + +// free function +template +struct js_traits> +{ + static JSValue wrap(JSContext * ctx, fwrapper fw) noexcept + { + return JS_NewCFunction(ctx, [](JSContext * ctx, JSValueConst this_value, int argc, + JSValueConst * argv) noexcept -> JSValue { + if constexpr(PassThis) + return detail::wrap_this_call(ctx, F, this_value, argv); + else + return detail::wrap_call(ctx, F, argv); + }, fw.name, sizeof...(Args)); - // class member function + } +}; - template - struct js_traits> - { - static JSValue wrap(JSContext * ctx, fwrapper fw) noexcept - { - return JS_NewCFunction(ctx, [](JSContext * ctx, JSValueConst this_value, int argc, - JSValueConst * argv) noexcept -> JSValue { - return wrap_this_call, Args...>(ctx, F, this_value, argv); - }, fw.name, sizeof...(Args)); +// class member function - } - }; +template +struct js_traits> +{ + static JSValue wrap(JSContext * ctx, fwrapper fw) noexcept + { + return JS_NewCFunction(ctx, [](JSContext * ctx, JSValueConst this_value, int argc, + JSValueConst * argv) noexcept -> JSValue { + return detail::wrap_this_call, Args...>(ctx, F, this_value, argv); + }, fw.name, sizeof...(Args)); - template - struct js_traits> - { - static JSValue wrap(JSContext * ctx, fwrapper fw) noexcept - { - return JS_NewCFunction(ctx, [](JSContext * ctx, JSValueConst this_value, int argc, - JSValueConst * argv) noexcept -> JSValue { - return wrap_this_call, Args...>(ctx, F, this_value, argv); - }, fw.name, sizeof...(Args)); + } +}; - } - }; +template +struct js_traits> +{ + static JSValue wrap(JSContext * ctx, fwrapper fw) noexcept + { + return JS_NewCFunction(ctx, [](JSContext * ctx, JSValueConst this_value, int argc, + JSValueConst * argv) noexcept -> JSValue { + return detail::wrap_this_call, Args...>(ctx, F, this_value, argv); + }, fw.name, sizeof...(Args)); - // class constructor + } +}; - template - struct ctor_wrapper - { - static_assert(std::is_constructible::value, "no such constructor!"); - const char * name = nullptr; - }; +// class constructor - template - struct js_traits> - { - static JSValue wrap(JSContext * ctx, ctor_wrapper cw) noexcept - { - return JS_NewCFunction2(ctx, [](JSContext * ctx, JSValueConst this_value, int argc, - JSValueConst * argv) noexcept -> JSValue { - return wrap_call, Args...>(ctx, std::make_shared, argv); - }, cw.name, sizeof...(Args), JS_CFUNC_constructor, 0); +template +struct ctor_wrapper +{ + static_assert(std::is_constructible::value, "no such constructor!"); + const char * name = nullptr; +}; - } - }; +template +struct js_traits> +{ + static JSValue wrap(JSContext * ctx, ctor_wrapper cw) noexcept + { + return JS_NewCFunction2(ctx, [](JSContext * ctx, JSValueConst this_value, int argc, + JSValueConst * argv) noexcept -> JSValue { + return detail::wrap_call, Args...>(ctx, std::make_shared, argv); + }, cw.name, sizeof...(Args), JS_CFUNC_constructor, 0); + } +}; - // SP class - template - struct js_traits> - { - inline static JSClassID QJSClassId; +// SP class - static void register_class(JSContext * ctx, const char * name, JSValue proto) - { - JSClassDef def{ - name, - // destructor - [](JSRuntime * rt, JSValue obj) noexcept { - auto pptr = reinterpret_cast *>(JS_GetOpaque(obj, QJSClassId)); - assert(pptr); - //delete pptr; - auto alloc = allocator>{rt}; - using atraits = std::allocator_traits; - atraits::destroy(alloc, pptr); - atraits::deallocate(alloc, pptr, 1); - } - }; - int e = JS_NewClass(JS_GetRuntime(ctx), JS_NewClassID(&QJSClassId), &def); - if(e < 0) - throw exception{}; - JS_SetClassProto(ctx, QJSClassId, proto); - } +template +struct js_traits> +{ + inline static JSClassID QJSClassId; - static JSValue wrap(JSContext * ctx, std::shared_ptr ptr) - { - if(QJSClassId == 0) // not registered - throw exception{}; - auto jsobj = JS_NewObjectClass(ctx, QJSClassId); - if(JS_IsException(jsobj)) - { - return jsobj; + static void register_class(JSContext * ctx, const char * name, JSValue proto) + { + JSClassDef def{ + name, + // destructor + [](JSRuntime * rt, JSValue obj) noexcept { + auto pptr = reinterpret_cast *>(JS_GetOpaque(obj, QJSClassId)); + assert(pptr); + //delete pptr; + auto alloc = allocator>{rt}; + using atraits = std::allocator_traits; + atraits::destroy(alloc, pptr); + atraits::deallocate(alloc, pptr, 1); } - //auto pptr = new std::shared_ptr(std::move(ptr)); - auto alloc = allocator>{ctx}; - using atraits = std::allocator_traits; - auto pptr = atraits::allocate(alloc, 1); - atraits::construct(alloc, pptr, std::move(ptr)); - - JS_SetOpaque(jsobj, pptr); - return jsobj; - } - - static const std::shared_ptr& unwrap(JSContext * ctx, JSValueConst v) - { - auto ptr = reinterpret_cast *>(JS_GetOpaque2(ctx, v, QJSClassId)); - if(!ptr) - throw exception{}; - return *ptr; - } }; + int e = JS_NewClass(JS_GetRuntime(ctx), JS_NewClassID(&QJSClassId), &def); + if(e < 0) + throw exception{}; + JS_SetClassProto(ctx, QJSClassId, proto); + } - // T * - non-owning pointer - template - struct js_traits + static JSValue wrap(JSContext * ctx, std::shared_ptr ptr) + { + if(QJSClassId == 0) // not registered + throw exception{}; + auto jsobj = JS_NewObjectClass(ctx, QJSClassId); + if(JS_IsException(jsobj)) { - static JSValue wrap(JSContext * ctx, T * ptr) - { - if(js_traits>::QJSClassId == 0) // not registered - throw exception{}; - auto jsobj = JS_NewObjectClass(ctx, js_traits>::QJSClassId); - if(JS_IsException(jsobj)) - { - return jsobj; - } - //auto pptr = new std::shared_ptr(ptr, [](T *){}); - auto alloc = allocator>{ctx}; - using atraits = std::allocator_traits; - auto pptr = atraits::allocate(alloc, 1); - atraits::construct(alloc, pptr, ptr, [](T *){}); // shared_ptr with empty deleter - - JS_SetOpaque(jsobj, pptr); - return jsobj; - } - - static T * unwrap(JSContext * ctx, JSValueConst v) - { - auto ptr = reinterpret_cast *>(JS_GetOpaque2(ctx, v, js_traits>::QJSClassId)); - if(!ptr) - throw exception{}; - return ptr->get(); - } - }; + return jsobj; + } + //auto pptr = new std::shared_ptr(std::move(ptr)); + auto alloc = allocator>{ctx}; + using atraits = std::allocator_traits; + auto pptr = atraits::allocate(alloc, 1); + atraits::construct(alloc, pptr, std::move(ptr)); + + JS_SetOpaque(jsobj, pptr); + return jsobj; + } + static const std::shared_ptr& unwrap(JSContext * ctx, JSValueConst v) + { + auto ptr = reinterpret_cast *>(JS_GetOpaque2(ctx, v, QJSClassId)); + if(!ptr) + throw exception{}; + return *ptr; + } +}; - struct function // std::function replacement +// T * - non-owning pointer +template +struct js_traits +{ + static JSValue wrap(JSContext * ctx, T * ptr) + { + if(js_traits>::QJSClassId == 0) // not registered + throw exception{}; + auto jsobj = JS_NewObjectClass(ctx, js_traits>::QJSClassId); + if(JS_IsException(jsobj)) { - JSValue (*invoker)(function * self, JSContext * ctx, JSValueConst this_value, int argc, JSValueConst * argv) = nullptr; - void (*destroyer)(function * self) = nullptr; - alignas(std::max_align_t) char functor[]; + return jsobj; + } + //auto pptr = new std::shared_ptr(ptr, [](T *){}); + auto alloc = allocator>{ctx}; + using atraits = std::allocator_traits; + auto pptr = atraits::allocate(alloc, 1); + atraits::construct(alloc, pptr, ptr, [](T *) {}); // shared_ptr with empty deleter + + JS_SetOpaque(jsobj, pptr); + return jsobj; + } - template - static function * create(JSRuntime * rt, Functor&& f) - { - auto fptr = reinterpret_cast(js_malloc_rt(rt, sizeof(function) + sizeof(Functor))); - if(!fptr) - throw std::bad_alloc{}; - new (fptr) function; + static T * unwrap(JSContext * ctx, JSValueConst v) + { + auto ptr = reinterpret_cast *>(JS_GetOpaque2(ctx, v, + js_traits>::QJSClassId)); + if(!ptr) + throw exception{}; + return ptr->get(); + } +}; + +namespace detail { +struct function // std::function replacement +{ + JSValue + (* invoker)(function * self, JSContext * ctx, JSValueConst this_value, int argc, JSValueConst * argv) = nullptr; + + void (* destroyer)(function * self) = nullptr; + + alignas(std::max_align_t) char functor[]; + + template + static function * create(JSRuntime * rt, Functor&& f) + { + auto fptr = reinterpret_cast(js_malloc_rt(rt, sizeof(function) + sizeof(Functor))); + if(!fptr) + throw std::bad_alloc{}; + new(fptr) function; + auto functorptr = reinterpret_cast(fptr->functor); + new(functorptr) Functor(std::forward(f)); + fptr->destroyer = nullptr; + if constexpr(!std::is_trivially_destructible_v) + { + fptr->destroyer = [](function * fptr) { auto functorptr = reinterpret_cast(fptr->functor); - new(functorptr) Functor(std::forward(f)); - fptr->destroyer = nullptr; - if constexpr(!std::is_trivially_destructible_v) - { - fptr->destroyer = [](function * fptr) { - auto functorptr = reinterpret_cast(fptr->functor); - functorptr->~Functor(); - }; + functorptr->~Functor(); + }; + } + return fptr; + } +}; + +static_assert(std::is_trivially_destructible_v); +} + +template <> +struct js_traits +{ + inline static JSClassID QJSClassId; + + static void register_class(JSContext * ctx, const char * name) + { + JSClassDef def{ + name, + // destructor + [](JSRuntime * rt, JSValue obj) noexcept { + auto fptr = reinterpret_cast(JS_GetOpaque(obj, QJSClassId)); + assert(fptr); + if(fptr->destroyer) + fptr->destroyer(fptr); + js_free_rt(rt, fptr); + }, + nullptr, // mark + // call + [](JSContext * ctx, JSValueConst func_obj, JSValueConst this_val, int argc, + JSValueConst * argv) -> JSValue { + auto ptr = reinterpret_cast(JS_GetOpaque2(ctx, func_obj, QJSClassId)); + if(!ptr) + return JS_EXCEPTION; + return ptr->invoker(ptr, ctx, this_val, argc, argv); } - return fptr; - } }; - static_assert(std::is_trivially_destructible_v); + int e = JS_NewClass(JS_GetRuntime(ctx), JS_NewClassID(&QJSClassId), &def); + if(e < 0) + throw exception{}; + } +}; - template <> - struct js_traits - { - inline static JSClassID QJSClassId; - static void register_class(JSContext * ctx, const char * name) - { - JSClassDef def{ - name, - // destructor - [](JSRuntime * rt, JSValue obj) noexcept { - auto fptr = reinterpret_cast(JS_GetOpaque(obj, QJSClassId)); - assert(fptr); - if(fptr->destroyer) - fptr->destroyer(fptr); - js_free_rt(rt, fptr); - }, - nullptr, // mark - // call - [](JSContext *ctx, JSValueConst func_obj, JSValueConst this_val, int argc, JSValueConst *argv) -> JSValue { - auto ptr = reinterpret_cast(JS_GetOpaque2(ctx, func_obj, QJSClassId)); - if(!ptr) - return JS_EXCEPTION; - return ptr->invoker(ptr, ctx, this_val, argc, argv); - } - }; - int e = JS_NewClass(JS_GetRuntime(ctx), JS_NewClassID(&QJSClassId), &def); - if(e < 0) - throw exception{}; - } - }; +// properties +template +struct js_property_traits +{ + // static void set_property(JSContext * ctx, JSValue this_obj, R key, JSValue value) + // static JSValue get_property(JSContext * ctx, JSValue this_obj, R key) +}; - // properties +template <> +struct js_property_traits +{ + static void set_property(JSContext * ctx, JSValue this_obj, const char * name, JSValue value) + { + int err = JS_SetPropertyStr(ctx, this_obj, name, value); + if(err < 0) + throw exception{}; + } - template - struct js_property_traits - { - // static void set_property(JSContext * ctx, JSValue this_obj, R key, JSValue value) - // static JSValue get_property(JSContext * ctx, JSValue this_obj, R key) - }; + static JSValue get_property(JSContext * ctx, JSValue this_obj, const char * name) noexcept + { + return JS_GetPropertyStr(ctx, this_obj, name); + } +}; - template <> - struct js_property_traits - { - static void set_property(JSContext * ctx, JSValue this_obj, const char * name, JSValue value) - { - int err = JS_SetPropertyStr(ctx, this_obj, name, value); - if(err < 0) - throw exception{}; - } +template <> +struct js_property_traits +{ + static void set_property(JSContext * ctx, JSValue this_obj, uint32_t idx, JSValue value) + { + int err = JS_SetPropertyUint32(ctx, this_obj, idx, value); + if(err < 0) + throw exception{}; + } - static JSValue get_property(JSContext * ctx, JSValue this_obj, const char * name) noexcept - { - return JS_GetPropertyStr(ctx, this_obj, name); - } - }; + static JSValue get_property(JSContext * ctx, JSValue this_obj, uint32_t idx) noexcept + { + return JS_GetPropertyUint32(ctx, this_obj, idx); + } +}; + +namespace detail { +template +struct property_proxy +{ + JSContext * ctx; + JSValue this_obj; + Key key; + + template + operator Value() const + { + return unwrap_free(ctx, js_property_traits::get_property(ctx, this_obj, key)); + } - template <> - struct js_property_traits - { - static void set_property(JSContext * ctx, JSValue this_obj, uint32_t idx, JSValue value) - { - int err = JS_SetPropertyUint32(ctx, this_obj, idx, value); - if(err < 0) - throw exception{}; - } + template + property_proxy& operator =(Value value) + { + js_property_traits::set_property(ctx, this_obj, key, + js_traits::wrap(ctx, std::move(value))); + return *this; + } +}; - static JSValue get_property(JSContext * ctx, JSValue this_obj, uint32_t idx) noexcept - { - return JS_GetPropertyUint32(ctx, this_obj, idx); - } - }; - template - struct property_proxy - { - JSContext * ctx; - JSValue this_obj; - Key key; +// class member variable getter/setter +template +struct get_set {}; - template - operator Value() const - { - return unwrap_free(ctx, js_property_traits::get_property(ctx, this_obj, key)); - } +template +struct get_set +{ + using is_const = std::is_const; - template - property_proxy& operator =(Value value) - { - js_property_traits::set_property(ctx, this_obj, key, - js_traits::wrap(ctx, std::move(value))); - return *this; - } - }; + static const R& get(const std::shared_ptr& ptr) + { + return *ptr.*M; + } + static R& set(const std::shared_ptr& ptr, R value) + { + return *ptr.*M = std::move(value); + } +}; - // class member variable getter/setter - template - struct get_set - {}; +} // namespace detail - template - struct get_set - { - using is_const = std::is_const; +class Value +{ +public: + JSValue v; + JSContext * ctx = nullptr; - static const R& get(const std::shared_ptr& ptr) - { - return *ptr.*M; - } +public: + template + Value(JSContext * ctx, T val) : ctx(ctx) + { + v = js_traits::wrap(ctx, val); + } - static R& set(const std::shared_ptr& ptr, R value) - { - return *ptr.*M = std::move(value); - } + Value(const Value& rhs) + { + ctx = rhs.ctx; + v = JS_DupValue(ctx, rhs.v); + } - }; + Value(Value&& rhs) + { + std::swap(ctx, rhs.ctx); + v = rhs.v; + } + ~Value() + { + if(ctx) JS_FreeValue(ctx, v); } - class Value + + template + T cast() const { - public: - JSValue v; - JSContext * ctx = nullptr; + return js_traits::unwrap(ctx, v); + } - public: - template - Value(JSContext * ctx, T val) : ctx(ctx) - { - v = detail::js_traits::wrap(ctx, val); - } + JSValue release() // dont call freevalue + { + ctx = nullptr; + return v; + } - Value(const Value& rhs) - { - ctx = rhs.ctx; - v = JS_DupValue(ctx, rhs.v); - } + operator JSValue()&& + { + return release(); + } - Value(Value&& rhs) - { - std::swap(ctx, rhs.ctx); - v = rhs.v; - } - ~Value() - { - if(ctx) JS_FreeValue(ctx, v); - } + // access properties + template + detail::property_proxy operator [](Key key) + { + return {ctx, v, std::move(key)}; + } - template - T cast() const - { - return detail::js_traits::unwrap(ctx, v); - } + // add("f", []() {...}); + template + Value& add(const char * name, Function&& f) + { + (*this)[name] = js_traits(f)})>::wrap(ctx, + std::forward(f)); + return *this; + } - JSValue release() // dont call freevalue - { - ctx = nullptr; - return v; - } + // add<&f>("f"); + // add<&T::f>("f"); + template + std::enable_if_t, Value&> + add(const char * name) + { + (*this)[name] = fwrapper{name}; + return *this; + } - operator JSValue()&& + // add<&T::member>("member"); + template + std::enable_if_t, Value&> + add(const char * name) + { + auto prop = JS_NewAtom(ctx, name); + using fgetter = fwrapper::get, true>; + int ret; + if constexpr (detail::get_set::is_const::value) { - return release(); + ret = JS_DefinePropertyGetSet(ctx, v, prop, + js_traits::wrap(ctx, fgetter{name}), + JS_UNDEFINED, + 0 // ? + ); + } else + { + using fsetter = fwrapper::set, true>; + ret = JS_DefinePropertyGetSet(ctx, v, prop, + js_traits::wrap(ctx, fgetter{name}), + js_traits::wrap(ctx, fsetter{name}), + JS_PROP_WRITABLE // ? + ); } + JS_FreeAtom(ctx, prop); + if(ret < 0) + throw exception{}; + return *this; + } - // access properties - template - detail::property_proxy operator [](Key key) - { - return {ctx, v, std::move(key)}; - } +}; + + +class Runtime +{ +public: + JSRuntime * rt; + + Runtime() + { + rt = JS_NewRuntime(); + if(!rt) + throw exception{}; + } + + Runtime(const Runtime&) = delete; + ~Runtime() + { + JS_FreeRuntime(rt); + } +}; + + +class Context +{ +public: + JSContext * ctx; - // add("f", []() {...}); - template - Value& add(const char * name, Function&& f) + //private: + class Module + { + friend class Context; + + JSModuleDef * m; + JSContext * ctx; + const char * name; + + using nvp = std::pair; + std::vector> exports; + public: + Module(JSContext * ctx, const char * name) : ctx(ctx), name(name), exports(JS_GetRuntime(ctx)) { - (*this)[name] = detail::js_traits(f)})>::wrap(ctx, std::forward(f)); - return *this; + m = JS_NewCModule(ctx, name, [](JSContext * ctx, JSModuleDef * m) noexcept { + auto context = reinterpret_cast(JS_GetContextOpaque(ctx)); + if(!context) + return -1; + auto it = std::find_if(context->modules.begin(), context->modules.end(), + [m](const Module& module) { return module.m == m; }); + if(it == context->modules.end()) + return -1; + for(const auto& e : it->exports) + { + if(JS_SetModuleExport(ctx, m, e.first, JS_DupValue(ctx, e.second.v)) != 0) + return -1; + } + return 0; + }); + if(!m) + throw exception{}; } - // add<&f>("f"); - // add<&T::f>("f"); - template - std::enable_if_t, Value&> - add(const char * name) + Module& add(const char * name, JSValue value) { - (*this)[name] = detail::fwrapper{name}; + exports.push_back({name, {ctx, value}}); + JS_AddModuleExport(ctx, m, name); return *this; } - // add<&T::member>("member"); - template - std::enable_if_t, Value&> - add(const char * name) + Module& add(const char * name, Value value) { - auto prop = JS_NewAtom(ctx, name); - using fgetter = detail::fwrapper::get, true>; - int ret; - if constexpr (detail::get_set::is_const::value) - { - ret = JS_DefinePropertyGetSet(ctx, v, prop, - detail::js_traits::wrap(ctx, fgetter{name}), - JS_UNDEFINED, - 0 // ? - ); - } - else - { - using fsetter = detail::fwrapper::set, true>; - ret = JS_DefinePropertyGetSet(ctx, v, prop, - detail::js_traits::wrap(ctx, fgetter{name}), - detail::js_traits::wrap(ctx, fsetter{name}), - JS_PROP_WRITABLE // ? - ); - } - JS_FreeAtom(ctx, prop); - if(ret < 0) - throw detail::exception{}; + assert(value.ctx == ctx); + exports.push_back({name, std::move(value)}); + JS_AddModuleExport(ctx, m, name); return *this; } + template + Module& add(const char * name, T value) + { + return add(name, js_traits::wrap(ctx, std::move(value))); + } - }; + Module(const Module&) = delete; + Module(Module&&) = default; + //Module& operator=(Module&&) = default; - class Runtime - { - public: - JSRuntime * rt; - Runtime() + // function wrappers + template + Module& function(const char * name) { - rt = JS_NewRuntime(); - if(!rt) - throw detail::exception{}; + return add(name, qjs::fwrapper{name}); } - Runtime(const Runtime&) = delete; - - ~Runtime() + template + Module& function(const char * name, F&& f) { - JS_FreeRuntime(rt); + return add(name, js_traits(f)})>::wrap(std::forward(f))); } - }; - - class Context - { - public: - JSContext * ctx; - - //private: - class Module + // class register wrapper + private: + template + class class_registrar { - friend class Context; - - JSModuleDef * m; - JSContext * ctx; const char * name; - - using nvp = std::pair; - std::vector> exports; + qjs::Value prototype; + qjs::Context::Module& module; + qjs::Context& context; public: - Module(JSContext * ctx, const char * name) : ctx(ctx), name(name), exports(JS_GetRuntime(ctx)) + explicit class_registrar(const char * name, qjs::Context::Module& module, qjs::Context& context) : + name(name), + prototype(context.newObject()), + module(module), + context(context) { - m = JS_NewCModule(ctx, name, [](JSContext * ctx, JSModuleDef * m) noexcept { - auto context = reinterpret_cast(JS_GetContextOpaque(ctx)); - if(!context) - return -1; - auto it = std::find_if(context->modules.begin(), context->modules.end(), - [m](const Module& module) { return module.m == m; }); - if(it == context->modules.end()) - return -1; - for(const auto& e : it->exports) - { - if(JS_SetModuleExport(ctx, m, e.first, JS_DupValue(ctx, e.second.v)) != 0) - return -1; - } - return 0; - }); - if(!m) - throw detail::exception{}; } - Module& add(const char * name, JSValue value) + class_registrar(const class_registrar&) = delete; + + template + class_registrar& fun(const char * name, F&& f) { - exports.push_back({name, {ctx, value}}); - JS_AddModuleExport(ctx, m, name); + prototype.add(name, std::forward(f)); return *this; } - Module& add(const char * name, Value value) + template + class_registrar& fun(const char * name) { - assert(value.ctx == ctx); - exports.push_back({name, std::move(value)}); - JS_AddModuleExport(ctx, m, name); + prototype.add(name); return *this; } - template - Module& add(const char * name, T value) + template + class_registrar& constructor(const char * name = nullptr) { - return add(name, detail::js_traits::wrap(ctx, std::move(value))); + if(!name) + name = this->name; + module.add(name, qjs::ctor_wrapper{name}); + return *this; } - Module(const Module&) = delete; - Module(Module&&) = default; - //Module& operator=(Module&&) = default; - - - // function wrappers - template - Module& function(const char * name) - { - return add(name, qjs::detail::fwrapper{name}); - } - template - Module& function(const char * name, F&& f) + /* TODO: needs casting to base class + template + class_registrar& base() { - return add(name, detail::js_traits(f)})>::wrap(std::forward(f))); + assert(js_traits>::QJSClassId && "base class is not registered"); + auto base_proto = JS_GetClassProto(context.ctx, js_traits>::QJSClassId); + int err = JS_SetPrototype(context.ctx, prototype.v, base_proto); + JS_FreeValue(context.ctx, base_proto); + if(err < 0) + throw exception{}; + return *this; } + */ - // class register wrapper - private: - template - class class_registrar + ~class_registrar() { - const char * name; - qjs::Value prototype; - qjs::Context::Module& module; - qjs::Context& context; - public: - explicit class_registrar(const char * name, qjs::Context::Module& module, qjs::Context& context) : - name(name), - prototype(context.newObject()), - module(module), - context(context) - { - } - - class_registrar(const class_registrar&) = delete; - - template - class_registrar& fun(const char * name, F&& f) - { - prototype.add(name, std::forward(f)); - return *this; - } - - template - class_registrar& fun(const char * name) - { - prototype.add(name); - return *this; - } - - template - class_registrar& constructor(const char * name = nullptr) - { - if(!name) - name = this->name; - module.add(name, qjs::detail::ctor_wrapper{name}); - return *this; - } - - /* TODO: needs casting to base class - template - class_registrar& base() - { - assert(detail::js_traits>::QJSClassId && "base class is not registered"); - auto base_proto = JS_GetClassProto(context.ctx, detail::js_traits>::QJSClassId); - int err = JS_SetPrototype(context.ctx, prototype.v, base_proto); - JS_FreeValue(context.ctx, base_proto); - if(err < 0) - throw detail::exception{}; - return *this; - } - */ - - ~class_registrar() - { - context.registerClass(name, std::move(prototype)); - } - }; - public: - template - class_registrar class_(const char * name) - { - return class_registrar{name, *this, *reinterpret_cast(JS_GetContextOpaque(ctx))}; + context.registerClass(name, std::move(prototype)); } - }; - std::vector> modules; - private: - void init() - { - JS_SetContextOpaque(ctx, this); - detail::js_traits::register_class(ctx, "C++ function"); - } public: - Context(Runtime& rt) : Context(rt.rt) - {} - - Context(JSRuntime * rt) : modules{rt} - { - ctx = JS_NewContext(rt); - if(!ctx) - throw detail::exception{}; - init(); - } - - Context(JSContext * ctx) : ctx{ctx}, modules{ctx} + template + class_registrar class_(const char * name) { - init(); + return class_registrar{name, *this, *reinterpret_cast(JS_GetContextOpaque(ctx))}; } - Context(const Context&) = delete; + }; - ~Context() - { - modules.clear(); - JS_FreeContext(ctx); - } + std::vector> modules; +private: + void init() + { + JS_SetContextOpaque(ctx, this); + js_traits::register_class(ctx, "C++ function"); + } - Module& addModule(const char * name) - { - modules.emplace_back(ctx, name); - return modules.back(); - } +public: + Context(Runtime& rt) : Context(rt.rt) + {} - Value global() - { - return Value{ctx, JS_GetGlobalObject(ctx)}; - } + Context(JSRuntime * rt) : modules{rt} + { + ctx = JS_NewContext(rt); + if(!ctx) + throw exception{}; + init(); + } - Value newObject() - { - return Value{ctx, JS_NewObject(ctx)}; - } + Context(JSContext * ctx) : ctx{ctx}, modules{ctx} + { + init(); + } - template - void registerClass(const char * name, JSValue proto) - { - detail::js_traits>::register_class(ctx, name, proto); - } + Context(const Context&) = delete; - Value eval(std::string_view buffer, const char * filename = "", unsigned eval_flags = 0) - { - JSValue v = JS_Eval(ctx, buffer.data(), buffer.size(), filename, eval_flags); - //if(JS_IsException(v)) - //throw detail::exception{}; - return Value{ctx, v}; - } + ~Context() + { + modules.clear(); + JS_FreeContext(ctx); + } - Value evalFile(const char * filename, unsigned eval_flags = 0) - { - size_t buf_len; - auto deleter = [this](void * p) { js_free(ctx, p); }; - auto buf = std::unique_ptr{js_load_file(ctx, &buf_len, filename), deleter}; - if(!buf) - throw std::runtime_error{std::string{"evalFile: can't read file: "} + filename}; - return eval({reinterpret_cast(buf.get()), buf_len}, filename, eval_flags); - } + Module& addModule(const char * name) + { + modules.emplace_back(ctx, name); + return modules.back(); + } - }; + Value global() + { + return Value{ctx, JS_GetGlobalObject(ctx)}; + } + Value newObject() + { + return Value{ctx, JS_NewObject(ctx)}; + } - namespace detail { + template + void registerClass(const char * name, JSValue proto) + { + js_traits>::register_class(ctx, name, proto); + } - template - struct js_traits> - { - static std::function unwrap(JSContext * ctx, JSValueConst fun_obj) - { - return [jsfun_obj = Value{ctx, JS_DupValue(ctx, fun_obj)}](Args&&... args) -> R { - const int argc = sizeof...(Args); - JSValue argv[argc]; - wrap_args(jsfun_obj.ctx, argv, std::forward(args)...); - JSValue result = JS_Call(jsfun_obj.ctx, jsfun_obj.v, JS_UNDEFINED, argc, const_cast(argv)); - for(int i = 0; i < argc; i++) JS_FreeValue(jsfun_obj.ctx, argv[i]); - return unwrap_free(jsfun_obj.ctx, result); - }; - } + Value eval(std::string_view buffer, const char * filename = "", unsigned eval_flags = 0) + { + JSValue v = JS_Eval(ctx, buffer.data(), buffer.size(), filename, eval_flags); + //if(JS_IsException(v)) + //throw exception{}; + return Value{ctx, v}; + } - template - static JSValue wrap(JSContext * ctx, Functor&& functor) - { - auto obj = JS_NewObjectClass(ctx, js_traits::QJSClassId); - if(JS_IsException(obj)) - return JS_EXCEPTION; - auto fptr = function::create(JS_GetRuntime(ctx), std::forward(functor)); - fptr->invoker = [](function * self, JSContext * ctx, JSValueConst this_value, int argc, JSValueConst * argv) { - assert(self); - auto f = reinterpret_cast(&self->functor); - return wrap_call(ctx, *f, argv); - }; - JS_SetOpaque(obj, fptr); - return obj; - } - }; + Value evalFile(const char * filename, unsigned eval_flags = 0) + { + size_t buf_len; + auto deleter = [this](void * p) { js_free(ctx, p); }; + auto buf = std::unique_ptr{js_load_file(ctx, &buf_len, filename), deleter}; + if(!buf) + throw std::runtime_error{std::string{"evalFile: can't read file: "} + filename}; + return eval({reinterpret_cast(buf.get()), buf_len}, filename, eval_flags); + } - // std::vector <-> Array - template - struct js_traits> - { - static JSValue wrap(JSContext * ctx, const std::vector& arr) - { - auto jsarray = Value{ctx, JS_NewArray(ctx)}; - if(JS_IsException(jsarray.v)) - throw detail::exception{}; +}; - for(uint32_t i = 0; i < (uint32_t) arr.size(); i++) - jsarray[i] = arr[i]; - return std::move(jsarray); - } +template +struct js_traits> +{ + static std::function unwrap(JSContext * ctx, JSValueConst fun_obj) + { + return [jsfun_obj = Value{ctx, JS_DupValue(ctx, fun_obj)}](Args&& ... args) -> R { + const int argc = sizeof...(Args); + JSValue argv[argc]; + detail::wrap_args(jsfun_obj.ctx, argv, std::forward(args)...); + JSValue result = JS_Call(jsfun_obj.ctx, jsfun_obj.v, JS_UNDEFINED, argc, const_cast(argv)); + for(int i = 0; i < argc; i++) JS_FreeValue(jsfun_obj.ctx, argv[i]); + return detail::unwrap_free(jsfun_obj.ctx, result); + }; + } - static std::vector unwrap(JSContext * ctx, JSValueConst jsarr) - { - if(!JS_IsArray(ctx, jsarr)) - throw exception{}; - Value jsarray {ctx, JS_DupValue(ctx, jsarr)}; - std::vector arr; - int32_t len = jsarray["length"]; - arr.reserve((uint32_t)len); - for(uint32_t i = 0; i < (uint32_t)len; i++) - arr.push_back(jsarray[i]); - return arr; - } + template + static JSValue wrap(JSContext * ctx, Functor&& functor) + { + using detail::function; + auto obj = JS_NewObjectClass(ctx, js_traits::QJSClassId); + if(JS_IsException(obj)) + return JS_EXCEPTION; + auto fptr = function::create(JS_GetRuntime(ctx), std::forward(functor)); + fptr->invoker = [](function * self, JSContext * ctx, JSValueConst this_value, int argc, JSValueConst * argv) { + assert(self); + auto f = reinterpret_cast(&self->functor); + return detail::wrap_call(ctx, *f, argv); }; + JS_SetOpaque(obj, fptr); + return obj; + } +}; + +// std::vector <-> Array +template +struct js_traits> +{ + static JSValue wrap(JSContext * ctx, const std::vector& arr) + { + auto jsarray = Value{ctx, JS_NewArray(ctx)}; + if(JS_IsException(jsarray.v)) + throw exception{}; + for(uint32_t i = 0; i < (uint32_t) arr.size(); i++) + jsarray[i] = arr[i]; + return std::move(jsarray); } + static std::vector unwrap(JSContext * ctx, JSValueConst jsarr) + { + if(!JS_IsArray(ctx, jsarr)) + throw exception{}; + Value jsarray{ctx, JS_DupValue(ctx, jsarr)}; + std::vector arr; + int32_t len = jsarray["length"]; + arr.reserve((uint32_t) len); + for(uint32_t i = 0; i < (uint32_t) len; i++) + arr.push_back(jsarray[i]); + return arr; + } +}; + + } \ No newline at end of file From 11c0ac6e5a874dc8fab04d06389c993b7539dd4b Mon Sep 17 00:00:00 2001 From: ftk Date: Thu, 29 Aug 2019 14:44:16 +0300 Subject: [PATCH 019/185] add documentation --- quickjspp.hpp | 206 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 174 insertions(+), 32 deletions(-) diff --git a/quickjspp.hpp b/quickjspp.hpp index 496302f20f..23e0c355e4 100644 --- a/quickjspp.hpp +++ b/quickjspp.hpp @@ -17,7 +17,8 @@ extern "C" { namespace qjs { - +/** A custom allocator that uses js_malloc_rt and js_free_rt + */ template struct allocator { @@ -53,17 +54,31 @@ struct allocator bool operator !=(const allocator& other) const { return rt != other.rt; } }; - +/** Exception type. + * Indicates that exception has occured in JS context. + */ class exception {}; +/** Javascript conversion traits. + * Describes how to convert type R to/from JSValue. + */ template struct js_traits { - //static R unwrap(JSContext * ctx, JSValueConst v); - //static JSValue wrap(JSContext * ctx, R value); + /** Create an object of C++ type R given JSValue v and JSContext. + * This function is intentionally not implemented. User should implement this function for their own type. + * @param v This value is passed as JSValueConst so it should be freed by the caller. + */ + static R unwrap(JSContext * ctx, JSValueConst v); + /** Create JSValue from an object of type R and JSContext. + * This function is intentionally not implemented. User should implement this function for their own type. + * @return Returns JSValue which should be freed by the caller. + */ + static JSValue wrap(JSContext * ctx, R value); }; -// identity +/** Conversion traits for JSValue (identity). + */ template <> struct js_traits { @@ -78,9 +93,13 @@ struct js_traits } }; +/** Conversion traits for int32. + */ template <> struct js_traits { + + /// @throws exception static int32_t unwrap(JSContext * ctx, JSValueConst v) { int32_t r; @@ -95,6 +114,8 @@ struct js_traits } }; +/** Conversion traits for boolean. + */ template <> struct js_traits { @@ -109,19 +130,25 @@ struct js_traits } }; +/** Conversion trait for void. + */ template <> struct js_traits { + /// @throws exception if jsvalue is neither undefined nor null static void unwrap(JSContext * ctx, JSValueConst undefined) { - if(!JS_IsUndefined(undefined)) + if(!JS_IsUndefined(undefined) && !JS_IsNull(undefined)) throw exception{}; } }; +/** Conversion traits for float64/double. + */ template <> struct js_traits { + /// @throws exception static double unwrap(JSContext * ctx, JSValueConst v) { double r; @@ -137,6 +164,8 @@ struct js_traits }; namespace detail { +/** Fake std::string_view which frees the string on destruction. +*/ class js_string : public std::string_view { using Base = std::string_view; @@ -163,6 +192,7 @@ class js_string : public std::string_view }; } // namespace detail +/** Conversion traits from std::string_view and to detail::js_string. */ template <> struct js_traits { @@ -181,6 +211,7 @@ struct js_traits } }; +/** Conversion traits for std::string */ template <> // slower struct js_traits { @@ -198,7 +229,7 @@ struct js_traits namespace detail { -// unwrap and free value +/** Helper function to convert and then free JSValue. */ template T unwrap_free(JSContext * ctx, JSValue val) { @@ -228,12 +259,24 @@ Tuple unwrap_args_impl(JSContext * ctx, JSValueConst * argv, std::index_sequence return Tuple{js_traits>>::unwrap(ctx, argv[I])...}; } +/** Helper function to convert an array of JSValues to a tuple. + * @tparam Args C++ types of the argv array + */ template std::tuple unwrap_args(JSContext * ctx, JSValueConst * argv) { return unwrap_args_impl>(ctx, argv, std::make_index_sequence()); } +/** Helper function to call f with an array of JSValues. + * @tparam R return type of f + * @tparam Args argument types of f + * @tparam Callable type of f (inferred) + * @param ctx JSContext + * @param f callable object + * @param argv array of JSValue's + * @return converted return value of f or JS_NULL if f returns void + */ template JSValue wrap_call(JSContext * ctx, Callable&& f, JSValueConst * argv) noexcept { @@ -242,7 +285,7 @@ JSValue wrap_call(JSContext * ctx, Callable&& f, JSValueConst * argv) noexcept if constexpr(std::is_same_v) { std::apply(std::forward(f), unwrap_args(ctx, argv)); - return JS_UNDEFINED; + return JS_NULL; } else { return js_traits>::wrap(ctx, @@ -256,6 +299,9 @@ JSValue wrap_call(JSContext * ctx, Callable&& f, JSValueConst * argv) noexcept } } +/** Same as wrap_call, but pass this_value as first argument. + * @tparam FirstArg type of this_value + */ template JSValue wrap_this_call(JSContext * ctx, Callable&& f, JSValueConst this_value, JSValueConst * argv) noexcept { @@ -265,7 +311,7 @@ JSValue wrap_this_call(JSContext * ctx, Callable&& f, JSValueConst this_value, J { std::apply(std::forward(f), std::tuple_cat(unwrap_args(ctx, &this_value), unwrap_args(ctx, argv))); - return JS_UNDEFINED; + return JS_NULL; } else { return js_traits>::wrap(ctx, @@ -287,6 +333,10 @@ void wrap_args_impl(JSContext * ctx, JSValue * argv, Tuple tuple, std::index_seq ((argv[I] = js_traits>>::wrap(ctx, std::get(tuple))), ...); } +/** Converts C++ args to JSValue array. + * @tparam Args argument types + * @param argv array of size at least sizeof...(Args) + */ template void wrap_args(JSContext * ctx, JSValue * argv, Args&& ... args) { @@ -295,13 +345,19 @@ void wrap_args(JSContext * ctx, JSValue * argv, Args&& ... args) } } // namespace detail +/** A wrapper type for free and class member functions. + * Pointer to function F is a template argument. + * @tparam F either a pointer to free function or a pointer to class member function + * @tparam PassThis if true and F is a pointer to free function, passes Javascript "this" value as first argument: + */ template struct fwrapper { + /// "name" property of the JS function object (not defined if nullptr) const char * name = nullptr; }; -// free function +/** Conversion to JSValue for free function in fwrapper. */ template struct js_traits> { @@ -318,8 +374,7 @@ struct js_traits> } }; -// class member function - +/** Conversion to JSValue for class member function in fwrapper. */ template struct js_traits> { @@ -333,6 +388,7 @@ struct js_traits> } }; +/** Conversion to JSValue for const class member function in fwrapper. */ template struct js_traits> { @@ -346,15 +402,19 @@ struct js_traits> } }; -// class constructor - +/** A wrapper type for constructor of type T with arguments Args. + * Compilation fails if no such constructor is defined. + * @tparam Args constructor arguments + */ template struct ctor_wrapper { static_assert(std::is_constructible::value, "no such constructor!"); + /// "name" property of JS constructor object const char * name = nullptr; }; +/** Conversion to JSValue for ctor_wrapper. */ template struct js_traits> { @@ -364,18 +424,27 @@ struct js_traits> JSValueConst * argv) noexcept -> JSValue { return detail::wrap_call, Args...>(ctx, std::make_shared, argv); }, cw.name, sizeof...(Args), JS_CFUNC_constructor, 0); - } }; -// SP class - +/** Conversions for std::shared_ptr. + * T should be registered to a context before conversions. + * @tparam T class type + */ template struct js_traits> { + /// Registered class id in QuickJS. inline static JSClassID QJSClassId; + /** Register class in QuickJS context. + * + * @param ctx context + * @param name class name + * @param proto class prototype + * @throws exception + */ static void register_class(JSContext * ctx, const char * name, JSValue proto) { JSClassDef def{ @@ -397,6 +466,10 @@ struct js_traits> JS_SetClassProto(ctx, QJSClassId, proto); } + /** Create a JSValue from std::shared_ptr. + * Creates an object with class if #QJSClassId and sets its opaque pointer to a new copy of #ptr. + * @throws exception if class T is not registered or error on object creation + */ static JSValue wrap(JSContext * ctx, std::shared_ptr ptr) { if(QJSClassId == 0) // not registered @@ -416,6 +489,7 @@ struct js_traits> return jsobj; } + /// @throws exception if #v doesn't have the correct class id static const std::shared_ptr& unwrap(JSContext * ctx, JSValueConst v) { auto ptr = reinterpret_cast *>(JS_GetOpaque2(ctx, v, QJSClassId)); @@ -459,7 +533,10 @@ struct js_traits }; namespace detail { -struct function // std::function replacement +/** A faster std::function-like object with type erasure. + * Used to convert any callable objects (including lambdas) to JSValue. + */ +struct function { JSValue (* invoker)(function * self, JSContext * ctx, JSValueConst this_value, int argc, JSValueConst * argv) = nullptr; @@ -614,6 +691,13 @@ struct get_set } // namespace detail +/** JSValue with RAAI semantics. + * A wrapper over (JSValue v, JSContext * ctx). + * Calls JS_FreeValue(ctx, v) on destruction. Can be copied and moved. + * A JSValue can be released by either JSValue x = std::move(value); or JSValue x = value.release(), then the Value becomes invalid and FreeValue won't be called + * Can be converted to C++ type, for example: auto string = value.as(); qjs::exception would be thrown on error + * Properties can be accessed (read/write): value["property1"] = 1; value[2] = "2"; + */ class Value { public: @@ -648,7 +732,13 @@ class Value template T cast() const { - return js_traits::unwrap(ctx, v); + return js_traits>::unwrap(ctx, v); + } + + template + T as() const + { + return cast(); } JSValue release() // dont call freevalue @@ -703,7 +793,7 @@ class Value ret = JS_DefinePropertyGetSet(ctx, v, prop, js_traits::wrap(ctx, fgetter{name}), JS_UNDEFINED, - 0 // ? + JS_PROP_CONFIGURABLE | JS_PROP_ENUMERABLE ); } else { @@ -711,7 +801,7 @@ class Value ret = JS_DefinePropertyGetSet(ctx, v, prop, js_traits::wrap(ctx, fgetter{name}), js_traits::wrap(ctx, fsetter{name}), - JS_PROP_WRITABLE // ? + JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE | JS_PROP_ENUMERABLE ); } JS_FreeAtom(ctx, prop); @@ -723,7 +813,9 @@ class Value }; - +/** Thin wrapper over JSRuntime * rt + * Calls JS_FreeRuntime on destruction. noncopyable. + */ class Runtime { public: @@ -744,13 +836,17 @@ class Runtime } }; - +/** Wrapper over JSContext * ctx + * Calls JS_SetContextOpaque(ctx, this); on construction and JS_FreeContext on destruction + */ class Context { public: JSContext * ctx; - //private: + /** Module wrapper + * Workaround for lack of opaque pointer for module load function by keeping a list of modules in qjs::Context. + */ class Module { friend class Context; @@ -765,12 +861,10 @@ class Context Module(JSContext * ctx, const char * name) : ctx(ctx), name(name), exports(JS_GetRuntime(ctx)) { m = JS_NewCModule(ctx, name, [](JSContext * ctx, JSModuleDef * m) noexcept { - auto context = reinterpret_cast(JS_GetContextOpaque(ctx)); - if(!context) - return -1; - auto it = std::find_if(context->modules.begin(), context->modules.end(), + auto& context = Context::get(ctx); + auto it = std::find_if(context.modules.begin(), context.modules.end(), [m](const Module& module) { return module.m == m; }); - if(it == context->modules.end()) + if(it == context.modules.end()) return -1; for(const auto& e : it->exports) { @@ -811,12 +905,21 @@ class Context // function wrappers + + /** Add free function F. + * Example: + * module.function(&::sin)>("sin"); + */ template Module& function(const char * name) { return add(name, qjs::fwrapper{name}); } + /** Add function object f. + * Slower than template version. + * Example: module.function("sin", [](double x) { return ::sin(x); }); + */ template Module& function(const char * name, F&& f) { @@ -825,6 +928,10 @@ class Context // class register wrapper private: + /** Helper class to register class members and constructors. + * See \fun, \constructor. + * Actual registration occurs at object destruction. + */ template class class_registrar { @@ -843,6 +950,8 @@ class Context class_registrar(const class_registrar&) = delete; + /** Add functional object f + */ template class_registrar& fun(const char * name, F&& f) { @@ -850,6 +959,12 @@ class Context return *this; } + /** Add class member function or class member variable F + * Example: + * struct T { int var; int func(); } + * auto& module = context.addModule("module"); + * module.class_("T").fun<&T::var>("var").fun<&T::func>("func"); + */ template class_registrar& fun(const char * name) { @@ -857,6 +972,10 @@ class Context return *this; } + /** Add class constructor + * @tparam Args contructor arguments + * @param name constructor name (if not specified class name will be used) + */ template class_registrar& constructor(const char * name = nullptr) { @@ -887,10 +1006,13 @@ class Context }; public: + /** Add class to module. + * See \class_registrar. + */ template class_registrar class_(const char * name) { - return class_registrar{name, *this, *reinterpret_cast(JS_GetContextOpaque(ctx))}; + return class_registrar{name, *this, qjs::Context::get(ctx)}; } }; @@ -928,6 +1050,7 @@ class Context JS_FreeContext(ctx); } + /** Create module and return a reference to it */ Module& addModule(const char * name) { modules.emplace_back(ctx, name); @@ -944,6 +1067,12 @@ class Context return Value{ctx, JS_NewObject(ctx)}; } + /** Register class \T for conversions to/from std::shared_ptr to work. + * Wherever possible module.class_("T")... should be used instead. + * @tparam T class type + * @param name class name in JS engine + * @param proto JS class prototype or JS_UNDEFINED + */ template void registerClass(const char * name, JSValue proto) { @@ -968,9 +1097,19 @@ class Context return eval({reinterpret_cast(buf.get()), buf_len}, filename, eval_flags); } + /** Get qjs::Context from JSContext opaque pointer */ + static Context& get(JSContext * ctx) + { + void * ptr = JS_GetContextOpaque(ctx); + assert(ptr); + return *reinterpret_cast(ptr); + } }; - +/** Convert to/from std::function + * @tparam R return type + * @tparam Args argument types + */ template struct js_traits> { @@ -986,6 +1125,9 @@ struct js_traits> }; } + /** Convert from function object \functor to JSValue. + * Uses detail::function for type-erasure. + */ template static JSValue wrap(JSContext * ctx, Functor&& functor) { @@ -1004,7 +1146,7 @@ struct js_traits> } }; -// std::vector <-> Array +/** Convert from std::vector to Array and vice-versa. If Array holds objects that are non-convertible to \T throws qjs::exception */ template struct js_traits> { From ba9866a4a6efdd8a9b7135fb8834fd721a2d48cc Mon Sep 17 00:00:00 2001 From: ftk Date: Thu, 29 Aug 2019 11:57:49 +0000 Subject: [PATCH 020/185] add github CI --- .github/workflows/cxx.yml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 .github/workflows/cxx.yml diff --git a/.github/workflows/cxx.yml b/.github/workflows/cxx.yml new file mode 100644 index 0000000000..2cdb87f9d6 --- /dev/null +++ b/.github/workflows/cxx.yml @@ -0,0 +1,26 @@ +name: CMake C/C++ CI + +on: [push] + +jobs: + build: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, windows-latest] + compiler: [native, second] # second - clang for linux, mingw gcc for win + include: + - os: ubuntu-latest + compiler: second + cmake_opts: -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ + - os: windows-latest + compiler: second + cmake_opts: -G "MSYS Makefiles" -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ + steps: + - uses: actions/checkout@v1 + - name: configure + run: cmake . -Wdev ${{ matrix.cmake_opts }} + - name: build + run: cmake --build . # --verbose + - name: test + run: ctest --extra-verbose From 11326d67549e2d0f3a4cbea1d95fb00ad5bc659b Mon Sep 17 00:00:00 2001 From: ftk Date: Thu, 29 Aug 2019 12:05:05 +0000 Subject: [PATCH 021/185] lower minimum cmake version --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2808e3e46e..3951eef502 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.14) +cmake_minimum_required(VERSION 3.8) project(quickjspp) set(CMAKE_CXX_STANDARD 17) From 262cca2592f41c7dfd8bdbe021001447277fa1aa Mon Sep 17 00:00:00 2001 From: ftk Date: Sat, 31 Aug 2019 11:12:35 +0000 Subject: [PATCH 022/185] exclude MSVS CI --- .github/workflows/cxx.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/cxx.yml b/.github/workflows/cxx.yml index 2cdb87f9d6..aca66f8a39 100644 --- a/.github/workflows/cxx.yml +++ b/.github/workflows/cxx.yml @@ -16,6 +16,9 @@ jobs: - os: windows-latest compiler: second cmake_opts: -G "MSYS Makefiles" -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ + exclude: # msvs + - os: windows-latest + compiler: native steps: - uses: actions/checkout@v1 - name: configure From 6356b5902cd1382c8ba214b28a751f540bf1ed26 Mon Sep 17 00:00:00 2001 From: ftk Date: Thu, 12 Sep 2019 09:06:59 +0000 Subject: [PATCH 023/185] update quickjs to 2019-09-01 --- quickjs/VERSION | 2 +- quickjs/cutils.c | 1 - quickjs/quickjs-atom.h | 2 + quickjs/quickjs-libc.c | 481 +++++++++++++- quickjs/quickjs-libc.h | 2 + quickjs/quickjs-opcode.h | 5 +- quickjs/quickjs.c | 1296 +++++++++++++++++++++++++------------- quickjs/quickjs.h | 34 +- 8 files changed, 1346 insertions(+), 477 deletions(-) diff --git a/quickjs/VERSION b/quickjs/VERSION index c88c1f0c71..bbe29cb5e2 100644 --- a/quickjs/VERSION +++ b/quickjs/VERSION @@ -1 +1 @@ -2019-08-10 +2019-09-01 diff --git a/quickjs/cutils.c b/quickjs/cutils.c index 869b79c4e1..64a32d362f 100644 --- a/quickjs/cutils.c +++ b/quickjs/cutils.c @@ -572,7 +572,6 @@ void rqsort(void *base, size_t nmemb, size_t size, cmp_f cmp, void *opaque) */ span = plt - ptr; span2 = pi - plt; - plt = pi - span; lt = i - lt; if (span > span2) span = span2; diff --git a/quickjs/quickjs-atom.h b/quickjs/quickjs-atom.h index 6bbc3b2982..233294c6cd 100644 --- a/quickjs/quickjs-atom.h +++ b/quickjs/quickjs-atom.h @@ -151,6 +151,7 @@ DEF(brand, "") DEF(hash_constructor, "#constructor") DEF(as, "as") DEF(from, "from") +DEF(meta, "meta") DEF(_default_, "*default*") DEF(_star_, "*") DEF(Module, "Module") @@ -165,6 +166,7 @@ DEF(exec, "exec") DEF(groups, "groups") DEF(status, "status") DEF(reason, "reason") +DEF(globalThis, "globalThis") #ifdef CONFIG_BIGNUM DEF(bigint, "bigint") DEF(bigfloat, "bigfloat") diff --git a/quickjs/quickjs-libc.c b/quickjs/quickjs-libc.c index a4a4c1c8d4..37da67b97b 100644 --- a/quickjs/quickjs-libc.c +++ b/quickjs/quickjs-libc.c @@ -34,6 +34,9 @@ #include #include #include +#include +#include +#include #if defined(_WIN32) #include #include @@ -300,18 +303,40 @@ uint8_t *js_load_file(JSContext *ctx, size_t *pbuf_len, const char *filename) FILE *f; uint8_t *buf; size_t buf_len; - + long lret; + f = fopen(filename, "rb"); if (!f) return NULL; - fseek(f, 0, SEEK_END); - buf_len = ftell(f); - fseek(f, 0, SEEK_SET); + if (fseek(f, 0, SEEK_END) < 0) + goto fail; + lret = ftell(f); + if (lret < 0) + goto fail; + /* XXX: on Linux, ftell() return LONG_MAX for directories */ + if (lret == LONG_MAX) { + errno = EISDIR; + goto fail; + } + buf_len = lret; + if (fseek(f, 0, SEEK_SET) < 0) + goto fail; if (ctx) buf = js_malloc(ctx, buf_len + 1); else buf = malloc(buf_len + 1); - fread(buf, 1, buf_len, f); + if (!buf) + goto fail; + if (fread(buf, 1, buf_len, f) != buf_len) { + errno = EIO; + if (ctx) + js_free(ctx, buf); + else + free(buf); + fail: + fclose(f); + return NULL; + } buf[buf_len] = '\0'; fclose(f); *pbuf_len = buf_len; @@ -405,6 +430,56 @@ static JSModuleDef *js_module_loader_so(JSContext *ctx, } #endif /* !_WIN32 */ +int js_module_set_import_meta(JSContext *ctx, JSValueConst func_val, + JS_BOOL use_realpath, JS_BOOL is_main) +{ + JSModuleDef *m; + char buf[PATH_MAX + 16], *res; + JSValue meta_obj; + JSAtom module_name_atom; + const char *module_name; + + assert(JS_VALUE_GET_TAG(func_val) == JS_TAG_MODULE); + m = JS_VALUE_GET_PTR(func_val); + + module_name_atom = JS_GetModuleName(ctx, m); + module_name = JS_AtomToCString(ctx, module_name_atom); + JS_FreeAtom(ctx, module_name_atom); + if (!module_name) + return -1; + if (!strchr(module_name, ':')) { + strcpy(buf, "file://"); + /* realpath() cannot be used with modules compiled with qjsc + because the corresponding module source code is not + necessarily present */ + if (use_realpath) { + res = realpath(module_name, buf + strlen(buf)); + if (!res) { + JS_ThrowTypeError(ctx, "realpath failure"); + JS_FreeCString(ctx, module_name); + return -1; + } + } else { + pstrcat(buf, sizeof(buf), module_name); + } + } else { + pstrcpy(buf, sizeof(buf), module_name); + } + JS_FreeCString(ctx, module_name); + + meta_obj = JS_GetImportMeta(ctx, m); + if (JS_IsException(meta_obj)) + return -1; + JS_DefinePropertyValueStr(ctx, meta_obj, "url", + JS_NewString(ctx, buf), + JS_PROP_C_W_E); + JS_DefinePropertyValueStr(ctx, meta_obj, "main", + JS_NewBool(ctx, is_main), + JS_PROP_C_W_E); + JS_FreeValue(ctx, meta_obj); + return 0; +} + JSModuleDef *js_module_loader(JSContext *ctx, const char *module_name, void *opaque) { @@ -430,6 +505,8 @@ JSModuleDef *js_module_loader(JSContext *ctx, js_free(ctx, buf); if (JS_IsException(func_val)) return NULL; + /* XXX: could propagate the exception */ + js_module_set_import_meta(ctx, func_val, TRUE, FALSE); /* the module is already referenced, so we must free it */ m = JS_VALUE_GET_PTR(func_val); JS_FreeValue(ctx, func_val); @@ -506,14 +583,19 @@ static JSClassID js_std_file_class_id; typedef struct { FILE *f; BOOL close_in_finalizer; + BOOL is_popen; } JSSTDFile; static void js_std_file_finalizer(JSRuntime *rt, JSValue val) { JSSTDFile *s = JS_GetOpaque(val, js_std_file_class_id); if (s) { - if (s->f && s->close_in_finalizer) - fclose(s->f); + if (s->f && s->close_in_finalizer) { + if (s->is_popen) + pclose(s->f); + else + fclose(s->f); + } js_free_rt(rt, s); } } @@ -559,7 +641,9 @@ static JSValue js_std_throw_errno(JSContext *ctx, int err) return JS_Throw(ctx, obj); } -static JSValue js_new_std_file(JSContext *ctx, FILE *f, BOOL close_in_finalizer) +static JSValue js_new_std_file(JSContext *ctx, FILE *f, + BOOL close_in_finalizer, + BOOL is_popen) { JSSTDFile *s; JSValue obj; @@ -572,6 +656,7 @@ static JSValue js_new_std_file(JSContext *ctx, FILE *f, BOOL close_in_finalizer) return JS_EXCEPTION; } s->close_in_finalizer = close_in_finalizer; + s->is_popen = is_popen; s->f = f; JS_SetOpaque(obj, s); return obj; @@ -599,7 +684,36 @@ static JSValue js_std_open(JSContext *ctx, JSValueConst this_val, JS_FreeCString(ctx, mode); if (!f) return js_std_throw_errno(ctx, errno); - return js_new_std_file(ctx, f, TRUE); + return js_new_std_file(ctx, f, TRUE, FALSE); + fail: + JS_FreeCString(ctx, filename); + JS_FreeCString(ctx, mode); + return JS_EXCEPTION; +} + +static JSValue js_std_popen(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + const char *filename, *mode = NULL; + FILE *f; + + filename = JS_ToCString(ctx, argv[0]); + if (!filename) + goto fail; + mode = JS_ToCString(ctx, argv[1]); + if (!mode) + goto fail; + if (mode[strspn(mode, "rw")] != '\0') { + js_std_throw_errno(ctx, EINVAL); + goto fail; + } + + f = popen(filename, mode); + JS_FreeCString(ctx, filename); + JS_FreeCString(ctx, mode); + if (!f) + return js_std_throw_errno(ctx, errno); + return js_new_std_file(ctx, f, TRUE, TRUE); fail: JS_FreeCString(ctx, filename); JS_FreeCString(ctx, mode); @@ -613,7 +727,7 @@ static JSValue js_std_tmpfile(JSContext *ctx, JSValueConst this_val, f = tmpfile(); if (!f) return js_std_throw_errno(ctx, errno); - return js_new_std_file(ctx, f, TRUE); + return js_new_std_file(ctx, f, TRUE, FALSE); } static JSValue js_std_sprintf(JSContext *ctx, JSValueConst this_val, @@ -673,7 +787,11 @@ static JSValue js_std_file_close(JSContext *ctx, JSValueConst this_val, return JS_EXCEPTION; if (!s->f) return js_std_throw_errno(ctx, EBADF); - fclose(s->f); + /* XXX: could return exit code */ + if (s->is_popen) + pclose(s->f); + else + fclose(s->f); s->f = NULL; return JS_UNDEFINED; } @@ -1084,6 +1202,7 @@ static const JSCFunctionListEntry js_std_funcs[] = { /* FILE I/O */ JS_CFUNC_DEF("open", 2, js_std_open ), + JS_CFUNC_DEF("popen", 2, js_std_popen ), JS_CFUNC_DEF("tmpfile", 0, js_std_tmpfile ), JS_CFUNC_MAGIC_DEF("puts", 1, js_std_file_puts, 0 ), JS_CFUNC_DEF("printf", 1, js_std_printf ), @@ -1147,9 +1266,9 @@ static int js_std_init(JSContext *ctx, JSModuleDef *m) JS_SetModuleExportList(ctx, m, js_std_funcs, countof(js_std_funcs)); - JS_SetModuleExport(ctx, m, "in", js_new_std_file(ctx, stdin, FALSE)); - JS_SetModuleExport(ctx, m, "out", js_new_std_file(ctx, stdout, FALSE)); - JS_SetModuleExport(ctx, m, "err", js_new_std_file(ctx, stderr, FALSE)); + JS_SetModuleExport(ctx, m, "in", js_new_std_file(ctx, stdin, FALSE, FALSE)); + JS_SetModuleExport(ctx, m, "out", js_new_std_file(ctx, stdout, FALSE, FALSE)); + JS_SetModuleExport(ctx, m, "err", js_new_std_file(ctx, stderr, FALSE, FALSE)); obj = JS_NewCFunction2(ctx, js_std_error_constructor, "Error", 1, JS_CFUNC_constructor, 0); @@ -1157,8 +1276,6 @@ static int js_std_init(JSContext *ctx, JSModuleDef *m) countof(js_std_error_funcs)); JS_SetModuleExport(ctx, m, "Error", obj); - /* global object */ - JS_SetModuleExport(ctx, m, "global", JS_GetGlobalObject(ctx)); return 0; } @@ -1172,7 +1289,6 @@ JSModuleDef *js_init_module_std(JSContext *ctx, const char *module_name) JS_AddModuleExport(ctx, m, "in"); JS_AddModuleExport(ctx, m, "out"); JS_AddModuleExport(ctx, m, "err"); - JS_AddModuleExport(ctx, m, "global"); JS_AddModuleExport(ctx, m, "Error"); return m; } @@ -1815,6 +1931,285 @@ static int js_os_poll(JSContext *ctx) } #endif /* !_WIN32 */ +static JSValue make_obj_error(JSContext *ctx, + JSValue obj, + int err) +{ + JSValue arr; + if (JS_IsException(obj)) + return obj; + arr = JS_NewArray(ctx); + if (JS_IsException(arr)) + return JS_EXCEPTION; + JS_DefinePropertyValueUint32(ctx, arr, 0, obj, + JS_PROP_C_W_E); + JS_DefinePropertyValueUint32(ctx, arr, 1, JS_NewInt32(ctx, err), + JS_PROP_C_W_E); + return arr; +} + +static JSValue make_string_error(JSContext *ctx, + const char *buf, + int err) +{ + return make_obj_error(ctx, JS_NewString(ctx, buf), err); +} + +/* return [cwd, errorcode] */ +static JSValue js_os_getcwd(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + char buf[PATH_MAX]; + int err; + + if (!getcwd(buf, sizeof(buf))) { + buf[0] = '\0'; + err = -errno; + } else { + err = 0; + } + return make_string_error(ctx, buf, err); +} + +/* return [path, errorcode] */ +static JSValue js_os_realpath(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + const char *path; + char buf[PATH_MAX], *res; + int err; + + path = JS_ToCString(ctx, argv[0]); + if (!path) + return JS_EXCEPTION; + res = realpath(path, buf); + JS_FreeCString(ctx, path); + if (!res) { + buf[0] = '\0'; + err = -errno; + } else { + err = 0; + } + return make_string_error(ctx, buf, err); +} + +static JSValue js_os_mkdir(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + int mode, ret; + const char *path; + + if (argc >= 2) { + if (JS_ToInt32(ctx, &mode, argv[1])) + return JS_EXCEPTION; + } else { + mode = 0777; + } + path = JS_ToCString(ctx, argv[0]); + if (!path) + return JS_EXCEPTION; + ret = mkdir(path, mode); + JS_FreeCString(ctx, path); + return js_os_return(ctx, ret); +} + +static int64_t timespec_to_ms(const struct timespec *tv) +{ + return (int64_t)tv->tv_sec * 1000 + (tv->tv_nsec / 1000000); +} + +/* return [obj, errcode] */ +static JSValue js_os_stat(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv, int is_lstat) +{ + const char *path; + int err, res; + struct stat st; + JSValue obj; + + path = JS_ToCString(ctx, argv[0]); + if (!path) + return JS_EXCEPTION; + if (is_lstat) + res = lstat(path, &st); + else + res = stat(path, &st); + JS_FreeCString(ctx, path); + if (res < 0) { + err = -errno; + obj = JS_NULL; + } else { + err = 0; + obj = JS_NewObject(ctx); + if (JS_IsException(obj)) + return JS_EXCEPTION; + JS_DefinePropertyValueStr(ctx, obj, "dev", + JS_NewInt64(ctx, st.st_dev), + JS_PROP_C_W_E); + JS_DefinePropertyValueStr(ctx, obj, "ino", + JS_NewInt64(ctx, st.st_ino), + JS_PROP_C_W_E); + JS_DefinePropertyValueStr(ctx, obj, "mode", + JS_NewInt32(ctx, st.st_mode), + JS_PROP_C_W_E); + JS_DefinePropertyValueStr(ctx, obj, "nlink", + JS_NewInt64(ctx, st.st_nlink), + JS_PROP_C_W_E); + JS_DefinePropertyValueStr(ctx, obj, "uid", + JS_NewInt64(ctx, st.st_uid), + JS_PROP_C_W_E); + JS_DefinePropertyValueStr(ctx, obj, "gid", + JS_NewInt64(ctx, st.st_gid), + JS_PROP_C_W_E); + JS_DefinePropertyValueStr(ctx, obj, "rdev", + JS_NewInt64(ctx, st.st_rdev), + JS_PROP_C_W_E); + JS_DefinePropertyValueStr(ctx, obj, "size", + JS_NewInt64(ctx, st.st_size), + JS_PROP_C_W_E); + JS_DefinePropertyValueStr(ctx, obj, "blocks", + JS_NewInt64(ctx, st.st_blocks), + JS_PROP_C_W_E); +#if defined(__APPLE__) + JS_DefinePropertyValueStr(ctx, obj, "atime", + JS_NewInt64(ctx, timespec_to_ms(&st.st_atimespec)), + JS_PROP_C_W_E); + JS_DefinePropertyValueStr(ctx, obj, "mtime", + JS_NewInt64(ctx, timespec_to_ms(&st.st_mtimespec)), + JS_PROP_C_W_E); + JS_DefinePropertyValueStr(ctx, obj, "ctime", + JS_NewInt64(ctx, timespec_to_ms(&st.st_ctimespec)), + JS_PROP_C_W_E); +#else + JS_DefinePropertyValueStr(ctx, obj, "atime", + JS_NewInt64(ctx, timespec_to_ms(&st.st_atim)), + JS_PROP_C_W_E); + JS_DefinePropertyValueStr(ctx, obj, "mtime", + JS_NewInt64(ctx, timespec_to_ms(&st.st_mtim)), + JS_PROP_C_W_E); + JS_DefinePropertyValueStr(ctx, obj, "ctime", + JS_NewInt64(ctx, timespec_to_ms(&st.st_ctim)), + JS_PROP_C_W_E); +#endif + } + return make_obj_error(ctx, obj, err); +} + +static JSValue js_os_symlink(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + const char *target, *linkpath; + int err; + + target = JS_ToCString(ctx, argv[0]); + if (!target) + return JS_EXCEPTION; + linkpath = JS_ToCString(ctx, argv[1]); + if (!linkpath) { + JS_FreeCString(ctx, target); + return JS_EXCEPTION; + } + err = symlink(target, linkpath); + JS_FreeCString(ctx, target); + JS_FreeCString(ctx, linkpath); + return js_os_return(ctx, err); +} + +/* return [path, errorcode] */ +static JSValue js_os_readlink(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + const char *path; + char buf[PATH_MAX]; + int err; + ssize_t res; + + path = JS_ToCString(ctx, argv[0]); + if (!path) + return JS_EXCEPTION; + res = readlink(path, buf, sizeof(buf) - 1); + JS_FreeCString(ctx, path); + if (res < 0) { + buf[0] = '\0'; + err = -errno; + } else { + buf[res] = '\0'; + err = 0; + } + return make_string_error(ctx, buf, err); +} + +/* return [array, errorcode] */ +static JSValue js_os_readdir(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + const char *path; + DIR *f; + struct dirent *d; + JSValue obj; + int err; + uint32_t len; + + path = JS_ToCString(ctx, argv[0]); + if (!path) + return JS_EXCEPTION; + obj = JS_NewArray(ctx); + if (JS_IsException(obj)) { + JS_FreeCString(ctx, path); + return JS_EXCEPTION; + } + f = opendir(path); + JS_FreeCString(ctx, path); + err = 0; + if (!f) { + err = -errno; + goto done; + } + len = 0; + for(;;) { + errno = 0; + d = readdir(f); + if (!d) { + err = -errno; + break; + } + JS_DefinePropertyValueUint32(ctx, obj, len++, + JS_NewString(ctx, d->d_name), + JS_PROP_C_W_E); + } + closedir(f); + done: + return make_obj_error(ctx, obj, err); +} + +static void ms_to_timeval(struct timeval *tv, uint64_t v) +{ + tv->tv_sec = v / 1000; + tv->tv_usec = (v % 1000) * 1000; +} + +static JSValue js_os_utimes(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + const char *path; + int64_t atime, mtime; + int ret; + struct timeval times[2]; + + if (JS_ToInt64(ctx, &atime, argv[1])) + return JS_EXCEPTION; + if (JS_ToInt64(ctx, &mtime, argv[2])) + return JS_EXCEPTION; + path = JS_ToCString(ctx, argv[0]); + if (!path) + return JS_EXCEPTION; + ms_to_timeval(×[0], atime); + ms_to_timeval(×[1], mtime); + ret = utimes(path, times); + JS_FreeCString(ctx, path); + return js_os_return(ctx, ret); +} + #if defined(_WIN32) #define OS_PLATFORM "win32" #elif defined(__APPLE__) @@ -1861,7 +2256,26 @@ static const JSCFunctionListEntry js_os_funcs[] = { JS_CFUNC_DEF("setTimeout", 2, js_os_setTimeout ), JS_CFUNC_DEF("clearTimeout", 1, js_os_clearTimeout ), JS_PROP_STRING_DEF("platform", OS_PLATFORM, 0 ), - /* stat, readlink, opendir, closedir, ... */ + JS_CFUNC_DEF("getcwd", 0, js_os_getcwd ), + JS_CFUNC_DEF("realpath", 1, js_os_realpath ), + JS_CFUNC_DEF("mkdir", 1, js_os_mkdir ), + JS_CFUNC_MAGIC_DEF("stat", 1, js_os_stat, 0 ), + JS_CFUNC_MAGIC_DEF("lstat", 1, js_os_stat, 1 ), + /* st_mode constants */ + OS_FLAG(S_IFMT), + OS_FLAG(S_IFIFO), + OS_FLAG(S_IFCHR), + OS_FLAG(S_IFDIR), + OS_FLAG(S_IFBLK), + OS_FLAG(S_IFREG), + OS_FLAG(S_IFSOCK), + OS_FLAG(S_IFLNK), + OS_FLAG(S_ISGID), + OS_FLAG(S_ISUID), + JS_CFUNC_DEF("symlink", 2, js_os_symlink ), + JS_CFUNC_DEF("readlink", 1, js_os_readlink ), + JS_CFUNC_DEF("readdir", 1, js_os_readdir ), + JS_CFUNC_DEF("utimes", 3, js_os_utimes ), }; static int js_os_init(JSContext *ctx, JSModuleDef *m) @@ -2010,13 +2424,30 @@ void js_std_loop(JSContext *ctx) } void js_std_eval_binary(JSContext *ctx, const uint8_t *buf, size_t buf_len, - int flags) + int load_only) { - JSValue val; - val = JS_EvalBinary(ctx, buf, buf_len, flags); - if (JS_IsException(val)) { - js_std_dump_error(ctx); - exit(1); + JSValue obj, val; + obj = JS_ReadObject(ctx, buf, buf_len, JS_READ_OBJ_BYTECODE); + if (JS_IsException(obj)) + goto exception; + if (load_only) { + if (JS_VALUE_GET_TAG(obj) == JS_TAG_MODULE) { + js_module_set_import_meta(ctx, obj, FALSE, FALSE); + } + } else { + if (JS_VALUE_GET_TAG(obj) == JS_TAG_MODULE) { + if (JS_ResolveModule(ctx, obj) < 0) { + JS_FreeValue(ctx, obj); + goto exception; + } + js_module_set_import_meta(ctx, obj, FALSE, TRUE); + } + val = JS_EvalFunction(ctx, obj); + if (JS_IsException(val)) { + exception: + js_std_dump_error(ctx); + exit(1); + } + JS_FreeValue(ctx, val); } - JS_FreeValue(ctx, val); } diff --git a/quickjs/quickjs-libc.h b/quickjs/quickjs-libc.h index 35ca4cffe7..ac7947e4fe 100644 --- a/quickjs/quickjs-libc.h +++ b/quickjs/quickjs-libc.h @@ -36,6 +36,8 @@ void js_std_loop(JSContext *ctx); void js_std_free_handlers(JSRuntime *rt); void js_std_dump_error(JSContext *ctx); uint8_t *js_load_file(JSContext *ctx, size_t *pbuf_len, const char *filename); +int js_module_set_import_meta(JSContext *ctx, JSValueConst func_val, + JS_BOOL use_realpath, JS_BOOL is_main); JSModuleDef *js_module_loader(JSContext *ctx, const char *module_name, void *opaque); void js_std_eval_binary(JSContext *ctx, const uint8_t *buf, size_t buf_len, diff --git a/quickjs/quickjs-opcode.h b/quickjs/quickjs-opcode.h index 0ea029eecf..0981453666 100644 --- a/quickjs/quickjs-opcode.h +++ b/quickjs/quickjs-opcode.h @@ -155,7 +155,8 @@ DEF( append, 1, 3, 2, none) /* append enumerated object, update length * DEF(copy_data_properties, 2, 3, 3, u8) DEF( define_method, 6, 2, 1, atom_u8) DEF(define_method_computed, 2, 3, 1, u8) /* must come after define_method */ -DEF( define_class, 6, 2, 2, atom_u8) +DEF( define_class, 6, 2, 2, atom_u8) /* parent ctor -> ctor proto */ +DEF( define_class_computed, 6, 3, 3, atom_u8) /* field_name parent ctor -> field_name ctor proto (class with computed name) */ DEF( get_loc, 3, 0, 1, loc) DEF( put_loc, 3, 1, 0, loc) /* must come after get_loc */ @@ -284,6 +285,8 @@ def(scope_get_private_field, 7, 1, 1, atom_u16) /* obj -> value, emitted in phas def(scope_get_private_field2, 7, 1, 2, atom_u16) /* obj -> obj value, emitted in phase 1, removed in phase 2 */ def(scope_put_private_field, 7, 1, 1, atom_u16) /* obj value ->, emitted in phase 1, removed in phase 2 */ +def( set_class_name, 5, 1, 1, u32) /* emitted in phase 1, removed in phase 2 */ + def( line_num, 5, 0, 0, u32) /* emitted in phase 1, removed in phase 3 */ #if SHORT_OPCODES diff --git a/quickjs/quickjs.c b/quickjs/quickjs.c index 7bb20cb4db..d5c1c8342d 100644 --- a/quickjs/quickjs.c +++ b/quickjs/quickjs.c @@ -434,6 +434,9 @@ typedef struct JSVarScope { typedef enum { /* XXX: add more variable kinds here instead of using bit fields */ JS_VAR_NORMAL, + JS_VAR_FUNCTION_DECL, /* lexical var with function declaration */ + JS_VAR_NEW_FUNCTION_DECL, /* lexical var with async/generator + function declaration */ JS_VAR_CATCH, JS_VAR_PRIVATE_FIELD, JS_VAR_PRIVATE_METHOD, @@ -447,13 +450,17 @@ typedef struct JSVarDef { int scope_level; /* index into fd->scopes of this variable lexical scope */ int scope_next; /* index into fd->vars of the next variable in the * same or enclosing lexical scope */ - uint8_t is_function : 1; /* only used for debug */ uint8_t is_func_var : 1; /* used for the function self reference */ uint8_t is_const : 1; uint8_t is_lexical : 1; uint8_t is_captured : 1; - uint8_t var_kind : 3; /* see JSVarKindEnum */ - int func_pool_idx : 24; /* only used during compilation */ + uint8_t var_kind : 4; /* see JSVarKindEnum */ + /* only used during compilation: function pool index for lexical + variables with var_kind = + JS_VAR_FUNCTION_DECL/JS_VAR_NEW_FUNCTION_DECL or scope level of + the definition of the 'var' variables (they have scope_level = + 0) */ + int func_pool_or_scope_idx : 24; /* only used during compilation */ } JSVarDef; /* for the encoding of the pc2line table */ @@ -643,6 +650,7 @@ struct JSModuleDef { eval_exception */ BOOL eval_has_exception : 8; JSValue eval_exception; + JSValue meta_obj; /* for import.meta */ }; typedef struct JSJobEntry { @@ -980,6 +988,7 @@ static JSValue JS_EvalInternal(JSContext *ctx, JSValueConst this_obj, const char *input, size_t input_len, const char *filename, int flags, int scope_idx); static void js_free_module_def(JSContext *ctx, JSModuleDef *m); +static JSValue js_import_meta(JSContext *ctx); static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier); static void free_var_ref(JSRuntime *rt, JSVarRef *var_ref); static JSValue js_new_promise_capability(JSContext *ctx, @@ -4460,15 +4469,13 @@ JSValue JS_NewObject(JSContext *ctx) } static void js_function_set_properties(JSContext *ctx, JSValueConst func_obj, - JSValue name, int len) + JSAtom name, int len) { /* ES6 feature non compatible with ES5.1: length is configurable */ JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_length, JS_NewInt32(ctx, len), JS_PROP_CONFIGURABLE); - if (!JS_IsUndefined(name)) { - JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_name, name, - JS_PROP_CONFIGURABLE); - } + JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_name, + JS_AtomToString(ctx, name), JS_PROP_CONFIGURABLE); } static BOOL js_class_has_bytecode(JSClassID class_id) @@ -4557,9 +4564,10 @@ static JSValue JS_NewCFunction3(JSContext *ctx, JSCFunction *func, int length, JSCFunctionEnum cproto, int magic, JSValueConst proto_val) { - JSValue func_obj, name_val; + JSValue func_obj; JSObject *p; - + JSAtom name_atom; + func_obj = JS_NewObjectProtoClass(ctx, proto_val, JS_CLASS_C_FUNCTION); if (JS_IsException(func_obj)) return func_obj; @@ -4572,11 +4580,11 @@ static JSValue JS_NewCFunction3(JSContext *ctx, JSCFunction *func, cproto == JS_CFUNC_constructor_magic || cproto == JS_CFUNC_constructor_or_func || cproto == JS_CFUNC_constructor_or_func_magic); - if (name) - name_val = JS_NewAtomString(ctx, name); - else - name_val = JS_UNDEFINED; - js_function_set_properties(ctx, func_obj, name_val, length); + if (!name) + name = ""; + name_atom = JS_NewAtom(ctx, name); + js_function_set_properties(ctx, func_obj, name_atom, length); + JS_FreeAtom(ctx, name_atom); return func_obj; } @@ -4669,7 +4677,8 @@ JSValue JS_NewCFunctionData(JSContext *ctx, JSCFunctionData *func, for(i = 0; i < data_len; i++) s->data[i] = JS_DupValue(ctx, data[i]); JS_SetOpaque(func_obj, s); - js_function_set_properties(ctx, func_obj, JS_UNDEFINED, length); + js_function_set_properties(ctx, func_obj, + JS_ATOM_empty_string, length); return func_obj; } @@ -8729,12 +8738,33 @@ static int JS_CreateDataPropertyUint32(JSContext *ctx, JSValueConst this_obj, JS_PROP_ENUMERABLE | JS_PROP_WRITABLE); } + +/* return TRUE if 'obj' has a non empty 'name' string */ +static BOOL js_object_has_name(JSContext *ctx, JSValueConst obj) +{ + JSProperty *pr; + JSShapeProperty *prs; + JSValueConst val; + JSString *p; + + prs = find_own_property(&pr, JS_VALUE_GET_OBJ(obj), JS_ATOM_name); + if (!prs) + return FALSE; + if ((prs->flags & JS_PROP_TMASK) != JS_PROP_NORMAL) + return TRUE; + val = pr->u.value; + if (JS_VALUE_GET_TAG(val) != JS_TAG_STRING) + return TRUE; + p = JS_VALUE_GET_STRING(val); + return (p->len != 0); +} + static int JS_DefineObjectName(JSContext *ctx, JSValueConst obj, JSAtom name, int flags) { if (name != JS_ATOM_NULL && JS_IsObject(obj) - && !find_own_property1(JS_VALUE_GET_OBJ(obj), JS_ATOM_name) + && !js_object_has_name(ctx, obj) && JS_DefinePropertyValue(ctx, obj, JS_ATOM_name, JS_AtomToString(ctx, name), flags) < 0) { return -1; } @@ -8745,7 +8775,7 @@ static int JS_DefineObjectNameComputed(JSContext *ctx, JSValueConst obj, JSValueConst str, int flags) { if (JS_IsObject(obj) && - !find_own_property1(JS_VALUE_GET_OBJ(obj), JS_ATOM_name)) { + !js_object_has_name(ctx, obj)) { JSAtom prop; JSValue name_str; prop = js_value_to_atom(ctx, str); @@ -12210,11 +12240,6 @@ static no_inline __exception int js_add_slow(JSContext *ctx, JSValue *sp) bf_delete(b); JS_FreeValue(ctx, op1); JS_FreeValue(ctx, op2); - if (unlikely(ret)) { - bf_delete(r); - throw_bf_exception(ctx, ret); - goto exception; - } sp[-2] = JS_NewBigFloat(ctx, r); } return 0; @@ -14354,7 +14379,7 @@ static JSValue js_closure(JSContext *ctx, JSValue bfunc, JSStackFrame *sf) { JSFunctionBytecode *b; - JSValue name_val, func_obj; + JSValue func_obj; JSAtom name_atom; static const uint16_t func_kind_to_class_id[] = { [JS_FUNC_NORMAL] = JS_CLASS_BYTECODE_FUNCTION, @@ -14374,11 +14399,10 @@ static JSValue js_closure(JSContext *ctx, JSValue bfunc, /* bfunc has been freed */ goto fail; } - name_val = JS_UNDEFINED; name_atom = b->func_name; - if (name_atom != JS_ATOM_NULL) - name_val = JS_AtomToString(ctx, name_atom); - js_function_set_properties(ctx, func_obj, name_val, + if (name_atom == JS_ATOM_NULL) + name_atom = JS_ATOM_empty_string; + js_function_set_properties(ctx, func_obj, name_atom, b->defined_arg_count); if (b->func_kind & JS_FUNC_GENERATOR) { @@ -14416,7 +14440,7 @@ static JSValue js_closure(JSContext *ctx, JSValue bfunc, static int js_op_define_class(JSContext *ctx, JSValue *sp, JSAtom class_name, int class_flags, JSVarRef **cur_var_refs, - JSStackFrame *sf) + JSStackFrame *sf, BOOL is_computed_name) { JSValue bfunc, parent_class, proto = JS_UNDEFINED; JSValue ctor = JS_UNDEFINED, parent_proto = JS_UNDEFINED; @@ -14468,6 +14492,15 @@ static int js_op_define_class(JSContext *ctx, JSValue *sp, JS_NewInt32(ctx, b->defined_arg_count), JS_PROP_CONFIGURABLE); + if (is_computed_name) { + if (JS_DefineObjectNameComputed(ctx, ctor, sp[-3], + JS_PROP_CONFIGURABLE) < 0) + goto fail; + } else { + if (JS_DefineObjectName(ctx, ctor, class_name, JS_PROP_CONFIGURABLE) < 0) + goto fail; + } + /* the constructor property must be first. It can be overriden by computed property names */ if (JS_DefinePropertyValue(ctx, proto, JS_ATOM_constructor, @@ -14482,11 +14515,6 @@ static int js_op_define_class(JSContext *ctx, JSValue *sp, set_cycle_flag(ctx, ctor); set_cycle_flag(ctx, proto); - if (class_name != JS_ATOM_NULL) { - if (JS_DefineObjectName(ctx, ctor, class_name, JS_PROP_CONFIGURABLE) < 0) - goto fail; - } - JS_FreeValue(ctx, parent_proto); JS_FreeValue(ctx, parent_class); @@ -14746,6 +14774,7 @@ typedef enum { OP_SPECIAL_OBJECT_NEW_TARGET, OP_SPECIAL_OBJECT_HOME_OBJECT, OP_SPECIAL_OBJECT_VAR_OBJECT, + OP_SPECIAL_OBJECT_IMPORT_META, } OPSpecialObjectEnum; #define FUNC_RET_AWAIT 0 @@ -15015,6 +15044,11 @@ static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj, if (unlikely(JS_IsException(sp[-1]))) goto exception; break; + case OP_SPECIAL_OBJECT_IMPORT_META: + *sp++ = js_import_meta(ctx); + if (unlikely(JS_IsException(sp[-1]))) + goto exception; + break; default: abort(); } @@ -16278,6 +16312,7 @@ static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj, BREAK; CASE(OP_define_class): + CASE(OP_define_class_computed): { int class_flags; JSAtom atom; @@ -16286,7 +16321,8 @@ static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj, class_flags = pc[4]; pc += 5; if (js_op_define_class(ctx, sp, atom, class_flags, - var_refs, sf) < 0) + var_refs, sf, + (opcode == OP_define_class_computed)) < 0) goto exception; } BREAK; @@ -18461,7 +18497,6 @@ typedef struct JSHoistedDef { uint8_t force_init : 1; /* initialize to undefined */ uint8_t is_lexical : 1; /* global let/const definition */ uint8_t is_const : 1; /* const definition */ - uint8_t is_for_of : 1; /* variable defined in for-of */ int var_idx; /* function object index if cpool_idx >= 0 */ int scope_level; /* scope of definition */ JSAtom var_name; /* variable name if cpool_idx < 0 */ @@ -19025,32 +19060,6 @@ static inline BOOL token_is_pseudo_keyword(JSParseState *s, JSAtom atom) { !s->token.u.ident.has_escape; } -#if 0 -/* return TRUE if a regexp literal is allowed after this token */ -static BOOL is_regexp_allowed(JSParseState *s) -{ - switch (s->token.val) { - case TOK_NUMBER: - case TOK_STRING: - case TOK_REGEXP: - case TOK_DEC: - case TOK_INC: - case TOK_NULL: - case TOK_FALSE: - case TOK_TRUE: - case TOK_THIS: - case ')': - case ']': - case '}': - return FALSE; - case TOK_IDENT: - return token_is_pseudo_keyword(s, JS_ATOM_of) || token_is_pseudo_keyword(s, JS_ATOM_yield); - default: - return TRUE; - } -} -#endif - static __exception int js_parse_regexp(JSParseState *s) { const uint8_t *p; @@ -19259,16 +19268,7 @@ static __exception int next_token(JSParseState *s) } } goto redo; - } -#if 0 - else if (is_regexp_allowed(s)) { - s->buf_ptr = p; - if (js_parse_regexp(s)) - goto fail; - p = s->buf_ptr; - } -#endif - else if (p[1] == '=') { + } else if (p[1] == '=') { p += 2; s->token.val = TOK_DIV_ASSIGN; } else { @@ -19761,15 +19761,17 @@ static __exception int next_token(JSParseState *s) return -1; } -/* only used for ':' and '=>', 'let' or 'function' look-ahead */ +/* only used for ':' and '=>', 'let' or 'function' look-ahead. *pp is + only set if TOK_IMPORT is returned */ /* XXX: handle all unicode cases */ -static int peek_token(JSParseState *s, BOOL no_line_terminator) +static int simple_next_token(const uint8_t **pp, BOOL no_line_terminator) { const uint8_t *p; uint32_t c; - + /* skip spaces and comments */ - for (p = s->buf_ptr;;) { + p = *pp; + for (;;) { switch(c = *p++) { case '\r': case '\n': @@ -19807,16 +19809,24 @@ static int peek_token(JSParseState *s, BOOL no_line_terminator) break; default: if (lre_js_is_ident_first(c)) { - if (c == 'i' && *p == 'n' && !lre_js_is_ident_next(p[1])) - return TOK_IN; - if (c == 'o' && *p == 'f' && !lre_js_is_ident_next(p[1])) + if (c == 'i') { + if (p[0] == 'n' && !lre_js_is_ident_next(p[1])) { + return TOK_IN; + } + if (p[0] == 'm' && p[1] == 'p' && p[2] == 'o' && + p[3] == 'r' && p[4] == 't' && + !lre_js_is_ident_next(p[5])) { + *pp = p + 5; + return TOK_IMPORT; + } + } else if (c == 'o' && *p == 'f' && !lre_js_is_ident_next(p[1])) { return TOK_OF; - else if (c == 'f' && p[0] == 'u' && p[1] == 'n' && + } else if (c == 'f' && p[0] == 'u' && p[1] == 'n' && p[2] == 'c' && p[3] == 't' && p[4] == 'i' && - p[5] == 'o' && p[6] == 'n' && !lre_js_is_ident_next(p[7])) + p[5] == 'o' && p[6] == 'n' && !lre_js_is_ident_next(p[7])) { return TOK_FUNCTION; - else - return TOK_IDENT; + } + return TOK_IDENT; } break; } @@ -19824,6 +19834,28 @@ static int peek_token(JSParseState *s, BOOL no_line_terminator) } } +static int peek_token(JSParseState *s, BOOL no_line_terminator) +{ + const uint8_t *p = s->buf_ptr; + return simple_next_token(&p, no_line_terminator); +} + +/* return true if 'input' contains the source of a module + (heuristic). 'input' must be a zero terminated. + + Heuristic: skip comments and expect 'import' keyword not followed + by '(' or '.' +*/ +BOOL JS_DetectModule(const char *input, size_t input_len) +{ + const uint8_t *p = (const uint8_t *)input; + int tok; + if (simple_next_token(&p, FALSE) != TOK_IMPORT) + return FALSE; + tok = simple_next_token(&p, FALSE); + return (tok != '.' && tok != '('); +} + static inline int get_prev_opcode(JSFunctionDef *fd) { if (fd->last_opcode_pos < 0) return OP_invalid; @@ -20030,6 +20062,36 @@ static int find_var(JSContext *ctx, JSFunctionDef *fd, JSAtom name) return find_arg(ctx, fd, name); } +/* return true if scope == parent_scope or if scope is a child of + parent_scope */ +static BOOL is_child_scope(JSContext *ctx, JSFunctionDef *fd, + int scope, int parent_scope) +{ + while (scope >= 0) { + if (scope == parent_scope) + return TRUE; + scope = fd->scopes[scope].parent; + } + return FALSE; +} + +/* find a 'var' declaration in the same scope or a child scope */ +static int find_var_in_child_scope(JSContext *ctx, JSFunctionDef *fd, + JSAtom name, int scope_level) +{ + int i; + for(i = 0; i < fd->var_count; i++) { + JSVarDef *vd = &fd->vars[i]; + if (vd->var_name == name && vd->scope_level == 0) { + if (is_child_scope(ctx, fd, vd->func_pool_or_scope_idx, + scope_level)) + return i; + } + } + return -1; +} + + static JSHoistedDef *find_hoisted_def(JSFunctionDef *fd, JSAtom name) { int i; @@ -20165,6 +20227,21 @@ static int add_var(JSContext *ctx, JSFunctionDef *fd, JSAtom name) return fd->var_count - 1; } +static int add_scope_var(JSContext *ctx, JSFunctionDef *fd, JSAtom name, + JSVarKindEnum var_kind) +{ + int idx = add_var(ctx, fd, name); + if (idx >= 0) { + JSVarDef *vd = &fd->vars[idx]; + vd->var_kind = var_kind; + vd->scope_level = fd->scope_level; + vd->scope_next = fd->scope_first; + fd->scopes[fd->scope_level].first = idx; + fd->scope_first = idx; + } + return idx; +} + static int add_func_var(JSContext *ctx, JSFunctionDef *fd, JSAtom name) { int idx = fd->func_var_idx; @@ -20239,7 +20316,6 @@ static JSHoistedDef *add_hoisted_def(JSContext *ctx, hf->force_init = 0; hf->is_lexical = is_lexical; hf->is_const = FALSE; - hf->is_for_of = FALSE; hf->var_idx = var_idx; hf->scope_level = s->scope_level; hf->var_name = JS_ATOM_NULL; @@ -20249,102 +20325,113 @@ static JSHoistedDef *add_hoisted_def(JSContext *ctx, return hf; } -static int define_var(JSParseState *s, JSFunctionDef *fd, JSAtom name, int tok) +typedef enum { + JS_VAR_DEF_WITH, + JS_VAR_DEF_LET, + JS_VAR_DEF_CONST, + JS_VAR_DEF_FUNCTION_DECL, /* function declaration */ + JS_VAR_DEF_NEW_FUNCTION_DECL, /* async/generator function declaration */ + JS_VAR_DEF_CATCH, + JS_VAR_DEF_VAR, +} JSVarDefEnum; + +static int define_var(JSParseState *s, JSFunctionDef *fd, JSAtom name, + JSVarDefEnum var_def_type) { JSContext *ctx = s->ctx; JSVarDef *vd; int idx; - switch (tok) { - case TOK_WITH: - idx = add_var(ctx, fd, name); - if (idx >= 0) { - vd = &fd->vars[idx]; - vd->scope_level = fd->scope_level; - vd->scope_next = fd->scope_first; - fd->scopes[fd->scope_level].first = idx; - fd->scope_first = idx; - } + switch (var_def_type) { + case JS_VAR_DEF_WITH: + idx = add_scope_var(ctx, fd, name, JS_VAR_NORMAL); break; - case TOK_LET: - case TOK_CONST: - case TOK_FUNCTION: + case JS_VAR_DEF_LET: + case JS_VAR_DEF_CONST: + case JS_VAR_DEF_FUNCTION_DECL: + case JS_VAR_DEF_NEW_FUNCTION_DECL: idx = find_lexical_decl(ctx, fd, name, fd->scope_first, TRUE); if (idx >= 0) { - if ((idx < GLOBAL_VAR_OFFSET && - (fd->vars[idx].scope_level == fd->scope_level || - (fd->vars[idx].var_kind == JS_VAR_CATCH && (fd->vars[idx].scope_level + 2) == fd->scope_level))) || - (idx == GLOBAL_VAR_OFFSET && fd->scope_level == 1)) { - /* redefining a scoped var in the same scope: error */ - return js_parse_error(s, "invalid redefinition of lexical identifier"); + if (idx < GLOBAL_VAR_OFFSET) { + if (fd->vars[idx].scope_level == fd->scope_level) { + /* same scope: in non strict mode, functions + can be redefined (annex B.3.3.4). */ + if (!(!(fd->js_mode & JS_MODE_STRICT) && + var_def_type == JS_VAR_DEF_FUNCTION_DECL && + fd->vars[idx].var_kind == JS_VAR_FUNCTION_DECL)) { + goto redef_lex_error; + } + } else if (fd->vars[idx].var_kind == JS_VAR_CATCH && (fd->vars[idx].scope_level + 2) == fd->scope_level) { + goto redef_lex_error; + } + } else { + if (fd->scope_level == 1) { + redef_lex_error: + /* redefining a scoped var in the same scope: error */ + return js_parse_error(s, "invalid redefinition of lexical identifier"); + } } } - if (tok != TOK_FUNCTION && + if (var_def_type != JS_VAR_DEF_FUNCTION_DECL && + var_def_type != JS_VAR_DEF_NEW_FUNCTION_DECL && (fd->func_kind == JS_FUNC_ASYNC || fd->func_kind == JS_FUNC_GENERATOR || fd->func_kind == JS_FUNC_ASYNC_GENERATOR || - fd->func_type == JS_PARSE_FUNC_METHOD) && + fd->func_type == JS_PARSE_FUNC_METHOD || + fd->scope_level == 1) && find_arg(ctx, fd, name) >= 0) { /* lexical variable redefines a parameter name */ return js_parse_error(s, "invalid redefinition of parameter name"); } + if (find_var_in_child_scope(ctx, fd, name, fd->scope_level) >= 0) { + return js_parse_error(s, "invalid redefinition of a variable"); + } + + if (fd->is_global_var) { + JSHoistedDef *hf; + hf = find_hoisted_def(fd, name); + if (hf && is_child_scope(ctx, fd, hf->scope_level, + fd->scope_level)) { + return js_parse_error(s, "invalid redefinition of global identifier"); + } + } + if (fd->is_eval && (fd->eval_type == JS_EVAL_TYPE_GLOBAL || fd->eval_type == JS_EVAL_TYPE_MODULE) && fd->scope_level == 1) { JSHoistedDef *hf; - hf = find_hoisted_def(fd, name); - /* XXX: should check scope chain */ - if (hf && hf->scope_level == fd->scope_level) { - return js_parse_error(s, "invalid redefinition of global identifier"); - } hf = add_hoisted_def(s->ctx, fd, -1, name, -1, TRUE); if (!hf) return -1; - hf->is_const = (tok == TOK_CONST); + hf->is_const = (var_def_type == JS_VAR_DEF_CONST); idx = GLOBAL_VAR_OFFSET; } else { - if (fd->is_global_var) { - JSHoistedDef *hf; - hf = find_hoisted_def(fd, name); - /* XXX: should check scope chain */ - if (hf && hf->scope_level == fd->scope_level) { - return js_parse_error(s, "invalid redefinition of global identifier"); - } - } - /* XXX: should also fail at scope_level 1 if name duplicates argument or var name */ - idx = add_var(ctx, fd, name); + JSVarKindEnum var_kind; + if (var_def_type == JS_VAR_DEF_FUNCTION_DECL) + var_kind = JS_VAR_FUNCTION_DECL; + else if (var_def_type == JS_VAR_DEF_NEW_FUNCTION_DECL) + var_kind = JS_VAR_NEW_FUNCTION_DECL; + else + var_kind = JS_VAR_NORMAL; + idx = add_scope_var(ctx, fd, name, var_kind); if (idx >= 0) { vd = &fd->vars[idx]; vd->is_lexical = 1; - vd->is_function = (tok == TOK_FUNCTION); - vd->is_const = (tok == TOK_CONST); - vd->scope_level = fd->scope_level; - vd->scope_next = fd->scope_first; - fd->scopes[fd->scope_level].first = idx; - fd->scope_first = idx; + vd->is_const = (var_def_type == JS_VAR_DEF_CONST); } } break; - case TOK_CATCH: - idx = add_var(ctx, fd, name); - if (idx >= 0) { - vd = &fd->vars[idx]; - vd->var_kind = JS_VAR_CATCH; - vd->scope_level = fd->scope_level; - vd->scope_next = fd->scope_first; - fd->scopes[fd->scope_level].first = idx; - fd->scope_first = idx; - } + case JS_VAR_DEF_CATCH: + idx = add_scope_var(ctx, fd, name, JS_VAR_CATCH); break; - default: - /* TOK_VAR, TOK_FOR (used for for-of variable definition) */ + case JS_VAR_DEF_VAR: if (find_lexical_decl(ctx, fd, name, fd->scope_first, - (tok == TOK_FOR)) >= 0) { + FALSE) >= 0) { invalid_lexical_redefinition: /* error to redefine a var that inside a lexical scope */ return js_parse_error(s, "invalid redefinition of lexical identifier"); @@ -20359,7 +20446,6 @@ static int define_var(JSParseState *s, JSFunctionDef *fd, JSAtom name, int tok) hf = add_hoisted_def(s->ctx, fd, -1, name, -1, FALSE); if (!hf) return -1; - hf->is_for_of = (tok == TOK_FOR); idx = GLOBAL_VAR_OFFSET; } else { /* if the variable already exists, don't add it again */ @@ -20370,13 +20456,33 @@ static int define_var(JSParseState *s, JSFunctionDef *fd, JSAtom name, int tok) if (idx >= 0) { if (name == JS_ATOM_arguments && fd->has_arguments_binding) fd->arguments_var_idx = idx; + fd->vars[idx].func_pool_or_scope_idx = fd->scope_level; } } break; + default: + abort(); } return idx; } +/* add a private field variable in the current scope */ +static int add_private_class_field(JSParseState *s, JSFunctionDef *fd, + JSAtom name, JSVarKindEnum var_kind) +{ + JSContext *ctx = s->ctx; + JSVarDef *vd; + int idx; + + idx = add_scope_var(ctx, fd, name, var_kind); + if (idx < 0) + return idx; + vd = &fd->vars[idx]; + vd->is_lexical = 1; + vd->is_const = 1; + return idx; +} + static __exception int js_parse_expr(JSParseState *s); static __exception int js_parse_function_decl(JSParseState *s, JSParseFunctionEnum func_type, @@ -20556,6 +20662,7 @@ static int __exception js_parse_property_name(JSParseState *s, BOOL allow_private) { int is_private = 0; + BOOL is_non_reserved_ident; JSAtom name; int prop_type; @@ -20568,8 +20675,10 @@ static int __exception js_parse_property_name(JSParseState *s, if (next_token(s)) goto fail1; if (s->token.val == ':' || s->token.val == ',' || - s->token.val == '}' || s->token.val == '(') - goto done; + s->token.val == '}' || s->token.val == '(') { + is_non_reserved_ident = TRUE; + goto ident_found; + } prop_type = PROP_TYPE_GET + (name == JS_ATOM_set); JS_FreeAtom(s->ctx, name); } else if (s->token.val == '*') { @@ -20582,8 +20691,10 @@ static int __exception js_parse_property_name(JSParseState *s, if (next_token(s)) goto fail1; if (s->token.val == ':' || s->token.val == ',' || - s->token.val == '}' || s->token.val == '(') - goto done; + s->token.val == '}' || s->token.val == '(') { + is_non_reserved_ident = TRUE; + goto ident_found; + } JS_FreeAtom(s->ctx, name); if (s->token.val == '*') { if (next_token(s)) @@ -20597,17 +20708,20 @@ static int __exception js_parse_property_name(JSParseState *s, if (token_is_ident(s->token.val)) { /* variable can only be a non-reserved identifier */ - if (s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved && - prop_type == PROP_TYPE_IDENT && allow_var) { - int tok = peek_token(s, FALSE); - if (!(tok == ':' || (tok == '(' && allow_method))) { - prop_type = PROP_TYPE_VAR; - } - } + is_non_reserved_ident = + (s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved); /* keywords and reserved words have a valid atom */ name = JS_DupAtom(s->ctx, s->token.u.ident.atom); if (next_token(s)) goto fail1; + ident_found: + if (is_non_reserved_ident && + prop_type == PROP_TYPE_IDENT && allow_var) { + if (!(s->token.val == ':' || + (s->token.val == '(' && allow_method))) { + prop_type = PROP_TYPE_VAR; + } + } } else if (s->token.val == TOK_STRING) { name = js_value_to_atom(s->ctx, s->token.u.str.str); if (name == JS_ATOM_NULL) @@ -20658,7 +20772,6 @@ static int __exception js_parse_property_name(JSParseState *s, js_parse_error(s, "invalid property name"); goto fail; } - done: *pname = name; return prop_type | is_private; fail1: @@ -20693,6 +20806,29 @@ static __exception int js_parse_seek_token(JSParseState *s, const JSParsePos *sp return next_token(s); } +/* return TRUE if a regexp literal is allowed after this token */ +static BOOL is_regexp_allowed(int tok) +{ + switch (tok) { + case TOK_NUMBER: + case TOK_STRING: + case TOK_REGEXP: + case TOK_DEC: + case TOK_INC: + case TOK_NULL: + case TOK_FALSE: + case TOK_TRUE: + case TOK_THIS: + case ')': + case ']': + case '}': /* XXX: regexp may occur after */ + case TOK_IDENT: + return FALSE; + default: + return TRUE; + } +} + #define SKIP_HAS_SEMI (1 << 0) #define SKIP_HAS_ELLIPSIS (1 << 1) @@ -20704,13 +20840,14 @@ static int js_parse_skip_parens_token(JSParseState *s, int *pbits, BOOL no_line_ char state[256]; size_t level = 0; JSParsePos pos; - int tok = TOK_EOF; - int bits = 0; + int last_tok, tok = TOK_EOF; + int tok_len, bits = 0; /* protect from underflow */ state[level++] = 0; js_parse_get_pos(s, &pos); + last_tok = 0; for (;;) { switch(s->token.val) { case '(': @@ -20744,6 +20881,29 @@ static int js_parse_skip_parens_token(JSParseState *s, int *pbits, BOOL no_line_ bits |= SKIP_HAS_ELLIPSIS; } break; + + case TOK_DIV_ASSIGN: + tok_len = 2; + goto parse_regexp; + case '/': + tok_len = 1; + parse_regexp: + if (is_regexp_allowed(last_tok)) { + s->buf_ptr -= tok_len; + if (js_parse_regexp(s)) { + /* XXX: should clear the exception */ + goto done; + } + } + break; + } + /* last_tok is only used to recognize regexps */ + if (s->token.val == TOK_IDENT && + (token_is_pseudo_keyword(s, JS_ATOM_of) || + token_is_pseudo_keyword(s, JS_ATOM_yield))) { + last_tok = TOK_OF; + } else { + last_tok = s->token.val; } if (next_token(s)) { /* XXX: should clear the exception generated by next_token() */ @@ -20767,30 +20927,52 @@ static int js_parse_skip_parens_token(JSParseState *s, int *pbits, BOOL no_line_ return tok; } -static BOOL set_object_name(JSParseState *s, JSAtom name) +static void set_object_name(JSParseState *s, JSAtom name) { JSFunctionDef *fd = s->cur_func; + int opcode; - if (get_prev_opcode(fd) == OP_set_name) { + opcode = get_prev_opcode(fd); + if (opcode == OP_set_name) { /* XXX: should free atom after OP_set_name? */ fd->byte_code.size = fd->last_opcode_pos; fd->last_opcode_pos = -1; emit_op(s, OP_set_name); emit_atom(s, name); - return TRUE; + } else if (opcode == OP_set_class_name) { + int define_class_pos; + JSAtom atom; + define_class_pos = fd->last_opcode_pos + 1 - + get_u32(fd->byte_code.buf + fd->last_opcode_pos + 1); + assert(fd->byte_code.buf[define_class_pos] == OP_define_class); + /* for consistency we free the previous atom which is + JS_ATOM_empty_string */ + atom = get_u32(fd->byte_code.buf + define_class_pos + 1); + JS_FreeAtom(s->ctx, atom); + put_u32(fd->byte_code.buf + define_class_pos + 1, + JS_DupAtom(s->ctx, name)); + fd->last_opcode_pos = -1; } - return FALSE; } static void set_object_name_computed(JSParseState *s) { JSFunctionDef *fd = s->cur_func; + int opcode; - if (get_prev_opcode(fd) == OP_set_name) { + opcode = get_prev_opcode(fd); + if (opcode == OP_set_name) { /* XXX: should free atom after OP_set_name? */ fd->byte_code.size = fd->last_opcode_pos; fd->last_opcode_pos = -1; emit_op(s, OP_set_name_computed); + } else if (opcode == OP_set_class_name) { + int define_class_pos; + define_class_pos = fd->last_opcode_pos + 1 - + get_u32(fd->byte_code.buf + fd->last_opcode_pos + 1); + assert(fd->byte_code.buf[define_class_pos] == OP_define_class); + fd->byte_code.buf[define_class_pos] = OP_define_class_computed; + fd->last_opcode_pos = -1; } } @@ -20961,28 +21143,6 @@ static int find_private_class_field(JSContext *ctx, JSFunctionDef *fd, return -1; } -/* add field in the current scope */ -static int add_private_class_field(JSParseState *s, JSFunctionDef *fd, - JSAtom name, JSVarKindEnum var_kind) -{ - JSContext *ctx = s->ctx; - JSVarDef *vd; - int idx; - - idx = add_var(ctx, fd, name); - if (idx < 0) - return idx; - vd = &fd->vars[idx]; - vd->is_lexical = 1; - vd->is_const = 1; - vd->var_kind = var_kind; - vd->scope_level = fd->scope_level; - vd->scope_next = fd->scope_first; - fd->scopes[fd->scope_level].first = idx; - fd->scope_first = idx; - return idx; -} - /* initialize the class fields, called by the constructor. Note: super() can be called in an arrow function, so and can be variable references */ @@ -21098,7 +21258,7 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr, JSAtom class_var_name = JS_ATOM_NULL; JSFunctionDef *method_fd, *ctor_fd; int saved_js_mode, class_name_var_idx, prop_type, ctor_cpool_offset; - int class_flags = 0, i; + int class_flags = 0, i, define_class_offset; BOOL is_static, is_private; const uint8_t *class_start_ptr = s->token.ptr; const uint8_t *start_ptr; @@ -21144,7 +21304,7 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr, /* add a 'const' definition for the class name */ if (class_name != JS_ATOM_NULL) { - class_name_var_idx = define_var(s, fd, class_name, TOK_CONST); + class_name_var_idx = define_var(s, fd, class_name, JS_VAR_DEF_CONST); if (class_name_var_idx < 0) goto fail; } @@ -21159,14 +21319,19 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr, ctor_cpool_offset = fd->byte_code.size; emit_u32(s, 0); /* will be patched at the end of the class parsing */ - if (class_var_name != JS_ATOM_NULL && class_name == JS_ATOM_NULL) - class_name1 = JS_ATOM_default; - else + if (class_name == JS_ATOM_NULL) { + if (class_var_name != JS_ATOM_NULL) + class_name1 = JS_ATOM_default; + else + class_name1 = JS_ATOM_empty_string; + } else { class_name1 = class_name; + } emit_op(s, OP_define_class); emit_atom(s, class_name1); emit_u8(s, class_flags); + define_class_offset = fd->last_opcode_pos; for(i = 0; i < 2; i++) { ClassFieldsDef *cf = &class_fields[i]; @@ -21300,7 +21465,7 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr, field_var_name = js_atom_concat_num(ctx, JS_ATOM_computed_field + is_static, cf->computed_fields_count); if (field_var_name == JS_ATOM_NULL) goto fail; - if (define_var(s, fd, field_var_name, TOK_CONST) < 0) { + if (define_var(s, fd, field_var_name, JS_VAR_DEF_CONST) < 0) { JS_FreeAtom(ctx, field_var_name); goto fail; } @@ -21445,7 +21610,8 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr, ClassFieldsDef *cf = &class_fields[0]; int var_idx; - var_idx = define_var(s, fd, JS_ATOM_class_fields_init, TOK_CONST); + var_idx = define_var(s, fd, JS_ATOM_class_fields_init, + JS_VAR_DEF_CONST); if (var_idx < 0) goto fail; if (cf->fields_init_fd) { @@ -21485,18 +21651,18 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr, /* the class statements have a block level scope */ if (class_var_name != JS_ATOM_NULL) { - if (define_var(s, fd, class_var_name, TOK_LET) < 0) + if (define_var(s, fd, class_var_name, JS_VAR_DEF_LET) < 0) goto fail; emit_op(s, OP_scope_put_var_init); emit_atom(s, class_var_name); emit_u16(s, fd->scope_level); } else { if (class_name == JS_ATOM_NULL) { - /* XXX: should be done before calling the initializers. It - could be done with a specific opcode to patch the code - before */ - emit_op(s, OP_set_name); - emit_atom(s, class_name); /* will be patched by assignment */ + /* cannot use OP_set_name because the name of the class + must be defined before the static initializers are + executed */ + emit_op(s, OP_set_class_name); + emit_u32(s, fd->last_opcode_pos + 1 - define_class_offset); } } @@ -21908,7 +22074,8 @@ static int js_unsupported_keyword(JSParseState *s, JSAtom atom) static __exception int js_define_var(JSParseState *s, JSAtom name, int tok) { JSFunctionDef *fd = s->cur_func; - + JSVarDefEnum var_def_type; + if (name == JS_ATOM_yield && fd->func_kind == JS_FUNC_GENERATOR) { return js_parse_error(s, "yield is a reserved identifier"); } @@ -21920,7 +22087,23 @@ static __exception int js_define_var(JSParseState *s, JSAtom name, int tok) && (tok == TOK_LET || tok == TOK_CONST)) { return js_parse_error(s, "invalid lexical variable name"); } - if (define_var(s, fd, name, tok) < 0) + switch(tok) { + case TOK_LET: + var_def_type = JS_VAR_DEF_LET; + break; + case TOK_CONST: + var_def_type = JS_VAR_DEF_CONST; + break; + case TOK_VAR: + var_def_type = JS_VAR_DEF_VAR; + break; + case TOK_CATCH: + var_def_type = JS_VAR_DEF_CATCH; + break; + default: + abort(); + } + if (define_var(s, fd, name, var_def_type) < 0) return -1; return 0; } @@ -22666,17 +22849,30 @@ static __exception int js_parse_postfix_expr(JSParseState *s, BOOL accept_lparen } break; case TOK_IMPORT: - if (!accept_lparen) - return js_parse_error(s, "invalid use of 'import'"); if (next_token(s)) return -1; - if (js_parse_expect(s, '(')) - return -1; - if (js_parse_assign_expr(s, TRUE)) - return -1; - if (js_parse_expect(s, ')')) - return -1; - emit_op(s, OP_import); + if (s->token.val == '.') { + if (next_token(s)) + return -1; + if (!token_is_pseudo_keyword(s, JS_ATOM_meta)) + return js_parse_error(s, "meta expected"); + if (!s->is_module) + return js_parse_error(s, "import.meta only valid in module code"); + if (next_token(s)) + return -1; + emit_op(s, OP_special_object); + emit_u8(s, OP_SPECIAL_OBJECT_IMPORT_META); + } else { + if (js_parse_expect(s, '(')) + return -1; + if (!accept_lparen) + return js_parse_error(s, "invalid use of 'import()'"); + if (js_parse_assign_expr(s, TRUE)) + return -1; + if (js_parse_expect(s, ')')) + return -1; + emit_op(s, OP_import); + } break; default: return js_parse_error(s, "unexpected token in expression: '%.*s'", @@ -24028,9 +24224,6 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name, JS_FreeAtom(s->ctx, var_name); return -1; } - /* Note: if there is a '=' after, it cannot be a for-of. */ - if (tok == TOK_VAR && token_is_pseudo_keyword(s, JS_ATOM_of)) - tok = TOK_FOR; if (js_define_var(s, var_name, tok)) { JS_FreeAtom(s->ctx, var_name); return -1; @@ -24833,7 +25026,8 @@ static __exception int js_parse_statement_or_decl(JSParseState *s, goto fail; push_scope(s); - with_idx = define_var(s, s->cur_func, JS_ATOM__with_, TOK_WITH); + with_idx = define_var(s, s->cur_func, JS_ATOM__with_, + JS_VAR_DEF_WITH); if (with_idx < 0) goto fail; emit_op(s, OP_to_object); @@ -24896,6 +25090,13 @@ static __exception int js_parse_statement_or_decl(JSParseState *s, break; case TOK_DEBUGGER: + /* currently no debugger, so just skip the keyword */ + if (next_token(s)) + goto fail; + if (js_parse_expect_semi(s)) + goto fail; + break; + case TOK_ENUM: case TOK_EXPORT: case TOK_EXTENDS: @@ -24940,6 +25141,7 @@ static JSModuleDef *js_new_module_def(JSContext *ctx, JSAtom name) m->module_ns = JS_UNDEFINED; m->func_obj = JS_UNDEFINED; m->eval_exception = JS_UNDEFINED; + m->meta_obj = JS_UNDEFINED; list_add_tail(&m->link, &ctx->loaded_modules); return m; } @@ -24976,6 +25178,7 @@ static void js_free_module_def(JSContext *ctx, JSModuleDef *m) JS_FreeValue(ctx, m->module_ns); JS_FreeValue(ctx, m->func_obj); JS_FreeValue(ctx, m->eval_exception); + JS_FreeValue(ctx, m->meta_obj); list_del(&m->link); js_free(ctx, m); } @@ -25201,13 +25404,26 @@ static char *js_default_module_normalize_name(JSContext *ctx, return filename; } +static JSModuleDef *js_find_loaded_module(JSContext *ctx, JSAtom name) +{ + struct list_head *el; + JSModuleDef *m; + + /* first look at the loaded modules */ + list_for_each(el, &ctx->loaded_modules) { + m = list_entry(el, JSModuleDef, link); + if (m->module_name == name) + return m; + } + return NULL; +} + /* return NULL in case of exception (e.g. module could not be loaded) */ static JSModuleDef *js_host_resolve_imported_module(JSContext *ctx, JSAtom base_module_name, JSAtom module_name1) { JSRuntime *rt = ctx->rt; - struct list_head *el; JSModuleDef *m; char *cname; const char *base_cname, *cname1; @@ -25240,13 +25456,11 @@ static JSModuleDef *js_host_resolve_imported_module(JSContext *ctx, } /* first look at the loaded modules */ - list_for_each(el, &ctx->loaded_modules) { - m = list_entry(el, JSModuleDef, link); - if (m->module_name == module_name) { - js_free(ctx, cname); - JS_FreeAtom(ctx, module_name); - return m; - } + m = js_find_loaded_module(ctx, module_name); + if (m) { + js_free(ctx, cname); + JS_FreeAtom(ctx, module_name); + return m; } JS_FreeAtom(ctx, module_name); @@ -25953,20 +26167,12 @@ static int js_instantiate_module(JSContext *ctx, JSModuleDef *m) return -1; } -static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier) +/* warning: the returned atom is not allocated */ +static JSAtom js_get_script_or_module_name(JSContext *ctx) { JSStackFrame *sf; JSFunctionBytecode *b; JSObject *p; - JSModuleDef *m; - JSAtom basename, filename; - JSValue promise, resolving_funcs[2]; - JSValue specifierString, ret, func_obj, err, ns; - - promise = JS_NewPromiseCapability(ctx, resolving_funcs); - if (JS_IsException(promise)) - return promise; - /* XXX: currently we just use the filename of the englobing function. It does not work for eval(). Need to add a ScriptOrModule info in JSFunctionBytecode */ @@ -25976,11 +26182,66 @@ static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier) p = JS_VALUE_GET_OBJ(sf->cur_func); assert(js_class_has_bytecode(p->class_id)); b = p->u.func.function_bytecode; - if (!b->has_debug) { + if (!b->has_debug) + return JS_ATOM_NULL; + return b->debug.filename; +} + +JSAtom JS_GetModuleName(JSContext *ctx, JSModuleDef *m) +{ + return JS_DupAtom(ctx, m->module_name); +} + +JSValue JS_GetImportMeta(JSContext *ctx, JSModuleDef *m) +{ + JSValue obj; + /* allocate meta_obj only if requested to save memory */ + obj = m->meta_obj; + if (JS_IsUndefined(obj)) { + obj = JS_NewObjectProto(ctx, JS_NULL); + if (JS_IsException(obj)) + return JS_EXCEPTION; + m->meta_obj = obj; + } + return JS_DupValue(ctx, obj); +} + +static JSValue js_import_meta(JSContext *ctx) +{ + JSAtom filename; + JSModuleDef *m; + + filename = js_get_script_or_module_name(ctx); + if (filename == JS_ATOM_NULL) + goto fail; + + /* XXX: inefficient, need to add a module or script pointer in + JSFunctionBytecode */ + m = js_find_loaded_module(ctx, filename); + if (!m) { + fail: + JS_ThrowTypeError(ctx, "import.meta not supported in this context"); + return JS_EXCEPTION; + } + return JS_GetImportMeta(ctx, m); +} + +static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier) +{ + JSModuleDef *m; + JSAtom basename, filename; + JSValue promise, resolving_funcs[2]; + JSValue specifierString, ret, func_obj, err, ns; + + promise = JS_NewPromiseCapability(ctx, resolving_funcs); + if (JS_IsException(promise)) + return promise; + + basename = js_get_script_or_module_name(ctx); + if (basename == JS_ATOM_NULL) { JS_ThrowTypeError(ctx, "no function filename for import()"); goto exception; } - basename = b->debug.filename; specifierString = JS_ToString(ctx, specifier); if (JS_IsException(specifierString)) @@ -26003,7 +26264,7 @@ static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier) /* Evaluate the module code */ func_obj = JS_DupValue(ctx, JS_MKPTR(JS_TAG_MODULE, m)); - ret = JS_EvalFunction(ctx, func_obj, ctx->global_obj); + ret = JS_EvalFunction(ctx, func_obj); if (JS_IsException(ret)) goto exception; JS_FreeValue(ctx, ret); @@ -26253,7 +26514,7 @@ static __exception int js_parse_export(JSParseState *s) /* store the value in the _default_ global variable and export it */ local_name = JS_ATOM__default_; - if (define_var(s, s->cur_func, local_name, TOK_LET) < 0) + if (define_var(s, s->cur_func, local_name, JS_VAR_DEF_LET) < 0) return -1; emit_op(s, OP_scope_put_var_init); emit_atom(s, local_name); @@ -26428,7 +26689,8 @@ static __exception int js_parse_import(JSParseState *s) static __exception int js_parse_source_element(JSParseState *s) { JSFunctionDef *fd = s->cur_func; - + int tok; + if (s->token.val == TOK_FUNCTION || (token_is_pseudo_keyword(s, JS_ATOM_async) && peek_token(s, TRUE) == TOK_FUNCTION)) { @@ -26440,9 +26702,9 @@ static __exception int js_parse_source_element(JSParseState *s) if (js_parse_export(s)) return -1; } else if (s->token.val == TOK_IMPORT && fd->module && - peek_token(s, FALSE) != '(') { + ((tok = peek_token(s, FALSE)) != '(' && tok != '.')) { /* the peek_token is needed to avoid confusion with ImportCall - (dynamic import) */ + (dynamic import) or import.meta */ if (js_parse_import(s)) return -1; } else { @@ -26978,7 +27240,8 @@ static __attribute__((unused)) void js_dump_function_bytecode(JSContext *ctx, JS JSVarDef *vd = &b->vardefs[b->arg_count + i]; printf("%5d: %s %s", i, vd->var_kind == JS_VAR_CATCH ? "catch" : - vd->is_function ? "function" : + (vd->var_kind == JS_VAR_FUNCTION_DECL || + vd->var_kind == JS_VAR_NEW_FUNCTION_DECL) ? "function" : vd->is_const ? "const" : vd->is_lexical ? "let" : "var", JS_AtomGetStr(ctx, atom_buf, sizeof(atom_buf), vd->var_name)); @@ -27765,12 +28028,13 @@ static int find_private_class_field_all(JSContext *ctx, JSFunctionDef *fd, static void get_loc_or_ref(DynBuf *bc, BOOL is_ref, int idx) { + /* Note: the private field can be uninitialized, so the _check is + necessary */ if (is_ref) - dbuf_putc(bc, OP_get_var_ref); + dbuf_putc(bc, OP_get_var_ref_check); else - dbuf_putc(bc, OP_get_loc); + dbuf_putc(bc, OP_get_loc_check); dbuf_put_u16(bc, idx); - } static int resolve_scope_private_field1(JSContext *ctx, @@ -28469,8 +28733,7 @@ static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s) JSClosureVar *cv = &s->closure_var[idx]; if (cv->var_name == hf->var_name) { if (s->eval_type == JS_EVAL_TYPE_DIRECT && - (cv->is_lexical || - (cv->var_kind == JS_VAR_CATCH && hf->is_for_of))) { + cv->is_lexical) { /* Check if a lexical variable is redefined as 'var'. XXX: Could abort compilation here, but for consistency @@ -28664,10 +28927,11 @@ static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s) for(scope_idx = s->scopes[scope].first; scope_idx >= 0;) { JSVarDef *vd = &s->vars[scope_idx]; if (vd->scope_level == scope) { - if (vd->is_function) { + if (vd->var_kind == JS_VAR_FUNCTION_DECL || + vd->var_kind == JS_VAR_NEW_FUNCTION_DECL) { /* Initialize lexical variable upon entering scope */ dbuf_putc(&bc_out, OP_fclosure); - dbuf_put_u32(&bc_out, vd->func_pool_idx); + dbuf_put_u32(&bc_out, vd->func_pool_or_scope_idx); dbuf_putc(&bc_out, OP_put_loc); dbuf_put_u16(&bc_out, scope_idx); } else { @@ -28754,7 +29018,10 @@ static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s) case OP_nop: /* remove erased code */ break; - + case OP_set_class_name: + /* only used during parsing */ + break; + default: no_change: dbuf_put(&bc_out, bc_buf + pos, len); @@ -30639,7 +30906,10 @@ static __exception int js_parse_function_decl2(JSParseState *s, /* Always create a lexical name, fail if at the same scope as existing name */ /* Lexical variable will be initialized upon entering scope */ - lexical_func_idx = define_var(s, fd, func_name, TOK_FUNCTION); + lexical_func_idx = define_var(s, fd, func_name, + func_kind != JS_FUNC_NORMAL ? + JS_VAR_DEF_NEW_FUNCTION_DECL : + JS_VAR_DEF_FUNCTION_DECL); if (lexical_func_idx < 0) { JS_FreeAtom(ctx, func_name); return -1; @@ -30960,6 +31230,10 @@ static __exception int js_parse_function_decl2(JSParseState *s, hf = add_hoisted_def(ctx, s->cur_func, -1, func_name, -1, FALSE); if (!hf) goto fail; + /* it is considered as defined at the top level + (needed for annex B.3.3.4 and B.3.3.5 + checks) */ + hf->scope_level = 0; hf->force_init = ((s->cur_func->js_mode & JS_MODE_STRICT) != 0); /* store directly into global var, bypass lexical scope */ emit_op(s, OP_dup); @@ -30983,7 +31257,7 @@ static __exception int js_parse_function_decl2(JSParseState *s, } if (lexical_func_idx >= 0) { /* lexical variable will be initialized upon entering scope */ - s->cur_func->vars[lexical_func_idx].func_pool_idx = idx; + s->cur_func->vars[lexical_func_idx].func_pool_or_scope_idx = idx; emit_op(s, OP_drop); } else { /* store function object into its lexical name */ @@ -30994,7 +31268,7 @@ static __exception int js_parse_function_decl2(JSParseState *s, } } else { if (!s->cur_func->is_global_var) { - int var_idx = define_var(s, s->cur_func, func_name, TOK_VAR); + int var_idx = define_var(s, s->cur_func, func_name, JS_VAR_DEF_VAR); if (var_idx < 0) goto fail; @@ -31124,9 +31398,9 @@ static JSValue JS_EvalFunctionInternal(JSContext *ctx, JSValue fun_obj, return ret_val; } -JSValue JS_EvalFunction(JSContext *ctx, JSValue fun_obj, JSValueConst this_obj) +JSValue JS_EvalFunction(JSContext *ctx, JSValue fun_obj) { - return JS_EvalFunctionInternal(ctx, fun_obj, this_obj, NULL, NULL); + return JS_EvalFunctionInternal(ctx, fun_obj, ctx->global_obj, NULL, NULL); } static void skip_shebang(JSParseState *s) @@ -31303,27 +31577,16 @@ JSValue JS_Eval(JSContext *ctx, const char *input, size_t input_len, return ret; } -JSValue JS_EvalBinary(JSContext *ctx, - const uint8_t *buf, size_t buf_len, int flags) +int JS_ResolveModule(JSContext *ctx, JSValueConst obj) { - JSValue obj; - obj = JS_ReadObject(ctx, buf, buf_len, JS_READ_OBJ_BYTECODE); - if (JS_IsException(obj)) - return obj; - if (flags & JS_EVAL_BINARY_LOAD_ONLY) { - return obj; - } else { - /* if a module, we load the dependencies here */ - if (JS_VALUE_GET_TAG(obj) == JS_TAG_MODULE) { - JSModuleDef *m = JS_VALUE_GET_PTR(obj); - if (js_resolve_module(ctx, m) < 0) { - JS_FreeValue(ctx, obj); - js_free_modules(ctx, JS_FREE_MODULE_NOT_RESOLVED); - return JS_EXCEPTION; - } + if (JS_VALUE_GET_TAG(obj) == JS_TAG_MODULE) { + JSModuleDef *m = JS_VALUE_GET_PTR(obj); + if (js_resolve_module(ctx, m) < 0) { + js_free_modules(ctx, JS_FREE_MODULE_NOT_RESOLVED); + return -1; } - return JS_EvalFunction(ctx, obj, ctx->global_obj); } + return 0; } /*******************************************************************/ @@ -31689,8 +31952,7 @@ static int JS_WriteObjectRec(BCWriterState *s, JSValueConst obj) bc_put_leb128(s, vd->scope_level); bc_put_leb128(s, vd->scope_next + 1); flags = idx = 0; - bc_set_flags(&flags, &idx, vd->var_kind, 3); - bc_set_flags(&flags, &idx, vd->is_function, 1); + bc_set_flags(&flags, &idx, vd->var_kind, 4); bc_set_flags(&flags, &idx, vd->is_func_var, 1); bc_set_flags(&flags, &idx, vd->is_const, 1); bc_set_flags(&flags, &idx, vd->is_lexical, 1); @@ -31711,7 +31973,7 @@ static int JS_WriteObjectRec(BCWriterState *s, JSValueConst obj) bc_set_flags(&flags, &idx, cv->is_arg, 1); bc_set_flags(&flags, &idx, cv->is_const, 1); bc_set_flags(&flags, &idx, cv->is_lexical, 1); - bc_set_flags(&flags, &idx, cv->var_kind, 3); + bc_set_flags(&flags, &idx, cv->var_kind, 4); assert(idx <= 8); bc_put_u8(s, flags); } @@ -32454,8 +32716,7 @@ static JSValue JS_ReadObjectRec(BCReaderState *s) if (bc_get_u8(s, &v8)) goto fail; idx = 0; - vd->var_kind = bc_get_flags(v8, &idx, 3); - vd->is_function = bc_get_flags(v8, &idx, 1); + vd->var_kind = bc_get_flags(v8, &idx, 4); vd->is_func_var = bc_get_flags(v8, &idx, 1); vd->is_const = bc_get_flags(v8, &idx, 1); vd->is_lexical = bc_get_flags(v8, &idx, 1); @@ -32484,7 +32745,7 @@ static JSValue JS_ReadObjectRec(BCReaderState *s) cv->is_arg = bc_get_flags(v8, &idx, 1); cv->is_const = bc_get_flags(v8, &idx, 1); cv->is_lexical = bc_get_flags(v8, &idx, 1); - cv->var_kind = bc_get_flags(v8, &idx, 3); + cv->var_kind = bc_get_flags(v8, &idx, 4); #ifdef DUMP_READ_OBJECT bc_read_trace(s, "name: "); print_atom(s->ctx, cv->var_name); printf("\n"); #endif @@ -34441,17 +34702,65 @@ static JSValue js_function_proto(JSContext *ctx, JSValueConst this_val, return JS_UNDEFINED; } +/* insert a '\n' at unicode character position 'pos' in the source of + 'func_obj' */ +static int patch_function_constructor_source(JSContext *ctx, + JSValueConst func_obj, + size_t pos) +{ + JSObject *p; + JSFunctionBytecode *b; + char *r, *r_end, *new_source; + int c; + size_t idx, len; + + if (JS_VALUE_GET_TAG(func_obj) != JS_TAG_OBJECT) + return 0; + p = JS_VALUE_GET_OBJ(func_obj); + if (!js_class_has_bytecode(p->class_id)) + return 0; + b = p->u.func.function_bytecode; + if (!b->has_debug) + return 0; + r = b->debug.source; + r_end = b->debug.source + b->debug.source_len; + idx = 0; + while (r < r_end) { + if (idx == pos) { + /* add the '\n' */ + new_source = js_realloc(ctx, b->debug.source, + b->debug.source_len + 2); + if (!new_source) + return -1; + len = r - b->debug.source; + memmove(new_source + len + 1, new_source + len, + b->debug.source_len + 1 - len); + new_source[len] = '\n'; + b->debug.source = new_source; + b->debug.source_len++; + break; + } + c = unicode_from_utf8((const uint8_t *)r, UTF8_CHAR_LEN_MAX, + (const uint8_t **)&r); + if (c < 0) + break; + idx++; + } + return 0; +} + +/* XXX: add a specific eval mode so that Function("}), ({") is rejected */ static JSValue js_function_constructor(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv, int magic) { JSFunctionKindEnum func_kind = magic; - int i, n, ret; + int i, n, ret, func_start_pos; JSValue s, proto, obj = JS_UNDEFINED; StringBuffer b_s, *b = &b_s; string_buffer_init(ctx, b, 0); string_buffer_putc8(b, '('); - + if (func_kind == JS_FUNC_ASYNC || func_kind == JS_FUNC_ASYNC_GENERATOR) { string_buffer_puts8(b, "async "); } @@ -34470,7 +34779,13 @@ static JSValue js_function_constructor(JSContext *ctx, JSValueConst new_target, if (string_buffer_concat_value(b, argv[i])) goto fail; } - string_buffer_puts8(b, "\n) {\n"); + string_buffer_puts8(b, "\n) {"); + /* Annex B HTML comments: We don't add a '\n' after "{" so that + "-->" is not considered as an HTML comment. It is necessary + because in the spec the function body is parsed separately. */ + /* XXX: find a simpler way or be deliberately incompatible to + simplify the code ? */ + func_start_pos = b->len - 1; /* the leading '(' is not in the source */ if (n >= 0) { if (string_buffer_concat_value(b, argv[n])) goto fail; @@ -34484,6 +34799,8 @@ static JSValue js_function_constructor(JSContext *ctx, JSValueConst new_target, JS_FreeValue(ctx, s); if (JS_IsException(obj)) goto fail1; + if (patch_function_constructor_source(ctx, obj, func_start_pos) < 0) + goto fail1; if (!JS_IsUndefined(new_target)) { /* set the prototype */ proto = js_get_prototype_from_ctor(ctx, new_target, JS_UNDEFINED); @@ -41052,18 +41369,6 @@ static JSValue JS_ToQuotedStringFree(JSContext *ctx, JSValue val) { return r; } -static JSValue js_json_unbox(JSContext *ctx, JSValue val) { - if (JS_IsObject(val)) { - JSObject *p = JS_VALUE_GET_OBJ(val); - if (p->class_id == JS_CLASS_STRING || p->class_id == JS_CLASS_NUMBER) { - JSValue r = JS_DupValue(ctx, p->u.object_data); - JS_FreeValue(ctx, val); - val = r; - } - } - return val; -} - #ifdef CONFIG_BIGNUM static inline BOOL JS_IsBigInt(JSContext *ctx, JSValueConst v); #endif @@ -41133,13 +41438,14 @@ static JSValue js_json_check(JSContext *ctx, JSONStringifyContext *jsc, static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc, JSValueConst holder, JSValue val, - JSValueConst key, JSValueConst indent) + JSValueConst indent) { JSValue indent1, sep, sep1, tab, v, prop; JSObject *p; int64_t i, len; - int cl, res; - + int cl, ret; + BOOL has_content; + indent1 = JS_UNDEFINED; sep = JS_UNDEFINED; sep1 = JS_UNDEFINED; @@ -41151,15 +41457,22 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc, p = JS_VALUE_GET_OBJ(val); cl = p->class_id; if (cl == JS_CLASS_STRING) { - val = JS_InvokeFree(ctx, val, JS_ATOM_toString, 0, NULL); + val = JS_ToStringFree(ctx, val); if (JS_IsException(val)) goto exception; val = JS_ToQuotedStringFree(ctx, val); if (JS_IsException(val)) goto exception; return string_buffer_concat_value_free(jsc->b, val); - } else if (cl == JS_CLASS_NUMBER || cl == JS_CLASS_BOOLEAN) { + } else if (cl == JS_CLASS_NUMBER) { + val = JS_ToNumberFree(ctx, val); + if (JS_IsException(val)) + goto exception; return string_buffer_concat_value_free(jsc->b, val); + } else if (cl == JS_CLASS_BOOLEAN) { + ret = string_buffer_concat_value(jsc->b, p->u.object_data); + JS_FreeValue(ctx, val); + return ret; } #ifdef CONFIG_BIGNUM else if (cl == JS_CLASS_BIG_FLOAT) { @@ -41169,10 +41482,10 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc, goto exception; } #endif - res = JS_ToBoolFree(ctx, js_array_includes(ctx, jsc->stack, 1, (JSValueConst *)&val)); - if (res < 0) + v = js_array_includes(ctx, jsc->stack, 1, (JSValueConst *)&val); + if (JS_IsException(v)) goto exception; - if (res) { + if (JS_ToBoolFree(ctx, v)) { JS_ThrowTypeError(ctx, "circular reference"); goto exception; } @@ -41180,7 +41493,7 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc, if (JS_IsException(indent1)) goto exception; if (!JS_IsEmptyString(jsc->gap)) { - sep = JS_ConcatString3(ctx, "\n", JS_DupValue(ctx, indent), ""); + sep = JS_ConcatString3(ctx, "\n", JS_DupValue(ctx, indent1), ""); if (JS_IsException(sep)) goto exception; sep1 = JS_NewString(ctx, " "); @@ -41193,7 +41506,10 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc, v = js_array_push(ctx, jsc->stack, 1, (JSValueConst *)&val, 0); if (check_exception_free(ctx, v)) goto exception; - if (JS_IsArray(ctx, val)) { + ret = JS_IsArray(ctx, val); + if (ret < 0) + goto exception; + if (ret) { if (js_get_length64(ctx, &len, val)) goto exception; string_buffer_putc8(jsc->b, '['); @@ -41204,12 +41520,18 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc, v = JS_GetPropertyInt64(ctx, val, i); if (JS_IsException(v)) goto exception; - v = js_json_check(ctx, jsc, val, v, JS_NewInt32(ctx, i)); + /* XXX: could do this string conversion only when needed */ + prop = JS_ToStringFree(ctx, JS_NewInt64(ctx, i)); + if (JS_IsException(prop)) + goto exception; + v = js_json_check(ctx, jsc, val, v, prop); + JS_FreeValue(ctx, prop); + prop = JS_UNDEFINED; if (JS_IsException(v)) goto exception; if (JS_IsUndefined(v)) v = JS_NULL; - if (js_json_to_str(ctx, jsc, val, v, JS_NewInt32(ctx, i), indent1)) + if (js_json_to_str(ctx, jsc, val, v, indent1)) goto exception; } if (len > 0 && !JS_IsEmptyString(jsc->gap)) { @@ -41227,6 +41549,7 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc, if (js_get_length64(ctx, &len, tab)) goto exception; string_buffer_putc8(jsc->b, '{'); + has_content = FALSE; for(i = 0; i < len; i++) { JS_FreeValue(ctx, prop); prop = JS_GetPropertyInt64(ctx, tab, i); @@ -41239,7 +41562,7 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc, if (JS_IsException(v)) goto exception; if (!JS_IsUndefined(v)) { - if (i > 0) + if (has_content) string_buffer_putc8(jsc->b, ','); prop = JS_ToQuotedStringFree(ctx, prop); if (JS_IsException(prop)) { @@ -41250,11 +41573,12 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc, string_buffer_concat_value(jsc->b, prop); string_buffer_putc8(jsc->b, ':'); string_buffer_concat_value(jsc->b, sep1); - if (js_json_to_str(ctx, jsc, val, v, prop, indent1)) + if (js_json_to_str(ctx, jsc, val, v, indent1)) goto exception; + has_content = TRUE; } } - if (len > 0 && JS_VALUE_GET_STRING(jsc->gap)->len != 0) { + if (has_content && JS_VALUE_GET_STRING(jsc->gap)->len != 0) { string_buffer_putc8(jsc->b, '\n'); string_buffer_concat_value(jsc->b, indent); } @@ -41273,14 +41597,19 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc, val = JS_ToQuotedStringFree(ctx, val); if (JS_IsException(val)) goto exception; - /* fall thru */ - case JS_TAG_INT: + goto concat_value; case JS_TAG_FLOAT64: + if (!isfinite(JS_VALUE_GET_FLOAT64(val))) { + val = JS_NULL; + } + goto concat_value; + case JS_TAG_INT: #ifdef CONFIG_BIGNUM case JS_TAG_BIG_FLOAT: #endif case JS_TAG_BOOL: case JS_TAG_NULL: + concat_value: return string_buffer_concat_value_free(jsc->b, val); #ifdef CONFIG_BIGNUM case JS_TAG_BIG_INT: @@ -41309,7 +41638,7 @@ static JSValue js_json_stringify(JSContext *ctx, JSValueConst this_val, StringBuffer b_s; JSONStringifyContext jsc_s, *jsc = &jsc_s; JSValueConst replacer = argv[1]; - JSValue val, v, space, ret; + JSValue val, v, space, ret, wrapper; int res; int64_t i, j, n; @@ -41320,6 +41649,7 @@ static JSValue js_json_stringify(JSContext *ctx, JSValueConst this_val, jsc->b = &b_s; jsc->empty = JS_AtomToString(ctx, JS_ATOM_empty_string); ret = JS_UNDEFINED; + wrapper = JS_UNDEFINED; string_buffer_init(ctx, jsc->b, 0); jsc->stack = JS_NewArray(ctx); @@ -41339,21 +41669,56 @@ static JSValue js_json_stringify(JSContext *ctx, JSValueConst this_val, if (js_get_length64(ctx, &n, replacer)) goto exception; for (i = j = 0; i < n; i++) { + JSValue present; v = JS_GetPropertyInt64(ctx, replacer, i); if (JS_IsException(v)) goto exception; - v = js_json_unbox(ctx, v); - if (JS_IsNumber(v)) { + if (JS_IsObject(v)) { + JSObject *p = JS_VALUE_GET_OBJ(v); + if (p->class_id == JS_CLASS_STRING || + p->class_id == JS_CLASS_NUMBER) { + v = JS_ToStringFree(ctx, v); + if (JS_IsException(v)) + goto exception; + } else { + JS_FreeValue(ctx, v); + continue; + } + } else if (JS_IsNumber(v)) { v = JS_ToStringFree(ctx, v); + if (JS_IsException(v)) + goto exception; } else if (!JS_IsString(v)) { JS_FreeValue(ctx, v); continue; } - JS_SetPropertyInt64(ctx, jsc->property_list, j++, v); + present = js_array_includes(ctx, jsc->property_list, + 1, (JSValueConst *)&v); + if (JS_IsException(present)) { + JS_FreeValue(ctx, v); + goto exception; + } + if (!JS_ToBoolFree(ctx, present)) { + JS_SetPropertyInt64(ctx, jsc->property_list, j++, v); + } else { + JS_FreeValue(ctx, v); + } } } } - space = js_json_unbox(ctx, JS_DupValue(ctx, argv[2])); + space = JS_DupValue(ctx, argv[2]); + if (JS_IsObject(space)) { + JSObject *p = JS_VALUE_GET_OBJ(space); + if (p->class_id == JS_CLASS_NUMBER) { + space = JS_ToNumberFree(ctx, space); + } else if (p->class_id == JS_CLASS_STRING) { + space = JS_ToStringFree(ctx, space); + } + if (JS_IsException(space)) { + JS_FreeValue(ctx, space); + goto exception; + } + } if (JS_IsNumber(space)) { int n; if (JS_ToInt32Clamp(ctx, &n, space, 0, 10, 0)) @@ -41368,15 +41733,22 @@ static JSValue js_json_stringify(JSContext *ctx, JSValueConst this_val, JS_FreeValue(ctx, space); if (JS_IsException(jsc->gap)) goto exception; + wrapper = JS_NewObject(ctx); + if (JS_IsException(wrapper)) + goto exception; + if (JS_DefinePropertyValue(ctx, wrapper, JS_ATOM_empty_string, + JS_DupValue(ctx, argv[0]), JS_PROP_C_W_E) < 0) + goto exception; val = JS_DupValue(ctx, argv[0]); - val = js_json_check(ctx, jsc, JS_NULL, val, jsc->empty); + + val = js_json_check(ctx, jsc, wrapper, val, jsc->empty); if (JS_IsException(val)) goto exception; if (JS_IsUndefined(val)) { ret = JS_UNDEFINED; goto done1; } - if (js_json_to_str(ctx, jsc, JS_NULL, val, jsc->empty, jsc->empty)) + if (js_json_to_str(ctx, jsc, wrapper, val, jsc->empty)) goto exception; ret = string_buffer_end(jsc->b); @@ -41387,6 +41759,7 @@ static JSValue js_json_stringify(JSContext *ctx, JSValueConst this_val, done1: string_buffer_free(jsc->b); done: + JS_FreeValue(ctx, wrapper); JS_FreeValue(ctx, jsc->empty); JS_FreeValue(ctx, jsc->gap); JS_FreeValue(ctx, jsc->property_list); @@ -41967,11 +42340,11 @@ static int js_proxy_get_own_property(JSContext *ctx, JSPropertyDescriptor *pdesc JSValueConst obj, JSAtom prop) { JSProxyData *s; - JSValue method, ret1, prop_val; - int res, target_res, ret; + JSValue method, trap_result_obj, prop_val; + int res, target_desc_ret, ret; JSObject *p; JSValueConst args[2]; - JSPropertyDescriptor desc, target_desc; + JSPropertyDescriptor result_desc, target_desc; s = get_proxy_method(ctx, &method, obj, JS_ATOM_getOwnPropertyDescriptor); if (!s) @@ -41987,38 +42360,43 @@ static int js_proxy_get_own_property(JSContext *ctx, JSPropertyDescriptor *pdesc } args[0] = s->target; args[1] = prop_val; - ret1 = JS_CallFree(ctx, method, s->handler, 2, args); + trap_result_obj = JS_CallFree(ctx, method, s->handler, 2, args); JS_FreeValue(ctx, prop_val); - if (JS_IsException(ret1)) + if (JS_IsException(trap_result_obj)) return -1; - if (!JS_IsObject(ret1) && !JS_IsUndefined(ret1)) { - JS_FreeValue(ctx, ret1); + if (!JS_IsObject(trap_result_obj) && !JS_IsUndefined(trap_result_obj)) { + JS_FreeValue(ctx, trap_result_obj); goto fail; } - target_res = JS_GetOwnPropertyInternal(ctx, &target_desc, p, prop); - if (target_res < 0) { - JS_FreeValue(ctx, ret1); + target_desc_ret = JS_GetOwnPropertyInternal(ctx, &target_desc, p, prop); + if (target_desc_ret < 0) { + JS_FreeValue(ctx, trap_result_obj); return -1; } - if (target_res) + if (target_desc_ret) js_free_desc(ctx, &target_desc); - if (JS_IsUndefined(ret1)) { - if (target_res) { + if (JS_IsUndefined(trap_result_obj)) { + if (target_desc_ret) { if (!(target_desc.flags & JS_PROP_CONFIGURABLE) || !p->extensible) goto fail; } ret = FALSE; } else { - int flags1; - - res = js_obj_to_desc(ctx, &desc, ret1); - JS_FreeValue(ctx, ret1); + int flags1, extensible_target; + extensible_target = JS_IsExtensible(ctx, s->target); + if (extensible_target < 0) { + JS_FreeValue(ctx, trap_result_obj); + return -1; + } + res = js_obj_to_desc(ctx, &result_desc, trap_result_obj); + JS_FreeValue(ctx, trap_result_obj); if (res < 0) return -1; - if (target_res) { - /* convert desc.flags to defineProperty flags */ - flags1 = desc.flags | JS_PROP_HAS_CONFIGURABLE | JS_PROP_HAS_ENUMERABLE; - if (desc.flags & JS_PROP_GETSET) + + if (target_desc_ret) { + /* convert result_desc.flags to defineProperty flags */ + flags1 = result_desc.flags | JS_PROP_HAS_CONFIGURABLE | JS_PROP_HAS_ENUMERABLE; + if (result_desc.flags & JS_PROP_GETSET) flags1 |= JS_PROP_HAS_GET | JS_PROP_HAS_SET; else flags1 |= JS_PROP_HAS_VALUE | JS_PROP_HAS_WRITABLE; @@ -42027,23 +42405,29 @@ static int js_proxy_get_own_property(JSContext *ctx, JSPropertyDescriptor *pdesc if (!check_define_prop_flags(target_desc.flags, flags1)) goto fail1; } else { - if (!p->extensible) + if (!extensible_target) goto fail1; } - res = (!(desc.flags & JS_PROP_CONFIGURABLE) && - (!target_res || (target_desc.flags & JS_PROP_CONFIGURABLE))); - if (res) { - fail1: - js_free_desc(ctx, &desc); - fail: - JS_ThrowTypeError(ctx, "proxy: inconsistent getOwnPropertyDescriptor"); - return -1; + if (!(result_desc.flags & JS_PROP_CONFIGURABLE)) { + if (!target_desc_ret || (target_desc.flags & JS_PROP_CONFIGURABLE)) + goto fail1; + if ((result_desc.flags & + (JS_PROP_GETSET | JS_PROP_WRITABLE)) == 0 && + target_desc_ret && + (target_desc.flags & JS_PROP_WRITABLE) != 0) { + /* proxy-missing-checks */ + fail1: + js_free_desc(ctx, &result_desc); + fail: + JS_ThrowTypeError(ctx, "proxy: inconsistent getOwnPropertyDescriptor"); + return -1; + } } ret = TRUE; if (pdesc) { - *pdesc = desc; + *pdesc = result_desc; } else { - js_free_desc(ctx, &desc); + js_free_desc(ctx, &result_desc); } } return ret; @@ -42124,8 +42508,19 @@ static int js_proxy_define_own_property(JSContext *ctx, JSValueConst obj, } } } else if (flags & JS_PROP_HAS_VALUE) { - if ((desc.flags & (JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE)) == 0 && + if ((desc.flags & (JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE)) == + JS_PROP_WRITABLE && !(flags & JS_PROP_WRITABLE)) { + /* missing-proxy-check feature */ + goto fail1; + } else if ((desc.flags & (JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE)) == 0 && !js_same_value(ctx, val, desc.value)) { + goto fail1; + } + } + if (flags & JS_PROP_HAS_WRITABLE) { + if ((desc.flags & (JS_PROP_GETSET | JS_PROP_CONFIGURABLE | + JS_PROP_WRITABLE)) == JS_PROP_WRITABLE) { + /* proxy-missing-checks */ fail1: js_free_desc(ctx, &desc); fail: @@ -42143,7 +42538,7 @@ static int js_proxy_delete_property(JSContext *ctx, JSValueConst obj, { JSProxyData *s; JSValue method, ret, atom_val; - int res, res2; + int res, res2, is_extensible; JSValueConst args[2]; s = get_proxy_method(ctx, &method, obj, JS_ATOM_deleteProperty); @@ -42170,12 +42565,20 @@ static int js_proxy_delete_property(JSContext *ctx, JSValueConst obj, if (res2 < 0) return -1; if (res2) { - res2 = !(desc.flags & JS_PROP_CONFIGURABLE); - js_free_desc(ctx, &desc); - if (res2) { + if (!(desc.flags & JS_PROP_CONFIGURABLE)) + goto fail; + is_extensible = JS_IsExtensible(ctx, s->target); + if (is_extensible < 0) + goto fail1; + if (!is_extensible) { + /* proxy-missing-checks */ + fail: JS_ThrowTypeError(ctx, "proxy: inconsistent deleteProperty"); + fail1: + js_free_desc(ctx, &desc); return -1; } + js_free_desc(ctx, &desc); } } return res; @@ -42322,8 +42725,10 @@ static JSValue js_proxy_call(JSContext *ctx, JSValueConst func_obj, s = get_proxy_method(ctx, &method, func_obj, JS_ATOM_apply); if (!s) return JS_EXCEPTION; - if (!s->is_func) + if (!s->is_func) { + JS_FreeValue(ctx, method); return JS_ThrowTypeError(ctx, "not a function"); + } if (JS_IsUndefined(method)) return JS_Call(ctx, s->target, this_obj, argc, argv); arg_array = js_create_array(ctx, argc, argv); @@ -43608,8 +44013,7 @@ static int js_create_resolving_functions(JSContext *ctx, s->presolved = sr; s->promise = JS_DupValue(ctx, promise); JS_SetOpaque(obj, s); - JS_DefinePropertyValue(ctx, obj, JS_ATOM_length, JS_NewInt32(ctx, 1), - JS_PROP_CONFIGURABLE); + js_function_set_properties(ctx, obj, JS_ATOM_empty_string, 1); resolving_funcs[i] = obj; } js_promise_resolve_function_free_resolved(ctx->rt, sr); @@ -44383,25 +44787,23 @@ static const JSCFunctionListEntry js_async_function_proto_funcs[] = { JS_PROP_STRING_DEF("[Symbol.toStringTag]", "AsyncFunction", JS_PROP_CONFIGURABLE ), }; -static JSValue js_async_from_async_iterator_unwrap(JSContext *ctx, - JSValueConst this_val, - int argc, JSValueConst *argv, - int magic, JSValue *func_data) +static JSValue js_async_from_sync_iterator_unwrap(JSContext *ctx, + JSValueConst this_val, + int argc, JSValueConst *argv, + int magic, JSValue *func_data) { - return js_create_iterator_result(ctx, JS_DupValue(ctx, func_data[0]), - JS_ToBool(ctx, func_data[1])); + return js_create_iterator_result(ctx, JS_DupValue(ctx, argv[0]), + JS_ToBool(ctx, func_data[0])); } -static JSValue js_async_from_async_iterator_unwrap_func_create(JSContext *ctx, - JSValueConst value, - BOOL done) +static JSValue js_async_from_sync_iterator_unwrap_func_create(JSContext *ctx, + BOOL done) { - JSValueConst func_data[2]; + JSValueConst func_data[1]; - func_data[0] = value; - func_data[1] = (JSValueConst)JS_NewBool(ctx, done); - return JS_NewCFunctionData(ctx, js_async_from_async_iterator_unwrap, - 0, 0, 2, func_data); + func_data[0] = (JSValueConst)JS_NewBool(ctx, done); + return JS_NewCFunctionData(ctx, js_async_from_sync_iterator_unwrap, + 1, 0, 1, func_data); } /* AsyncIteratorPrototype */ @@ -44539,7 +44941,8 @@ static JSValue js_async_from_sync_iterator_next(JSContext *ctx, JSValueConst thi goto reject; } - resolve_reject[0] = js_async_from_async_iterator_unwrap_func_create(ctx, value, done); + resolve_reject[0] = + js_async_from_sync_iterator_unwrap_func_create(ctx, done); if (JS_IsException(resolve_reject[0])) { JS_FreeValue(ctx, value_wrapper_promise); goto fail; @@ -46887,6 +47290,10 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx) /* global properties */ JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_global_funcs, countof(js_global_funcs)); + + JS_DefinePropertyValue(ctx, ctx->global_obj, JS_ATOM_globalThis, + JS_DupValue(ctx, ctx->global_obj), + JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE); } /* Typed Arrays */ @@ -48283,7 +48690,7 @@ static int js_cmp_doubles(double x, double y) if (x > y) return 1; if (x != 0) return 0; if (signbit(x)) return signbit(y) ? 0 : -1; - else return signbit(y) ? -1 : 0; + else return signbit(y) ? 1 : 0; } static int js_TA_cmp_int8(const void *a, const void *b, void *opaque) { @@ -48378,51 +48785,32 @@ static JSValue js_TA_get_float64(JSContext *ctx, const void *a) { return __JS_NewFloat64(ctx, *(const double *)a); } -static void js_TA_swap_uint8(void *a, void *b) { - uint8_t x = *(uint8_t *)a; - *(uint8_t *)a = *(uint8_t *)b; - *(uint8_t *)b = x; -} - -static void js_TA_swap_uint16(void *a, void *b) { - uint16_t x = *(uint16_t *)a; - *(uint16_t *)a = *(uint16_t *)b; - *(uint16_t *)b = x; -} - -static void js_TA_swap_uint32(void *a, void *b) { - uint32_t x = *(uint32_t *)a; - *(uint32_t *)a = *(uint32_t *)b; - *(uint32_t *)b = x; -} - -static void js_TA_swap_uint64(void *a, void *b) { - uint64_t x = *(uint64_t *)a; - *(uint64_t *)a = *(uint64_t *)b; - *(uint64_t *)b = x; -} - struct TA_sort_context { JSContext *ctx; int exception; JSValueConst arr; JSValueConst cmp; JSValue (*getfun)(JSContext *ctx, const void *a); - int (*cmpfun)(const void *a, const void *b, void *opaque); - void (*swapfun)(void *a, void *b); + void *array_ptr; /* cannot change unless the array is detached */ + int elt_size; }; static int js_TA_cmp_generic(const void *a, const void *b, void *opaque) { struct TA_sort_context *psc = opaque; JSContext *ctx = psc->ctx; + uint32_t a_idx, b_idx; JSValueConst argv[2]; JSValue res; int cmp; cmp = 0; if (!psc->exception) { - argv[0] = psc->getfun(ctx, a); - argv[1] = psc->getfun(ctx, b); + a_idx = *(uint32_t *)a; + b_idx = *(uint32_t *)b; + argv[0] = psc->getfun(ctx, psc->array_ptr + + a_idx * (size_t)psc->elt_size); + argv[1] = psc->getfun(ctx, psc->array_ptr + + b_idx * (size_t)(psc->elt_size)); res = JS_Call(ctx, psc->cmp, JS_UNDEFINED, 2, argv); if (JS_IsException(res)) { psc->exception = 1; @@ -48440,6 +48828,10 @@ static int js_TA_cmp_generic(const void *a, const void *b, void *opaque) { cmp = (val > 0) - (val < 0); } } + if (cmp == 0) { + /* make sort stable: compare array offsets */ + cmp = (a_idx > b_idx) - (a_idx < b_idx); + } if (validate_typed_array(ctx, psc->arr) < 0) { psc->exception = 1; } @@ -48454,9 +48846,10 @@ static JSValue js_typed_array_sort(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { JSObject *p; - int len, elt_size; + int len; + size_t elt_size; struct TA_sort_context tsc; - void *array_ptr, *array_copy = NULL, *array_org; + void *array_ptr; int (*cmpfun)(const void *a, const void *b, void *opaque); tsc.ctx = ctx; @@ -48475,81 +48868,110 @@ static JSValue js_typed_array_sort(JSContext *ctx, JSValueConst this_val, switch (p->class_id) { case JS_CLASS_INT8_ARRAY: tsc.getfun = js_TA_get_int8; - tsc.cmpfun = js_TA_cmp_int8; - tsc.swapfun = js_TA_swap_uint8; + cmpfun = js_TA_cmp_int8; break; case JS_CLASS_UINT8C_ARRAY: case JS_CLASS_UINT8_ARRAY: tsc.getfun = js_TA_get_uint8; - tsc.cmpfun = js_TA_cmp_uint8; - tsc.swapfun = js_TA_swap_uint8; + cmpfun = js_TA_cmp_uint8; break; case JS_CLASS_INT16_ARRAY: tsc.getfun = js_TA_get_int16; - tsc.cmpfun = js_TA_cmp_int16; - tsc.swapfun = js_TA_swap_uint16; + cmpfun = js_TA_cmp_int16; break; case JS_CLASS_UINT16_ARRAY: tsc.getfun = js_TA_get_uint16; - tsc.cmpfun = js_TA_cmp_uint16; - tsc.swapfun = js_TA_swap_uint16; + cmpfun = js_TA_cmp_uint16; break; case JS_CLASS_INT32_ARRAY: tsc.getfun = js_TA_get_int32; - tsc.cmpfun = js_TA_cmp_int32; - tsc.swapfun = js_TA_swap_uint32; + cmpfun = js_TA_cmp_int32; break; case JS_CLASS_UINT32_ARRAY: tsc.getfun = js_TA_get_uint32; - tsc.cmpfun = js_TA_cmp_uint32; - tsc.swapfun = js_TA_swap_uint32; + cmpfun = js_TA_cmp_uint32; break; #ifdef CONFIG_BIGNUM case JS_CLASS_BIG_INT64_ARRAY: tsc.getfun = js_TA_get_int64; - tsc.cmpfun = js_TA_cmp_int64; - tsc.swapfun = js_TA_swap_uint64; + cmpfun = js_TA_cmp_int64; break; case JS_CLASS_BIG_UINT64_ARRAY: tsc.getfun = js_TA_get_uint64; - tsc.cmpfun = js_TA_cmp_uint64; - tsc.swapfun = js_TA_swap_uint64; + cmpfun = js_TA_cmp_uint64; break; #endif case JS_CLASS_FLOAT32_ARRAY: tsc.getfun = js_TA_get_float32; - tsc.cmpfun = js_TA_cmp_float32; - tsc.swapfun = js_TA_swap_uint32; + cmpfun = js_TA_cmp_float32; break; case JS_CLASS_FLOAT64_ARRAY: tsc.getfun = js_TA_get_float64; - tsc.cmpfun = js_TA_cmp_float64; - tsc.swapfun = js_TA_swap_uint64; + cmpfun = js_TA_cmp_float64; break; default: abort(); } - array_ptr = array_org = p->u.array.u.ptr; + array_ptr = p->u.array.u.ptr; elt_size = 1 << typed_array_size_log2(p->class_id); - cmpfun = tsc.cmpfun; if (!JS_IsUndefined(tsc.cmp)) { - /* must copy internal array if user defined comparison function to - avoid crash if the array gets reallocated by the compare function */ - array_copy = js_malloc(ctx, len * elt_size); - if (array_copy == NULL) + uint32_t *array_idx; + void *array_tmp; + size_t i, j; + + /* XXX: a stable sort would use less memory */ + array_idx = js_malloc(ctx, len * sizeof(array_idx[0])); + if (!array_idx) + return JS_EXCEPTION; + for(i = 0; i < len; i++) + array_idx[i] = i; + tsc.array_ptr = array_ptr; + tsc.elt_size = elt_size; + rqsort(array_idx, len, sizeof(array_idx[0]), + js_TA_cmp_generic, &tsc); + if (tsc.exception) + goto fail; + array_tmp = js_malloc(ctx, len * elt_size); + if (!array_tmp) { + fail: + js_free(ctx, array_idx); + return JS_EXCEPTION; + } + memcpy(array_tmp, array_ptr, len * elt_size); + switch(elt_size) { + case 1: + for(i = 0; i < len; i++) { + j = array_idx[i]; + ((uint8_t *)array_ptr)[i] = ((uint8_t *)array_tmp)[j]; + } + break; + case 2: + for(i = 0; i < len; i++) { + j = array_idx[i]; + ((uint16_t *)array_ptr)[i] = ((uint16_t *)array_tmp)[j]; + } + break; + case 4: + for(i = 0; i < len; i++) { + j = array_idx[i]; + ((uint32_t *)array_ptr)[i] = ((uint32_t *)array_tmp)[j]; + } + break; + case 8: + for(i = 0; i < len; i++) { + j = array_idx[i]; + ((uint64_t *)array_ptr)[i] = ((uint64_t *)array_tmp)[j]; + } + break; + default: + abort(); + } + js_free(ctx, array_tmp); + js_free(ctx, array_idx); + } else { + rqsort(array_ptr, len, elt_size, cmpfun, &tsc); + if (tsc.exception) return JS_EXCEPTION; - array_ptr = memcpy(array_copy, array_ptr, len * elt_size); - cmpfun = js_TA_cmp_generic; - } - rqsort(array_ptr, len, elt_size, cmpfun, &tsc); - if (tsc.exception) { - js_free(ctx, array_copy); - return JS_EXCEPTION; - } - if (array_ptr == array_copy) { - if (array_org == p->u.array.u.ptr) - memcpy(array_org, array_copy, len * elt_size); - js_free(ctx, array_copy); } } return JS_DupValue(ctx, this_val); diff --git a/quickjs/quickjs.h b/quickjs/quickjs.h index 5936032725..206516b04a 100644 --- a/quickjs/quickjs.h +++ b/quickjs/quickjs.h @@ -28,6 +28,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + #if defined(__GNUC__) || defined(__clang__) #define js_likely(x) __builtin_expect(!!(x), 1) #define js_unlikely(x) __builtin_expect(!!(x), 0) @@ -201,13 +205,8 @@ typedef struct JSValue { #define JS_VALUE_GET_FLOAT64(v) ((v).u.float64) #define JS_VALUE_GET_PTR(v) ((v).u.ptr) -#ifdef __cplusplus -#define JS_MKVAL(tag, val) JSValue{ JSValueUnion{.int32 = val}, tag } -#define JS_MKPTR(tag, p) JSValue{ JSValueUnion{.ptr = p}, tag } -#else -#define JS_MKVAL(tag, val) (JSValue){ .u.int32 = val, tag } -#define JS_MKPTR(tag, p) (JSValue){ .u.ptr = p, tag } -#endif +#define JS_MKVAL(tag, val) (JSValue){ (JSValueUnion){ .int32 = val }, tag } +#define JS_MKPTR(tag, p) (JSValue){ (JSValueUnion){ .ptr = p }, tag } #define JS_TAG_IS_FLOAT64(tag) ((unsigned)(tag) == JS_TAG_FLOAT64) @@ -280,7 +279,10 @@ static inline JSValue __JS_NewFloat64(JSContext *ctx, double d) #define JS_EVAL_FLAG_STRICT (1 << 3) /* force 'strict' mode */ #define JS_EVAL_FLAG_STRIP (1 << 4) /* force 'strip' mode */ -#define JS_EVAL_FLAG_COMPILE_ONLY (1 << 5) /* internal use */ +/* compile but do not run. The result is an object with a + JS_TAG_FUNCTION_BYTECODE or JS_TAG_MODULE tag. It can be executed + with JS_EvalFunction(). */ +#define JS_EVAL_FLAG_COMPILE_ONLY (1 << 5) typedef JSValue JSCFunction(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv); typedef JSValue JSCFunctionMagic(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic); @@ -692,11 +694,10 @@ JSValue JS_CallConstructor(JSContext *ctx, JSValueConst func_obj, JSValue JS_CallConstructor2(JSContext *ctx, JSValueConst func_obj, JSValueConst new_target, int argc, JSValueConst *argv); +JS_BOOL JS_DetectModule(const char *input, size_t input_len); JSValue JS_Eval(JSContext *ctx, const char *input, size_t input_len, const char *filename, int eval_flags); -#define JS_EVAL_BINARY_LOAD_ONLY (1 << 0) /* only load the module */ -JSValue JS_EvalBinary(JSContext *ctx, - const uint8_t *buf, size_t buf_len, int flags); +JSValue JS_EvalFunction(JSContext *ctx, JSValue fun_obj); JSValue JS_GetGlobalObject(JSContext *ctx); int JS_IsInstanceOf(JSContext *ctx, JSValueConst val, JSValueConst obj); int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj, @@ -746,6 +747,9 @@ typedef JSModuleDef *JSModuleLoaderFunc(JSContext *ctx, void JS_SetModuleLoaderFunc(JSRuntime *rt, JSModuleNormalizeFunc *module_normalize, JSModuleLoaderFunc *module_loader, void *opaque); +/* return the import.meta object of a module */ +JSValue JS_GetImportMeta(JSContext *ctx, JSModuleDef *m); +JSAtom JS_GetModuleName(JSContext *ctx, JSModuleDef *m); /* JS Job support */ @@ -764,7 +768,9 @@ uint8_t *JS_WriteObject(JSContext *ctx, size_t *psize, JSValueConst obj, #define JS_READ_OBJ_ROM_DATA (1 << 1) /* avoid duplicating 'buf' data */ JSValue JS_ReadObject(JSContext *ctx, const uint8_t *buf, size_t buf_len, int flags); -JSValue JS_EvalFunction(JSContext *ctx, JSValue fun_obj, JSValueConst this_obj); +/* load the dependencies of the module 'obj'. Useful when JS_ReadObject() + returns a module. */ +int JS_ResolveModule(JSContext *ctx, JSValueConst obj); /* C function definition */ typedef enum JSCFunctionEnum { /* XXX: should rename for namespace isolation */ @@ -900,4 +906,8 @@ int JS_SetModuleExportList(JSContext *ctx, JSModuleDef *m, #undef js_unlikely #undef js_force_inline +#ifdef __cplusplus +} /* extern "C" { */ +#endif + #endif /* QUICKJS_H */ From d9538a75b47310961469b276cca74474ffd9ad53 Mon Sep 17 00:00:00 2001 From: ftk Date: Thu, 12 Sep 2019 09:24:37 +0000 Subject: [PATCH 024/185] globalThis --- main.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/main.cpp b/main.cpp index 186d65ed4f..13e163cf36 100644 --- a/main.cpp +++ b/main.cpp @@ -110,9 +110,9 @@ int main(int argc, char ** argv) const char * str = "import * as std from 'std';\n" "import * as os from 'os';\n" "import * as test from 'test';\n" - "std.global.std = std;\n" - "std.global.test = test;\n" - "std.global.os = os;\n"; + "globalThis.std = std;\n" + "globalThis.test = test;\n" + "globalThis.os = os;\n"; context.eval(str, "", JS_EVAL_TYPE_MODULE); const char * filename = argv[1]; From 5c026b98e93a5e9c0098f63797bd82b545182840 Mon Sep 17 00:00:00 2001 From: ftk Date: Thu, 19 Sep 2019 06:24:48 +0000 Subject: [PATCH 025/185] updated quickjs to 2019-09-18 --- quickjs/VERSION | 2 +- quickjs/cplusplus.patch | 54 ------ quickjs/cutils.h | 1 + quickjs/libbf.c | 5 +- quickjs/libregexp.c | 2 +- quickjs/libunicode.c | 2 +- quickjs/quickjs-libc.c | 351 +++++++++++++++++++++++++++++++++++++-- quickjs/quickjs-opcode.h | 4 +- quickjs/quickjs.c | 286 ++++++++++++++++++++----------- quickjs/quickjs.h | 1 + 10 files changed, 531 insertions(+), 177 deletions(-) delete mode 100644 quickjs/cplusplus.patch diff --git a/quickjs/VERSION b/quickjs/VERSION index bbe29cb5e2..80c17d9faf 100644 --- a/quickjs/VERSION +++ b/quickjs/VERSION @@ -1 +1 @@ -2019-09-01 +2019-09-18 diff --git a/quickjs/cplusplus.patch b/quickjs/cplusplus.patch deleted file mode 100644 index 159dd92f88..0000000000 --- a/quickjs/cplusplus.patch +++ /dev/null @@ -1,54 +0,0 @@ -diff --git a/quickjs/quickjs.h b/quickjs/quickjs.h -index 60cd0e7..4cb62b5 100644 ---- a/quickjs/quickjs.h -+++ b/quickjs/quickjs.h -@@ -201,8 +201,13 @@ typedef struct JSValue { - #define JS_VALUE_GET_FLOAT64(v) ((v).u.float64) - #define JS_VALUE_GET_PTR(v) ((v).u.ptr) - -+#ifdef __cplusplus -+#define JS_MKVAL(tag, val) JSValue{ JSValueUnion{.int32 = val}, tag } -+#define JS_MKPTR(tag, p) JSValue{ JSValueUnion{.ptr = p}, tag } -+#else - #define JS_MKVAL(tag, val) (JSValue){ .u.int32 = val, tag } - #define JS_MKPTR(tag, p) (JSValue){ .u.ptr = p, tag } -+#endif - - #define JS_TAG_IS_FLOAT64(tag) ((unsigned)(tag) == JS_TAG_FLOAT64) - -@@ -555,7 +560,7 @@ void __JS_FreeValue(JSContext *ctx, JSValue v); - static inline void JS_FreeValue(JSContext *ctx, JSValue v) - { - if (JS_VALUE_HAS_REF_COUNT(v)) { -- JSRefCountHeader *p = JS_VALUE_GET_PTR(v); -+ JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v); - if (--p->ref_count <= 0) { - __JS_FreeValue(ctx, v); - } -@@ -565,7 +570,7 @@ void __JS_FreeValueRT(JSRuntime *rt, JSValue v); - static inline void JS_FreeValueRT(JSRuntime *rt, JSValue v) - { - if (JS_VALUE_HAS_REF_COUNT(v)) { -- JSRefCountHeader *p = JS_VALUE_GET_PTR(v); -+ JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v); - if (--p->ref_count <= 0) { - __JS_FreeValueRT(rt, v); - } -@@ -575,7 +580,7 @@ static inline void JS_FreeValueRT(JSRuntime *rt, JSValue v) - static inline JSValue JS_DupValue(JSContext *ctx, JSValueConst v) - { - if (JS_VALUE_HAS_REF_COUNT(v)) { -- JSRefCountHeader *p = JS_VALUE_GET_PTR(v); -+ JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v); - p->ref_count++; - } - return (JSValue)v; -@@ -584,7 +589,7 @@ static inline JSValue JS_DupValue(JSContext *ctx, JSValueConst v) - static inline JSValue JS_DupValueRT(JSRuntime *rt, JSValueConst v) - { - if (JS_VALUE_HAS_REF_COUNT(v)) { -- JSRefCountHeader *p = JS_VALUE_GET_PTR(v); -+ JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v); - p->ref_count++; - } - return (JSValue)v; diff --git a/quickjs/cutils.h b/quickjs/cutils.h index fdbf44a881..26c68ee617 100644 --- a/quickjs/cutils.h +++ b/quickjs/cutils.h @@ -35,6 +35,7 @@ #define unlikely(x) __builtin_expect(!!(x), 0) #define force_inline inline __attribute__((always_inline)) #define no_inline __attribute__((noinline)) +#define __maybe_unused __attribute__((unused)) #define xglue(x, y) x ## y #define glue(x, y) xglue(x, y) diff --git a/quickjs/libbf.c b/quickjs/libbf.c index cbabf9525d..17418097fa 100644 --- a/quickjs/libbf.c +++ b/quickjs/libbf.c @@ -41,7 +41,6 @@ #define USE_FFT_MUL //#define inline __attribute__((always_inline)) -#define unused __attribute__((unused)) #ifdef __AVX2__ #define FFT_MUL_THRESHOLD 100 /* in limbs of the smallest factor */ @@ -613,7 +612,7 @@ int bf_round(bf_t *r, limb_t prec, bf_flags_t flags) } /* for debugging */ -static unused void dump_limbs(const char *str, const limb_t *tab, limb_t n) +static __maybe_unused void dump_limbs(const char *str, const limb_t *tab, limb_t n) { limb_t i; printf("%s: len=%" PRId_LIMB "\n", str, n); @@ -1570,7 +1569,7 @@ int bf_remquo(slimb_t *pq, bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, return ret; } -static unused inline limb_t mul_mod(limb_t a, limb_t b, limb_t m) +static __maybe_unused inline limb_t mul_mod(limb_t a, limb_t b, limb_t m) { dlimb_t t; t = (dlimb_t)a * (dlimb_t)b; diff --git a/quickjs/libregexp.c b/quickjs/libregexp.c index ad1e6bf065..4425ce55b8 100644 --- a/quickjs/libregexp.c +++ b/quickjs/libregexp.c @@ -269,7 +269,7 @@ static int cr_canonicalize(CharRange *cr) } #ifdef DUMP_REOP -static __attribute__((unused)) void lre_dump_bytecode(const uint8_t *buf, +static __maybe_unused void lre_dump_bytecode(const uint8_t *buf, int buf_len) { int pos, len, opcode, bc_len, re_flags, i; diff --git a/quickjs/libunicode.c b/quickjs/libunicode.c index 6fe6945d5a..96ff002072 100644 --- a/quickjs/libunicode.c +++ b/quickjs/libunicode.c @@ -271,7 +271,7 @@ BOOL lre_is_case_ignorable(uint32_t c) /* character range */ -static __attribute__((unused)) void cr_dump(CharRange *cr) +static __maybe_unused void cr_dump(CharRange *cr) { int i; for(i = 0; i < cr->len; i++) diff --git a/quickjs/quickjs-libc.c b/quickjs/quickjs-libc.c index 37da67b97b..eba52cfd10 100644 --- a/quickjs/quickjs-libc.c +++ b/quickjs/quickjs-libc.c @@ -44,6 +44,7 @@ #include #include #include +#include #if defined(__APPLE__) typedef sig_t sighandler_t; #endif @@ -59,7 +60,7 @@ static void js_std_dbuf_init(JSContext *ctx, DynBuf *s) } /* TODO: - - add exec() wrapper + - add worker - add minimal VT100 emulation for win32 - add socket calls */ @@ -434,7 +435,7 @@ int js_module_set_import_meta(JSContext *ctx, JSValueConst func_val, JS_BOOL use_realpath, JS_BOOL is_main) { JSModuleDef *m; - char buf[PATH_MAX + 16], *res; + char buf[PATH_MAX + 16]; JSValue meta_obj; JSAtom module_name_atom; const char *module_name; @@ -449,17 +450,20 @@ int js_module_set_import_meta(JSContext *ctx, JSValueConst func_val, return -1; if (!strchr(module_name, ':')) { strcpy(buf, "file://"); +#if !defined(_WIN32) /* realpath() cannot be used with modules compiled with qjsc because the corresponding module source code is not necessarily present */ if (use_realpath) { - res = realpath(module_name, buf + strlen(buf)); + char *res = realpath(module_name, buf + strlen(buf)); if (!res) { JS_ThrowTypeError(ctx, "realpath failure"); JS_FreeCString(ctx, module_name); return -1; } - } else { + } else +#endif + { pstrcat(buf, sizeof(buf), module_name); } } else { @@ -720,6 +724,33 @@ static JSValue js_std_popen(JSContext *ctx, JSValueConst this_val, return JS_EXCEPTION; } +static JSValue js_std_fdopen(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + const char *mode; + FILE *f; + int fd; + + if (JS_ToInt32(ctx, &fd, argv[0])) + return JS_EXCEPTION; + mode = JS_ToCString(ctx, argv[1]); + if (!mode) + goto fail; + if (mode[strspn(mode, "rwa+")] != '\0') { + js_std_throw_errno(ctx, EINVAL); + goto fail; + } + + f = fdopen(fd, mode); + JS_FreeCString(ctx, mode); + if (!f) + return js_std_throw_errno(ctx, errno); + return js_new_std_file(ctx, f, TRUE, FALSE); + fail: + JS_FreeCString(ctx, mode); + return JS_EXCEPTION; +} + static JSValue js_std_tmpfile(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { @@ -1036,6 +1067,21 @@ static int http_get_status(const char *buf) return atoi(p); } +static int get_bool_option(JSContext *ctx, BOOL *pbool, + JSValueConst obj, + const char *option) +{ + JSValue val; + val = JS_GetPropertyStr(ctx, obj, option); + if (JS_IsException(val)) + return -1; + if (!JS_IsUndefined(val)) { + *pbool = JS_ToBool(ctx, val); + } + JS_FreeValue(ctx, val); + return 0; +} + static JSValue js_std_urlGet(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { @@ -1046,7 +1092,7 @@ static JSValue js_std_urlGet(JSContext *ctx, JSValueConst this_val, char *buf; size_t i, len; int c, status; - JSValue val, response = JS_UNDEFINED, ret_obj; + JSValue response = JS_UNDEFINED, ret_obj; JSValueConst options_obj; FILE *f; BOOL binary_flag, full_flag; @@ -1061,23 +1107,16 @@ static JSValue js_std_urlGet(JSContext *ctx, JSValueConst this_val, if (argc >= 2) { options_obj = argv[1]; - val = JS_GetPropertyStr(ctx, options_obj, "binary"); - if (JS_IsException(val)) - goto fail_opt; - binary_flag = JS_ToBool(ctx, val); - JS_FreeValue(ctx, val); + if (get_bool_option(ctx, &binary_flag, options_obj, "binary")) + goto fail_obj; - val = JS_GetPropertyStr(ctx, options_obj, "full"); - if (JS_IsException(val)) { - fail_opt: + if (get_bool_option(ctx, &full_flag, options_obj, "full")) { + fail_obj: JS_FreeCString(ctx, url); return JS_EXCEPTION; } - full_flag = JS_ToBool(ctx, val); - JS_FreeValue(ctx, val); } - js_std_dbuf_init(ctx, &cmd_buf); dbuf_printf(&cmd_buf, "%s ''", URL_GET_PROGRAM); len = strlen(url); @@ -1203,6 +1242,7 @@ static const JSCFunctionListEntry js_std_funcs[] = { /* FILE I/O */ JS_CFUNC_DEF("open", 2, js_std_open ), JS_CFUNC_DEF("popen", 2, js_std_popen ), + JS_CFUNC_DEF("fdopen", 2, js_std_fdopen ), JS_CFUNC_DEF("tmpfile", 0, js_std_tmpfile ), JS_CFUNC_MAGIC_DEF("puts", 1, js_std_file_puts, 0 ), JS_CFUNC_DEF("printf", 1, js_std_printf ), @@ -1971,6 +2011,8 @@ static JSValue js_os_getcwd(JSContext *ctx, JSValueConst this_val, return make_string_error(ctx, buf, err); } +#if !defined(_WIN32) + /* return [path, errorcode] */ static JSValue js_os_realpath(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) @@ -2210,6 +2252,260 @@ static JSValue js_os_utimes(JSContext *ctx, JSValueConst this_val, return js_os_return(ctx, ret); } +/* exec(args[, options]) -> exitcode */ +static JSValue js_os_exec(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + JSValueConst options, args = argv[0]; + JSValue val, ret_val; + const char **exec_argv, *file = NULL, *str, *cwd = NULL; + uint32_t exec_argc, i; + int ret, pid, status; + BOOL block_flag = TRUE, use_path = TRUE; + static const char *std_name[3] = { "stdin", "stdout", "stderr" }; + int std_fds[3]; + + val = JS_GetPropertyStr(ctx, args, "length"); + if (JS_IsException(val)) + return JS_EXCEPTION; + ret = JS_ToUint32(ctx, &exec_argc, val); + JS_FreeValue(ctx, val); + if (ret) + return JS_EXCEPTION; + /* arbitrary limit to avoid overflow */ + if (exec_argc < 1 || exec_argc > 65535) { + return JS_ThrowTypeError(ctx, "invalid number of arguments"); + } + exec_argv = js_mallocz(ctx, sizeof(exec_argv[0]) * (exec_argc + 1)); + if (!exec_argv) + return JS_EXCEPTION; + for(i = 0; i < exec_argc; i++) { + val = JS_GetPropertyUint32(ctx, args, i); + if (JS_IsException(val)) + goto exception; + str = JS_ToCString(ctx, val); + JS_FreeValue(ctx, val); + if (!str) + goto exception; + exec_argv[i] = str; + } + exec_argv[exec_argc] = NULL; + + for(i = 0; i < 3; i++) + std_fds[i] = i; + + /* get the options, if any */ + if (argc >= 2) { + options = argv[1]; + + if (get_bool_option(ctx, &block_flag, options, "block")) + goto exception; + if (get_bool_option(ctx, &use_path, options, "usePath")) + goto exception; + + val = JS_GetPropertyStr(ctx, options, "file"); + if (JS_IsException(val)) + goto exception; + if (!JS_IsUndefined(val)) { + file = JS_ToCString(ctx, val); + JS_FreeValue(ctx, val); + if (!file) + goto exception; + } + + val = JS_GetPropertyStr(ctx, options, "cwd"); + if (JS_IsException(val)) + goto exception; + if (!JS_IsUndefined(val)) { + cwd = JS_ToCString(ctx, val); + JS_FreeValue(ctx, val); + if (!cwd) + goto exception; + } + + /* stdin/stdout/stderr handles */ + for(i = 0; i < 3; i++) { + val = JS_GetPropertyStr(ctx, options, std_name[i]); + if (JS_IsException(val)) + goto exception; + if (!JS_IsUndefined(val)) { + int fd; + ret = JS_ToInt32(ctx, &fd, val); + JS_FreeValue(ctx, val); + if (ret) + goto exception; + std_fds[i] = fd; + } + } + } + + pid = fork(); + if (pid < 0) { + JS_ThrowTypeError(ctx, "fork error"); + goto exception; + } + if (pid == 0) { + /* child */ + int fd_max = sysconf(_SC_OPEN_MAX); + + /* remap the stdin/stdout/stderr handles if necessary */ + for(i = 0; i < 3; i++) { + if (std_fds[i] != i) { + if (dup2(std_fds[i], i) < 0) + _exit(127); + } + } + + for(i = 3; i < fd_max; i++) + close(i); + if (cwd) { + if (chdir(cwd) < 0) + _exit(127); + } + if (!file) + file = exec_argv[0]; + if (use_path) + ret = execvp(file, (char **)exec_argv); + else + ret = execv(file, (char **)exec_argv); + _exit(127); + } + /* parent */ + if (block_flag) { + for(;;) { + ret = waitpid(pid, &status, 0); + if (ret == pid) { + if (WIFEXITED(status)) { + ret = WEXITSTATUS(status); + break; + } else if (WIFSIGNALED(status)) { + ret = -WTERMSIG(status); + break; + } + } + } + } else { + ret = pid; + } + ret_val = JS_NewInt32(ctx, ret); + done: + JS_FreeCString(ctx, file); + JS_FreeCString(ctx, cwd); + for(i = 0; i < exec_argc; i++) + JS_FreeCString(ctx, exec_argv[i]); + js_free(ctx, exec_argv); + return ret_val; + exception: + ret_val = JS_EXCEPTION; + goto done; +} + +/* waitpid(pid, block) -> [pid, status] */ +static JSValue js_os_waitpid(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + int pid, status, options, ret; + JSValue obj; + + if (JS_ToInt32(ctx, &pid, argv[0])) + return JS_EXCEPTION; + if (JS_ToInt32(ctx, &options, argv[1])) + return JS_EXCEPTION; + + ret = waitpid(pid, &status, options); + if (ret < 0) { + ret = -errno; + status = 0; + } + + obj = JS_NewArray(ctx); + if (JS_IsException(obj)) + return obj; + JS_DefinePropertyValueUint32(ctx, obj, 0, JS_NewInt32(ctx, ret), + JS_PROP_C_W_E); + JS_DefinePropertyValueUint32(ctx, obj, 1, JS_NewInt32(ctx, status), + JS_PROP_C_W_E); + return obj; +} + +/* pipe() -> [read_fd, write_fd] or null if error */ +static JSValue js_os_pipe(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + int pipe_fds[2], ret; + JSValue obj; + + ret = pipe(pipe_fds); + if (ret < 0) + return JS_NULL; + obj = JS_NewArray(ctx); + if (JS_IsException(obj)) + return obj; + JS_DefinePropertyValueUint32(ctx, obj, 0, JS_NewInt32(ctx, pipe_fds[0]), + JS_PROP_C_W_E); + JS_DefinePropertyValueUint32(ctx, obj, 1, JS_NewInt32(ctx, pipe_fds[1]), + JS_PROP_C_W_E); + return obj; +} + +/* kill(pid, sig) */ +static JSValue js_os_kill(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + int pid, sig, ret; + + if (JS_ToInt32(ctx, &pid, argv[0])) + return JS_EXCEPTION; + if (JS_ToInt32(ctx, &sig, argv[1])) + return JS_EXCEPTION; + ret = kill(pid, sig); + return js_os_return(ctx, ret); +} + +/* sleep(delay_ms) */ +static JSValue js_os_sleep(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + int64_t delay; + struct timespec ts; + int ret; + + if (JS_ToInt64(ctx, &delay, argv[0])) + return JS_EXCEPTION; + ts.tv_sec = delay / 1000; + ts.tv_nsec = (delay % 1000) * 1000000; + ret = nanosleep(&ts, NULL); + return js_os_return(ctx, ret); +} + +/* dup(fd) */ +static JSValue js_os_dup(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + int fd, ret; + + if (JS_ToInt32(ctx, &fd, argv[0])) + return JS_EXCEPTION; + ret = dup(fd); + return js_os_return(ctx, ret); +} + +/* dup2(fd) */ +static JSValue js_os_dup2(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + int fd, fd2, ret; + + if (JS_ToInt32(ctx, &fd, argv[0])) + return JS_EXCEPTION; + if (JS_ToInt32(ctx, &fd2, argv[1])) + return JS_EXCEPTION; + ret = dup2(fd, fd2); + return js_os_return(ctx, ret); +} + +#endif /* !_WIN32 */ + #if defined(_WIN32) #define OS_PLATFORM "win32" #elif defined(__APPLE__) @@ -2253,10 +2549,24 @@ static const JSCFunctionListEntry js_os_funcs[] = { OS_FLAG(SIGILL), OS_FLAG(SIGSEGV), OS_FLAG(SIGTERM), +#if !defined(_WIN32) + OS_FLAG(SIGQUIT), + OS_FLAG(SIGPIPE), + OS_FLAG(SIGALRM), + OS_FLAG(SIGUSR1), + OS_FLAG(SIGUSR2), + OS_FLAG(SIGCHLD), + OS_FLAG(SIGCONT), + OS_FLAG(SIGSTOP), + OS_FLAG(SIGTSTP), + OS_FLAG(SIGTTIN), + OS_FLAG(SIGTTOU), +#endif JS_CFUNC_DEF("setTimeout", 2, js_os_setTimeout ), JS_CFUNC_DEF("clearTimeout", 1, js_os_clearTimeout ), JS_PROP_STRING_DEF("platform", OS_PLATFORM, 0 ), JS_CFUNC_DEF("getcwd", 0, js_os_getcwd ), +#if !defined(_WIN32) JS_CFUNC_DEF("realpath", 1, js_os_realpath ), JS_CFUNC_DEF("mkdir", 1, js_os_mkdir ), JS_CFUNC_MAGIC_DEF("stat", 1, js_os_stat, 0 ), @@ -2276,6 +2586,15 @@ static const JSCFunctionListEntry js_os_funcs[] = { JS_CFUNC_DEF("readlink", 1, js_os_readlink ), JS_CFUNC_DEF("readdir", 1, js_os_readdir ), JS_CFUNC_DEF("utimes", 3, js_os_utimes ), + JS_CFUNC_DEF("exec", 1, js_os_exec ), + JS_CFUNC_DEF("waitpid", 2, js_os_waitpid ), + OS_FLAG(WNOHANG), + JS_CFUNC_DEF("pipe", 0, js_os_pipe ), + JS_CFUNC_DEF("kill", 2, js_os_kill ), + JS_CFUNC_DEF("sleep", 1, js_os_sleep ), + JS_CFUNC_DEF("dup", 1, js_os_dup ), + JS_CFUNC_DEF("dup2", 2, js_os_dup2 ), +#endif }; static int js_os_init(JSContext *ctx, JSModuleDef *m) diff --git a/quickjs/quickjs-opcode.h b/quickjs/quickjs-opcode.h index 0981453666..910bb75c05 100644 --- a/quickjs/quickjs-opcode.h +++ b/quickjs/quickjs-opcode.h @@ -39,6 +39,7 @@ FMT(i16) FMT(label16) FMT(npop) FMT(npopx) +FMT(npop_u16) FMT(loc) FMT(arg) FMT(var_ref) @@ -114,7 +115,8 @@ DEF( add_brand, 1, 2, 0, none) /* this_obj home_obj -> */ DEF( return_async, 1, 1, 0, none) DEF( throw, 1, 1, 0, none) DEF( throw_var, 6, 0, 0, atom_u8) -DEF( eval, 3, 1, 1, u16) +DEF( eval, 5, 1, 1, npop_u16) /* func args... -> ret_val */ +DEF( apply_eval, 3, 2, 1, u16) /* func array -> ret_eval */ DEF( regexp, 1, 2, 1, none) /* create a RegExp object from the pattern and a bytecode string */ DEF( get_super_ctor, 1, 1, 1, none) diff --git a/quickjs/quickjs.c b/quickjs/quickjs.c index d5c1c8342d..5d833b0432 100644 --- a/quickjs/quickjs.c +++ b/quickjs/quickjs.c @@ -343,6 +343,7 @@ struct JSContext { JSValue async_iterator_proto; JSValue array_proto_values; JSValue throw_type_error; + JSValue eval_obj; JSValue global_obj; /* global object */ JSValue global_var_obj; /* contains the global let/const definitions */ @@ -854,18 +855,18 @@ static __exception int JS_ToArrayLengthFree(JSContext *ctx, uint32_t *plen, static JSValue JS_EvalObject(JSContext *ctx, JSValueConst this_obj, JSValueConst val, int flags, int scope_idx); JSValue __attribute__((format(printf, 2, 3))) JS_ThrowInternalError(JSContext *ctx, const char *fmt, ...); -static __attribute__((unused)) void JS_DumpAtoms(JSRuntime *rt); -static __attribute__((unused)) void JS_DumpString(JSRuntime *rt, +static __maybe_unused void JS_DumpAtoms(JSRuntime *rt); +static __maybe_unused void JS_DumpString(JSRuntime *rt, const JSString *p); -static __attribute__((unused)) void JS_DumpObjectHeader(JSRuntime *rt); -static __attribute__((unused)) void JS_DumpObject(JSRuntime *rt, JSObject *p); -static __attribute__((unused)) void JS_DumpValueShort(JSRuntime *rt, +static __maybe_unused void JS_DumpObjectHeader(JSRuntime *rt); +static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p); +static __maybe_unused void JS_DumpValueShort(JSRuntime *rt, JSValueConst val); -static __attribute__((unused)) void JS_DumpValue(JSContext *ctx, JSValueConst val); -static __attribute__((unused)) void JS_PrintValue(JSContext *ctx, +static __maybe_unused void JS_DumpValue(JSContext *ctx, JSValueConst val); +static __maybe_unused void JS_PrintValue(JSContext *ctx, const char *str, JSValueConst val); -static __attribute__((unused)) void JS_DumpShapes(JSRuntime *rt); +static __maybe_unused void JS_DumpShapes(JSRuntime *rt); static JSValue js_function_apply(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic); static void js_array_finalizer(JSRuntime *rt, JSValue val); @@ -1023,6 +1024,9 @@ static __exception int js_get_length32(JSContext *ctx, uint32_t *pres, JSValueConst obj); static __exception int js_get_length64(JSContext *ctx, int64_t *pres, JSValueConst obj); +static void free_arg_list(JSContext *ctx, JSValue *tab, uint32_t len); +static JSValue *build_arg_list(JSContext *ctx, uint32_t *plen, + JSValueConst array_arg); static BOOL js_get_fast_array(JSContext *ctx, JSValueConst obj, JSValue **arrpp, uint32_t *countp); static JSValue JS_CreateAsyncFromSyncIterator(JSContext *ctx, @@ -1033,7 +1037,6 @@ static void js_c_function_data_mark(JSRuntime *rt, JSValueConst val, static JSValue js_c_function_data_call(JSContext *ctx, JSValueConst func_obj, JSValueConst this_val, int argc, JSValueConst *argv); -static JSAtom js_value_to_atom(JSContext *ctx, JSValueConst val); static JSAtom js_symbol_to_atom(JSContext *ctx, JSValue val); static const JSClassExoticMethods js_arguments_exotic_methods; @@ -1945,6 +1948,7 @@ void JS_FreeContext(JSContext *ctx) JS_FreeValue(ctx, ctx->global_var_obj); JS_FreeValue(ctx, ctx->throw_type_error); + JS_FreeValue(ctx, ctx->eval_obj); JS_FreeValue(ctx, ctx->array_proto_values); for(i = 0; i < JS_NATIVE_ERROR_COUNT; i++) { @@ -2133,7 +2137,7 @@ static uint32_t hash_string(const JSString *str, uint32_t h) return h; } -static __attribute__((unused)) void JS_DumpString(JSRuntime *rt, +static __maybe_unused void JS_DumpString(JSRuntime *rt, const JSString *p) { int i, c, sep; @@ -2165,7 +2169,7 @@ static __attribute__((unused)) void JS_DumpString(JSRuntime *rt, putchar(sep); } -static __attribute__((unused)) void JS_DumpAtoms(JSRuntime *rt) +static __maybe_unused void JS_DumpAtoms(JSRuntime *rt) { JSAtomStruct *p; int h, i; @@ -2918,7 +2922,7 @@ static BOOL JS_AtomSymbolHasDescription(JSContext *ctx, JSAtom v) !(p->len == 0 && p->is_wide_char != 0)); } -static __attribute__((unused)) void print_atom(JSContext *ctx, JSAtom atom) +static __maybe_unused void print_atom(JSContext *ctx, JSAtom atom) { char buf[ATOM_GET_STR_BUF_SIZE]; const char *p; @@ -4234,7 +4238,7 @@ static JSShape *find_hashed_shape_prop(JSRuntime *rt, JSShape *sh, return NULL; } -static __attribute__((unused)) void JS_DumpShape(JSRuntime *rt, int i, JSShape *sh) +static __maybe_unused void JS_DumpShape(JSRuntime *rt, int i, JSShape *sh) { char atom_buf[ATOM_GET_STR_BUF_SIZE]; int j; @@ -4250,7 +4254,7 @@ static __attribute__((unused)) void JS_DumpShape(JSRuntime *rt, int i, JSShape * printf("\n"); } -static __attribute__((unused)) void JS_DumpShapes(JSRuntime *rt) +static __maybe_unused void JS_DumpShapes(JSRuntime *rt) { int i; JSShape *sh; @@ -5163,6 +5167,7 @@ static void mark_context(JSRuntime *rt, JSContext *ctx) JS_MarkValue(rt, ctx->native_error_proto[i]); JS_MarkValue(rt, ctx->throw_type_error); + JS_MarkValue(rt, ctx->eval_obj); JS_MarkValue(rt, ctx->global_obj); JS_MarkValue(rt, ctx->global_var_obj); } @@ -7214,7 +7219,7 @@ static JSAtom js_symbol_to_atom(JSContext *ctx, JSValue val) } /* return JS_ATOM_NULL in case of exception */ -static JSAtom js_value_to_atom(JSContext *ctx, JSValueConst val) +JSAtom JS_ValueToAtom(JSContext *ctx, JSValueConst val) { JSAtom atom; uint32_t tag; @@ -7288,7 +7293,7 @@ static JSValue JS_GetPropertyValue(JSContext *ctx, JSValueConst this_obj, } } else { slow_path: - atom = js_value_to_atom(ctx, prop); + atom = JS_ValueToAtom(ctx, prop); JS_FreeValue(ctx, prop); if (unlikely(atom == JS_ATOM_NULL)) return JS_EXCEPTION; @@ -8121,7 +8126,7 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj, JSAtom atom; int ret; slow_path: - atom = js_value_to_atom(ctx, prop); + atom = JS_ValueToAtom(ctx, prop); JS_FreeValue(ctx, prop); if (unlikely(atom == JS_ATOM_NULL)) { JS_FreeValue(ctx, val); @@ -8680,7 +8685,7 @@ int JS_DefinePropertyValueValue(JSContext *ctx, JSValueConst this_obj, { JSAtom atom; int ret; - atom = js_value_to_atom(ctx, prop); + atom = JS_ValueToAtom(ctx, prop); JS_FreeValue(ctx, prop); if (unlikely(atom == JS_ATOM_NULL)) { JS_FreeValue(ctx, val); @@ -8778,7 +8783,7 @@ static int JS_DefineObjectNameComputed(JSContext *ctx, JSValueConst obj, !js_object_has_name(ctx, obj)) { JSAtom prop; JSValue name_str; - prop = js_value_to_atom(ctx, str); + prop = JS_ValueToAtom(ctx, str); if (prop == JS_ATOM_NULL) return -1; name_str = js_get_function_name(ctx, prop); @@ -9020,12 +9025,18 @@ static int JS_SetGlobalVar(JSContext *ctx, JSAtom prop, JSValue val, flags can be 0, JS_PROP_THROW or JS_PROP_THROW_STRICT */ int JS_DeleteProperty(JSContext *ctx, JSValueConst obj, JSAtom prop, int flags) { - if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) { - JSObject *p = JS_VALUE_GET_OBJ(obj); - int res = delete_property(ctx, p, prop); - if (res != FALSE) - return res; - } + JSValue obj1; + JSObject *p; + int res; + + obj1 = JS_ToObject(ctx, obj); + if (JS_IsException(obj1)) + return -1; + p = JS_VALUE_GET_OBJ(obj1); + res = delete_property(ctx, p, prop); + JS_FreeValue(ctx, obj1); + if (res != FALSE) + return res; if ((flags & JS_PROP_THROW) || ((flags & JS_PROP_THROW_STRICT) && is_strict_mode(ctx))) { JS_ThrowTypeError(ctx, "could not delete property"); @@ -9752,7 +9763,7 @@ static JSValue JS_ToNumber(JSContext *ctx, JSValueConst val) return JS_ToNumberFree(ctx, JS_DupValue(ctx, val)); } -static __attribute__((unused)) JSValue JS_ToIntegerFree(JSContext *ctx, JSValue val) +static __maybe_unused JSValue JS_ToIntegerFree(JSContext *ctx, JSValue val) { uint32_t tag; JSValue ret; @@ -10821,14 +10832,14 @@ static JSValue JS_ToQuotedString(JSContext *ctx, JSValueConst val1) return JS_EXCEPTION; } -static __attribute__((unused)) void JS_DumpObjectHeader(JSRuntime *rt) +static __maybe_unused void JS_DumpObjectHeader(JSRuntime *rt) { printf("%14s %4s %4s %14s %10s %s\n", "ADDRESS", "REFS", "SHRF", "PROTO", "CLASS", "PROPS"); } /* for debug only: dump an object without side effect */ -static __attribute__((unused)) void JS_DumpObject(JSRuntime *rt, JSObject *p) +static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p) { uint32_t i; char atom_buf[ATOM_GET_STR_BUF_SIZE]; @@ -10920,7 +10931,7 @@ static __attribute__((unused)) void JS_DumpObject(JSRuntime *rt, JSObject *p) printf("\n"); } -static __attribute__((unused)) void JS_DumpValueShort(JSRuntime *rt, +static __maybe_unused void JS_DumpValueShort(JSRuntime *rt, JSValueConst val) { uint32_t tag = JS_VALUE_GET_NORM_TAG(val); @@ -11018,13 +11029,13 @@ static __attribute__((unused)) void JS_DumpValueShort(JSRuntime *rt, } } -static __attribute__((unused)) void JS_DumpValue(JSContext *ctx, +static __maybe_unused void JS_DumpValue(JSContext *ctx, JSValueConst val) { JS_DumpValueShort(ctx->rt, val); } -static __attribute__((unused)) void JS_PrintValue(JSContext *ctx, +static __maybe_unused void JS_PrintValue(JSContext *ctx, const char *str, JSValueConst val) { @@ -11245,7 +11256,7 @@ static bf_t *JS_ToBigInt(JSContext *ctx, bf_t *buf, JSValueConst val) return JS_ToBigIntFree(ctx, buf, JS_DupValue(ctx, val)); } -static __attribute__((unused)) JSValue JS_ToBigIntValueFree(JSContext *ctx, JSValue val) +static __maybe_unused JSValue JS_ToBigIntValueFree(JSContext *ctx, JSValue val) { if (JS_VALUE_GET_TAG(val) == JS_TAG_BIG_INT) { return val; @@ -13361,7 +13372,7 @@ static __exception int js_operator_in(JSContext *ctx, JSValue *sp) JS_ThrowTypeError(ctx, "invalid 'in' operand"); return -1; } - atom = js_value_to_atom(ctx, op1); + atom = JS_ValueToAtom(ctx, op1); if (unlikely(atom == JS_ATOM_NULL)) return -1; ret = JS_HasProperty(ctx, op2, atom); @@ -13474,7 +13485,7 @@ static __exception int js_operator_delete(JSContext *ctx, JSValue *sp) op1 = sp[-2]; op2 = sp[-1]; - atom = js_value_to_atom(ctx, op2); + atom = JS_ValueToAtom(ctx, op2); if (unlikely(atom == JS_ATOM_NULL)) return -1; ret = JS_DeleteProperty(ctx, op1, atom, JS_PROP_THROW_STRICT); @@ -15366,10 +15377,12 @@ static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj, #define JS_THROW_VAR_RO 0 #define JS_THROW_VAR_REDECL 1 #define JS_THROW_VAR_UNINITIALIZED 2 +#define JS_THROW_VAR_DELETE_SUPER 3 { JSAtom atom; + int type; atom = get_u32(pc); - int type = pc[4]; + type = pc[4]; pc += 5; if (type == JS_THROW_VAR_RO) JS_ThrowTypeErrorReadOnly(ctx, JS_PROP_THROW, atom); @@ -15379,6 +15392,9 @@ static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj, else if (type == JS_THROW_VAR_UNINITIALIZED) JS_ThrowReferenceErrorUninitialized(ctx, atom); + else + if (type == JS_THROW_VAR_DELETE_SUPER) + JS_ThrowReferenceError(ctx, "unsupported reference to 'super'"); else JS_ThrowInternalError(ctx, "invalid throw var type %d", type); } @@ -15386,17 +15402,63 @@ static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj, CASE(OP_eval): { - JSValue obj; + JSValueConst obj; int scope_idx; + call_argc = get_u16(pc); + scope_idx = get_u16(pc + 2) - 1; + pc += 4; + call_argv = sp - call_argc; + sf->cur_pc = pc; + if (js_same_value(ctx, call_argv[-1], ctx->eval_obj)) { + if (call_argc >= 1) + obj = call_argv[0]; + else + obj = JS_UNDEFINED; + ret_val = JS_EvalObject(ctx, JS_UNDEFINED, obj, + JS_EVAL_TYPE_DIRECT, scope_idx); + } else { + ret_val = JS_CallInternal(ctx, call_argv[-1], JS_UNDEFINED, + JS_UNDEFINED, call_argc, call_argv, 0); + } + if (unlikely(JS_IsException(ret_val))) + goto exception; + for(i = -1; i < call_argc; i++) + JS_FreeValue(ctx, call_argv[i]); + sp -= call_argc + 1; + *sp++ = ret_val; + } + BREAK; + /* could merge with OP_apply */ + CASE(OP_apply_eval): + { + int scope_idx; + uint32_t len; + JSValue *tab; + JSValueConst obj; scope_idx = get_u16(pc) - 1; pc += 2; - obj = sp[-1]; - sp[-1] = JS_EvalObject(ctx, JS_UNDEFINED, obj, - JS_EVAL_TYPE_DIRECT, scope_idx); - JS_FreeValue(ctx, obj); - if (unlikely(JS_IsException(sp[-1]))) + tab = build_arg_list(ctx, &len, sp[-1]); + if (!tab) + goto exception; + if (js_same_value(ctx, sp[-2], ctx->eval_obj)) { + if (len >= 1) + obj = tab[0]; + else + obj = JS_UNDEFINED; + ret_val = JS_EvalObject(ctx, JS_UNDEFINED, obj, + JS_EVAL_TYPE_DIRECT, scope_idx); + } else { + ret_val = JS_Call(ctx, sp[-2], JS_UNDEFINED, len, + (JSValueConst *)tab); + } + free_arg_list(ctx, tab, len); + if (unlikely(JS_IsException(ret_val))) goto exception; + JS_FreeValue(ctx, sp[-2]); + JS_FreeValue(ctx, sp[-1]); + sp -= 2; + *sp++ = ret_val; } BREAK; @@ -16266,7 +16328,7 @@ static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj, is_computed = (opcode == OP_define_method_computed); if (is_computed) { - atom = js_value_to_atom(ctx, sp[-2]); + atom = JS_ValueToAtom(ctx, sp[-2]); if (unlikely(atom == JS_ATOM_NULL)) goto exception; opcode += OP_define_method - OP_define_method_computed; @@ -16355,7 +16417,7 @@ static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj, { JSValue val; if (unlikely(JS_IsUndefined(sp[-2]))) { - JSAtom atom = js_value_to_atom(ctx, sp[-1]); + JSAtom atom = JS_ValueToAtom(ctx, sp[-1]); if (atom != JS_ATOM_NULL) { JS_ThrowReferenceErrorNotDefined(ctx, atom); JS_FreeAtom(ctx, atom); @@ -16375,7 +16437,7 @@ static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj, { JSValue val; JSAtom atom; - atom = js_value_to_atom(ctx, sp[-1]); + atom = JS_ValueToAtom(ctx, sp[-1]); if (unlikely(atom == JS_ATOM_NULL)) goto exception; val = JS_GetPropertyInternal(ctx, sp[-2], atom, sp[-3], FALSE); @@ -16407,7 +16469,7 @@ static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj, int ret; if (unlikely(JS_IsUndefined(sp[-3]))) { if (is_strict_mode(ctx)) { - JSAtom atom = js_value_to_atom(ctx, sp[-2]); + JSAtom atom = JS_ValueToAtom(ctx, sp[-2]); if (atom != JS_ATOM_NULL) { JS_ThrowReferenceErrorNotDefined(ctx, atom); JS_FreeAtom(ctx, atom); @@ -16433,7 +16495,7 @@ static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj, JS_ThrowTypeErrorNotAnObject(ctx); goto exception; } - atom = js_value_to_atom(ctx, sp[-2]); + atom = JS_ValueToAtom(ctx, sp[-2]); if (unlikely(atom == JS_ATOM_NULL)) goto exception; ret = JS_SetPropertyGeneric(ctx, JS_VALUE_GET_OBJ(sp[-3]), @@ -20723,7 +20785,7 @@ static int __exception js_parse_property_name(JSParseState *s, } } } else if (s->token.val == TOK_STRING) { - name = js_value_to_atom(s->ctx, s->token.u.str.str); + name = JS_ValueToAtom(s->ctx, s->token.u.str.str); if (name == JS_ATOM_NULL) goto fail; if (next_token(s)) @@ -20738,12 +20800,12 @@ static int __exception js_parse_property_name(JSParseState *s, d = bf_mul_pow10_to_float64(s->ctx, &p->num, s->token.u.num.exponent); val = __JS_NewFloat64(s->ctx, d); - name = js_value_to_atom(s->ctx, val); + name = JS_ValueToAtom(s->ctx, val); JS_FreeValue(s->ctx, val); } else #endif { - name = js_value_to_atom(s->ctx, val); + name = JS_ValueToAtom(s->ctx, val); } if (name == JS_ATOM_NULL) goto fail; @@ -22917,9 +22979,6 @@ static __exception int js_parse_postfix_expr(JSParseState *s, BOOL accept_lparen scope = get_u16(fd->byte_code.buf + fd->last_opcode_pos + 5); if (name == JS_ATOM_eval && call_type == FUNC_CALL_NORMAL) { /* direct 'eval' */ - JS_FreeAtom(s->ctx, name); - fd->byte_code.size = fd->last_opcode_pos; - fd->last_opcode_pos = -1; opcode = OP_eval; } else { /* verify if function name resolves to a simple @@ -23056,10 +23115,7 @@ static __exception int js_parse_postfix_expr(JSParseState *s, BOOL accept_lparen emit_u16(s, call_type == FUNC_CALL_NEW); break; case OP_eval: - /* eval needs a single argument */ - emit_op(s, OP_get_field); - emit_atom(s, __JS_AtomFromUInt32(0)); - emit_op(s, OP_eval); + emit_op(s, OP_apply_eval); emit_u16(s, fd->scope_level); fd->has_eval_call = TRUE; break; @@ -23101,21 +23157,10 @@ static __exception int js_parse_postfix_expr(JSParseState *s, BOOL accept_lparen emit_u16(s, arg_count); break; case OP_eval: - /* eval needs a single argument */ - if (arg_count == 0) { - /* no actual eval call is needed? */ - emit_op(s, OP_undefined); - } else { - int i; - /* pop extra arguments. Contrary to ECMA spec, - browsers seem to evaluate extra arguments - to direct eval */ - for(i = 1; i < arg_count; i++) - emit_op(s, OP_drop); - emit_op(s, OP_eval); - emit_u16(s, fd->scope_level); - fd->has_eval_call = TRUE; - } + emit_op(s, OP_eval); + emit_u16(s, arg_count); + emit_u16(s, fd->scope_level); + fd->has_eval_call = TRUE; break; default: if (call_type == FUNC_CALL_SUPER_CTOR) { @@ -23248,6 +23293,11 @@ static __exception int js_parse_delete(JSParseState *s) break; case OP_scope_get_private_field: return js_parse_error(s, "cannot delete a private class field"); + case OP_get_super_value: + emit_op(s, OP_throw_var); + emit_atom(s, JS_ATOM_NULL); + emit_u8(s, JS_THROW_VAR_DELETE_SUPER); + break; default: ret_true: emit_op(s, OP_drop); @@ -25386,11 +25436,19 @@ static char *js_default_module_normalize_name(JSContext *ctx, if (r[0] == '.' && r[1] == '/') { r += 2; } else if (r[0] == '.' && r[1] == '.' && r[2] == '/') { + /* remove the last path element of filename, except if "." + or ".." */ if (filename[0] == '\0') break; p = strrchr(filename, '/'); if (!p) p = filename; + else + p++; + if (!strcmp(p, ".") || !strcmp(p, "..")) + break; + if (p > filename) + p--; *p = '\0'; r += 3; } else { @@ -26246,7 +26304,7 @@ static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier) specifierString = JS_ToString(ctx, specifier); if (JS_IsException(specifierString)) goto exception; - filename = js_value_to_atom(ctx, specifierString); + filename = JS_ValueToAtom(ctx, specifierString); JS_FreeValue(ctx, specifierString); if (filename == JS_ATOM_NULL) goto exception; @@ -26362,7 +26420,7 @@ static __exception JSAtom js_parse_from_clause(JSParseState *s) js_parse_error(s, "string expected"); return JS_ATOM_NULL; } - module_name = js_value_to_atom(s->ctx, s->token.u.str.str); + module_name = JS_ValueToAtom(s->ctx, s->token.u.str.str); if (module_name == JS_ATOM_NULL) return JS_ATOM_NULL; if (next_token(s)) { @@ -26587,7 +26645,7 @@ static __exception int js_parse_import(JSParseState *s) first_import = m->import_entries_count; if (s->token.val == TOK_STRING) { - module_name = js_value_to_atom(ctx, s->token.u.str.str); + module_name = JS_ValueToAtom(ctx, s->token.u.str.str); if (module_name == JS_ATOM_NULL) return -1; if (next_token(s)) { @@ -27026,6 +27084,9 @@ static void dump_byte_code(JSContext *ctx, int pass, case OP_FMT_npop: printf(" %u", get_u16(tab + pos)); break; + case OP_FMT_npop_u16: + printf(" %u,%u", get_u16(tab + pos), get_u16(tab + pos + 2)); + break; case OP_FMT_i16: printf(" %d", get_i16(tab + pos)); break; @@ -27158,7 +27219,7 @@ static void dump_byte_code(JSContext *ctx, int pass, js_free(ctx, bits); } -static __attribute__((unused)) void dump_pc2line(JSContext *ctx, const uint8_t *buf, int len, +static __maybe_unused void dump_pc2line(JSContext *ctx, const uint8_t *buf, int len, int line_num) { const uint8_t *p_end, *p_next, *p; @@ -27203,7 +27264,7 @@ static __attribute__((unused)) void dump_pc2line(JSContext *ctx, const uint8_t * } } -static __attribute__((unused)) void js_dump_function_bytecode(JSContext *ctx, JSFunctionBytecode *b) +static __maybe_unused void js_dump_function_bytecode(JSContext *ctx, JSFunctionBytecode *b) { int i; char atom_buf[ATOM_GET_STR_BUF_SIZE]; @@ -28778,6 +28839,16 @@ static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s) arg_valid = get_u16(bc_buf + pos + 1); break; case OP_eval: /* convert scope index to adjusted variable index */ + { + int call_argc = get_u16(bc_buf + pos + 1); + scope = get_u16(bc_buf + pos + 1 + 2); + mark_eval_captured_variables(ctx, s, scope); + dbuf_putc(&bc_out, op); + dbuf_put_u16(&bc_out, call_argc); + dbuf_put_u16(&bc_out, s->scopes[scope].first + 1); + } + break; + case OP_apply_eval: /* convert scope index to adjusted variable index */ scope = get_u16(bc_buf + pos + 1); mark_eval_captured_variables(ctx, s, scope); dbuf_putc(&bc_out, op); @@ -30219,7 +30290,7 @@ static __exception int compute_stack_size_rec(JSContext *ctx, } n_pop = oi->n_pop; /* call pops a variable number of arguments */ - if (oi->fmt == OP_FMT_npop) { + if (oi->fmt == OP_FMT_npop || oi->fmt == OP_FMT_npop_u16) { n_pop += get_u16(bc_buf + pos + 1); } else { #if SHORT_OPCODES @@ -31666,7 +31737,7 @@ static void bc_put_u16(BCWriterState *s, uint16_t v) dbuf_put_u16(&s->dbuf, v); } -static __attribute__((unused)) void bc_put_u32(BCWriterState *s, uint32_t v) +static __maybe_unused void bc_put_u32(BCWriterState *s, uint32_t v) { if (s->byte_swap) v = bswap32(v); @@ -31814,6 +31885,12 @@ static void bc_byte_swap(uint8_t *bc_buf, int bc_len) bswap16(get_u16(bc_buf + pos + 1 + 4 + 4))); } break; + case OP_FMT_npop_u16: + put_u16(bc_buf + pos + 1, + bswap16(get_u16(bc_buf + pos + 1))); + put_u16(bc_buf + pos + 1 + 2, + bswap16(get_u16(bc_buf + pos + 1 + 2))); + break; default: break; } @@ -32363,7 +32440,7 @@ static int bc_get_u16(BCReaderState *s, uint16_t *pval) return 0; } -static __attribute__((unused)) int bc_get_u32(BCReaderState *s, uint32_t *pval) +static __maybe_unused int bc_get_u32(BCReaderState *s, uint32_t *pval) { if (unlikely(s->buf_end - s->ptr < 4)) { *pval = 0; /* avoid warning */ @@ -33763,7 +33840,7 @@ static JSValue js_object_defineProperty(JSContext *ctx, JSValueConst this_val, if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) return JS_ThrowTypeErrorNotAnObject(ctx); - atom = js_value_to_atom(ctx, prop); + atom = JS_ValueToAtom(ctx, prop); if (unlikely(atom == JS_ATOM_NULL)) return JS_EXCEPTION; flags = 0; @@ -33812,7 +33889,7 @@ static JSValue js_object___defineGetter__(JSContext *ctx, JSValueConst this_val, JS_FreeValue(ctx, obj); return JS_EXCEPTION; } - atom = js_value_to_atom(ctx, prop); + atom = JS_ValueToAtom(ctx, prop); if (unlikely(atom == JS_ATOM_NULL)) { JS_FreeValue(ctx, obj); return JS_EXCEPTION; @@ -33842,23 +33919,26 @@ static JSValue js_object___defineGetter__(JSContext *ctx, JSValueConst this_val, static JSValue js_object_getOwnPropertyDescriptor(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic) { - JSValueConst obj, prop; + JSValueConst prop; JSAtom atom; - JSValue ret; + JSValue ret, obj; JSPropertyDescriptor desc; int res, flags; - obj = argv[0]; - if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) { - /* ES6 feature non compatible with ES5.1: obj can be a primitive type */ - if (magic || JS_VALUE_GET_TAG(obj) == JS_TAG_NULL || - JS_VALUE_GET_TAG(obj) == JS_TAG_UNDEFINED) + if (magic) { + /* Reflect.getOwnPropertyDescriptor case */ + if (JS_VALUE_GET_TAG(argv[0]) != JS_TAG_OBJECT) return JS_ThrowTypeErrorNotAnObject(ctx); + obj = JS_DupValue(ctx, argv[0]); + } else { + obj = JS_ToObject(ctx, argv[0]); + if (JS_IsException(obj)) + return obj; } prop = argv[1]; - atom = js_value_to_atom(ctx, prop); + atom = JS_ValueToAtom(ctx, prop); if (unlikely(atom == JS_ATOM_NULL)) - return JS_EXCEPTION; + goto exception; ret = JS_UNDEFINED; if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) { res = JS_GetOwnPropertyInternal(ctx, &desc, JS_VALUE_GET_OBJ(obj), atom); @@ -33888,6 +33968,7 @@ static JSValue js_object_getOwnPropertyDescriptor(JSContext *ctx, JSValueConst t } } JS_FreeAtom(ctx, atom); + JS_FreeValue(ctx, obj); return ret; exception1: @@ -33895,6 +33976,7 @@ static JSValue js_object_getOwnPropertyDescriptor(JSContext *ctx, JSValueConst t JS_FreeValue(ctx, ret); exception: JS_FreeAtom(ctx, atom); + JS_FreeValue(ctx, obj); return JS_EXCEPTION; } @@ -34099,7 +34181,7 @@ static JSValue js_object_hasOwnProperty(JSContext *ctx, JSValueConst this_val, JSObject *p; BOOL ret; - atom = js_value_to_atom(ctx, argv[0]); /* must be done first */ + atom = JS_ValueToAtom(ctx, argv[0]); /* must be done first */ if (unlikely(atom == JS_ATOM_NULL)) return JS_EXCEPTION; obj = JS_ToObject(ctx, this_val); @@ -34582,7 +34664,7 @@ static JSValue js_object_propertyIsEnumerable(JSContext *ctx, JSValueConst this_ obj = JS_ToObject(ctx, this_val); if (JS_IsException(obj)) goto exception; - prop = js_value_to_atom(ctx, argv[0]); + prop = JS_ValueToAtom(ctx, argv[0]); if (unlikely(prop == JS_ATOM_NULL)) goto exception; @@ -34614,7 +34696,7 @@ static JSValue js_object___lookupGetter__(JSContext *ctx, JSValueConst this_val, obj = JS_ToObject(ctx, this_val); if (JS_IsException(obj)) goto exception; - prop = js_value_to_atom(ctx, argv[0]); + prop = JS_ValueToAtom(ctx, argv[0]); if (unlikely(prop == JS_ATOM_NULL)) goto exception; @@ -41825,7 +41907,7 @@ static JSValue js_reflect_deleteProperty(JSContext *ctx, JSValueConst this_val, obj = argv[0]; if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) return JS_ThrowTypeErrorNotAnObject(ctx); - atom = js_value_to_atom(ctx, argv[1]); + atom = JS_ValueToAtom(ctx, argv[1]); if (unlikely(atom == JS_ATOM_NULL)) return JS_EXCEPTION; ret = JS_DeleteProperty(ctx, obj, atom, 0); @@ -41851,7 +41933,7 @@ static JSValue js_reflect_get(JSContext *ctx, JSValueConst this_val, receiver = argv[2]; else receiver = obj; - atom = js_value_to_atom(ctx, prop); + atom = JS_ValueToAtom(ctx, prop); if (unlikely(atom == JS_ATOM_NULL)) return JS_EXCEPTION; ret = JS_GetPropertyInternal(ctx, obj, atom, receiver, FALSE); @@ -41870,7 +41952,7 @@ static JSValue js_reflect_has(JSContext *ctx, JSValueConst this_val, prop = argv[1]; if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) return JS_ThrowTypeErrorNotAnObject(ctx); - atom = js_value_to_atom(ctx, prop); + atom = JS_ValueToAtom(ctx, prop); if (unlikely(atom == JS_ATOM_NULL)) return JS_EXCEPTION; ret = JS_HasProperty(ctx, obj, atom); @@ -41897,7 +41979,7 @@ static JSValue js_reflect_set(JSContext *ctx, JSValueConst this_val, receiver = obj; if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) return JS_ThrowTypeErrorNotAnObject(ctx); - atom = js_value_to_atom(ctx, prop); + atom = JS_ValueToAtom(ctx, prop); if (unlikely(atom == JS_ATOM_NULL)) return JS_EXCEPTION; ret = JS_SetPropertyGeneric(ctx, JS_VALUE_GET_OBJ(obj), atom, @@ -42639,7 +42721,7 @@ static int js_proxy_get_own_property_names(JSContext *ctx, JS_ThrowTypeError(ctx, "proxy: properties must be strings or symbols"); goto fail; } - atom = js_value_to_atom(ctx, val); + atom = JS_ValueToAtom(ctx, val); JS_FreeValue(ctx, val); if (atom == JS_ATOM_NULL) goto fail; @@ -45370,7 +45452,6 @@ static const JSCFunctionListEntry js_global_funcs[] = { JS_CFUNC_DEF("parseFloat", 1, js_parseFloat ), JS_CFUNC_DEF("isNaN", 1, js_global_isNaN ), JS_CFUNC_DEF("isFinite", 1, js_global_isFinite ), - JS_CFUNC_DEF("eval", 1, js_global_eval ), JS_CFUNC_MAGIC_DEF("decodeURI", 1, js_global_decodeURI, 0 ), JS_CFUNC_MAGIC_DEF("decodeURIComponent", 1, js_global_decodeURI, 1 ), @@ -46058,7 +46139,7 @@ static JSValue js_date_Symbol_toPrimitive(JSContext *ctx, JSValueConst this_val, return JS_ThrowTypeErrorNotAnObject(ctx); if (JS_IsString(argv[0])) { - hint = js_value_to_atom(ctx, argv[0]); + hint = JS_ValueToAtom(ctx, argv[0]); if (hint == JS_ATOM_NULL) return JS_EXCEPTION; JS_FreeAtom(ctx, hint); @@ -47288,6 +47369,11 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx) countof(js_float_env_funcs)); #endif /* global properties */ + ctx->eval_obj = JS_NewCFunction(ctx, js_global_eval, "eval", 1); + JS_DefinePropertyValue(ctx, ctx->global_obj, JS_ATOM_eval, + JS_DupValue(ctx, ctx->eval_obj), + JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_global_funcs, countof(js_global_funcs)); diff --git a/quickjs/quickjs.h b/quickjs/quickjs.h index 206516b04a..eb4eb8d792 100644 --- a/quickjs/quickjs.h +++ b/quickjs/quickjs.h @@ -385,6 +385,7 @@ void JS_FreeAtomRT(JSRuntime *rt, JSAtom v); JSValue JS_AtomToValue(JSContext *ctx, JSAtom atom); JSValue JS_AtomToString(JSContext *ctx, JSAtom atom); const char *JS_AtomToCString(JSContext *ctx, JSAtom atom); +JSAtom JS_ValueToAtom(JSContext *ctx, JSValueConst val); /* object class support */ From 9e38aeb277b05b7dc766d5ec1810ccdc07383f58 Mon Sep 17 00:00:00 2001 From: ftk Date: Fri, 20 Sep 2019 13:14:22 +0300 Subject: [PATCH 026/185] more consistent conversion operators for Value, exception handling in eval --- main.cpp | 24 +++++++----- quickjspp.hpp | 101 +++++++++++++++++++++++++++++++++----------------- 2 files changed, 83 insertions(+), 42 deletions(-) diff --git a/main.cpp b/main.cpp index 13e163cf36..d0c4545232 100644 --- a/main.cpp +++ b/main.cpp @@ -114,7 +114,6 @@ int main(int argc, char ** argv) "globalThis.test = test;\n" "globalThis.os = os;\n"; context.eval(str, "", JS_EVAL_TYPE_MODULE); - const char * filename = argv[1]; try { @@ -138,22 +137,29 @@ int main(int argc, char ** argv) //"console.log(5.1 === q.base_field);" "console.log(q.spt === q.fspt(t.vb, t.vi, t.vd, t, t, t.vs, \"test\"));" // false "q.fi(t.vb, t.vi, t.vd, t, t, t.vs, \"test\")"); - assert(xxx.cast() == 18); + assert((int)xxx == 18); auto yyy = context.eval("q.fi.bind(t)(t.vb, t.vi, t.vd, t, t, t.vs, \"test\")"); - assert(yyy.cast() == 13); + assert((int)yyy == 13); - auto f = context.eval("q.fi.bind(q)").cast>(); - int zzz = f(false, 1, 0., context.eval("q").cast>(), - context.eval("t").cast>(), "test string", std::string{"test"}); + auto f = context.eval("q.fi.bind(q)").as>(); + int zzz = f(false, 1, 0., context.eval("q").as>(), + context.eval("t").as>(), "test string", std::string{"test"}); assert(zzz == 19); + + + if(argv[1]) + context.evalFile(argv[1]); } catch(exception) { - js_std_dump_error(ctx); + //js_std_dump_error(ctx); + auto exc = context.getException(); + std::cerr << (exc.isError() ? "Error: " : "Throw: ") << (std::string)exc << std::endl; + if((bool)exc["stack"]) + std::cerr << (std::string)exc["stack"] << std::endl; } - if(filename) - context.evalFile(filename, JS_EVAL_TYPE_MODULE); + JSMemoryUsage mem; JS_ComputeMemoryUsage(rt, &mem); diff --git a/quickjspp.hpp b/quickjspp.hpp index 23e0c355e4..90aed0c750 100644 --- a/quickjspp.hpp +++ b/quickjspp.hpp @@ -644,6 +644,8 @@ struct js_property_traits } }; +class Value; + namespace detail { template struct property_proxy @@ -652,12 +654,20 @@ struct property_proxy JSValue this_obj; Key key; - template - operator Value() const + /** Conversion helper function */ + template + T as() const { - return unwrap_free(ctx, js_property_traits::get_property(ctx, this_obj, key)); + return unwrap_free(ctx, js_property_traits::get_property(ctx, this_obj, key)); } + /** Explicit conversion operator (to any type) */ + template + explicit operator T() const { return as(); } + + /** Implicit converion to qjs::Value */ + operator Value() const; // defined later due to Value being incomplete type + template property_proxy& operator =(Value value) { @@ -705,10 +715,11 @@ class Value JSContext * ctx = nullptr; public: + /** Use context.newValue(val) instead */ template - Value(JSContext * ctx, T val) : ctx(ctx) + Value(JSContext * ctx, T&& val) : ctx(ctx) { - v = js_traits::wrap(ctx, val); + v = js_traits>::wrap(ctx, std::forward(val)); } Value(const Value& rhs) @@ -728,18 +739,15 @@ class Value if(ctx) JS_FreeValue(ctx, v); } + bool isError() const { return JS_IsError(ctx, v); } + /** Conversion helper function. Both value.as() and static_cast(value) are supported */ template - T cast() const - { - return js_traits>::unwrap(ctx, v); - } + T as() const { return js_traits>::unwrap(ctx, v); } + /** Explicit conversion to any type */ template - T as() const - { - return cast(); - } + explicit operator T() const { return as(); } JSValue release() // dont call freevalue { @@ -747,13 +755,11 @@ class Value return v; } - operator JSValue()&& - { - return release(); - } + /** Implicit conversion to JSValue (rvalue only). Example: JSValue v = std::move(value); */ + operator JSValue() && { return release(); } - // access properties + /** Access JS properties. Returns proxy type which is implicitly convertible to qjs::Value */ template detail::property_proxy operator [](Key key) { @@ -825,9 +831,10 @@ class Runtime { rt = JS_NewRuntime(); if(!rt) - throw exception{}; + throw std::runtime_error{"qjs: Cannot create runtime"}; } + // noncopyable Runtime(const Runtime&) = delete; ~Runtime() @@ -1033,7 +1040,7 @@ class Context { ctx = JS_NewContext(rt); if(!ctx) - throw exception{}; + throw std::runtime_error{"qjs: Cannot create context"}; init(); } @@ -1042,6 +1049,7 @@ class Context init(); } + // noncopyable Context(const Context&) = delete; ~Context() @@ -1057,15 +1065,18 @@ class Context return modules.back(); } - Value global() - { - return Value{ctx, JS_GetGlobalObject(ctx)}; - } + /** returns globalThis */ + Value global() { return Value{ctx, JS_GetGlobalObject(ctx)}; } - Value newObject() - { - return Value{ctx, JS_NewObject(ctx)}; - } + /** returns new Object() */ + Value newObject() { return Value{ctx, JS_NewObject(ctx)}; } + + /** returns JS value converted from c++ object \val */ + template + Value newValue(T&& val) { return Value{ctx, std::forward(val)}; } + + /** returns current exception associated with context, and resets it. Should be called when qjs::exception is caught */ + Value getException() { return Value{ctx, JS_GetException(ctx)}; } /** Register class \T for conversions to/from std::shared_ptr to work. * Wherever possible module.class_("T")... should be used instead. @@ -1082,8 +1093,8 @@ class Context Value eval(std::string_view buffer, const char * filename = "", unsigned eval_flags = 0) { JSValue v = JS_Eval(ctx, buffer.data(), buffer.size(), filename, eval_flags); - //if(JS_IsException(v)) - //throw exception{}; + if(JS_IsException(v)) + throw exception{}; return Value{ctx, v}; } @@ -1106,6 +1117,23 @@ class Context } }; +/** Conversion traits for Value. + */ +template <> +struct js_traits +{ + static Value unwrap(JSContext * ctx, JSValueConst v) noexcept + { + return Value{ctx, JS_DupValue(ctx, v)}; + } + + static JSValue wrap(JSContext * ctx, Value v) noexcept + { + assert(ctx == v.ctx); + return v.release(); + } +}; + /** Convert to/from std::function * @tparam R return type * @tparam Args argument types @@ -1168,13 +1196,20 @@ struct js_traits> throw exception{}; Value jsarray{ctx, JS_DupValue(ctx, jsarr)}; std::vector arr; - int32_t len = jsarray["length"]; + auto len = static_cast(jsarray["length"]); arr.reserve((uint32_t) len); for(uint32_t i = 0; i < (uint32_t) len; i++) - arr.push_back(jsarray[i]); + arr.push_back(static_cast(jsarray[i])); return arr; } }; +namespace detail { +template +property_proxy::operator Value() const +{ + return as(); +} +} -} \ No newline at end of file +} // namespace qjs From 1e53dfcde3ec18a64b930990a3ca6768125732ed Mon Sep 17 00:00:00 2001 From: ftk Date: Fri, 20 Sep 2019 15:27:31 +0300 Subject: [PATCH 027/185] comparison and assignment operators for qjs::Value --- quickjspp.hpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/quickjspp.hpp b/quickjspp.hpp index 90aed0c750..0b621eee01 100644 --- a/quickjspp.hpp +++ b/quickjspp.hpp @@ -734,6 +734,30 @@ class Value v = rhs.v; } + Value& operator=(Value rhs) + { + std::swap(ctx, rhs.ctx); + std::swap(v, rhs.v); + return *this; + } + + bool operator==(JSValueConst other) const + { + return JS_VALUE_GET_TAG(v) == JS_VALUE_GET_TAG(other) && JS_VALUE_GET_PTR(v) == JS_VALUE_GET_PTR(other); + } + + bool operator!=(JSValueConst other) const { return !((*this) == other); } + + + /** Returns true if 2 values are the same (equality for arithmetic types or point to the same object) */ + bool operator==(const Value& rhs) const + { + return ctx == rhs.ctx && (*this == rhs.v); + } + + bool operator!=(const Value& rhs) const { return !((*this) == rhs); } + + ~Value() { if(ctx) JS_FreeValue(ctx, v); From 5c3e13120f23b21df89c3f8428a868d042976092 Mon Sep 17 00:00:00 2001 From: ftk Date: Fri, 20 Sep 2019 15:53:42 +0300 Subject: [PATCH 028/185] finally some tests --- CMakeLists.txt | 13 ++++--- qjs.cpp | 57 +++++++++++++++++++++++++++ quickjs/CMakeLists.txt | 3 ++ test/CMakeLists.txt | 13 +++++++ main.cpp => test/class.cpp | 79 +++++++++++++++++--------------------- test/value.cpp | 64 ++++++++++++++++++++++++++++++ 6 files changed, 180 insertions(+), 49 deletions(-) create mode 100644 qjs.cpp create mode 100644 test/CMakeLists.txt rename main.cpp => test/class.cpp (73%) create mode 100644 test/value.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 3951eef502..997baf6888 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,10 +4,13 @@ project(quickjspp) set(CMAKE_CXX_STANDARD 17) #set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE) -#if(GNU) -# add_compile_options(-Wall -Wno-unused-parameter) -# endif() +if(CMAKE_COMPILER_IS_GNUCC) + add_compile_options(-Wall -Wno-unused-parameter) +endif() add_subdirectory(quickjs) -add_executable(quickjspp main.cpp) -target_link_libraries(quickjspp quickjs ) +add_executable(qjs qjs.cpp) +target_link_libraries(qjs quickjs) + +enable_testing() +add_subdirectory(test) diff --git a/qjs.cpp b/qjs.cpp new file mode 100644 index 0000000000..a40d4f7b51 --- /dev/null +++ b/qjs.cpp @@ -0,0 +1,57 @@ +#include "quickjspp.hpp" + + +#include + +int main(int argc, char ** argv) +{ + JSRuntime * rt; + JSContext * ctx; + using namespace qjs; + + Runtime runtime; + rt = runtime.rt; + + Context context(runtime); + ctx = context.ctx; + + + /* loader for ES6 modules */ + JS_SetModuleLoaderFunc(rt, nullptr, js_module_loader, nullptr); + js_std_add_helpers(ctx, argc, argv); + + /* system modules */ + js_init_module_std(ctx, "std"); + js_init_module_os(ctx, "os"); + + /* make 'std' and 'os' visible to non module code */ + const char * str = "import * as std from 'std';\n" + "import * as os from 'os';\n" + "globalThis.std = std;\n" + "globalThis.os = os;\n"; + context.eval(str, "", JS_EVAL_TYPE_MODULE); + + try + { + if(argv[1]) + context.evalFile(argv[1]); + } + catch(exception) + { + //js_std_dump_error(ctx); + auto exc = context.getException(); + std::cerr << (exc.isError() ? "Error: " : "Throw: ") << (std::string)exc << std::endl; + if((bool)exc["stack"]) + std::cerr << (std::string)exc["stack"] << std::endl; + + js_std_free_handlers(rt); + return 1; + } + + js_std_loop(ctx); + + js_std_free_handlers(rt); + + return 0; + +} diff --git a/quickjs/CMakeLists.txt b/quickjs/CMakeLists.txt index a40ee724e4..11a94b0bee 100644 --- a/quickjs/CMakeLists.txt +++ b/quickjs/CMakeLists.txt @@ -16,7 +16,10 @@ endif() add_library(quickjs ${quickjs_src}) target_compile_definitions(quickjs PRIVATE ${quickjs_def} ) +add_library(quickjs-dumpleaks ${quickjs_src}) +target_compile_definitions(quickjs-dumpleaks PRIVATE ${quickjs_def} DUMP_LEAKS=1) if(UNIX) target_link_libraries(quickjs ${CMAKE_DL_LIBS} m ) + target_link_libraries(quickjs-dumpleaks ${CMAKE_DL_LIBS} m ) endif() diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000000..8f7101fbf6 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,13 @@ +include_directories(..) + +macro(make_test name) +add_executable(${name} ${name}.cpp) +target_link_libraries(${name} quickjs-dumpleaks) +add_test(${name} ${name}) +# try to compile with -DCONFIG_CHECK_JSVALUE +add_library(${name}-checkjsv OBJECT ${name}.cpp) +target_compile_definitions(${name}-checkjsv PRIVATE CONFIG_CHECK_JSVALUE=1) +endmacro() + +make_test(value) +make_test(class) diff --git a/main.cpp b/test/class.cpp similarity index 73% rename from main.cpp rename to test/class.cpp index d0c4545232..97fe942f72 100644 --- a/main.cpp +++ b/test/class.cpp @@ -1,14 +1,7 @@ #include "quickjspp.hpp" - - #include -#include -#include -#include - - #define TYPES bool, int32_t, double, std::shared_ptr, const std::shared_ptr&, std::string, const std::string& class base_test @@ -59,7 +52,7 @@ void f(TYPES) {} void qjs_glue(qjs::Context::Module& m) { m.function<&::f>("f"); // (bool, ::int32_t, double, ::std::shared_ptr, ::std::shared_ptr const &, ::std::string, ::std::string const &) m.class_<::base_test>("base_test") - // implicit: .constructor<::base_test const &>() + // implicit: .constructor<::base_test const &>() .constructor<>() .fun<&::base_test::base_method>("base_method") // (double) .fun<&::base_test::base_field>("base_field") // double @@ -83,7 +76,8 @@ void qjs_glue(qjs::Context::Module& m) { .fun<&::test::s>("s") // ::std::string ; } // qjs_glue -int main(int argc, char ** argv) + +int main() { JSRuntime * rt; JSContext * ctx; @@ -95,33 +89,37 @@ int main(int argc, char ** argv) Context context(runtime); ctx = context.ctx; - qjs_glue(context.addModule("test")); + try + { + qjs_glue(context.addModule("test")); - /* loader for ES6 modules */ - JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL); - js_std_add_helpers(ctx, argc, argv); + /* loader for ES6 modules */ + JS_SetModuleLoaderFunc(rt, nullptr, js_module_loader, nullptr); + js_std_add_helpers(ctx, 0, nullptr); - /* system modules */ - js_init_module_std(ctx, "std"); - js_init_module_os(ctx, "os"); + /* system modules */ + js_init_module_std(ctx, "std"); + js_init_module_os(ctx, "os"); + + /* make 'std' and 'os' visible to non module code */ + const char * str = "import * as std from 'std';\n" + "import * as os from 'os';\n" + "import * as test from 'test';\n" + "globalThis.std = std;\n" + "globalThis.test = test;\n" + "globalThis.os = os;\n"; + context.eval(str, "", JS_EVAL_TYPE_MODULE); + + + context.global().add("assert", [](bool t) { if(!t) std::exit(2); }); - /* make 'std' and 'os' visible to non module code */ - const char * str = "import * as std from 'std';\n" - "import * as os from 'os';\n" - "import * as test from 'test';\n" - "globalThis.std = std;\n" - "globalThis.test = test;\n" - "globalThis.os = os;\n"; - context.eval(str, "", JS_EVAL_TYPE_MODULE); - try - { auto xxx = context.eval("\"use strict\";" "var b = new test.base_test();" "b.base_field = [[5],[1,2,3,4],[6]];" - "console.log(b.base_field[1][3] === 4);" - "console.log(b.base_method() === 5);" + "assert(b.base_field[1][3] === 4);" + "assert(b.base_method() === 5);" "var t = new test.TestSimple(12);" "var q = new test.Test(13, t.vb, t.vi, t.vd, t, t, t.vs, t.vs);" @@ -130,12 +128,12 @@ int main(int argc, char ** argv) "q.s = \"STRING\";" "q.spt = t;" //"q.base_field = 105.5;" - "console.log(q.b === q.fb(t.vb, t.vi, t.vd, t, t, t.vs, \"test\"));" - "console.log(q.d === q.fd(t.vb, t.vi, t.vd, t, t, t.vs, \"test\"));" - "console.log(q.s === q.fs(t.vb, t.vi, t.vd, t, t, \"test\", t.vs));" - //"console.log(105.5 === q.base_method(5.1));" - //"console.log(5.1 === q.base_field);" - "console.log(q.spt === q.fspt(t.vb, t.vi, t.vd, t, t, t.vs, \"test\"));" // false + "assert(q.b === q.fb(t.vb, t.vi, t.vd, t, t, t.vs, \"test\"));" + "assert(q.d === q.fd(t.vb, t.vi, t.vd, t, t, t.vs, \"test\"));" + "assert(q.s === q.fs(t.vb, t.vi, t.vd, t, t, \"test\", t.vs));" + //"assert(105.5 === q.base_method(5.1));" + //"assert(5.1 === q.base_field);" + "assert(q.spt !== q.fspt(t.vb, t.vi, t.vd, t, t, t.vs, \"test\"));" // different objects "q.fi(t.vb, t.vi, t.vd, t, t, t.vs, \"test\")"); assert((int)xxx == 18); auto yyy = context.eval("q.fi.bind(t)(t.vb, t.vi, t.vd, t, t, t.vs, \"test\")"); @@ -146,24 +144,17 @@ int main(int argc, char ** argv) context.eval("t").as>(), "test string", std::string{"test"}); assert(zzz == 19); - - if(argv[1]) - context.evalFile(argv[1]); } catch(exception) { - //js_std_dump_error(ctx); auto exc = context.getException(); std::cerr << (exc.isError() ? "Error: " : "Throw: ") << (std::string)exc << std::endl; if((bool)exc["stack"]) std::cerr << (std::string)exc["stack"] << std::endl; - } - - - JSMemoryUsage mem; - JS_ComputeMemoryUsage(rt, &mem); - JS_DumpMemoryUsage(stderr, &mem, rt); + js_std_free_handlers(rt); + return 1; + } js_std_loop(ctx); diff --git a/test/value.cpp b/test/value.cpp new file mode 100644 index 0000000000..c6b6f759c0 --- /dev/null +++ b/test/value.cpp @@ -0,0 +1,64 @@ +#include "quickjspp.hpp" +#include +#include + +int main() +{ + qjs::Runtime runtime; + qjs::Context context(runtime); + + try + { + auto val1 = context.newValue(321); + auto val2 = context.newValue(123); + assert(val1 != val2); + + val1 = val2; + assert(val1 == val2); + + val1 = context.newValue(123); + assert(val1 == val2); + + val1 = std::move(val2); + assert(val1 != val2); + + assert(val1.as() == "123"); + + assert((double) val1 == 123.0); + + val2 = context.newValue((std::string) "123"); + assert(val1 != val2); + + context.global()["val1"] = val1; + context.global()["val2"] = val2; + + + assert((bool) context.eval("val1 !== val2")); + assert((bool) context.eval("val1 == val2")); + + // + + val1 = context.newObject(); + val1["a"] = 1; + val2 = context.newObject(); + val2["a"] = 1; + + assert(val1 != val2); + + context.global()["val1"] = val1; + context.global()["val2"] = val2; + + assert((bool) context.eval("val1 !== val2")); + assert((bool) context.eval("val1 != val2")); + assert((bool)context.eval("JSON.stringify(val1) === JSON.stringify(val2)")); + + } + catch(qjs::exception) + { + auto exc = context.getException(); + std::cerr << (exc.isError() ? "Error: " : "Throw: ") << (std::string) exc << std::endl; + if((bool) exc["stack"]) + std::cerr << (std::string) exc["stack"] << std::endl; + return 1; + } +} From ca46c80f5b277bb2a69077768015b146e682f293 Mon Sep 17 00:00:00 2001 From: ftk Date: Sat, 21 Sep 2019 13:31:30 +0300 Subject: [PATCH 029/185] const char * conversion --- quickjspp.hpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/quickjspp.hpp b/quickjspp.hpp index 0b621eee01..1584289152 100644 --- a/quickjspp.hpp +++ b/quickjspp.hpp @@ -198,7 +198,7 @@ struct js_traits { static detail::js_string unwrap(JSContext * ctx, JSValueConst v) { - std::size_t plen; + size_t plen; const char * ptr = JS_ToCStringLen(ctx, &plen, v); if(!ptr) throw exception{}; @@ -207,7 +207,7 @@ struct js_traits static JSValue wrap(JSContext * ctx, std::string_view str) noexcept { - return JS_NewStringLen(ctx, str.data(), (int) str.size()); + return JS_NewStringLen(ctx, str.data(), str.size()); } }; @@ -223,10 +223,21 @@ struct js_traits static JSValue wrap(JSContext * ctx, const std::string& str) noexcept { - return JS_NewStringLen(ctx, str.data(), (int) str.size()); + return JS_NewStringLen(ctx, str.data(), str.size()); } }; +/** Conversion from const char * */ +template <> +struct js_traits +{ + static JSValue wrap(JSContext * ctx, const char * str) noexcept + { + return JS_NewString(ctx, str); + } +}; + + namespace detail { /** Helper function to convert and then free JSValue. */ From c598e98be49422d57c72145a5e701eb696d82133 Mon Sep 17 00:00:00 2001 From: ftk Date: Sat, 21 Sep 2019 19:55:38 +0300 Subject: [PATCH 030/185] fix arguments unwrapping --- quickjspp.hpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/quickjspp.hpp b/quickjspp.hpp index 1584289152..1ada10778e 100644 --- a/quickjspp.hpp +++ b/quickjspp.hpp @@ -274,9 +274,9 @@ Tuple unwrap_args_impl(JSContext * ctx, JSValueConst * argv, std::index_sequence * @tparam Args C++ types of the argv array */ template -std::tuple unwrap_args(JSContext * ctx, JSValueConst * argv) +std::tuple...> unwrap_args(JSContext * ctx, JSValueConst * argv) { - return unwrap_args_impl>(ctx, argv, std::make_index_sequence()); + return unwrap_args_impl...>>(ctx, argv, std::make_index_sequence()); } /** Helper function to call f with an array of JSValues. @@ -731,6 +731,8 @@ class Value Value(JSContext * ctx, T&& val) : ctx(ctx) { v = js_traits>::wrap(ctx, std::forward(val)); + if(JS_IsException(v)) + throw exception{}; } Value(const Value& rhs) From 9bd88ac84b981cc3db629063e3c0595e014a8ddf Mon Sep 17 00:00:00 2001 From: ftk Date: Sun, 22 Sep 2019 12:16:39 +0300 Subject: [PATCH 031/185] fix multiple contexts creation --- quickjspp.hpp | 62 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 26 deletions(-) diff --git a/quickjspp.hpp b/quickjspp.hpp index 1ada10778e..63560fc8a7 100644 --- a/quickjspp.hpp +++ b/quickjspp.hpp @@ -447,33 +447,39 @@ template struct js_traits> { /// Registered class id in QuickJS. - inline static JSClassID QJSClassId; + inline static JSClassID QJSClassId = 0; /** Register class in QuickJS context. * * @param ctx context * @param name class name - * @param proto class prototype + * @param proto class prototype or JS_NULL * @throws exception */ - static void register_class(JSContext * ctx, const char * name, JSValue proto) + static void register_class(JSContext * ctx, const char * name, JSValue proto = JS_NULL) { - JSClassDef def{ - name, - // destructor - [](JSRuntime * rt, JSValue obj) noexcept { - auto pptr = reinterpret_cast *>(JS_GetOpaque(obj, QJSClassId)); - assert(pptr); - //delete pptr; - auto alloc = allocator>{rt}; - using atraits = std::allocator_traits; - atraits::destroy(alloc, pptr); - atraits::deallocate(alloc, pptr, 1); - } - }; - int e = JS_NewClass(JS_GetRuntime(ctx), JS_NewClassID(&QJSClassId), &def); - if(e < 0) - throw exception{}; + if(QJSClassId == 0) + { + JSClassDef def{ + name, + // destructor + [](JSRuntime * rt, JSValue obj) noexcept { + auto pptr = reinterpret_cast *>(JS_GetOpaque(obj, QJSClassId)); + assert(pptr); + //delete pptr; + auto alloc = allocator>{rt}; + using atraits = std::allocator_traits; + atraits::destroy(alloc, pptr); + atraits::deallocate(alloc, pptr, 1); + } + }; + int e = JS_NewClass(JS_GetRuntime(ctx), JS_NewClassID(&QJSClassId), &def); + if(e < 0) + { + JS_ThrowInternalError(ctx, "Cant register class %s", name); + throw exception{}; + } + } JS_SetClassProto(ctx, QJSClassId, proto); } @@ -583,10 +589,13 @@ static_assert(std::is_trivially_destructible_v); template <> struct js_traits { - inline static JSClassID QJSClassId; + inline static JSClassID QJSClassId = 0; + // TODO: replace ctx with rt static void register_class(JSContext * ctx, const char * name) { + if(QJSClassId) + return; JSClassDef def{ name, // destructor @@ -609,18 +618,19 @@ struct js_traits }; int e = JS_NewClass(JS_GetRuntime(ctx), JS_NewClassID(&QJSClassId), &def); if(e < 0) - throw exception{}; + throw std::runtime_error{"Cannot register C++ function class"}; } }; -// properties - +/** Traits for accessing object properties. + * @tparam Key property key type (uint32 and strings are supported) + */ template struct js_property_traits { - // static void set_property(JSContext * ctx, JSValue this_obj, R key, JSValue value) - // static JSValue get_property(JSContext * ctx, JSValue this_obj, R key) + static void set_property(JSContext * ctx, JSValue this_obj, Key key, JSValue value); + static JSValue get_property(JSContext * ctx, JSValue this_obj, Key key); }; template <> @@ -1122,7 +1132,7 @@ class Context * @param proto JS class prototype or JS_UNDEFINED */ template - void registerClass(const char * name, JSValue proto) + void registerClass(const char * name, JSValue proto = JS_NULL) { js_traits>::register_class(ctx, name, proto); } From ee9ed7b389e80b9519b24546f39349f528f6f93a Mon Sep 17 00:00:00 2001 From: ftk Date: Sun, 22 Sep 2019 12:42:11 +0300 Subject: [PATCH 032/185] remove duplicate exception check --- quickjspp.hpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/quickjspp.hpp b/quickjspp.hpp index 63560fc8a7..dde2e3546a 100644 --- a/quickjspp.hpp +++ b/quickjspp.hpp @@ -136,9 +136,9 @@ template <> struct js_traits { /// @throws exception if jsvalue is neither undefined nor null - static void unwrap(JSContext * ctx, JSValueConst undefined) + static void unwrap(JSContext * ctx, JSValueConst value) { - if(!JS_IsUndefined(undefined) && !JS_IsNull(undefined)) + if(JS_IsException(value)) throw exception{}; } }; @@ -1140,8 +1140,6 @@ class Context Value eval(std::string_view buffer, const char * filename = "", unsigned eval_flags = 0) { JSValue v = JS_Eval(ctx, buffer.data(), buffer.size(), filename, eval_flags); - if(JS_IsException(v)) - throw exception{}; return Value{ctx, v}; } From fdf34f8878bf9549e087f759637fce36ed170500 Mon Sep 17 00:00:00 2001 From: ftk Date: Sun, 22 Sep 2019 12:42:37 +0300 Subject: [PATCH 033/185] fix qjs arguments --- qjs.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qjs.cpp b/qjs.cpp index a40d4f7b51..a9718a8091 100644 --- a/qjs.cpp +++ b/qjs.cpp @@ -18,7 +18,7 @@ int main(int argc, char ** argv) /* loader for ES6 modules */ JS_SetModuleLoaderFunc(rt, nullptr, js_module_loader, nullptr); - js_std_add_helpers(ctx, argc, argv); + js_std_add_helpers(ctx, argc - 1, argv + 1); /* system modules */ js_init_module_std(ctx, "std"); @@ -34,7 +34,7 @@ int main(int argc, char ** argv) try { if(argv[1]) - context.evalFile(argv[1]); + context.evalFile(argv[1], JS_EVAL_TYPE_MODULE); } catch(exception) { From 3d6b37a9b0fad0721a7b7d9226b15be27d9ee691 Mon Sep 17 00:00:00 2001 From: ftk Date: Sun, 22 Sep 2019 12:45:06 +0300 Subject: [PATCH 034/185] more tests --- test/CMakeLists.txt | 13 +++++++-- test/example.cpp | 53 ++++++++++++++++++++++++++++++++++++ test/exception.cpp | 53 ++++++++++++++++++++++++++++++++++++ test/multicontext.cpp | 62 +++++++++++++++++++++++++++++++++++++++++++ test/value.cpp | 6 +++-- 5 files changed, 183 insertions(+), 4 deletions(-) create mode 100644 test/example.cpp create mode 100644 test/exception.cpp create mode 100644 test/multicontext.cpp diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 8f7101fbf6..35f6efbbf2 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,5 +1,10 @@ include_directories(..) +if(UNIX AND CMAKE_COMPILER_IS_GNUCC) + add_compile_options(-fsanitize=undefined) + add_link_options(-fsanitize=undefined) +endif() + macro(make_test name) add_executable(${name} ${name}.cpp) target_link_libraries(${name} quickjs-dumpleaks) @@ -9,5 +14,9 @@ add_library(${name}-checkjsv OBJECT ${name}.cpp) target_compile_definitions(${name}-checkjsv PRIVATE CONFIG_CHECK_JSVALUE=1) endmacro() -make_test(value) -make_test(class) +foreach(test + value class exception example multicontext + ) +make_test(${test}) +endforeach() + diff --git a/test/example.cpp b/test/example.cpp new file mode 100644 index 0000000000..73eff19f59 --- /dev/null +++ b/test/example.cpp @@ -0,0 +1,53 @@ +#include "quickjspp.hpp" +#include + +class MyClass +{ +public: + MyClass() {} + MyClass(std::vector) {} + + double member_variable = 5.5; + std::string member_function(const std::string& s) { return "Hello, " + s; } +}; + +void println(const std::string& str) { std::cout << str << std::endl; } + +int main() +{ + qjs::Runtime runtime; + qjs::Context context(runtime); + try + { + // export classes as a module + auto& module = context.addModule("MyModule"); + module.function<&println>("println"); + module.class_("MyClass") + .constructor<>() + .constructor>("MyClassA") + .fun<&MyClass::member_variable>("member_variable") + .fun<&MyClass::member_function>("member_function"); + // import module + context.eval("import * as my from 'MyModule'; globalThis.my = my;", "", JS_EVAL_TYPE_MODULE); + // evaluate js code + context.eval("let v1 = new my.MyClass();" "\n" + "v1.member_variable = 1;" "\n" + "let v2 = new my.MyClassA([1,2,3]);" "\n" + "function my_callback(str) {" "\n" + " my.println(v2.member_function(str));" "\n" + "}" "\n" + ); + + // callback + auto cb = (std::function) context.eval("my_callback"); + cb("world"); + } + catch(qjs::exception) + { + auto exc = context.getException(); + std::cerr << (std::string) exc << std::endl; + if((bool) exc["stack"]) + std::cerr << (std::string) exc["stack"] << std::endl; + return 1; + } +} \ No newline at end of file diff --git a/test/exception.cpp b/test/exception.cpp new file mode 100644 index 0000000000..c595698299 --- /dev/null +++ b/test/exception.cpp @@ -0,0 +1,53 @@ +#include "quickjspp.hpp" +#include + +struct A{}; + +int main() +{ + qjs::Runtime runtime; + qjs::Context context(runtime); + context.global().add("println", [](const std::string& s) { std::cout << s << std::endl; }); + + context.registerClass("A"); + context.registerClass("A"); + + try + { + auto obj = context.eval("Symbol.toPrimitive"); + std::cout << static_cast(obj) << std::endl; + assert(false); + } + catch(qjs::exception) + { + auto exc = context.getException(); + assert(exc.isError() && (std::string) exc == "TypeError: cannot convert symbol to number"); + } + + try + { + std::string big; + big.resize((1 << 30) + 1); + auto fun = context.eval("(function(a, b, c) { println(a); println(b); println(c); })").as>(); + fun(0, std::move(big), 0); + assert(false); + } + catch(qjs::exception) + { + auto exc = context.getException(); + std::cout << (std::string) exc << '\n' << (std::string_view) exc["stack"]; + } + + try + { + //context.global().add("emptyf", [](JSValue v) {} ); + auto f = (std::function) context.eval("(function() { +Symbol.toPrimitive })"); + f(); + assert(false); + } + catch(qjs::exception) + { + auto exc = context.getException(); + std::cout << (std::string) exc << '\n' << (std::string_view) exc["stack"]; + } +} diff --git a/test/multicontext.cpp b/test/multicontext.cpp new file mode 100644 index 0000000000..c0d65c693f --- /dev/null +++ b/test/multicontext.cpp @@ -0,0 +1,62 @@ +#include "quickjspp.hpp" +#include + +class MyClass +{ +public: + MyClass() {} + + void print_context(qjs::Value value) { std::cout << "Context: " << value.ctx << '\n'; } +}; + +void println(const std::string& str) { std::cout << str << std::endl; } + +static void glue(qjs::Context::Module& module) +{ + module.function<&println>("println"); + module.class_("MyClass") + .constructor<>() + .fun<&MyClass::print_context>("print_context"); +} + + +int main() +{ + qjs::Runtime runtime; + qjs::Context context1(runtime); + qjs::Context context2(runtime); + try + { + // export classes as a module + glue(context1.addModule("MyModule")); + // evaluate js code + context1.eval("import * as my from 'MyModule'; " "\n" + "(new my.MyClass()).print_context(undefined);" "\n" + , "", JS_EVAL_TYPE_MODULE + ); + } + catch(qjs::exception) + { + auto exc = context1.getException(); + std::cerr << (std::string) exc << std::endl; + if((bool) exc["stack"]) + std::cerr << (std::string) exc["stack"] << std::endl; + return 1; + } + try + { + glue(context2.addModule("MyModule")); + context2.eval("import * as my from 'MyModule'; " "\n" + "(new my.MyClass()).print_context(undefined);" "\n" + ,"", JS_EVAL_TYPE_MODULE + ); + } + catch(qjs::exception) + { + auto exc = context2.getException(); + std::cerr << (std::string) exc << std::endl; + if((bool) exc["stack"]) + std::cerr << (std::string) exc["stack"] << std::endl; + return 1; + } +} \ No newline at end of file diff --git a/test/value.cpp b/test/value.cpp index c6b6f759c0..01ca7e5fc9 100644 --- a/test/value.cpp +++ b/test/value.cpp @@ -39,9 +39,9 @@ int main() // val1 = context.newObject(); - val1["a"] = 1; + val1["a"] = "1"; val2 = context.newObject(); - val2["a"] = 1; + val2["a"] = "1"; assert(val1 != val2); @@ -52,6 +52,8 @@ int main() assert((bool) context.eval("val1 != val2")); assert((bool)context.eval("JSON.stringify(val1) === JSON.stringify(val2)")); + qjs::Value one = val1["a"]; + assert((int)one == 1); } catch(qjs::exception) { From ff903f8bd671d18842f1b9c9de691487d6300175 Mon Sep 17 00:00:00 2001 From: ftk Date: Tue, 24 Sep 2019 19:35:58 +0000 Subject: [PATCH 035/185] remove usan option from cmake files --- test/CMakeLists.txt | 5 ----- 1 file changed, 5 deletions(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 35f6efbbf2..0555c50f83 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,10 +1,5 @@ include_directories(..) -if(UNIX AND CMAKE_COMPILER_IS_GNUCC) - add_compile_options(-fsanitize=undefined) - add_link_options(-fsanitize=undefined) -endif() - macro(make_test name) add_executable(${name} ${name}.cpp) target_link_libraries(${name} quickjs-dumpleaks) From 29e03b91be969a81ac28d1111433c468bf48da0b Mon Sep 17 00:00:00 2001 From: ftk Date: Tue, 24 Sep 2019 19:37:04 +0000 Subject: [PATCH 036/185] new readme. fix #2 --- readme.md | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ readme.txt | 19 --------------- 2 files changed, 69 insertions(+), 19 deletions(-) create mode 100644 readme.md delete mode 100644 readme.txt diff --git a/readme.md b/readme.md new file mode 100644 index 0000000000..1876a1e00f --- /dev/null +++ b/readme.md @@ -0,0 +1,69 @@ +QuickJSPP is QuickJS wrapper for C++. It allows you to easily embed Javascript engine into your program. + +QuickJS is a small and embeddable Javascript engine. It supports the ES2020 specification including modules, asynchronous generators and proxies. More info: + +# Example +```cpp +#include "quickjspp.hpp" +#include + +class MyClass +{ +public: + MyClass() {} + MyClass(std::vector) {} + + double member_variable = 5.5; + std::string member_function(const std::string& s) { return "Hello, " + s; } +}; + +void println(const std::string& str) { std::cout << str << std::endl; } + +int main() +{ + qjs::Runtime runtime; + qjs::Context context(runtime); + try + { + // export classes as a module + auto& module = context.addModule("MyModule"); + module.function<&println>("println"); + module.class_("MyClass") + .constructor<>() + .constructor>("MyClassA") + .fun<&MyClass::member_variable>("member_variable") + .fun<&MyClass::member_function>("member_function"); + // import module + context.eval("import * as my from 'MyModule'; globalThis.my = my;", "", JS_EVAL_TYPE_MODULE); + // evaluate js code + context.eval("let v1 = new my.MyClass();" "\n" + "v1.member_variable = 1;" "\n" + "let v2 = new my.MyClassA([1,2,3]);" "\n" + "function my_callback(str) {" "\n" + " my.println(v2.member_function(str));" "\n" + "}" "\n" + ); + + // callback + auto cb = (std::function) context.eval("my_callback"); + cb("world"); + } + catch(qjs::exception) + { + auto exc = context.getException(); + std::cerr << (std::string) exc << std::endl; + if((bool) exc["stack"]) + std::cerr << (std::string) exc["stack"] << std::endl; + return 1; + } +} +``` + +# Installation +QuickJSPP is header-only - put quickjspp.hpp into your include search path. +Compiler that supports C++17 or later is required. +The program needs to be linked against QuickJS. +Sample CMake project files are provided. + +# License +QuickJSPP is licensed under [CC0](https://creativecommons.org/publicdomain/zero/1.0/). QuickJS is licensed under [MIT](https://opensource.org/licenses/MIT). diff --git a/readme.txt b/readme.txt deleted file mode 100644 index 2b3118454e..0000000000 --- a/readme.txt +++ /dev/null @@ -1,19 +0,0 @@ -QuickJS wrapper for C++. - - -* Status -+ conversions between int32_t, std::string, bool, double and JSValue -+ basic support for classes -+ basic support for modules -+ automatic function wrapping and unwrapping -- exception interop -- tests for memory leaks - -* Installation -QuickJSPP is header-only - C++17 or later is required. QuickJS needs to be compiled. Sample CMake files are provided. - -* Notes -A small patch for C++ support is applied to quickjs.h. - -* License -QuickJSPP is licensed under CC0 (https://creativecommons.org/publicdomain/zero/1.0/). From d169272302010b8c803863d8db9162ab0325950d Mon Sep 17 00:00:00 2001 From: ftk Date: Tue, 24 Sep 2019 20:17:31 +0000 Subject: [PATCH 037/185] doxygen autodoc --- .github/workflows/doxygen.yml | 23 + Doxyfile | 2464 +++++++++++++++++++++++++++++++++ quickjspp.hpp | 12 +- 3 files changed, 2493 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/doxygen.yml create mode 100644 Doxyfile diff --git a/.github/workflows/doxygen.yml b/.github/workflows/doxygen.yml new file mode 100644 index 0000000000..03de2e5c9c --- /dev/null +++ b/.github/workflows/doxygen.yml @@ -0,0 +1,23 @@ +name: Doxygen gh-pages +on: + push: + branches: + - master + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: Doxygen install + run: sudo apt-get install -y doxygen graphviz + - name: Doxygen + run: doxygen + - name: Deploy to gh-pages + uses: peaceiris/actions-gh-pages@v2.3.2 + env: + PERSONAL_TOKEN: ${{ secrets.TOKEN }} + PUBLISH_BRANCH: gh-pages + PUBLISH_DIR: ./html + with: + emptyCommits: false diff --git a/Doxyfile b/Doxyfile new file mode 100644 index 0000000000..e13744773b --- /dev/null +++ b/Doxyfile @@ -0,0 +1,2464 @@ +# Doxyfile 1.8.13 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all text +# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv +# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv +# for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = "QuickJSPP" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify a logo or an icon that is included +# in the documentation. The maximum height of the logo should not exceed 55 +# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy +# the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +CREATE_SUBDIRS = NO + +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = YES + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = YES + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new +# page for each member. If set to NO, the documentation of a member will be part +# of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: +# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: +# Fortran. In the later case the parser tries to guess whether the code is fixed +# or free formatted code, this is the default for Fortran type files), VHDL. For +# instance to make doxygen treat .inc files as Fortran files (default is PHP), +# and .f files as C (default is Fortran), use: inc=Fortran f=C. +# +# Note: For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up +# to that level are automatically included in the table of contents, even if +# they do not have an id attribute. +# Note: This feature currently applies only to Markdown headings. +# Minimum value: 0, maximum value: 99, default value: 0. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +TOC_INCLUDE_HEADINGS = 0 + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = YES + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# If one adds a struct or class to a group and this option is enabled, then also +# any nested class or struct is added to the same group. By default this option +# is disabled and one has to add nested compounds explicitly via \ingroup. +# The default value is: NO. + +GROUP_NESTED_COMPOUNDS = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = YES + +# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO, +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. If set to YES, local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO, only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO, these classes will be included in the various overviews. This option +# has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO, these declarations will be +# included in the documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO, these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES, upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. +# The default value is: system dependent. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES, the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = NO + +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will +# append additional text to a page's title, such as Class Reference. If set to +# YES the compound reference will be hidden. +# The default value is: NO. + +HIDE_COMPOUND_REFERENCE= NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = YES + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = NO + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = YES + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo +# list. This list is created by putting \todo commands in the documentation. +# The default value is: YES. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test +# list. This list is created by putting \test commands in the documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES, the +# list will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO, doxygen will only warn about wrong or incomplete +# parameter documentation, but not about the absence of documentation. +# The default value is: NO. + +WARN_NO_PARAMDOC = NO + +# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when +# a warning is encountered. +# The default value is: NO. + +WARN_AS_ERROR = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING +# Note: If this tag is empty the current directory is searched. + +INPUT = . \ + quickjs + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: http://www.gnu.org/software/libiconv) for the list of +# possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# read by doxygen. +# +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, +# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, +# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, +# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, +# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf and *.qsf. + +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.md \ + *.py \ + *.pyw + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = test + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = *.cpp + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = readme.md + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = YES + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# function all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = YES + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = NO + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see http://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + +# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the +# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the +# cost of reduced performance. This can be particularly helpful with template +# rich C++ code for which doxygen's built-in parser lacks the necessary type +# information. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse-libclang=ON option for CMake. +# The default value is: NO. + +CLANG_ASSISTED_PARSING = YES + +# If clang assisted parsing is enabled you can provide the compiler with command +# line options that you would normally use when invoking the compiler. Note that +# the include paths will already be set by doxygen for the files and directories +# specified with INPUT and INCLUDE_PATH. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. + +CLANG_OPTIONS = -std=c++17 + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = YES + +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefore more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). For an example see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the style sheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# http://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to YES can help to show when doxygen was last run and thus if the +# documentation is up to date. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = NO + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: http://developer.apple.com/tools/xcode/), introduced with +# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler (hhc.exe). If non-empty, +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated +# (YES) or that it should be included in the master .chm file (NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated +# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- +# folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# http://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from http://www.mathjax.org before deployment. +# The default value is: http://cdn.mathjax.org/mathjax/latest. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /