aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/app/qbs/commandlinefrontend.cpp13
-rw-r--r--src/conan/extensions/generators/qbsdeps.py218
-rw-r--r--src/lib/corelib/buildgraph/abstractcommandexecutor.cpp11
-rw-r--r--src/lib/corelib/buildgraph/qtmocscanner.cpp13
-rw-r--r--src/lib/corelib/buildgraph/rulecommands.cpp11
-rw-r--r--src/lib/corelib/buildgraph/rulecommands.h2
-rw-r--r--src/lib/corelib/buildgraph/rulesapplicator.cpp17
-rw-r--r--src/lib/corelib/jsextensions/domxml.cpp2
-rw-r--r--src/lib/corelib/jsextensions/moduleproperties.cpp2
-rw-r--r--src/lib/corelib/language/scriptengine.cpp34
-rw-r--r--src/lib/corelib/language/scriptengine.h2
-rw-r--r--src/lib/corelib/loader/itemreaderastvisitor.cpp2
-rw-r--r--src/lib/corelib/loader/moduleproviderloader.cpp4
-rw-r--r--src/lib/corelib/tools/scripttools.cpp9
-rw-r--r--src/lib/corelib/tools/scripttools.h2
-rw-r--r--src/shared/quickjs/.clang-format2
-rw-r--r--src/shared/quickjs/CMakeLists.txt1
-rw-r--r--src/shared/quickjs/LICENSE2
-rw-r--r--src/shared/quickjs/cutils.c6
-rw-r--r--src/shared/quickjs/cutils.h90
-rw-r--r--src/shared/quickjs/libbf.c8475
-rw-r--r--src/shared/quickjs/libbf.h543
-rw-r--r--src/shared/quickjs/libregexp-opcode.h5
-rw-r--r--src/shared/quickjs/libregexp.c483
-rw-r--r--src/shared/quickjs/libregexp.h49
-rw-r--r--src/shared/quickjs/libunicode-table.h2650
-rw-r--r--src/shared/quickjs/libunicode.c518
-rw-r--r--src/shared/quickjs/libunicode.h102
-rw-r--r--src/shared/quickjs/list.h11
-rw-r--r--src/shared/quickjs/quickjs-atom.h18
-rw-r--r--src/shared/quickjs/quickjs-opcode.h23
-rw-r--r--src/shared/quickjs/quickjs.c7962
-rw-r--r--src/shared/quickjs/quickjs.diff4061
-rw-r--r--src/shared/quickjs/quickjs.h59
-rw-r--r--src/shared/quickjs/quickjs.qbs5
35 files changed, 16516 insertions, 8891 deletions
diff --git a/src/app/qbs/commandlinefrontend.cpp b/src/app/qbs/commandlinefrontend.cpp
index 4a4781207..200740145 100644
--- a/src/app/qbs/commandlinefrontend.cpp
+++ b/src/app/qbs/commandlinefrontend.cpp
@@ -490,9 +490,22 @@ QString CommandLineFrontend::buildDirectory(const QString &profileName) const
}
QString projectName(QFileInfo(m_parser.projectFilePath()).baseName());
+ QString originalBuildDir = buildDir;
buildDir.replace(BuildDirectoryOption::magicProjectString(), projectName);
+ const QString buildDirPlaceHolderMsgTemplate = Tr::tr(
+ "You must provide the path to the project file when using build directory "
+ "placeholder '%1'.");
+ if (buildDir != originalBuildDir && projectName.isEmpty()) {
+ throw ErrorInfo(
+ buildDirPlaceHolderMsgTemplate.arg(BuildDirectoryOption::magicProjectString()));
+ }
QString projectDir(QFileInfo(m_parser.projectFilePath()).path());
+ originalBuildDir = buildDir;
buildDir.replace(BuildDirectoryOption::magicProjectDirString(), projectDir);
+ if (buildDir != originalBuildDir && projectDir.isEmpty()) {
+ throw ErrorInfo(
+ buildDirPlaceHolderMsgTemplate.arg(BuildDirectoryOption::magicProjectDirString()));
+ }
if (!QFileInfo(buildDir).isAbsolute())
buildDir = QDir::currentPath() + QLatin1Char('/') + buildDir;
buildDir = QDir::cleanPath(buildDir);
diff --git a/src/conan/extensions/generators/qbsdeps.py b/src/conan/extensions/generators/qbsdeps.py
new file mode 100644
index 000000000..77d875aa8
--- /dev/null
+++ b/src/conan/extensions/generators/qbsdeps.py
@@ -0,0 +1,218 @@
+############################################################################
+##
+## Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com).
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of Qbs.
+##
+## $QT_BEGIN_LICENSE:LGPL$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see https://www.qt.io/terms-conditions. For further
+## information use the contact form at https://www.qt.io/contact-us.
+##
+## GNU Lesser General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU Lesser
+## General Public License version 3 as published by the Free Software
+## Foundation and appearing in the file LICENSE.LGPL3 included in the
+## packaging of this file. Please review the following information to
+## ensure the GNU Lesser General Public License version 3 requirements
+## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 2.0 or (at your option) the GNU General
+## Public license version 3 or any later version approved by the KDE Free
+## Qt Foundation. The licenses are as published by the Free Software
+## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+## included in the packaging of this file. Please review the following
+## information to ensure the GNU General Public License requirements will
+## be met: https://www.gnu.org/licenses/gpl-2.0.html and
+## https://www.gnu.org/licenses/gpl-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+############################################################################
+
+from conan.tools.files import save
+from conan.errors import ConanException
+from conans.model.dependencies import get_transitive_requires
+import json
+import os
+
+
+class _QbsDepsModuleFile():
+ def __init__(self, qbsdeps, dep, component, deps, module_name):
+ self._qbsdeps = qbsdeps
+ self._dep = dep
+ self._component = component
+ self._deps = deps
+ self._module_name = module_name
+ self._build_bindirs = qbsdeps._build_bindirs
+
+ def _get_component_version(dep, component):
+ return (component.get_property("component_version") or
+ component.get_property("system_package_version") or
+ dep.ref.version)
+ self._version = _get_component_version(self._dep, self._component)
+
+ @property
+ def filename(self):
+ return self._module_name + '.json'
+
+ @property
+ def version(self):
+ return self._version
+
+ def get_content(self):
+ return {
+ 'package_name': self._dep.ref.name,
+ 'package_dir': self._get_package_dir(),
+ 'version': str(self._version),
+ 'cpp_info': self._component.serialize(),
+ 'build_bindirs': self._build_bindirs,
+ 'dependencies': [{'name': n, "version": str(v)} for n, v in self._deps],
+ 'settings': {k: v for k, v in self._dep.settings.items()},
+ 'options': {k: v for k, v in self._dep.options.items()}
+ }
+
+ def _get_package_dir(self):
+ # If editable, package_folder can be None
+ return self._dep.recipe_folder if self._dep.package_folder is None \
+ else self._dep.package_folder
+
+ def render(self):
+ return json.dumps(self.get_content(), indent=4)
+
+
+class _QbsDepGenerator:
+ ''' Handles a single package, can create multiple modules in case of several components '''
+ def __init__(self, conanfile, dep, build_bindirs):
+ self._conanfile = conanfile
+ self._dep = dep
+ self._build_bindirs = build_bindirs
+
+ @property
+ def content(self):
+ qbs_files = {}
+ transitive_reqs = get_transitive_requires(self._conanfile, self._dep)
+
+ def _get_package_name(dep):
+ # TODO: pkgconfig uses suffix, do we need it? see:
+ # https://github.com/conan-io/conan/blob/develop2/conan/tools/gnu/pkgconfigdeps.py#L319
+ return dep.cpp_info.get_property("pkg_config_name") or dep.ref.name
+
+ def _get_component_name(dep, comp_name):
+ if comp_name not in dep.cpp_info.components:
+ if dep.ref.name == comp_name:
+ return _get_package_name(dep)
+ raise ConanException("Component '{name}::{cname}' not found in '{name}' "
+ "package requirement".format(name=dep.ref.name,
+ cname=comp_name))
+
+ # TODO: pkgconfig uses suffix, do we need it?
+ # We re-use pkg_config_name for compatiblitity with the Qbs pkg-config provider:
+ # in that case, Qbs/its users do not need to do additional mapping on their side
+ pkg_config_name = dep.cpp_info.components[comp_name].get_property("pkg_config_name")
+ return pkg_config_name or comp_name
+
+ def _get_name_with_namespace(namespace, name):
+ """
+ Build a name with a namespace, e.g., openssl-crypto
+ """
+ return f"{namespace}-{name}"
+
+ def get_components(dep):
+ ret = {}
+ for comp_ref_name, info in dep.cpp_info.get_sorted_components().items():
+ comp_name = _get_component_name(dep, comp_ref_name)
+ ret[comp_name] = info
+ return ret
+
+ # copy & paste from pkgconfig deps
+ def get_cpp_info_requires_names(dep, cpp_info):
+ ret = []
+ dep_ref_name = dep.ref.name
+ for req in cpp_info.requires:
+ pkg_ref_name, comp_ref_name = (
+ req.split("::") if "::" in req else (dep_ref_name, req)
+ )
+
+ if dep_ref_name != pkg_ref_name:
+ try:
+ req_conanfile = transitive_reqs[pkg_ref_name]
+ except KeyError:
+ # If the dependency is not in the transitive, might be skipped
+ continue
+ # For instance, dep == "hello/1.0" and req == "hello::cmp1" -> hello == hello
+ else:
+ req_conanfile = dep
+
+ comp_name = _get_component_name(req_conanfile, comp_ref_name)
+ if not comp_name:
+ pkg_name = _get_package_name(req_conanfile)
+ # Creating a component name with namespace, e.g., dep-comp1
+ comp_name = _get_name_with_namespace(pkg_name, comp_ref_name)
+ ret.append((comp_name, req_conanfile.ref.version))
+ return ret
+
+ if not self._dep.cpp_info.has_components:
+ module_name = _get_package_name(self._dep)
+ requires = get_cpp_info_requires_names(self._dep, self._dep.cpp_info._package)
+ if not requires:
+ # If no requires were found, let's try to get all the direct visible
+ # dependencies, e.g., requires = "other_pkg/1.0"
+ for deprequire, _ in self._dep.dependencies.direct_host.items():
+ requires.append((deprequire.ref.name, deprequire.ref.version))
+ file = _QbsDepsModuleFile(
+ self, self._dep, self._dep.cpp_info._package, requires, module_name
+ )
+ qbs_files[file.filename] = file
+ else:
+ full_requires = []
+ for module_name, component in get_components(self._dep).items():
+ requires = get_cpp_info_requires_names(self._dep, component)
+ file = _QbsDepsModuleFile(self, self._dep, component, requires, module_name)
+ qbs_files[file.filename] = file
+ full_requires.append((module_name, file.version))
+ module_name = _get_package_name(self._dep)
+ file = _QbsDepsModuleFile(
+ self, self._dep, self._dep.cpp_info._package, full_requires, module_name)
+ # We create the root package's module file ONLY
+ # if it does not already exist in components
+ # An example is a grpc package where they have a "grpc" component
+ if file.filename not in qbs_files:
+ qbs_files[file.filename] = file
+
+ return qbs_files
+
+
+class QbsDeps:
+ ''' Handles multiple packages '''
+ def __init__(self, conanfile):
+ self._conanfile = conanfile
+
+ @property
+ def content(self):
+ qbs_files = {}
+
+ build_bindirs = {
+ dep.ref.name: dep.cpp_info.bindirs
+ for _, dep in self._conanfile.dependencies.build.items()}
+
+ for require, dep in self._conanfile.dependencies.items():
+
+ # skip build deps for now
+ if require.build:
+ continue
+
+ dep_build_bindirs = build_bindirs.get(dep.ref.name, [])
+ qbs_files.update(_QbsDepGenerator(self._conanfile, dep, dep_build_bindirs).content)
+ return qbs_files
+
+ def generate(self):
+ for file_name, qbs_deps_file in self.content.items():
+ save(self._conanfile, os.path.join('conan-qbs-deps', file_name), qbs_deps_file.render())
diff --git a/src/lib/corelib/buildgraph/abstractcommandexecutor.cpp b/src/lib/corelib/buildgraph/abstractcommandexecutor.cpp
index 16c3621b6..ee82de43d 100644
--- a/src/lib/corelib/buildgraph/abstractcommandexecutor.cpp
+++ b/src/lib/corelib/buildgraph/abstractcommandexecutor.cpp
@@ -60,13 +60,12 @@ AbstractCommandExecutor::AbstractCommandExecutor(Logger logger, QObject *parent)
, m_logger(std::move(logger))
{
m_watchdog.setSingleShot(true);
- connect(&m_watchdog, &QTimer::timeout,
- this, [this]() {
- cancel(ErrorInfo{Tr::tr("Command cancelled because it exceeded the timeout.")});
+ connect(&m_watchdog, &QTimer::timeout, this, [this]() {
+ cancel(ErrorInfo{Tr::tr("Command cancelled because it exceeded the timeout: %1")
+ .arg(m_command->descriptionForCancelMessage(
+ m_transformer->product()->fullDisplayName()))});
});
- connect(this, &AbstractCommandExecutor::finished,
- &m_watchdog, &QTimer::stop);
-
+ connect(this, &AbstractCommandExecutor::finished, &m_watchdog, &QTimer::stop);
}
void AbstractCommandExecutor::start(Transformer *transformer, AbstractCommand *cmd)
diff --git a/src/lib/corelib/buildgraph/qtmocscanner.cpp b/src/lib/corelib/buildgraph/qtmocscanner.cpp
index 7df84e52c..fb9f08694 100644
--- a/src/lib/corelib/buildgraph/qtmocscanner.cpp
+++ b/src/lib/corelib/buildgraph/qtmocscanner.cpp
@@ -109,7 +109,7 @@ QtMocScanner::QtMocScanner(const ResolvedProductPtr &product, ScriptEngine *engi
attachPointerTo(scannerObj, this);
setJsProperty(engine->context(), targetScriptValue, qtMocScannerJsName(), scannerObj);
JSValue applyFunction = JS_NewCFunction(engine->context(), &js_apply, "QtMocScanner", 1);
- setJsProperty(engine->context(), scannerObj, QStringLiteral("apply"), applyFunction);
+ setJsProperty(engine->context(), scannerObj, std::string_view("apply"), applyFunction);
}
QtMocScanner::~QtMocScanner()
@@ -269,10 +269,13 @@ JSValue QtMocScanner::apply(ScriptEngine *engine, const Artifact *artifact)
JSValue obj = engine->newObject();
JSContext * const ctx = m_engine->context();
- setJsProperty(ctx, obj, QStringLiteral("hasQObjectMacro"), JS_NewBool(ctx, hasQObjectMacro));
- setJsProperty(ctx, obj, QStringLiteral("mustCompile"), JS_NewBool(ctx, mustCompile));
- setJsProperty(ctx, obj, QStringLiteral("hasPluginMetaDataMacro"),
- JS_NewBool(ctx, hasPluginMetaDataMacro));
+ setJsProperty(ctx, obj, std::string_view("hasQObjectMacro"), JS_NewBool(ctx, hasQObjectMacro));
+ setJsProperty(ctx, obj, std::string_view("mustCompile"), JS_NewBool(ctx, mustCompile));
+ setJsProperty(
+ ctx,
+ obj,
+ std::string_view("hasPluginMetaDataMacro"),
+ JS_NewBool(ctx, hasPluginMetaDataMacro));
engine->setUsesIo();
return obj;
}
diff --git a/src/lib/corelib/buildgraph/rulecommands.cpp b/src/lib/corelib/buildgraph/rulecommands.cpp
index 73d05eaca..be90c2fd5 100644
--- a/src/lib/corelib/buildgraph/rulecommands.cpp
+++ b/src/lib/corelib/buildgraph/rulecommands.cpp
@@ -135,6 +135,11 @@ QString AbstractCommand::fullDescription(const QString &productName) const
return description() + QLatin1String(" [") + productName + QLatin1Char(']');
}
+QString AbstractCommand::descriptionForCancelMessage(const QString &productName) const
+{
+ return fullDescription(productName);
+}
+
void AbstractCommand::load(PersistentPool &pool)
{
serializationOp<PersistentPool::Load>(pool);
@@ -335,6 +340,12 @@ void ProcessCommand::fillFromScriptValue(JSContext *ctx, const JSValue *scriptVa
applyCommandProperties(ctx, scriptValue);
}
+QString ProcessCommand::descriptionForCancelMessage(const QString &productName) const
+{
+ return description() + QLatin1String(" (") + QDir::toNativeSeparators(m_program)
+ + QLatin1String(") [") + productName + QLatin1Char(']');
+}
+
QStringList ProcessCommand::relevantEnvVars() const
{
QStringList vars = m_relevantEnvVars;
diff --git a/src/lib/corelib/buildgraph/rulecommands.h b/src/lib/corelib/buildgraph/rulecommands.h
index 7b08d1015..4296146d2 100644
--- a/src/lib/corelib/buildgraph/rulecommands.h
+++ b/src/lib/corelib/buildgraph/rulecommands.h
@@ -78,6 +78,7 @@ public:
virtual bool equals(const AbstractCommand *other) const;
virtual void fillFromScriptValue(JSContext *ctx, const JSValue *scriptValue,
const CodeLocation &codeLocation);
+ virtual QString descriptionForCancelMessage(const QString &productName) const;
QString fullDescription(const QString &productName) const;
const QString description() const { return m_description; }
@@ -129,6 +130,7 @@ public:
bool equals(const AbstractCommand *otherAbstractCommand) const override;
void fillFromScriptValue(JSContext *ctx, const JSValue *scriptValue,
const CodeLocation &codeLocation) override;
+ QString descriptionForCancelMessage(const QString &productName) const override;
const QString program() const { return m_program; }
const QStringList arguments() const { return m_arguments; }
const QString workingDir() const { return m_workingDir; }
diff --git a/src/lib/corelib/buildgraph/rulesapplicator.cpp b/src/lib/corelib/buildgraph/rulesapplicator.cpp
index e07abd74a..94cee0c62 100644
--- a/src/lib/corelib/buildgraph/rulesapplicator.cpp
+++ b/src/lib/corelib/buildgraph/rulesapplicator.cpp
@@ -420,11 +420,7 @@ RulesApplicator::OutputArtifactInfo RulesApplicator::createOutputArtifactFromRul
RulesApplicator::OutputArtifactInfo RulesApplicator::createOutputArtifact(const QString &filePath,
const FileTags &fileTags, bool alwaysUpdated, const ArtifactSet &inputArtifacts)
{
- QString outputPath = filePath;
- // don't let the output artifact "escape" its build dir
- outputPath.replace(StringConstants::dotDot(), QStringLiteral("dotdot"));
- outputPath = resolveOutPath(outputPath);
-
+ const QString outputPath = resolveOutPath(filePath);
if (m_rule->isDynamic()) {
const Set<FileTag> undeclaredTags = fileTags - m_rule->collectedOutputFileTags();
if (!undeclaredTags.empty()) {
@@ -676,9 +672,14 @@ Artifact *RulesApplicator::createOutputArtifactFromScriptValue(const JSValue &ob
QString RulesApplicator::resolveOutPath(const QString &path) const
{
- QString buildDir = m_product->topLevelProject()->buildDirectory;
- QString result = FileInfo::resolvePath(buildDir, path);
- result = QDir::cleanPath(result);
+ const QString buildDir = m_product->topLevelProject()->buildDirectory;
+ QString result = QDir::cleanPath(FileInfo::resolvePath(buildDir, path));
+ if (!result.startsWith(buildDir + QLatin1Char('/'))) {
+ throw ErrorInfo(
+ Tr::tr("Refusing to create artifact '%1' outside of build directory '%2'.")
+ .arg(QDir::toNativeSeparators(result), QDir::toNativeSeparators(buildDir)),
+ m_rule->prepareScript.location());
+ }
return result;
}
diff --git a/src/lib/corelib/jsextensions/domxml.cpp b/src/lib/corelib/jsextensions/domxml.cpp
index 35cff186b..e065124e6 100644
--- a/src/lib/corelib/jsextensions/domxml.cpp
+++ b/src/lib/corelib/jsextensions/domxml.cpp
@@ -549,5 +549,5 @@ void initializeJsExtensionXml(qbs::Internal::ScriptEngine *engine, JSValue exten
JSValue contextObject = engine->newObject();
XmlDomNode<QDomNode>::registerClass(engine, contextObject);
XmlDomNode<QDomDocument>::registerClass(engine, contextObject);
- setJsProperty(engine->context(), extensionObject, QLatin1String("Xml"), contextObject);
+ setJsProperty(engine->context(), extensionObject, std::string_view("Xml"), contextObject);
}
diff --git a/src/lib/corelib/jsextensions/moduleproperties.cpp b/src/lib/corelib/jsextensions/moduleproperties.cpp
index 2c73f2c53..f3583c872 100644
--- a/src/lib/corelib/jsextensions/moduleproperties.cpp
+++ b/src/lib/corelib/jsextensions/moduleproperties.cpp
@@ -234,7 +234,7 @@ static void initModuleProperties(ScriptEngine *engine, JSValue objectWithPropert
{
JSContext * const ctx = engine->context();
JSValue func = JS_NewCFunction(ctx, js_moduleProperty<ProductOrArtifact>, "moduleProperty", 2);
- setJsProperty(ctx, objectWithProperties, QStringLiteral("moduleProperty"), func);
+ setJsProperty(ctx, objectWithProperties, std::string_view("moduleProperty"), func);
}
static JSValue setupBaseModuleScriptValue(ScriptEngine *engine, const ResolvedModule *module)
diff --git a/src/lib/corelib/language/scriptengine.cpp b/src/lib/corelib/language/scriptengine.cpp
index 9131db7f5..6c0e4d770 100644
--- a/src/lib/corelib/language/scriptengine.cpp
+++ b/src/lib/corelib/language/scriptengine.cpp
@@ -137,18 +137,25 @@ LookupResult ScriptEngine::doExtraScopeLookup(JSContext *ctx, JSAtom prop)
ScriptEngine * const engine = engineForContext(ctx);
engine->m_lastLookupWasSuccess = false;
- JSValueList scopes;
- if (!engine->m_scopeChains.isEmpty())
- scopes = engine->m_scopeChains.last();
- if (JS_IsObject(engine->m_globalObject))
- scopes.insert(scopes.begin(), engine->m_globalObject);
- for (auto it = scopes.rbegin(); it != scopes.rend(); ++it) {
- const JSValue v = JS_GetProperty(ctx, *it, prop);
+ auto handleScope = [ctx, prop, engine](const JSValue &scope) -> LookupResult {
+ const JSValue v = JS_GetProperty(ctx, scope, prop);
if (!JS_IsUndefined(v) || engine->m_lastLookupWasSuccess) {
engine->m_lastLookupWasSuccess = false;
- return {v, *it, true};
+ return {v, scope, true};
+ }
+ return fail;
+ };
+
+ if (!engine->m_scopeChains.empty()) {
+ const JSValueList &scopes = engine->m_scopeChains.back().get();
+ for (auto it = scopes.rbegin(); it != scopes.rend(); ++it) {
+ const auto res = handleScope(*it);
+ if (res.useResult)
+ return res;
}
}
+ if (JS_IsObject(engine->m_globalObject))
+ return handleScope(engine->m_globalObject);
return fail;
}
@@ -510,8 +517,7 @@ JSValue ScriptEngine::asJsValue(const QVariant &v, quintptr id, bool frozen)
case QMetaType::Bool:
return JS_NewBool(m_context, v.toBool());
case QMetaType::QDateTime:
- return JS_NewDate(
- m_context, v.toDateTime().toString(Qt::ISODateWithMs).toUtf8().constData());
+ return JS_NewDate(m_context, v.toDateTime().toMSecsSinceEpoch());
case QMetaType::QVariantMap:
return asJsValue(v.toMap(), id, frozen);
default:
@@ -538,7 +544,7 @@ JSValue ScriptEngine::asJsValue(const QString &s)
JSValue ScriptEngine::asJsValue(const QStringList &l)
{
JSValue array = JS_NewArray(m_context);
- setJsProperty(m_context, array, QLatin1String("length"), JS_NewInt32(m_context, l.size()));
+ setJsProperty(m_context, array, std::string_view("length"), JS_NewInt32(m_context, l.size()));
for (int i = 0; i < l.size(); ++i)
JS_SetPropertyUint32(m_context, array, i, asJsValue(l.at(i)));
return array;
@@ -574,7 +580,7 @@ JSValue ScriptEngine::asJsValue(const QVariantList &l, quintptr id, bool frozen)
return JS_DupValue(m_context, it.value());
frozen = id || frozen;
JSValue array = JS_NewArray(m_context);
- setJsProperty(m_context, array, QLatin1String("length"), JS_NewInt32(m_context, l.size()));
+ setJsProperty(m_context, array, std::string_view("length"), JS_NewInt32(m_context, l.size()));
for (int i = 0; i < l.size(); ++i)
JS_SetPropertyUint32(m_context, array, i, asJsValue(l.at(i), 0, frozen));
if (frozen)
@@ -805,14 +811,14 @@ JSValue ScriptEngine::newArray(int length, JsValueOwner owner)
JSValue ScriptEngine::evaluate(JsValueOwner resultOwner, const QString &code,
const QString &filePath, int line, const JSValueList &scopeChain)
{
- m_scopeChains << scopeChain;
+ m_scopeChains.emplace_back(scopeChain);
const QByteArray &codeStr = code.toUtf8();
m_evalPositions.emplace(filePath, line);
const JSValue v = JS_EvalThis(m_context, globalObject(), codeStr.constData(), codeStr.length(),
filePath.toUtf8().constData(), line, JS_EVAL_TYPE_GLOBAL);
m_evalPositions.pop();
- m_scopeChains.removeLast();
+ m_scopeChains.pop_back();
if (resultOwner == JsValueOwner::ScriptEngine && JS_VALUE_HAS_REF_COUNT(v))
++m_evalResults[v];
return v;
diff --git a/src/lib/corelib/language/scriptengine.h b/src/lib/corelib/language/scriptengine.h
index 4a55392e3..8efa2d482 100644
--- a/src/lib/corelib/language/scriptengine.h
+++ b/src/lib/corelib/language/scriptengine.h
@@ -392,7 +392,7 @@ private:
std::unordered_map<const ResolvedModule *, JSValue> m_moduleArtifactsMapScriptValues;
std::unordered_map<const ResolvedProject *, JSValue> m_projectScriptValues;
std::unordered_map<const ResolvedModule *, JSValue> m_baseModuleScriptValues;
- QList<JSValueList> m_scopeChains;
+ std::vector<std::reference_wrapper<const JSValueList>> m_scopeChains;
JSValueList m_contextStack;
QHash<JSClassID, JSClassExoticMethods> m_exoticMethods;
QHash<QString, JSClassID> m_classes;
diff --git a/src/lib/corelib/loader/itemreaderastvisitor.cpp b/src/lib/corelib/loader/itemreaderastvisitor.cpp
index fe0d6c190..c3e6b9b89 100644
--- a/src/lib/corelib/loader/itemreaderastvisitor.cpp
+++ b/src/lib/corelib/loader/itemreaderastvisitor.cpp
@@ -248,6 +248,8 @@ bool ItemReaderASTVisitor::visit(AST::UiScriptBinding *ast)
const auto * const idExp = AST::cast<AST::IdentifierExpression *>(expStmt->expression);
if (Q_UNLIKELY(!idExp || idExp->name.isEmpty()))
throw ErrorInfo(Tr::tr("id: must be followed by identifier"));
+ if (m_item->type() == ItemType::Module)
+ throw ErrorInfo(Tr::tr("Module items cannot have an id property."));
m_item->m_id = idExp->name.toString();
m_file->ensureIdScope(m_itemPool);
ItemValueConstPtr existingId = m_file->idScope()->itemProperty(m_item->id(), *m_itemPool);
diff --git a/src/lib/corelib/loader/moduleproviderloader.cpp b/src/lib/corelib/loader/moduleproviderloader.cpp
index 086448955..d0789facd 100644
--- a/src/lib/corelib/loader/moduleproviderloader.cpp
+++ b/src/lib/corelib/loader/moduleproviderloader.cpp
@@ -362,7 +362,9 @@ ModuleProviderLoader::EvaluationResult ModuleProviderLoader::evaluateModuleProvi
BuiltinDeclarations::instance().nameForType(ItemType::ModuleProvider)));
}
- providerItem->setScope(createProviderScope(product, qbsModule));
+ Item * const scope = createProviderScope(product, qbsModule);
+ for (auto it = providerItem->properties().begin(); it != providerItem->properties().end(); ++it)
+ it.value()->setScope(scope, {});
providerItem->setProperty(
StringConstants::nameProperty(),
VariantValue::create(name.toString()));
diff --git a/src/lib/corelib/tools/scripttools.cpp b/src/lib/corelib/tools/scripttools.cpp
index e89e4a0ad..6aa44adbb 100644
--- a/src/lib/corelib/tools/scripttools.cpp
+++ b/src/lib/corelib/tools/scripttools.cpp
@@ -136,10 +136,15 @@ JSValue getJsProperty(JSContext *ctx, JSValue obj, const QString &prop)
return JS_GetPropertyStr(ctx, obj, prop.toUtf8().constData());
}
+void setJsProperty(JSContext *ctx, JSValueConst obj, std::string_view prop, JSValue val)
+{
+ JS_SetPropertyStr(ctx, obj, prop.data(), val);
+}
+
void setJsProperty(JSContext *ctx, JSValue obj, const QString &prop, JSValue val)
{
- if (JS_SetPropertyStr(ctx, obj, prop.toUtf8().constData(), val) <= 0)
- qDebug() << "Oje!";
+ const auto propUtf8 = prop.toUtf8();
+ setJsProperty(ctx, obj, std::string_view{propUtf8.data(), size_t(propUtf8.size())}, val);
}
void setJsProperty(JSContext *ctx, JSValue obj, const QString &prop, const QString &val)
diff --git a/src/lib/corelib/tools/scripttools.h b/src/lib/corelib/tools/scripttools.h
index ac7ed9928..20964cae5 100644
--- a/src/lib/corelib/tools/scripttools.h
+++ b/src/lib/corelib/tools/scripttools.h
@@ -50,6 +50,7 @@
#include <QtCore/qstringlist.h>
#include <QtCore/qvariant.h>
+#include <string_view>
#include <utility>
#include <vector>
@@ -62,6 +63,7 @@ using JSValueList = std::vector<JSValue>;
void defineJsProperty(JSContext *ctx, JSValueConst obj, const QString &prop, JSValue val);
JSValue getJsProperty(JSContext *ctx, JSValueConst obj, const QString &prop);
+void setJsProperty(JSContext *ctx, JSValueConst obj, std::string_view prop, JSValue val);
void setJsProperty(JSContext *ctx, JSValueConst obj, const QString &prop, JSValue val);
void setJsProperty(JSContext *ctx, JSValueConst obj, const QString &prop, const QString &val);
QString getJsStringProperty(JSContext *ctx, JSValueConst obj, const QString &prop);
diff --git a/src/shared/quickjs/.clang-format b/src/shared/quickjs/.clang-format
new file mode 100644
index 000000000..47a38a93f
--- /dev/null
+++ b/src/shared/quickjs/.clang-format
@@ -0,0 +1,2 @@
+DisableFormat: true
+SortIncludes: Never
diff --git a/src/shared/quickjs/CMakeLists.txt b/src/shared/quickjs/CMakeLists.txt
index a0af03c79..d88739ab0 100644
--- a/src/shared/quickjs/CMakeLists.txt
+++ b/src/shared/quickjs/CMakeLists.txt
@@ -2,6 +2,7 @@ add_qbs_library(qbsquickjs
STATIC
SOURCES
cutils.c cutils.h
+ libbf.c libbf.h
libregexp-opcode.h
libregexp.c libregexp.h
libunicode-table.h
diff --git a/src/shared/quickjs/LICENSE b/src/shared/quickjs/LICENSE
index 2c8fdebaf..2cf449dd3 100644
--- a/src/shared/quickjs/LICENSE
+++ b/src/shared/quickjs/LICENSE
@@ -1,5 +1,5 @@
QuickJS Javascript Engine
-
+
Copyright (c) 2017-2021 Fabrice Bellard
Copyright (c) 2017-2021 Charlie Gordon
diff --git a/src/shared/quickjs/cutils.c b/src/shared/quickjs/cutils.c
index 1f66fff3f..95ae5688d 100644
--- a/src/shared/quickjs/cutils.c
+++ b/src/shared/quickjs/cutils.c
@@ -1,6 +1,6 @@
/*
* C utilities
- *
+ *
* Copyright (c) 2017 Fabrice Bellard
* Copyright (c) 2018 Charlie Gordon
*
@@ -140,7 +140,7 @@ int dbuf_put(DynBuf *s, const uint8_t *data, size_t len)
if (dbuf_realloc(s, s->size + len))
return -1;
}
- memcpy(s->buf + s->size, data, len);
+ memcpy_no_ub(s->buf + s->size, data, len);
s->size += len;
return 0;
}
@@ -171,7 +171,7 @@ int FORMAT_ATTR(2, 3) dbuf_printf(DynBuf *s, const char *fmt, ...)
va_list ap;
char buf[128];
int len;
-
+
va_start(ap, fmt);
len = vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
diff --git a/src/shared/quickjs/cutils.h b/src/shared/quickjs/cutils.h
index ee0ce4a2e..265fd0aee 100644
--- a/src/shared/quickjs/cutils.h
+++ b/src/shared/quickjs/cutils.h
@@ -26,6 +26,7 @@
#define CUTILS_H
#include <stdlib.h>
+#include <string.h>
#include <inttypes.h>
#if defined(_MSC_VER)
@@ -35,21 +36,18 @@ typedef SSIZE_T ssize_t;
#include <sys/types.h>
#endif
-/* set if CPU is big endian */
-#undef WORDS_BIGENDIAN
-
#ifdef __GNUC__
#define likely(x) __builtin_expect(!!(x), 1)
#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 __maybe_unused __attribute__((unused))
#else
#define likely(x) (x)
#define unlikely(x) (x)
#define force_inline
#define no_inline
-#define maybe_unused
+#define __maybe_unused
#endif
#ifdef _MSC_VER
@@ -67,6 +65,16 @@ typedef SSIZE_T ssize_t;
#ifndef countof
#define countof(x) (sizeof(x) / sizeof((x)[0]))
#endif
+#ifndef container_of
+/* return the pointer of type 'type *' containing 'ptr' as field 'member' */
+#define container_of(ptr, type, member) ((type *)((uint8_t *)(ptr) - offsetof(type, member)))
+#endif
+
+#if !defined(_MSC_VER) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+#define minimum_length(n) static n
+#else
+#define minimum_length(n) n
+#endif
typedef int BOOL;
@@ -82,6 +90,12 @@ char *pstrcat(char *buf, int buf_size, const char *s);
int strstart(const char *str, const char *val, const char **ptr);
int has_suffix(const char *str, const char *suffix);
+/* Prevent UB when n == 0 and (src == NULL or dest == NULL) */
+static inline void memcpy_no_ub(void *dest, const void *src, size_t n) {
+ if (n)
+ memcpy(dest, src, n);
+}
+
static inline int max_int(int a, int b)
{
if (a > b)
@@ -140,6 +154,36 @@ static inline int clz32(unsigned int a)
#endif
}
+/* WARNING: undefined if a = 0 */
+static inline int clz64(uint64_t a)
+{
+#ifdef _MSC_VER
+ return (int) __lzcnt64(a);
+#else
+ return __builtin_clzll(a);
+#endif
+}
+
+/* WARNING: undefined if a = 0 */
+static inline int ctz32(unsigned int a)
+{
+#ifdef _MSC_VER
+ return (int) _tzcnt_u32(a);
+#else
+ return __builtin_ctz(a);
+#endif
+}
+
+/* WARNING: undefined if a = 0 */
+static inline int ctz64(uint64_t a)
+{
+#ifdef _MSC_VER
+ return (int) _tzcnt_u64(a);
+#else
+ return __builtin_ctzll(a);
+#endif
+}
+
#pragma pack(push, 1)
struct packed_u64 {
uint64_t v;
@@ -212,17 +256,22 @@ static inline void put_u8(uint8_t *tab, uint8_t val)
*tab = val;
}
+#ifndef bswap16
static inline uint16_t bswap16(uint16_t x)
{
return (x >> 8) | (x << 8);
}
+#endif
+#ifndef bswap32
static inline uint32_t bswap32(uint32_t v)
{
return ((v & 0xff000000) >> 24) | ((v & 0x00ff0000) >> 8) |
((v & 0x0000ff00) << 8) | ((v & 0x000000ff) << 24);
}
+#endif
+#ifndef bswap64
static inline uint64_t bswap64(uint64_t v)
{
return ((v & ((uint64_t)0xff << (7 * 8))) >> (7 * 8)) |
@@ -234,6 +283,7 @@ static inline uint64_t bswap64(uint64_t v)
((v & ((uint64_t)0xff << (1 * 8))) << (5 * 8)) |
((v & ((uint64_t)0xff << (0 * 8))) << (7 * 8));
}
+#endif
/* XXX: should take an extra argument to pass slack information to the caller */
typedef void *DynBufReallocFunc(void *opaque, void *ptr, size_t size);
@@ -290,6 +340,36 @@ static inline void dbuf_set_error(DynBuf *s)
int unicode_to_utf8(uint8_t *buf, unsigned int c);
int unicode_from_utf8(const uint8_t *p, int max_len, const uint8_t **pp);
+static inline BOOL is_surrogate(uint32_t c)
+{
+ return (c >> 11) == (0xD800 >> 11); // 0xD800-0xDFFF
+}
+
+static inline BOOL is_hi_surrogate(uint32_t c)
+{
+ return (c >> 10) == (0xD800 >> 10); // 0xD800-0xDBFF
+}
+
+static inline BOOL is_lo_surrogate(uint32_t c)
+{
+ return (c >> 10) == (0xDC00 >> 10); // 0xDC00-0xDFFF
+}
+
+static inline uint32_t get_hi_surrogate(uint32_t c)
+{
+ return (c >> 10) - (0x10000 >> 10) + 0xD800;
+}
+
+static inline uint32_t get_lo_surrogate(uint32_t c)
+{
+ return (c & 0x3FF) | 0xDC00;
+}
+
+static inline uint32_t from_surrogate(uint32_t hi, uint32_t lo)
+{
+ return 0x10000 + 0x400 * (hi - 0xD800) + (lo - 0xDC00);
+}
+
static inline int from_hex(int c)
{
if (c >= '0' && c <= '9')
diff --git a/src/shared/quickjs/libbf.c b/src/shared/quickjs/libbf.c
new file mode 100644
index 000000000..56b2be861
--- /dev/null
+++ b/src/shared/quickjs/libbf.c
@@ -0,0 +1,8475 @@
+/*
+ * Tiny arbitrary precision floating point library
+ *
+ * Copyright (c) 2017-2021 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <math.h>
+#include <string.h>
+#include <assert.h>
+
+#ifdef __AVX2__
+#include <immintrin.h>
+#endif
+
+#include "cutils.h"
+#include "libbf.h"
+
+/* enable it to check the multiplication result */
+//#define USE_MUL_CHECK
+/* enable it to use FFT/NTT multiplication */
+#define USE_FFT_MUL
+/* enable decimal floating point support */
+#define USE_BF_DEC
+
+//#define inline __attribute__((always_inline))
+
+#ifdef __AVX2__
+#define FFT_MUL_THRESHOLD 100 /* in limbs of the smallest factor */
+#else
+#define FFT_MUL_THRESHOLD 100 /* in limbs of the smallest factor */
+#endif
+
+/* XXX: adjust */
+#define DIVNORM_LARGE_THRESHOLD 50
+#define UDIV1NORM_THRESHOLD 3
+
+#if LIMB_BITS == 64
+#define FMT_LIMB1 "%" PRIx64
+#define FMT_LIMB "%016" PRIx64
+#define PRId_LIMB PRId64
+#define PRIu_LIMB PRIu64
+
+#else
+
+#define FMT_LIMB1 "%x"
+#define FMT_LIMB "%08x"
+#define PRId_LIMB "d"
+#define PRIu_LIMB "u"
+
+#endif
+
+typedef intptr_t mp_size_t;
+
+typedef int bf_op2_func_t(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
+ bf_flags_t flags);
+
+#ifdef USE_FFT_MUL
+
+#define FFT_MUL_R_OVERLAP_A (1 << 0)
+#define FFT_MUL_R_OVERLAP_B (1 << 1)
+#define FFT_MUL_R_NORESIZE (1 << 2)
+
+static no_inline int fft_mul(bf_context_t *s,
+ bf_t *res, limb_t *a_tab, limb_t a_len,
+ limb_t *b_tab, limb_t b_len, int mul_flags);
+static void fft_clear_cache(bf_context_t *s);
+#endif
+#ifdef USE_BF_DEC
+static limb_t get_digit(const limb_t *tab, limb_t len, slimb_t pos);
+#endif
+
+
+/* could leading zeros */
+static inline int clz(limb_t a)
+{
+ if (a == 0) {
+ return LIMB_BITS;
+ } else {
+#if LIMB_BITS == 64
+ return clz64(a);
+#else
+ return clz32(a);
+#endif
+ }
+}
+
+static inline int ctz(limb_t a)
+{
+ if (a == 0) {
+ return LIMB_BITS;
+ } else {
+#if LIMB_BITS == 64
+ return ctz64(a);
+#else
+ return ctz32(a);
+#endif
+ }
+}
+
+static inline int ceil_log2(limb_t a)
+{
+ if (a <= 1)
+ return 0;
+ else
+ return LIMB_BITS - clz(a - 1);
+}
+
+/* b must be >= 1 */
+static inline slimb_t ceil_div(slimb_t a, slimb_t b)
+{
+ if (a >= 0)
+ return (a + b - 1) / b;
+ else
+ return a / b;
+}
+
+#ifdef USE_BF_DEC
+/* b must be >= 1 */
+static inline slimb_t floor_div(slimb_t a, slimb_t b)
+{
+ if (a >= 0) {
+ return a / b;
+ } else {
+ return (a - b + 1) / b;
+ }
+}
+#endif
+
+/* return r = a modulo b (0 <= r <= b - 1. b must be >= 1 */
+static inline limb_t smod(slimb_t a, slimb_t b)
+{
+ a = a % (slimb_t)b;
+ if (a < 0)
+ a += b;
+ return a;
+}
+
+/* signed addition with saturation */
+static inline slimb_t sat_add(slimb_t a, slimb_t b)
+{
+ slimb_t r;
+ r = a + b;
+ /* overflow ? */
+ if (((a ^ r) & (b ^ r)) < 0)
+ r = (a >> (LIMB_BITS - 1)) ^ (((limb_t)1 << (LIMB_BITS - 1)) - 1);
+ return r;
+}
+
+static inline __maybe_unused limb_t shrd(limb_t low, limb_t high, long shift)
+{
+ if (shift != 0)
+ low = (low >> shift) | (high << (LIMB_BITS - shift));
+ return low;
+}
+
+static inline __maybe_unused limb_t shld(limb_t a1, limb_t a0, long shift)
+{
+ if (shift != 0)
+ return (a1 << shift) | (a0 >> (LIMB_BITS - shift));
+ else
+ return a1;
+}
+
+#define malloc(s) malloc_is_forbidden(s)
+#define free(p) free_is_forbidden(p)
+#define realloc(p, s) realloc_is_forbidden(p, s)
+
+void bf_context_init(bf_context_t *s, bf_realloc_func_t *realloc_func,
+ void *realloc_opaque)
+{
+ memset(s, 0, sizeof(*s));
+ s->realloc_func = realloc_func;
+ s->realloc_opaque = realloc_opaque;
+}
+
+void bf_context_end(bf_context_t *s)
+{
+ bf_clear_cache(s);
+}
+
+void bf_init(bf_context_t *s, bf_t *r)
+{
+ r->ctx = s;
+ r->sign = 0;
+ r->expn = BF_EXP_ZERO;
+ r->len = 0;
+ r->tab = NULL;
+}
+
+/* return 0 if OK, -1 if alloc error */
+int bf_resize(bf_t *r, limb_t len)
+{
+ limb_t *tab;
+
+ if (len != r->len) {
+ tab = bf_realloc(r->ctx, r->tab, len * sizeof(limb_t));
+ if (!tab && len != 0)
+ return -1;
+ r->tab = tab;
+ r->len = len;
+ }
+ return 0;
+}
+
+/* return 0 or BF_ST_MEM_ERROR */
+int bf_set_ui(bf_t *r, uint64_t a)
+{
+ r->sign = 0;
+ if (a == 0) {
+ r->expn = BF_EXP_ZERO;
+ bf_resize(r, 0); /* cannot fail */
+ }
+#if LIMB_BITS == 32
+ else if (a <= 0xffffffff)
+#else
+ else
+#endif
+ {
+ int shift;
+ if (bf_resize(r, 1))
+ goto fail;
+ shift = clz(a);
+ r->tab[0] = a << shift;
+ r->expn = LIMB_BITS - shift;
+ }
+#if LIMB_BITS == 32
+ else {
+ uint32_t a1, a0;
+ int shift;
+ if (bf_resize(r, 2))
+ goto fail;
+ a0 = a;
+ a1 = a >> 32;
+ shift = clz(a1);
+ r->tab[0] = a0 << shift;
+ r->tab[1] = shld(a1, a0, shift);
+ r->expn = 2 * LIMB_BITS - shift;
+ }
+#endif
+ return 0;
+ fail:
+ bf_set_nan(r);
+ return BF_ST_MEM_ERROR;
+}
+
+/* return 0 or BF_ST_MEM_ERROR */
+int bf_set_si(bf_t *r, int64_t a)
+{
+ int ret;
+
+ if (a < 0) {
+ ret = bf_set_ui(r, -a);
+ r->sign = 1;
+ } else {
+ ret = bf_set_ui(r, a);
+ }
+ return ret;
+}
+
+void bf_set_nan(bf_t *r)
+{
+ bf_resize(r, 0); /* cannot fail */
+ r->expn = BF_EXP_NAN;
+ r->sign = 0;
+}
+
+void bf_set_zero(bf_t *r, int is_neg)
+{
+ bf_resize(r, 0); /* cannot fail */
+ r->expn = BF_EXP_ZERO;
+ r->sign = is_neg;
+}
+
+void bf_set_inf(bf_t *r, int is_neg)
+{
+ bf_resize(r, 0); /* cannot fail */
+ r->expn = BF_EXP_INF;
+ r->sign = is_neg;
+}
+
+/* return 0 or BF_ST_MEM_ERROR */
+int bf_set(bf_t *r, const bf_t *a)
+{
+ if (r == a)
+ return 0;
+ if (bf_resize(r, a->len)) {
+ bf_set_nan(r);
+ return BF_ST_MEM_ERROR;
+ }
+ r->sign = a->sign;
+ r->expn = a->expn;
+ memcpy_no_ub(r->tab, a->tab, a->len * sizeof(limb_t));
+ return 0;
+}
+
+/* equivalent to bf_set(r, a); bf_delete(a) */
+void bf_move(bf_t *r, bf_t *a)
+{
+ bf_context_t *s = r->ctx;
+ if (r == a)
+ return;
+ bf_free(s, r->tab);
+ *r = *a;
+}
+
+static limb_t get_limbz(const bf_t *a, limb_t idx)
+{
+ if (idx >= a->len)
+ return 0;
+ else
+ return a->tab[idx];
+}
+
+/* get LIMB_BITS at bit position 'pos' in tab */
+static inline limb_t get_bits(const limb_t *tab, limb_t len, slimb_t pos)
+{
+ limb_t i, a0, a1;
+ int p;
+
+ i = pos >> LIMB_LOG2_BITS;
+ p = pos & (LIMB_BITS - 1);
+ if (i < len)
+ a0 = tab[i];
+ else
+ a0 = 0;
+ if (p == 0) {
+ return a0;
+ } else {
+ i++;
+ if (i < len)
+ a1 = tab[i];
+ else
+ a1 = 0;
+ return (a0 >> p) | (a1 << (LIMB_BITS - p));
+ }
+}
+
+static inline limb_t get_bit(const limb_t *tab, limb_t len, slimb_t pos)
+{
+ slimb_t i;
+ i = pos >> LIMB_LOG2_BITS;
+ if (i < 0 || i >= len)
+ return 0;
+ return (tab[i] >> (pos & (LIMB_BITS - 1))) & 1;
+}
+
+static inline limb_t limb_mask(int start, int last)
+{
+ limb_t v;
+ int n;
+ n = last - start + 1;
+ if (n == LIMB_BITS)
+ v = -1;
+ else
+ v = (((limb_t)1 << n) - 1) << start;
+ return v;
+}
+
+static limb_t mp_scan_nz(const limb_t *tab, mp_size_t n)
+{
+ mp_size_t i;
+ for(i = 0; i < n; i++) {
+ if (tab[i] != 0)
+ return 1;
+ }
+ return 0;
+}
+
+/* return != 0 if one bit between 0 and bit_pos inclusive is not zero. */
+static inline limb_t scan_bit_nz(const bf_t *r, slimb_t bit_pos)
+{
+ slimb_t pos;
+ limb_t v;
+
+ pos = bit_pos >> LIMB_LOG2_BITS;
+ if (pos < 0)
+ return 0;
+ v = r->tab[pos] & limb_mask(0, bit_pos & (LIMB_BITS - 1));
+ if (v != 0)
+ return 1;
+ pos--;
+ while (pos >= 0) {
+ if (r->tab[pos] != 0)
+ return 1;
+ pos--;
+ }
+ return 0;
+}
+
+/* return the addend for rounding. Note that prec can be <= 0 (for
+ BF_FLAG_RADPNT_PREC) */
+static int bf_get_rnd_add(int *pret, const bf_t *r, limb_t l,
+ slimb_t prec, int rnd_mode)
+{
+ int add_one, inexact;
+ limb_t bit1, bit0;
+
+ if (rnd_mode == BF_RNDF) {
+ bit0 = 1; /* faithful rounding does not honor the INEXACT flag */
+ } else {
+ /* starting limb for bit 'prec + 1' */
+ bit0 = scan_bit_nz(r, l * LIMB_BITS - 1 - bf_max(0, prec + 1));
+ }
+
+ /* get the bit at 'prec' */
+ bit1 = get_bit(r->tab, l, l * LIMB_BITS - 1 - prec);
+ inexact = (bit1 | bit0) != 0;
+
+ add_one = 0;
+ switch(rnd_mode) {
+ case BF_RNDZ:
+ break;
+ case BF_RNDN:
+ if (bit1) {
+ if (bit0) {
+ add_one = 1;
+ } else {
+ /* round to even */
+ add_one =
+ get_bit(r->tab, l, l * LIMB_BITS - 1 - (prec - 1));
+ }
+ }
+ break;
+ case BF_RNDD:
+ case BF_RNDU:
+ if (r->sign == (rnd_mode == BF_RNDD))
+ add_one = inexact;
+ break;
+ case BF_RNDA:
+ add_one = inexact;
+ break;
+ case BF_RNDNA:
+ case BF_RNDF:
+ add_one = bit1;
+ break;
+ default:
+ abort();
+ }
+
+ if (inexact)
+ *pret |= BF_ST_INEXACT;
+ return add_one;
+}
+
+static int bf_set_overflow(bf_t *r, int sign, limb_t prec, bf_flags_t flags)
+{
+ slimb_t i, l, e_max;
+ int rnd_mode;
+
+ rnd_mode = flags & BF_RND_MASK;
+ if (prec == BF_PREC_INF ||
+ rnd_mode == BF_RNDN ||
+ rnd_mode == BF_RNDNA ||
+ rnd_mode == BF_RNDA ||
+ (rnd_mode == BF_RNDD && sign == 1) ||
+ (rnd_mode == BF_RNDU && sign == 0)) {
+ bf_set_inf(r, sign);
+ } else {
+ /* set to maximum finite number */
+ l = (prec + LIMB_BITS - 1) / LIMB_BITS;
+ if (bf_resize(r, l)) {
+ bf_set_nan(r);
+ return BF_ST_MEM_ERROR;
+ }
+ r->tab[0] = limb_mask((-prec) & (LIMB_BITS - 1),
+ LIMB_BITS - 1);
+ for(i = 1; i < l; i++)
+ r->tab[i] = (limb_t)-1;
+ e_max = (limb_t)1 << (bf_get_exp_bits(flags) - 1);
+ r->expn = e_max;
+ r->sign = sign;
+ }
+ return BF_ST_OVERFLOW | BF_ST_INEXACT;
+}
+
+/* round to prec1 bits assuming 'r' is non zero and finite. 'r' is
+ assumed to have length 'l' (1 <= l <= r->len). Note: 'prec1' can be
+ infinite (BF_PREC_INF). 'ret' is 0 or BF_ST_INEXACT if the result
+ is known to be inexact. Can fail with BF_ST_MEM_ERROR in case of
+ overflow not returning infinity. */
+static int __bf_round(bf_t *r, limb_t prec1, bf_flags_t flags, limb_t l,
+ int ret)
+{
+ limb_t v, a;
+ int shift, add_one, rnd_mode;
+ slimb_t i, bit_pos, pos, e_min, e_max, e_range, prec;
+
+ /* e_min and e_max are computed to match the IEEE 754 conventions */
+ e_range = (limb_t)1 << (bf_get_exp_bits(flags) - 1);
+ e_min = -e_range + 3;
+ e_max = e_range;
+
+ if (flags & BF_FLAG_RADPNT_PREC) {
+ /* 'prec' is the precision after the radix point */
+ if (prec1 != BF_PREC_INF)
+ prec = r->expn + prec1;
+ else
+ prec = prec1;
+ } else if (unlikely(r->expn < e_min) && (flags & BF_FLAG_SUBNORMAL)) {
+ /* restrict the precision in case of potentially subnormal
+ result */
+ assert(prec1 != BF_PREC_INF);
+ prec = prec1 - (e_min - r->expn);
+ } else {
+ prec = prec1;
+ }
+
+ /* round to prec bits */
+ rnd_mode = flags & BF_RND_MASK;
+ add_one = bf_get_rnd_add(&ret, r, l, prec, rnd_mode);
+
+ if (prec <= 0) {
+ if (add_one) {
+ bf_resize(r, 1); /* cannot fail */
+ r->tab[0] = (limb_t)1 << (LIMB_BITS - 1);
+ r->expn += 1 - prec;
+ ret |= BF_ST_UNDERFLOW | BF_ST_INEXACT;
+ return ret;
+ } else {
+ goto underflow;
+ }
+ } else if (add_one) {
+ limb_t carry;
+
+ /* add one starting at digit 'prec - 1' */
+ bit_pos = l * LIMB_BITS - 1 - (prec - 1);
+ pos = bit_pos >> LIMB_LOG2_BITS;
+ carry = (limb_t)1 << (bit_pos & (LIMB_BITS - 1));
+
+ for(i = pos; i < l; i++) {
+ v = r->tab[i] + carry;
+ carry = (v < carry);
+ r->tab[i] = v;
+ if (carry == 0)
+ break;
+ }
+ if (carry) {
+ /* shift right by one digit */
+ v = 1;
+ for(i = l - 1; i >= pos; i--) {
+ a = r->tab[i];
+ r->tab[i] = (a >> 1) | (v << (LIMB_BITS - 1));
+ v = a;
+ }
+ r->expn++;
+ }
+ }
+
+ /* check underflow */
+ if (unlikely(r->expn < e_min)) {
+ if (flags & BF_FLAG_SUBNORMAL) {
+ /* if inexact, also set the underflow flag */
+ if (ret & BF_ST_INEXACT)
+ ret |= BF_ST_UNDERFLOW;
+ } else {
+ underflow:
+ ret |= BF_ST_UNDERFLOW | BF_ST_INEXACT;
+ bf_set_zero(r, r->sign);
+ return ret;
+ }
+ }
+
+ /* check overflow */
+ if (unlikely(r->expn > e_max))
+ return bf_set_overflow(r, r->sign, prec1, flags);
+
+ /* keep the bits starting at 'prec - 1' */
+ bit_pos = l * LIMB_BITS - 1 - (prec - 1);
+ i = bit_pos >> LIMB_LOG2_BITS;
+ if (i >= 0) {
+ shift = bit_pos & (LIMB_BITS - 1);
+ if (shift != 0)
+ r->tab[i] &= limb_mask(shift, LIMB_BITS - 1);
+ } else {
+ i = 0;
+ }
+ /* remove trailing zeros */
+ while (r->tab[i] == 0)
+ i++;
+ if (i > 0) {
+ l -= i;
+ memmove(r->tab, r->tab + i, l * sizeof(limb_t));
+ }
+ bf_resize(r, l); /* cannot fail */
+ return ret;
+}
+
+/* 'r' must be a finite number. */
+int bf_normalize_and_round(bf_t *r, limb_t prec1, bf_flags_t flags)
+{
+ limb_t l, v, a;
+ int shift, ret;
+ slimb_t i;
+
+ // bf_print_str("bf_renorm", r);
+ l = r->len;
+ while (l > 0 && r->tab[l - 1] == 0)
+ l--;
+ if (l == 0) {
+ /* zero */
+ r->expn = BF_EXP_ZERO;
+ bf_resize(r, 0); /* cannot fail */
+ ret = 0;
+ } else {
+ r->expn -= (r->len - l) * LIMB_BITS;
+ /* shift to have the MSB set to '1' */
+ v = r->tab[l - 1];
+ shift = clz(v);
+ if (shift != 0) {
+ v = 0;
+ for(i = 0; i < l; i++) {
+ a = r->tab[i];
+ r->tab[i] = (a << shift) | (v >> (LIMB_BITS - shift));
+ v = a;
+ }
+ r->expn -= shift;
+ }
+ ret = __bf_round(r, prec1, flags, l, 0);
+ }
+ // bf_print_str("r_final", r);
+ return ret;
+}
+
+/* return true if rounding can be done at precision 'prec' assuming
+ the exact result r is such that |r-a| <= 2^(EXP(a)-k). */
+/* XXX: check the case where the exponent would be incremented by the
+ rounding */
+int bf_can_round(const bf_t *a, slimb_t prec, bf_rnd_t rnd_mode, slimb_t k)
+{
+ BOOL is_rndn;
+ slimb_t bit_pos, n;
+ limb_t bit;
+
+ if (a->expn == BF_EXP_INF || a->expn == BF_EXP_NAN)
+ return FALSE;
+ if (rnd_mode == BF_RNDF) {
+ return (k >= (prec + 1));
+ }
+ if (a->expn == BF_EXP_ZERO)
+ return FALSE;
+ is_rndn = (rnd_mode == BF_RNDN || rnd_mode == BF_RNDNA);
+ if (k < (prec + 2))
+ return FALSE;
+ bit_pos = a->len * LIMB_BITS - 1 - prec;
+ n = k - prec;
+ /* bit pattern for RNDN or RNDNA: 0111.. or 1000...
+ for other rounding modes: 000... or 111...
+ */
+ bit = get_bit(a->tab, a->len, bit_pos);
+ bit_pos--;
+ n--;
+ bit ^= is_rndn;
+ /* XXX: slow, but a few iterations on average */
+ while (n != 0) {
+ if (get_bit(a->tab, a->len, bit_pos) != bit)
+ return TRUE;
+ bit_pos--;
+ n--;
+ }
+ return FALSE;
+}
+
+/* Cannot fail with BF_ST_MEM_ERROR. */
+int bf_round(bf_t *r, limb_t prec, bf_flags_t flags)
+{
+ if (r->len == 0)
+ return 0;
+ return __bf_round(r, prec, flags, r->len, 0);
+}
+
+/* for debugging */
+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);
+ for(i = 0; i < n; i++) {
+ printf("%" PRId_LIMB ": " FMT_LIMB "\n",
+ i, tab[i]);
+ }
+}
+
+void mp_print_str(const char *str, const limb_t *tab, limb_t n)
+{
+ slimb_t i;
+ printf("%s= 0x", str);
+ for(i = n - 1; i >= 0; i--) {
+ if (i != (n - 1))
+ printf("_");
+ printf(FMT_LIMB, tab[i]);
+ }
+ printf("\n");
+}
+
+static __maybe_unused void mp_print_str_h(const char *str,
+ const limb_t *tab, limb_t n,
+ limb_t high)
+{
+ slimb_t i;
+ printf("%s= 0x", str);
+ printf(FMT_LIMB, high);
+ for(i = n - 1; i >= 0; i--) {
+ printf("_");
+ printf(FMT_LIMB, tab[i]);
+ }
+ printf("\n");
+}
+
+/* for debugging */
+void bf_print_str(const char *str, const bf_t *a)
+{
+ slimb_t i;
+ printf("%s=", str);
+
+ if (a->expn == BF_EXP_NAN) {
+ printf("NaN");
+ } else {
+ if (a->sign)
+ putchar('-');
+ if (a->expn == BF_EXP_ZERO) {
+ putchar('0');
+ } else if (a->expn == BF_EXP_INF) {
+ printf("Inf");
+ } else {
+ printf("0x0.");
+ for(i = a->len - 1; i >= 0; i--)
+ printf(FMT_LIMB, a->tab[i]);
+ printf("p%" PRId_LIMB, a->expn);
+ }
+ }
+ printf("\n");
+}
+
+/* compare the absolute value of 'a' and 'b'. Return < 0 if a < b, 0
+ if a = b and > 0 otherwise. */
+int bf_cmpu(const bf_t *a, const bf_t *b)
+{
+ slimb_t i;
+ limb_t len, v1, v2;
+
+ if (a->expn != b->expn) {
+ if (a->expn < b->expn)
+ return -1;
+ else
+ return 1;
+ }
+ len = bf_max(a->len, b->len);
+ for(i = len - 1; i >= 0; i--) {
+ v1 = get_limbz(a, a->len - len + i);
+ v2 = get_limbz(b, b->len - len + i);
+ if (v1 != v2) {
+ if (v1 < v2)
+ return -1;
+ else
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* Full order: -0 < 0, NaN == NaN and NaN is larger than all other numbers */
+int bf_cmp_full(const bf_t *a, const bf_t *b)
+{
+ int res;
+
+ if (a->expn == BF_EXP_NAN || b->expn == BF_EXP_NAN) {
+ if (a->expn == b->expn)
+ res = 0;
+ else if (a->expn == BF_EXP_NAN)
+ res = 1;
+ else
+ res = -1;
+ } else if (a->sign != b->sign) {
+ res = 1 - 2 * a->sign;
+ } else {
+ res = bf_cmpu(a, b);
+ if (a->sign)
+ res = -res;
+ }
+ return res;
+}
+
+/* Standard floating point comparison: return 2 if one of the operands
+ is NaN (unordered) or -1, 0, 1 depending on the ordering assuming
+ -0 == +0 */
+int bf_cmp(const bf_t *a, const bf_t *b)
+{
+ int res;
+
+ if (a->expn == BF_EXP_NAN || b->expn == BF_EXP_NAN) {
+ res = 2;
+ } else if (a->sign != b->sign) {
+ if (a->expn == BF_EXP_ZERO && b->expn == BF_EXP_ZERO)
+ res = 0;
+ else
+ res = 1 - 2 * a->sign;
+ } else {
+ res = bf_cmpu(a, b);
+ if (a->sign)
+ res = -res;
+ }
+ return res;
+}
+
+/* Compute the number of bits 'n' matching the pattern:
+ a= X1000..0
+ b= X0111..1
+
+ When computing a-b, the result will have at least n leading zero
+ bits.
+
+ Precondition: a > b and a.expn - b.expn = 0 or 1
+*/
+static limb_t count_cancelled_bits(const bf_t *a, const bf_t *b)
+{
+ slimb_t bit_offset, b_offset, n;
+ int p, p1;
+ limb_t v1, v2, mask;
+
+ bit_offset = a->len * LIMB_BITS - 1;
+ b_offset = (b->len - a->len) * LIMB_BITS - (LIMB_BITS - 1) +
+ a->expn - b->expn;
+ n = 0;
+
+ /* first search the equals bits */
+ for(;;) {
+ v1 = get_limbz(a, bit_offset >> LIMB_LOG2_BITS);
+ v2 = get_bits(b->tab, b->len, bit_offset + b_offset);
+ // printf("v1=" FMT_LIMB " v2=" FMT_LIMB "\n", v1, v2);
+ if (v1 != v2)
+ break;
+ n += LIMB_BITS;
+ bit_offset -= LIMB_BITS;
+ }
+ /* find the position of the first different bit */
+ p = clz(v1 ^ v2) + 1;
+ n += p;
+ /* then search for '0' in a and '1' in b */
+ p = LIMB_BITS - p;
+ if (p > 0) {
+ /* search in the trailing p bits of v1 and v2 */
+ mask = limb_mask(0, p - 1);
+ p1 = bf_min(clz(v1 & mask), clz((~v2) & mask)) - (LIMB_BITS - p);
+ n += p1;
+ if (p1 != p)
+ goto done;
+ }
+ bit_offset -= LIMB_BITS;
+ for(;;) {
+ v1 = get_limbz(a, bit_offset >> LIMB_LOG2_BITS);
+ v2 = get_bits(b->tab, b->len, bit_offset + b_offset);
+ // printf("v1=" FMT_LIMB " v2=" FMT_LIMB "\n", v1, v2);
+ if (v1 != 0 || v2 != -1) {
+ /* different: count the matching bits */
+ p1 = bf_min(clz(v1), clz(~v2));
+ n += p1;
+ break;
+ }
+ n += LIMB_BITS;
+ bit_offset -= LIMB_BITS;
+ }
+ done:
+ return n;
+}
+
+static int bf_add_internal(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
+ bf_flags_t flags, int b_neg)
+{
+ const bf_t *tmp;
+ int is_sub, ret, cmp_res, a_sign, b_sign;
+
+ a_sign = a->sign;
+ b_sign = b->sign ^ b_neg;
+ is_sub = a_sign ^ b_sign;
+ cmp_res = bf_cmpu(a, b);
+ if (cmp_res < 0) {
+ tmp = a;
+ a = b;
+ b = tmp;
+ a_sign = b_sign; /* b_sign is never used later */
+ }
+ /* abs(a) >= abs(b) */
+ if (cmp_res == 0 && is_sub && a->expn < BF_EXP_INF) {
+ /* zero result */
+ bf_set_zero(r, (flags & BF_RND_MASK) == BF_RNDD);
+ ret = 0;
+ } else if (a->len == 0 || b->len == 0) {
+ ret = 0;
+ if (a->expn >= BF_EXP_INF) {
+ if (a->expn == BF_EXP_NAN) {
+ /* at least one operand is NaN */
+ bf_set_nan(r);
+ } else if (b->expn == BF_EXP_INF && is_sub) {
+ /* infinities with different signs */
+ bf_set_nan(r);
+ ret = BF_ST_INVALID_OP;
+ } else {
+ bf_set_inf(r, a_sign);
+ }
+ } else {
+ /* at least one zero and not subtract */
+ bf_set(r, a);
+ r->sign = a_sign;
+ goto renorm;
+ }
+ } else {
+ slimb_t d, a_offset, b_bit_offset, i, cancelled_bits;
+ limb_t carry, v1, v2, u, r_len, carry1, precl, tot_len, z, sub_mask;
+
+ r->sign = a_sign;
+ r->expn = a->expn;
+ d = a->expn - b->expn;
+ /* must add more precision for the leading cancelled bits in
+ subtraction */
+ if (is_sub) {
+ if (d <= 1)
+ cancelled_bits = count_cancelled_bits(a, b);
+ else
+ cancelled_bits = 1;
+ } else {
+ cancelled_bits = 0;
+ }
+
+ /* add two extra bits for rounding */
+ precl = (cancelled_bits + prec + 2 + LIMB_BITS - 1) / LIMB_BITS;
+ tot_len = bf_max(a->len, b->len + (d + LIMB_BITS - 1) / LIMB_BITS);
+ r_len = bf_min(precl, tot_len);
+ if (bf_resize(r, r_len))
+ goto fail;
+ a_offset = a->len - r_len;
+ b_bit_offset = (b->len - r_len) * LIMB_BITS + d;
+
+ /* compute the bits before for the rounding */
+ carry = is_sub;
+ z = 0;
+ sub_mask = -is_sub;
+ i = r_len - tot_len;
+ while (i < 0) {
+ slimb_t ap, bp;
+ BOOL inflag;
+
+ ap = a_offset + i;
+ bp = b_bit_offset + i * LIMB_BITS;
+ inflag = FALSE;
+ if (ap >= 0 && ap < a->len) {
+ v1 = a->tab[ap];
+ inflag = TRUE;
+ } else {
+ v1 = 0;
+ }
+ if (bp + LIMB_BITS > 0 && bp < (slimb_t)(b->len * LIMB_BITS)) {
+ v2 = get_bits(b->tab, b->len, bp);
+ inflag = TRUE;
+ } else {
+ v2 = 0;
+ }
+ if (!inflag) {
+ /* outside 'a' and 'b': go directly to the next value
+ inside a or b so that the running time does not
+ depend on the exponent difference */
+ i = 0;
+ if (ap < 0)
+ i = bf_min(i, -a_offset);
+ /* b_bit_offset + i * LIMB_BITS + LIMB_BITS >= 1
+ equivalent to
+ i >= ceil(-b_bit_offset + 1 - LIMB_BITS) / LIMB_BITS)
+ */
+ if (bp + LIMB_BITS <= 0)
+ i = bf_min(i, (-b_bit_offset) >> LIMB_LOG2_BITS);
+ } else {
+ i++;
+ }
+ v2 ^= sub_mask;
+ u = v1 + v2;
+ carry1 = u < v1;
+ u += carry;
+ carry = (u < carry) | carry1;
+ z |= u;
+ }
+ /* and the result */
+ for(i = 0; i < r_len; i++) {
+ v1 = get_limbz(a, a_offset + i);
+ v2 = get_bits(b->tab, b->len, b_bit_offset + i * LIMB_BITS);
+ v2 ^= sub_mask;
+ u = v1 + v2;
+ carry1 = u < v1;
+ u += carry;
+ carry = (u < carry) | carry1;
+ r->tab[i] = u;
+ }
+ /* set the extra bits for the rounding */
+ r->tab[0] |= (z != 0);
+
+ /* carry is only possible in add case */
+ if (!is_sub && carry) {
+ if (bf_resize(r, r_len + 1))
+ goto fail;
+ r->tab[r_len] = 1;
+ r->expn += LIMB_BITS;
+ }
+ renorm:
+ ret = bf_normalize_and_round(r, prec, flags);
+ }
+ return ret;
+ fail:
+ bf_set_nan(r);
+ return BF_ST_MEM_ERROR;
+}
+
+static int __bf_add(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
+ bf_flags_t flags)
+{
+ return bf_add_internal(r, a, b, prec, flags, 0);
+}
+
+static int __bf_sub(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
+ bf_flags_t flags)
+{
+ return bf_add_internal(r, a, b, prec, flags, 1);
+}
+
+limb_t mp_add(limb_t *res, const limb_t *op1, const limb_t *op2,
+ limb_t n, limb_t carry)
+{
+ slimb_t i;
+ limb_t k, a, v, k1;
+
+ k = carry;
+ for(i=0;i<n;i++) {
+ v = op1[i];
+ a = v + op2[i];
+ k1 = a < v;
+ a = a + k;
+ k = (a < k) | k1;
+ res[i] = a;
+ }
+ return k;
+}
+
+limb_t mp_add_ui(limb_t *tab, limb_t b, size_t n)
+{
+ size_t i;
+ limb_t k, a;
+
+ k=b;
+ for(i=0;i<n;i++) {
+ if (k == 0)
+ break;
+ a = tab[i] + k;
+ k = (a < k);
+ tab[i] = a;
+ }
+ return k;
+}
+
+limb_t mp_sub(limb_t *res, const limb_t *op1, const limb_t *op2,
+ mp_size_t n, limb_t carry)
+{
+ int i;
+ limb_t k, a, v, k1;
+
+ k = carry;
+ for(i=0;i<n;i++) {
+ v = op1[i];
+ a = v - op2[i];
+ k1 = a > v;
+ v = a - k;
+ k = (v > a) | k1;
+ res[i] = v;
+ }
+ return k;
+}
+
+/* compute 0 - op2 */
+static limb_t mp_neg(limb_t *res, const limb_t *op2, mp_size_t n, limb_t carry)
+{
+ int i;
+ limb_t k, a, v, k1;
+
+ k = carry;
+ for(i=0;i<n;i++) {
+ v = 0;
+ a = v - op2[i];
+ k1 = a > v;
+ v = a - k;
+ k = (v > a) | k1;
+ res[i] = v;
+ }
+ return k;
+}
+
+limb_t mp_sub_ui(limb_t *tab, limb_t b, mp_size_t n)
+{
+ mp_size_t i;
+ limb_t k, a, v;
+
+ k=b;
+ for(i=0;i<n;i++) {
+ v = tab[i];
+ a = v - k;
+ k = a > v;
+ tab[i] = a;
+ if (k == 0)
+ break;
+ }
+ return k;
+}
+
+/* r = (a + high*B^n) >> shift. Return the remainder r (0 <= r < 2^shift).
+ 1 <= shift <= LIMB_BITS - 1 */
+static limb_t mp_shr(limb_t *tab_r, const limb_t *tab, mp_size_t n,
+ int shift, limb_t high)
+{
+ mp_size_t i;
+ limb_t l, a;
+
+ assert(shift >= 1 && shift < LIMB_BITS);
+ l = high;
+ for(i = n - 1; i >= 0; i--) {
+ a = tab[i];
+ tab_r[i] = (a >> shift) | (l << (LIMB_BITS - shift));
+ l = a;
+ }
+ return l & (((limb_t)1 << shift) - 1);
+}
+
+/* tabr[] = taba[] * b + l. Return the high carry */
+static limb_t mp_mul1(limb_t *tabr, const limb_t *taba, limb_t n,
+ limb_t b, limb_t l)
+{
+ limb_t i;
+ dlimb_t t;
+
+ for(i = 0; i < n; i++) {
+ t = (dlimb_t)taba[i] * (dlimb_t)b + l;
+ tabr[i] = t;
+ l = t >> LIMB_BITS;
+ }
+ return l;
+}
+
+/* tabr[] += taba[] * b, return the high word. */
+static limb_t mp_add_mul1(limb_t *tabr, const limb_t *taba, limb_t n,
+ limb_t b)
+{
+ limb_t i, l;
+ dlimb_t t;
+
+ l = 0;
+ for(i = 0; i < n; i++) {
+ t = (dlimb_t)taba[i] * (dlimb_t)b + l + tabr[i];
+ tabr[i] = t;
+ l = t >> LIMB_BITS;
+ }
+ return l;
+}
+
+/* size of the result : op1_size + op2_size. */
+static void mp_mul_basecase(limb_t *result,
+ const limb_t *op1, limb_t op1_size,
+ const limb_t *op2, limb_t op2_size)
+{
+ limb_t i, r;
+
+ result[op1_size] = mp_mul1(result, op1, op1_size, op2[0], 0);
+ for(i=1;i<op2_size;i++) {
+ r = mp_add_mul1(result + i, op1, op1_size, op2[i]);
+ result[i + op1_size] = r;
+ }
+}
+
+/* return 0 if OK, -1 if memory error */
+/* XXX: change API so that result can be allocated */
+int mp_mul(bf_context_t *s, limb_t *result,
+ const limb_t *op1, limb_t op1_size,
+ const limb_t *op2, limb_t op2_size)
+{
+#ifdef USE_FFT_MUL
+ if (unlikely(bf_min(op1_size, op2_size) >= FFT_MUL_THRESHOLD)) {
+ bf_t r_s, *r = &r_s;
+ r->tab = result;
+ /* XXX: optimize memory usage in API */
+ if (fft_mul(s, r, (limb_t *)op1, op1_size,
+ (limb_t *)op2, op2_size, FFT_MUL_R_NORESIZE))
+ return -1;
+ } else
+#endif
+ {
+ mp_mul_basecase(result, op1, op1_size, op2, op2_size);
+ }
+ return 0;
+}
+
+/* tabr[] -= taba[] * b. Return the value to substract to the high
+ word. */
+static limb_t mp_sub_mul1(limb_t *tabr, const limb_t *taba, limb_t n,
+ limb_t b)
+{
+ limb_t i, l;
+ dlimb_t t;
+
+ l = 0;
+ for(i = 0; i < n; i++) {
+ t = tabr[i] - (dlimb_t)taba[i] * (dlimb_t)b - l;
+ tabr[i] = t;
+ l = -(t >> LIMB_BITS);
+ }
+ return l;
+}
+
+/* WARNING: d must be >= 2^(LIMB_BITS-1) */
+static inline limb_t udiv1norm_init(limb_t d)
+{
+ limb_t a0, a1;
+ a1 = -d - 1;
+ a0 = -1;
+ return (((dlimb_t)a1 << LIMB_BITS) | a0) / d;
+}
+
+/* return the quotient and the remainder in '*pr'of 'a1*2^LIMB_BITS+a0
+ / d' with 0 <= a1 < d. */
+static inline limb_t udiv1norm(limb_t *pr, limb_t a1, limb_t a0,
+ limb_t d, limb_t d_inv)
+{
+ limb_t n1m, n_adj, q, r, ah;
+ dlimb_t a;
+ n1m = ((slimb_t)a0 >> (LIMB_BITS - 1));
+ n_adj = a0 + (n1m & d);
+ a = (dlimb_t)d_inv * (a1 - n1m) + n_adj;
+ q = (a >> LIMB_BITS) + a1;
+ /* compute a - q * r and update q so that the remainder is\
+ between 0 and d - 1 */
+ a = ((dlimb_t)a1 << LIMB_BITS) | a0;
+ a = a - (dlimb_t)q * d - d;
+ ah = a >> LIMB_BITS;
+ q += 1 + ah;
+ r = (limb_t)a + (ah & d);
+ *pr = r;
+ return q;
+}
+
+/* b must be >= 1 << (LIMB_BITS - 1) */
+static limb_t mp_div1norm(limb_t *tabr, const limb_t *taba, limb_t n,
+ limb_t b, limb_t r)
+{
+ slimb_t i;
+
+ if (n >= UDIV1NORM_THRESHOLD) {
+ limb_t b_inv;
+ b_inv = udiv1norm_init(b);
+ for(i = n - 1; i >= 0; i--) {
+ tabr[i] = udiv1norm(&r, r, taba[i], b, b_inv);
+ }
+ } else {
+ dlimb_t a1;
+ for(i = n - 1; i >= 0; i--) {
+ a1 = ((dlimb_t)r << LIMB_BITS) | taba[i];
+ tabr[i] = a1 / b;
+ r = a1 % b;
+ }
+ }
+ return r;
+}
+
+static int mp_divnorm_large(bf_context_t *s,
+ limb_t *tabq, limb_t *taba, limb_t na,
+ const limb_t *tabb, limb_t nb);
+
+/* base case division: divides taba[0..na-1] by tabb[0..nb-1]. tabb[nb
+ - 1] must be >= 1 << (LIMB_BITS - 1). na - nb must be >= 0. 'taba'
+ is modified and contains the remainder (nb limbs). tabq[0..na-nb]
+ contains the quotient with tabq[na - nb] <= 1. */
+static int mp_divnorm(bf_context_t *s, limb_t *tabq, limb_t *taba, limb_t na,
+ const limb_t *tabb, limb_t nb)
+{
+ limb_t r, a, c, q, v, b1, b1_inv, n, dummy_r;
+ slimb_t i, j;
+
+ b1 = tabb[nb - 1];
+ if (nb == 1) {
+ taba[0] = mp_div1norm(tabq, taba, na, b1, 0);
+ return 0;
+ }
+ n = na - nb;
+ if (bf_min(n, nb) >= DIVNORM_LARGE_THRESHOLD) {
+ return mp_divnorm_large(s, tabq, taba, na, tabb, nb);
+ }
+
+ if (n >= UDIV1NORM_THRESHOLD)
+ b1_inv = udiv1norm_init(b1);
+ else
+ b1_inv = 0;
+
+ /* first iteration: the quotient is only 0 or 1 */
+ q = 1;
+ for(j = nb - 1; j >= 0; j--) {
+ if (taba[n + j] != tabb[j]) {
+ if (taba[n + j] < tabb[j])
+ q = 0;
+ break;
+ }
+ }
+ tabq[n] = q;
+ if (q) {
+ mp_sub(taba + n, taba + n, tabb, nb, 0);
+ }
+
+ for(i = n - 1; i >= 0; i--) {
+ if (unlikely(taba[i + nb] >= b1)) {
+ q = -1;
+ } else if (b1_inv) {
+ q = udiv1norm(&dummy_r, taba[i + nb], taba[i + nb - 1], b1, b1_inv);
+ } else {
+ dlimb_t al;
+ al = ((dlimb_t)taba[i + nb] << LIMB_BITS) | taba[i + nb - 1];
+ q = al / b1;
+ r = al % b1;
+ }
+ r = mp_sub_mul1(taba + i, tabb, nb, q);
+
+ v = taba[i + nb];
+ a = v - r;
+ c = (a > v);
+ taba[i + nb] = a;
+
+ if (c != 0) {
+ /* negative result */
+ for(;;) {
+ q--;
+ c = mp_add(taba + i, taba + i, tabb, nb, 0);
+ /* propagate carry and test if positive result */
+ if (c != 0) {
+ if (++taba[i + nb] == 0) {
+ break;
+ }
+ }
+ }
+ }
+ tabq[i] = q;
+ }
+ return 0;
+}
+
+/* compute r=B^(2*n)/a such as a*r < B^(2*n) < a*r + 2 with n >= 1. 'a'
+ has n limbs with a[n-1] >= B/2 and 'r' has n+1 limbs with r[n] = 1.
+
+ See Modern Computer Arithmetic by Richard P. Brent and Paul
+ Zimmermann, algorithm 3.5 */
+int mp_recip(bf_context_t *s, limb_t *tabr, const limb_t *taba, limb_t n)
+{
+ mp_size_t l, h, k, i;
+ limb_t *tabxh, *tabt, c, *tabu;
+
+ if (n <= 2) {
+ /* return ceil(B^(2*n)/a) - 1 */
+ /* XXX: could avoid allocation */
+ tabu = bf_malloc(s, sizeof(limb_t) * (2 * n + 1));
+ tabt = bf_malloc(s, sizeof(limb_t) * (n + 2));
+ if (!tabt || !tabu)
+ goto fail;
+ for(i = 0; i < 2 * n; i++)
+ tabu[i] = 0;
+ tabu[2 * n] = 1;
+ if (mp_divnorm(s, tabt, tabu, 2 * n + 1, taba, n))
+ goto fail;
+ for(i = 0; i < n + 1; i++)
+ tabr[i] = tabt[i];
+ if (mp_scan_nz(tabu, n) == 0) {
+ /* only happens for a=B^n/2 */
+ mp_sub_ui(tabr, 1, n + 1);
+ }
+ } else {
+ l = (n - 1) / 2;
+ h = n - l;
+ /* n=2p -> l=p-1, h = p + 1, k = p + 3
+ n=2p+1-> l=p, h = p + 1; k = p + 2
+ */
+ tabt = bf_malloc(s, sizeof(limb_t) * (n + h + 1));
+ tabu = bf_malloc(s, sizeof(limb_t) * (n + 2 * h - l + 2));
+ if (!tabt || !tabu)
+ goto fail;
+ tabxh = tabr + l;
+ if (mp_recip(s, tabxh, taba + l, h))
+ goto fail;
+ if (mp_mul(s, tabt, taba, n, tabxh, h + 1)) /* n + h + 1 limbs */
+ goto fail;
+ while (tabt[n + h] != 0) {
+ mp_sub_ui(tabxh, 1, h + 1);
+ c = mp_sub(tabt, tabt, taba, n, 0);
+ mp_sub_ui(tabt + n, c, h + 1);
+ }
+ /* T = B^(n+h) - T */
+ mp_neg(tabt, tabt, n + h + 1, 0);
+ tabt[n + h]++;
+ if (mp_mul(s, tabu, tabt + l, n + h + 1 - l, tabxh, h + 1))
+ goto fail;
+ /* n + 2*h - l + 2 limbs */
+ k = 2 * h - l;
+ for(i = 0; i < l; i++)
+ tabr[i] = tabu[i + k];
+ mp_add(tabr + l, tabr + l, tabu + 2 * h, h, 0);
+ }
+ bf_free(s, tabt);
+ bf_free(s, tabu);
+ return 0;
+ fail:
+ bf_free(s, tabt);
+ bf_free(s, tabu);
+ return -1;
+}
+
+/* return -1, 0 or 1 */
+static int mp_cmp(const limb_t *taba, const limb_t *tabb, mp_size_t n)
+{
+ mp_size_t i;
+ for(i = n - 1; i >= 0; i--) {
+ if (taba[i] != tabb[i]) {
+ if (taba[i] < tabb[i])
+ return -1;
+ else
+ return 1;
+ }
+ }
+ return 0;
+}
+
+//#define DEBUG_DIVNORM_LARGE
+//#define DEBUG_DIVNORM_LARGE2
+
+/* subquadratic divnorm */
+static int mp_divnorm_large(bf_context_t *s,
+ limb_t *tabq, limb_t *taba, limb_t na,
+ const limb_t *tabb, limb_t nb)
+{
+ limb_t *tabb_inv, nq, *tabt, i, n;
+ nq = na - nb;
+#ifdef DEBUG_DIVNORM_LARGE
+ printf("na=%d nb=%d nq=%d\n", (int)na, (int)nb, (int)nq);
+ mp_print_str("a", taba, na);
+ mp_print_str("b", tabb, nb);
+#endif
+ assert(nq >= 1);
+ n = nq;
+ if (nq < nb)
+ n++;
+ tabb_inv = bf_malloc(s, sizeof(limb_t) * (n + 1));
+ tabt = bf_malloc(s, sizeof(limb_t) * 2 * (n + 1));
+ if (!tabb_inv || !tabt)
+ goto fail;
+
+ if (n >= nb) {
+ for(i = 0; i < n - nb; i++)
+ tabt[i] = 0;
+ for(i = 0; i < nb; i++)
+ tabt[i + n - nb] = tabb[i];
+ } else {
+ /* truncate B: need to increment it so that the approximate
+ inverse is smaller that the exact inverse */
+ for(i = 0; i < n; i++)
+ tabt[i] = tabb[i + nb - n];
+ if (mp_add_ui(tabt, 1, n)) {
+ /* tabt = B^n : tabb_inv = B^n */
+ memset(tabb_inv, 0, n * sizeof(limb_t));
+ tabb_inv[n] = 1;
+ goto recip_done;
+ }
+ }
+ if (mp_recip(s, tabb_inv, tabt, n))
+ goto fail;
+ recip_done:
+ /* Q=A*B^-1 */
+ if (mp_mul(s, tabt, tabb_inv, n + 1, taba + na - (n + 1), n + 1))
+ goto fail;
+
+ for(i = 0; i < nq + 1; i++)
+ tabq[i] = tabt[i + 2 * (n + 1) - (nq + 1)];
+#ifdef DEBUG_DIVNORM_LARGE
+ mp_print_str("q", tabq, nq + 1);
+#endif
+
+ bf_free(s, tabt);
+ bf_free(s, tabb_inv);
+ tabb_inv = NULL;
+
+ /* R=A-B*Q */
+ tabt = bf_malloc(s, sizeof(limb_t) * (na + 1));
+ if (!tabt)
+ goto fail;
+ if (mp_mul(s, tabt, tabq, nq + 1, tabb, nb))
+ goto fail;
+ /* we add one more limb for the result */
+ mp_sub(taba, taba, tabt, nb + 1, 0);
+ bf_free(s, tabt);
+ /* the approximated quotient is smaller than than the exact one,
+ hence we may have to increment it */
+#ifdef DEBUG_DIVNORM_LARGE2
+ int cnt = 0;
+ static int cnt_max;
+#endif
+ for(;;) {
+ if (taba[nb] == 0 && mp_cmp(taba, tabb, nb) < 0)
+ break;
+ taba[nb] -= mp_sub(taba, taba, tabb, nb, 0);
+ mp_add_ui(tabq, 1, nq + 1);
+#ifdef DEBUG_DIVNORM_LARGE2
+ cnt++;
+#endif
+ }
+#ifdef DEBUG_DIVNORM_LARGE2
+ if (cnt > cnt_max) {
+ cnt_max = cnt;
+ printf("\ncnt=%d nq=%d nb=%d\n", cnt_max, (int)nq, (int)nb);
+ }
+#endif
+ return 0;
+ fail:
+ bf_free(s, tabb_inv);
+ bf_free(s, tabt);
+ return -1;
+}
+
+int bf_mul(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
+ bf_flags_t flags)
+{
+ int ret, r_sign;
+
+ if (a->len < b->len) {
+ const bf_t *tmp = a;
+ a = b;
+ b = tmp;
+ }
+ r_sign = a->sign ^ b->sign;
+ /* here b->len <= a->len */
+ if (b->len == 0) {
+ if (a->expn == BF_EXP_NAN || b->expn == BF_EXP_NAN) {
+ bf_set_nan(r);
+ ret = 0;
+ } else if (a->expn == BF_EXP_INF || b->expn == BF_EXP_INF) {
+ if ((a->expn == BF_EXP_INF && b->expn == BF_EXP_ZERO) ||
+ (a->expn == BF_EXP_ZERO && b->expn == BF_EXP_INF)) {
+ bf_set_nan(r);
+ ret = BF_ST_INVALID_OP;
+ } else {
+ bf_set_inf(r, r_sign);
+ ret = 0;
+ }
+ } else {
+ bf_set_zero(r, r_sign);
+ ret = 0;
+ }
+ } else {
+ bf_t tmp, *r1 = NULL;
+ limb_t a_len, b_len, precl;
+ limb_t *a_tab, *b_tab;
+
+ a_len = a->len;
+ b_len = b->len;
+
+ if ((flags & BF_RND_MASK) == BF_RNDF) {
+ /* faithful rounding does not require using the full inputs */
+ precl = (prec + 2 + LIMB_BITS - 1) / LIMB_BITS;
+ a_len = bf_min(a_len, precl);
+ b_len = bf_min(b_len, precl);
+ }
+ a_tab = a->tab + a->len - a_len;
+ b_tab = b->tab + b->len - b_len;
+
+#ifdef USE_FFT_MUL
+ if (b_len >= FFT_MUL_THRESHOLD) {
+ int mul_flags = 0;
+ if (r == a)
+ mul_flags |= FFT_MUL_R_OVERLAP_A;
+ if (r == b)
+ mul_flags |= FFT_MUL_R_OVERLAP_B;
+ if (fft_mul(r->ctx, r, a_tab, a_len, b_tab, b_len, mul_flags))
+ goto fail;
+ } else
+#endif
+ {
+ if (r == a || r == b) {
+ bf_init(r->ctx, &tmp);
+ r1 = r;
+ r = &tmp;
+ }
+ if (bf_resize(r, a_len + b_len)) {
+#ifdef USE_FFT_MUL
+ fail:
+#endif
+ bf_set_nan(r);
+ ret = BF_ST_MEM_ERROR;
+ goto done;
+ }
+ mp_mul_basecase(r->tab, a_tab, a_len, b_tab, b_len);
+ }
+ r->sign = r_sign;
+ r->expn = a->expn + b->expn;
+ ret = bf_normalize_and_round(r, prec, flags);
+ done:
+ if (r == &tmp)
+ bf_move(r1, &tmp);
+ }
+ return ret;
+}
+
+/* multiply 'r' by 2^e */
+int bf_mul_2exp(bf_t *r, slimb_t e, limb_t prec, bf_flags_t flags)
+{
+ slimb_t e_max;
+ if (r->len == 0)
+ return 0;
+ e_max = ((limb_t)1 << BF_EXT_EXP_BITS_MAX) - 1;
+ e = bf_max(e, -e_max);
+ e = bf_min(e, e_max);
+ r->expn += e;
+ return __bf_round(r, prec, flags, r->len, 0);
+}
+
+/* Return e such as a=m*2^e with m odd integer. return 0 if a is zero,
+ Infinite or Nan. */
+slimb_t bf_get_exp_min(const bf_t *a)
+{
+ slimb_t i;
+ limb_t v;
+ int k;
+
+ for(i = 0; i < a->len; i++) {
+ v = a->tab[i];
+ if (v != 0) {
+ k = ctz(v);
+ return a->expn - (a->len - i) * LIMB_BITS + k;
+ }
+ }
+ return 0;
+}
+
+/* a and b must be finite numbers with a >= 0 and b > 0. 'q' is the
+ integer defined as floor(a/b) and r = a - q * b. */
+static void bf_tdivremu(bf_t *q, bf_t *r,
+ const bf_t *a, const bf_t *b)
+{
+ if (bf_cmpu(a, b) < 0) {
+ bf_set_ui(q, 0);
+ bf_set(r, a);
+ } else {
+ bf_div(q, a, b, bf_max(a->expn - b->expn + 1, 2), BF_RNDZ);
+ bf_rint(q, BF_RNDZ);
+ bf_mul(r, q, b, BF_PREC_INF, BF_RNDZ);
+ bf_sub(r, a, r, BF_PREC_INF, BF_RNDZ);
+ }
+}
+
+static int __bf_div(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
+ bf_flags_t flags)
+{
+ bf_context_t *s = r->ctx;
+ int ret, r_sign;
+ limb_t n, nb, precl;
+
+ r_sign = a->sign ^ b->sign;
+ if (a->expn >= BF_EXP_INF || b->expn >= BF_EXP_INF) {
+ if (a->expn == BF_EXP_NAN || b->expn == BF_EXP_NAN) {
+ bf_set_nan(r);
+ return 0;
+ } else if (a->expn == BF_EXP_INF && b->expn == BF_EXP_INF) {
+ bf_set_nan(r);
+ return BF_ST_INVALID_OP;
+ } else if (a->expn == BF_EXP_INF) {
+ bf_set_inf(r, r_sign);
+ return 0;
+ } else {
+ bf_set_zero(r, r_sign);
+ return 0;
+ }
+ } else if (a->expn == BF_EXP_ZERO) {
+ if (b->expn == BF_EXP_ZERO) {
+ bf_set_nan(r);
+ return BF_ST_INVALID_OP;
+ } else {
+ bf_set_zero(r, r_sign);
+ return 0;
+ }
+ } else if (b->expn == BF_EXP_ZERO) {
+ bf_set_inf(r, r_sign);
+ return BF_ST_DIVIDE_ZERO;
+ }
+
+ /* number of limbs of the quotient (2 extra bits for rounding) */
+ precl = (prec + 2 + LIMB_BITS - 1) / LIMB_BITS;
+ nb = b->len;
+ n = bf_max(a->len, precl);
+
+ {
+ limb_t *taba, na;
+ slimb_t d;
+
+ na = n + nb;
+ taba = bf_malloc(s, (na + 1) * sizeof(limb_t));
+ if (!taba)
+ goto fail;
+ d = na - a->len;
+ memset(taba, 0, d * sizeof(limb_t));
+ memcpy(taba + d, a->tab, a->len * sizeof(limb_t));
+ if (bf_resize(r, n + 1))
+ goto fail1;
+ if (mp_divnorm(s, r->tab, taba, na, b->tab, nb)) {
+ fail1:
+ bf_free(s, taba);
+ goto fail;
+ }
+ /* see if non zero remainder */
+ if (mp_scan_nz(taba, nb))
+ r->tab[0] |= 1;
+ bf_free(r->ctx, taba);
+ r->expn = a->expn - b->expn + LIMB_BITS;
+ r->sign = r_sign;
+ ret = bf_normalize_and_round(r, prec, flags);
+ }
+ return ret;
+ fail:
+ bf_set_nan(r);
+ return BF_ST_MEM_ERROR;
+}
+
+/* division and remainder.
+
+ rnd_mode is the rounding mode for the quotient. The additional
+ rounding mode BF_RND_EUCLIDIAN is supported.
+
+ 'q' is an integer. 'r' is rounded with prec and flags (prec can be
+ BF_PREC_INF).
+*/
+int bf_divrem(bf_t *q, bf_t *r, const bf_t *a, const bf_t *b,
+ limb_t prec, bf_flags_t flags, int rnd_mode)
+{
+ bf_t a1_s, *a1 = &a1_s;
+ bf_t b1_s, *b1 = &b1_s;
+ int q_sign, ret;
+ BOOL is_ceil, is_rndn;
+
+ assert(q != a && q != b);
+ assert(r != a && r != b);
+ assert(q != r);
+
+ if (a->len == 0 || b->len == 0) {
+ bf_set_zero(q, 0);
+ if (a->expn == BF_EXP_NAN || b->expn == BF_EXP_NAN) {
+ bf_set_nan(r);
+ return 0;
+ } else if (a->expn == BF_EXP_INF || b->expn == BF_EXP_ZERO) {
+ bf_set_nan(r);
+ return BF_ST_INVALID_OP;
+ } else {
+ bf_set(r, a);
+ return bf_round(r, prec, flags);
+ }
+ }
+
+ q_sign = a->sign ^ b->sign;
+ is_rndn = (rnd_mode == BF_RNDN || rnd_mode == BF_RNDNA);
+ switch(rnd_mode) {
+ default:
+ case BF_RNDZ:
+ case BF_RNDN:
+ case BF_RNDNA:
+ is_ceil = FALSE;
+ break;
+ case BF_RNDD:
+ is_ceil = q_sign;
+ break;
+ case BF_RNDU:
+ is_ceil = q_sign ^ 1;
+ break;
+ case BF_RNDA:
+ is_ceil = TRUE;
+ break;
+ case BF_DIVREM_EUCLIDIAN:
+ is_ceil = a->sign;
+ break;
+ }
+
+ a1->expn = a->expn;
+ a1->tab = a->tab;
+ a1->len = a->len;
+ a1->sign = 0;
+
+ b1->expn = b->expn;
+ b1->tab = b->tab;
+ b1->len = b->len;
+ b1->sign = 0;
+
+ /* XXX: could improve to avoid having a large 'q' */
+ bf_tdivremu(q, r, a1, b1);
+ if (bf_is_nan(q) || bf_is_nan(r))
+ goto fail;
+
+ if (r->len != 0) {
+ if (is_rndn) {
+ int res;
+ b1->expn--;
+ res = bf_cmpu(r, b1);
+ b1->expn++;
+ if (res > 0 ||
+ (res == 0 &&
+ (rnd_mode == BF_RNDNA ||
+ get_bit(q->tab, q->len, q->len * LIMB_BITS - q->expn)))) {
+ goto do_sub_r;
+ }
+ } else if (is_ceil) {
+ do_sub_r:
+ ret = bf_add_si(q, q, 1, BF_PREC_INF, BF_RNDZ);
+ ret |= bf_sub(r, r, b1, BF_PREC_INF, BF_RNDZ);
+ if (ret & BF_ST_MEM_ERROR)
+ goto fail;
+ }
+ }
+
+ r->sign ^= a->sign;
+ q->sign = q_sign;
+ return bf_round(r, prec, flags);
+ fail:
+ bf_set_nan(q);
+ bf_set_nan(r);
+ return BF_ST_MEM_ERROR;
+}
+
+int bf_rem(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
+ bf_flags_t flags, int rnd_mode)
+{
+ bf_t q_s, *q = &q_s;
+ int ret;
+
+ bf_init(r->ctx, q);
+ ret = bf_divrem(q, r, a, b, prec, flags, rnd_mode);
+ bf_delete(q);
+ return ret;
+}
+
+static inline int bf_get_limb(slimb_t *pres, const bf_t *a, int flags)
+{
+#if LIMB_BITS == 32
+ return bf_get_int32(pres, a, flags);
+#else
+ return bf_get_int64(pres, a, flags);
+#endif
+}
+
+int bf_remquo(slimb_t *pq, bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
+ bf_flags_t flags, int rnd_mode)
+{
+ bf_t q_s, *q = &q_s;
+ int ret;
+
+ bf_init(r->ctx, q);
+ ret = bf_divrem(q, r, a, b, prec, flags, rnd_mode);
+ bf_get_limb(pq, q, BF_GET_INT_MOD);
+ bf_delete(q);
+ return ret;
+}
+
+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;
+ return t % m;
+}
+
+#if defined(USE_MUL_CHECK)
+static limb_t mp_mod1(const limb_t *tab, limb_t n, limb_t m, limb_t r)
+{
+ slimb_t i;
+ dlimb_t t;
+
+ for(i = n - 1; i >= 0; i--) {
+ t = ((dlimb_t)r << LIMB_BITS) | tab[i];
+ r = t % m;
+ }
+ return r;
+}
+#endif
+
+static const uint16_t sqrt_table[192] = {
+128,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,144,145,146,147,148,149,150,150,151,152,153,154,155,155,156,157,158,159,160,160,161,162,163,163,164,165,166,167,167,168,169,170,170,171,172,173,173,174,175,176,176,177,178,178,179,180,181,181,182,183,183,184,185,185,186,187,187,188,189,189,190,191,192,192,193,193,194,195,195,196,197,197,198,199,199,200,201,201,202,203,203,204,204,205,206,206,207,208,208,209,209,210,211,211,212,212,213,214,214,215,215,216,217,217,218,218,219,219,220,221,221,222,222,223,224,224,225,225,226,226,227,227,228,229,229,230,230,231,231,232,232,233,234,234,235,235,236,236,237,237,238,238,239,240,240,241,241,242,242,243,243,244,244,245,245,246,246,247,247,248,248,249,249,250,250,251,251,252,252,253,253,254,254,255,
+};
+
+/* a >= 2^(LIMB_BITS - 2). Return (s, r) with s=floor(sqrt(a)) and
+ r=a-s^2. 0 <= r <= 2 * s */
+static limb_t mp_sqrtrem1(limb_t *pr, limb_t a)
+{
+ limb_t s1, r1, s, r, q, u, num;
+
+ /* use a table for the 16 -> 8 bit sqrt */
+ s1 = sqrt_table[(a >> (LIMB_BITS - 8)) - 64];
+ r1 = (a >> (LIMB_BITS - 16)) - s1 * s1;
+ if (r1 > 2 * s1) {
+ r1 -= 2 * s1 + 1;
+ s1++;
+ }
+
+ /* one iteration to get a 32 -> 16 bit sqrt */
+ num = (r1 << 8) | ((a >> (LIMB_BITS - 32 + 8)) & 0xff);
+ q = num / (2 * s1); /* q <= 2^8 */
+ u = num % (2 * s1);
+ s = (s1 << 8) + q;
+ r = (u << 8) | ((a >> (LIMB_BITS - 32)) & 0xff);
+ r -= q * q;
+ if ((slimb_t)r < 0) {
+ s--;
+ r += 2 * s + 1;
+ }
+
+#if LIMB_BITS == 64
+ s1 = s;
+ r1 = r;
+ /* one more iteration for 64 -> 32 bit sqrt */
+ num = (r1 << 16) | ((a >> (LIMB_BITS - 64 + 16)) & 0xffff);
+ q = num / (2 * s1); /* q <= 2^16 */
+ u = num % (2 * s1);
+ s = (s1 << 16) + q;
+ r = (u << 16) | ((a >> (LIMB_BITS - 64)) & 0xffff);
+ r -= q * q;
+ if ((slimb_t)r < 0) {
+ s--;
+ r += 2 * s + 1;
+ }
+#endif
+ *pr = r;
+ return s;
+}
+
+/* return floor(sqrt(a)) */
+limb_t bf_isqrt(limb_t a)
+{
+ limb_t s, r;
+ int k;
+
+ if (a == 0)
+ return 0;
+ k = clz(a) & ~1;
+ s = mp_sqrtrem1(&r, a << k);
+ s >>= (k >> 1);
+ return s;
+}
+
+static limb_t mp_sqrtrem2(limb_t *tabs, limb_t *taba)
+{
+ limb_t s1, r1, s, q, u, a0, a1;
+ dlimb_t r, num;
+ int l;
+
+ a0 = taba[0];
+ a1 = taba[1];
+ s1 = mp_sqrtrem1(&r1, a1);
+ l = LIMB_BITS / 2;
+ num = ((dlimb_t)r1 << l) | (a0 >> l);
+ q = num / (2 * s1);
+ u = num % (2 * s1);
+ s = (s1 << l) + q;
+ r = ((dlimb_t)u << l) | (a0 & (((limb_t)1 << l) - 1));
+ if (unlikely((q >> l) != 0))
+ r -= (dlimb_t)1 << LIMB_BITS; /* special case when q=2^l */
+ else
+ r -= q * q;
+ if ((slimb_t)(r >> LIMB_BITS) < 0) {
+ s--;
+ r += 2 * (dlimb_t)s + 1;
+ }
+ tabs[0] = s;
+ taba[0] = r;
+ return r >> LIMB_BITS;
+}
+
+//#define DEBUG_SQRTREM
+
+/* tmp_buf must contain (n / 2 + 1 limbs). *prh contains the highest
+ limb of the remainder. */
+static int mp_sqrtrem_rec(bf_context_t *s, limb_t *tabs, limb_t *taba, limb_t n,
+ limb_t *tmp_buf, limb_t *prh)
+{
+ limb_t l, h, rh, ql, qh, c, i;
+
+ if (n == 1) {
+ *prh = mp_sqrtrem2(tabs, taba);
+ return 0;
+ }
+#ifdef DEBUG_SQRTREM
+ mp_print_str("a", taba, 2 * n);
+#endif
+ l = n / 2;
+ h = n - l;
+ if (mp_sqrtrem_rec(s, tabs + l, taba + 2 * l, h, tmp_buf, &qh))
+ return -1;
+#ifdef DEBUG_SQRTREM
+ mp_print_str("s1", tabs + l, h);
+ mp_print_str_h("r1", taba + 2 * l, h, qh);
+ mp_print_str_h("r2", taba + l, n, qh);
+#endif
+
+ /* the remainder is in taba + 2 * l. Its high bit is in qh */
+ if (qh) {
+ mp_sub(taba + 2 * l, taba + 2 * l, tabs + l, h, 0);
+ }
+ /* instead of dividing by 2*s, divide by s (which is normalized)
+ and update q and r */
+ if (mp_divnorm(s, tmp_buf, taba + l, n, tabs + l, h))
+ return -1;
+ qh += tmp_buf[l];
+ for(i = 0; i < l; i++)
+ tabs[i] = tmp_buf[i];
+ ql = mp_shr(tabs, tabs, l, 1, qh & 1);
+ qh = qh >> 1; /* 0 or 1 */
+ if (ql)
+ rh = mp_add(taba + l, taba + l, tabs + l, h, 0);
+ else
+ rh = 0;
+#ifdef DEBUG_SQRTREM
+ mp_print_str_h("q", tabs, l, qh);
+ mp_print_str_h("u", taba + l, h, rh);
+#endif
+
+ mp_add_ui(tabs + l, qh, h);
+#ifdef DEBUG_SQRTREM
+ mp_print_str_h("s2", tabs, n, sh);
+#endif
+
+ /* q = qh, tabs[l - 1 ... 0], r = taba[n - 1 ... l] */
+ /* subtract q^2. if qh = 1 then q = B^l, so we can take shortcuts */
+ if (qh) {
+ c = qh;
+ } else {
+ if (mp_mul(s, taba + n, tabs, l, tabs, l))
+ return -1;
+ c = mp_sub(taba, taba, taba + n, 2 * l, 0);
+ }
+ rh -= mp_sub_ui(taba + 2 * l, c, n - 2 * l);
+ if ((slimb_t)rh < 0) {
+ mp_sub_ui(tabs, 1, n);
+ rh += mp_add_mul1(taba, tabs, n, 2);
+ rh += mp_add_ui(taba, 1, n);
+ }
+ *prh = rh;
+ return 0;
+}
+
+/* 'taba' has 2*n limbs with n >= 1 and taba[2*n-1] >= 2 ^ (LIMB_BITS
+ - 2). Return (s, r) with s=floor(sqrt(a)) and r=a-s^2. 0 <= r <= 2
+ * s. tabs has n limbs. r is returned in the lower n limbs of
+ taba. Its r[n] is the returned value of the function. */
+/* Algorithm from the article "Karatsuba Square Root" by Paul Zimmermann and
+ inspirated from its GMP implementation */
+int mp_sqrtrem(bf_context_t *s, limb_t *tabs, limb_t *taba, limb_t n)
+{
+ limb_t tmp_buf1[8];
+ limb_t *tmp_buf;
+ mp_size_t n2;
+ int ret;
+ n2 = n / 2 + 1;
+ if (n2 <= countof(tmp_buf1)) {
+ tmp_buf = tmp_buf1;
+ } else {
+ tmp_buf = bf_malloc(s, sizeof(limb_t) * n2);
+ if (!tmp_buf)
+ return -1;
+ }
+ ret = mp_sqrtrem_rec(s, tabs, taba, n, tmp_buf, taba + n);
+ if (tmp_buf != tmp_buf1)
+ bf_free(s, tmp_buf);
+ return ret;
+}
+
+/* Integer square root with remainder. 'a' must be an integer. r =
+ floor(sqrt(a)) and rem = a - r^2. BF_ST_INEXACT is set if the result
+ is inexact. 'rem' can be NULL if the remainder is not needed. */
+int bf_sqrtrem(bf_t *r, bf_t *rem1, const bf_t *a)
+{
+ int ret;
+
+ if (a->len == 0) {
+ if (a->expn == BF_EXP_NAN) {
+ bf_set_nan(r);
+ } else if (a->expn == BF_EXP_INF && a->sign) {
+ goto invalid_op;
+ } else {
+ bf_set(r, a);
+ }
+ if (rem1)
+ bf_set_ui(rem1, 0);
+ ret = 0;
+ } else if (a->sign) {
+ invalid_op:
+ bf_set_nan(r);
+ if (rem1)
+ bf_set_ui(rem1, 0);
+ ret = BF_ST_INVALID_OP;
+ } else {
+ bf_t rem_s, *rem;
+
+ bf_sqrt(r, a, (a->expn + 1) / 2, BF_RNDZ);
+ bf_rint(r, BF_RNDZ);
+ /* see if the result is exact by computing the remainder */
+ if (rem1) {
+ rem = rem1;
+ } else {
+ rem = &rem_s;
+ bf_init(r->ctx, rem);
+ }
+ /* XXX: could avoid recomputing the remainder */
+ bf_mul(rem, r, r, BF_PREC_INF, BF_RNDZ);
+ bf_neg(rem);
+ bf_add(rem, rem, a, BF_PREC_INF, BF_RNDZ);
+ if (bf_is_nan(rem)) {
+ ret = BF_ST_MEM_ERROR;
+ goto done;
+ }
+ if (rem->len != 0) {
+ ret = BF_ST_INEXACT;
+ } else {
+ ret = 0;
+ }
+ done:
+ if (!rem1)
+ bf_delete(rem);
+ }
+ return ret;
+}
+
+int bf_sqrt(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags)
+{
+ bf_context_t *s = a->ctx;
+ int ret;
+
+ assert(r != a);
+
+ if (a->len == 0) {
+ if (a->expn == BF_EXP_NAN) {
+ bf_set_nan(r);
+ } else if (a->expn == BF_EXP_INF && a->sign) {
+ goto invalid_op;
+ } else {
+ bf_set(r, a);
+ }
+ ret = 0;
+ } else if (a->sign) {
+ invalid_op:
+ bf_set_nan(r);
+ ret = BF_ST_INVALID_OP;
+ } else {
+ limb_t *a1;
+ slimb_t n, n1;
+ limb_t res;
+
+ /* convert the mantissa to an integer with at least 2 *
+ prec + 4 bits */
+ n = (2 * (prec + 2) + 2 * LIMB_BITS - 1) / (2 * LIMB_BITS);
+ if (bf_resize(r, n))
+ goto fail;
+ a1 = bf_malloc(s, sizeof(limb_t) * 2 * n);
+ if (!a1)
+ goto fail;
+ n1 = bf_min(2 * n, a->len);
+ memset(a1, 0, (2 * n - n1) * sizeof(limb_t));
+ memcpy(a1 + 2 * n - n1, a->tab + a->len - n1, n1 * sizeof(limb_t));
+ if (a->expn & 1) {
+ res = mp_shr(a1, a1, 2 * n, 1, 0);
+ } else {
+ res = 0;
+ }
+ if (mp_sqrtrem(s, r->tab, a1, n)) {
+ bf_free(s, a1);
+ goto fail;
+ }
+ if (!res) {
+ res = mp_scan_nz(a1, n + 1);
+ }
+ bf_free(s, a1);
+ if (!res) {
+ res = mp_scan_nz(a->tab, a->len - n1);
+ }
+ if (res != 0)
+ r->tab[0] |= 1;
+ r->sign = 0;
+ r->expn = (a->expn + 1) >> 1;
+ ret = bf_round(r, prec, flags);
+ }
+ return ret;
+ fail:
+ bf_set_nan(r);
+ return BF_ST_MEM_ERROR;
+}
+
+static no_inline int bf_op2(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
+ bf_flags_t flags, bf_op2_func_t *func)
+{
+ bf_t tmp;
+ int ret;
+
+ if (r == a || r == b) {
+ bf_init(r->ctx, &tmp);
+ ret = func(&tmp, a, b, prec, flags);
+ bf_move(r, &tmp);
+ } else {
+ ret = func(r, a, b, prec, flags);
+ }
+ return ret;
+}
+
+int bf_add(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
+ bf_flags_t flags)
+{
+ return bf_op2(r, a, b, prec, flags, __bf_add);
+}
+
+int bf_sub(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
+ bf_flags_t flags)
+{
+ return bf_op2(r, a, b, prec, flags, __bf_sub);
+}
+
+int bf_div(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
+ bf_flags_t flags)
+{
+ return bf_op2(r, a, b, prec, flags, __bf_div);
+}
+
+int bf_mul_ui(bf_t *r, const bf_t *a, uint64_t b1, limb_t prec,
+ bf_flags_t flags)
+{
+ bf_t b;
+ int ret;
+ bf_init(r->ctx, &b);
+ ret = bf_set_ui(&b, b1);
+ ret |= bf_mul(r, a, &b, prec, flags);
+ bf_delete(&b);
+ return ret;
+}
+
+int bf_mul_si(bf_t *r, const bf_t *a, int64_t b1, limb_t prec,
+ bf_flags_t flags)
+{
+ bf_t b;
+ int ret;
+ bf_init(r->ctx, &b);
+ ret = bf_set_si(&b, b1);
+ ret |= bf_mul(r, a, &b, prec, flags);
+ bf_delete(&b);
+ return ret;
+}
+
+int bf_add_si(bf_t *r, const bf_t *a, int64_t b1, limb_t prec,
+ bf_flags_t flags)
+{
+ bf_t b;
+ int ret;
+
+ bf_init(r->ctx, &b);
+ ret = bf_set_si(&b, b1);
+ ret |= bf_add(r, a, &b, prec, flags);
+ bf_delete(&b);
+ return ret;
+}
+
+static int bf_pow_ui(bf_t *r, const bf_t *a, limb_t b, limb_t prec,
+ bf_flags_t flags)
+{
+ int ret, n_bits, i;
+
+ assert(r != a);
+ if (b == 0)
+ return bf_set_ui(r, 1);
+ ret = bf_set(r, a);
+ n_bits = LIMB_BITS - clz(b);
+ for(i = n_bits - 2; i >= 0; i--) {
+ ret |= bf_mul(r, r, r, prec, flags);
+ if ((b >> i) & 1)
+ ret |= bf_mul(r, r, a, prec, flags);
+ }
+ return ret;
+}
+
+static int bf_pow_ui_ui(bf_t *r, limb_t a1, limb_t b,
+ limb_t prec, bf_flags_t flags)
+{
+ bf_t a;
+ int ret;
+
+#ifdef USE_BF_DEC
+ if (a1 == 10 && b <= LIMB_DIGITS) {
+ /* use precomputed powers. We do not round at this point
+ because we expect the caller to do it */
+ ret = bf_set_ui(r, mp_pow_dec[b]);
+ } else
+#endif
+ {
+ bf_init(r->ctx, &a);
+ ret = bf_set_ui(&a, a1);
+ ret |= bf_pow_ui(r, &a, b, prec, flags);
+ bf_delete(&a);
+ }
+ return ret;
+}
+
+/* convert to integer (infinite precision) */
+int bf_rint(bf_t *r, int rnd_mode)
+{
+ return bf_round(r, 0, rnd_mode | BF_FLAG_RADPNT_PREC);
+}
+
+/* logical operations */
+#define BF_LOGIC_OR 0
+#define BF_LOGIC_XOR 1
+#define BF_LOGIC_AND 2
+
+static inline limb_t bf_logic_op1(limb_t a, limb_t b, int op)
+{
+ switch(op) {
+ case BF_LOGIC_OR:
+ return a | b;
+ case BF_LOGIC_XOR:
+ return a ^ b;
+ default:
+ case BF_LOGIC_AND:
+ return a & b;
+ }
+}
+
+static int bf_logic_op(bf_t *r, const bf_t *a1, const bf_t *b1, int op)
+{
+ bf_t b1_s, a1_s, *a, *b;
+ limb_t a_sign, b_sign, r_sign;
+ slimb_t l, i, a_bit_offset, b_bit_offset;
+ limb_t v1, v2, v1_mask, v2_mask, r_mask;
+ int ret;
+
+ assert(r != a1 && r != b1);
+
+ if (a1->expn <= 0)
+ a_sign = 0; /* minus zero is considered as positive */
+ else
+ a_sign = a1->sign;
+
+ if (b1->expn <= 0)
+ b_sign = 0; /* minus zero is considered as positive */
+ else
+ b_sign = b1->sign;
+
+ if (a_sign) {
+ a = &a1_s;
+ bf_init(r->ctx, a);
+ if (bf_add_si(a, a1, 1, BF_PREC_INF, BF_RNDZ)) {
+ b = NULL;
+ goto fail;
+ }
+ } else {
+ a = (bf_t *)a1;
+ }
+
+ if (b_sign) {
+ b = &b1_s;
+ bf_init(r->ctx, b);
+ if (bf_add_si(b, b1, 1, BF_PREC_INF, BF_RNDZ))
+ goto fail;
+ } else {
+ b = (bf_t *)b1;
+ }
+
+ r_sign = bf_logic_op1(a_sign, b_sign, op);
+ if (op == BF_LOGIC_AND && r_sign == 0) {
+ /* no need to compute extra zeros for and */
+ if (a_sign == 0 && b_sign == 0)
+ l = bf_min(a->expn, b->expn);
+ else if (a_sign == 0)
+ l = a->expn;
+ else
+ l = b->expn;
+ } else {
+ l = bf_max(a->expn, b->expn);
+ }
+ /* Note: a or b can be zero */
+ l = (bf_max(l, 1) + LIMB_BITS - 1) / LIMB_BITS;
+ if (bf_resize(r, l))
+ goto fail;
+ a_bit_offset = a->len * LIMB_BITS - a->expn;
+ b_bit_offset = b->len * LIMB_BITS - b->expn;
+ v1_mask = -a_sign;
+ v2_mask = -b_sign;
+ r_mask = -r_sign;
+ for(i = 0; i < l; i++) {
+ v1 = get_bits(a->tab, a->len, a_bit_offset + i * LIMB_BITS) ^ v1_mask;
+ v2 = get_bits(b->tab, b->len, b_bit_offset + i * LIMB_BITS) ^ v2_mask;
+ r->tab[i] = bf_logic_op1(v1, v2, op) ^ r_mask;
+ }
+ r->expn = l * LIMB_BITS;
+ r->sign = r_sign;
+ bf_normalize_and_round(r, BF_PREC_INF, BF_RNDZ); /* cannot fail */
+ if (r_sign) {
+ if (bf_add_si(r, r, -1, BF_PREC_INF, BF_RNDZ))
+ goto fail;
+ }
+ ret = 0;
+ done:
+ if (a == &a1_s)
+ bf_delete(a);
+ if (b == &b1_s)
+ bf_delete(b);
+ return ret;
+ fail:
+ bf_set_nan(r);
+ ret = BF_ST_MEM_ERROR;
+ goto done;
+}
+
+/* 'a' and 'b' must be integers. Return 0 or BF_ST_MEM_ERROR. */
+int bf_logic_or(bf_t *r, const bf_t *a, const bf_t *b)
+{
+ return bf_logic_op(r, a, b, BF_LOGIC_OR);
+}
+
+/* 'a' and 'b' must be integers. Return 0 or BF_ST_MEM_ERROR. */
+int bf_logic_xor(bf_t *r, const bf_t *a, const bf_t *b)
+{
+ return bf_logic_op(r, a, b, BF_LOGIC_XOR);
+}
+
+/* 'a' and 'b' must be integers. Return 0 or BF_ST_MEM_ERROR. */
+int bf_logic_and(bf_t *r, const bf_t *a, const bf_t *b)
+{
+ return bf_logic_op(r, a, b, BF_LOGIC_AND);
+}
+
+/* conversion between fixed size types */
+
+typedef union {
+ double d;
+ uint64_t u;
+} Float64Union;
+
+int bf_get_float64(const bf_t *a, double *pres, bf_rnd_t rnd_mode)
+{
+ Float64Union u;
+ int e, ret;
+ uint64_t m;
+
+ ret = 0;
+ if (a->expn == BF_EXP_NAN) {
+ u.u = 0x7ff8000000000000; /* quiet nan */
+ } else {
+ bf_t b_s, *b = &b_s;
+
+ bf_init(a->ctx, b);
+ bf_set(b, a);
+ if (bf_is_finite(b)) {
+ ret = bf_round(b, 53, rnd_mode | BF_FLAG_SUBNORMAL | bf_set_exp_bits(11));
+ }
+ if (b->expn == BF_EXP_INF) {
+ e = (1 << 11) - 1;
+ m = 0;
+ } else if (b->expn == BF_EXP_ZERO) {
+ e = 0;
+ m = 0;
+ } else {
+ e = b->expn + 1023 - 1;
+#if LIMB_BITS == 32
+ if (b->len == 2) {
+ m = ((uint64_t)b->tab[1] << 32) | b->tab[0];
+ } else {
+ m = ((uint64_t)b->tab[0] << 32);
+ }
+#else
+ m = b->tab[0];
+#endif
+ if (e <= 0) {
+ /* subnormal */
+ m = m >> (12 - e);
+ e = 0;
+ } else {
+ m = (m << 1) >> 12;
+ }
+ }
+ u.u = m | ((uint64_t)e << 52) | ((uint64_t)b->sign << 63);
+ bf_delete(b);
+ }
+ *pres = u.d;
+ return ret;
+}
+
+int bf_set_float64(bf_t *a, double d)
+{
+ Float64Union u;
+ uint64_t m;
+ int shift, e, sgn;
+
+ u.d = d;
+ sgn = u.u >> 63;
+ e = (u.u >> 52) & ((1 << 11) - 1);
+ m = u.u & (((uint64_t)1 << 52) - 1);
+ if (e == ((1 << 11) - 1)) {
+ if (m != 0) {
+ bf_set_nan(a);
+ } else {
+ bf_set_inf(a, sgn);
+ }
+ } else if (e == 0) {
+ if (m == 0) {
+ bf_set_zero(a, sgn);
+ } else {
+ /* subnormal number */
+ m <<= 12;
+ shift = clz64(m);
+ m <<= shift;
+ e = -shift;
+ goto norm;
+ }
+ } else {
+ m = (m << 11) | ((uint64_t)1 << 63);
+ norm:
+ a->expn = e - 1023 + 1;
+#if LIMB_BITS == 32
+ if (bf_resize(a, 2))
+ goto fail;
+ a->tab[0] = m;
+ a->tab[1] = m >> 32;
+#else
+ if (bf_resize(a, 1))
+ goto fail;
+ a->tab[0] = m;
+#endif
+ a->sign = sgn;
+ }
+ return 0;
+fail:
+ bf_set_nan(a);
+ return BF_ST_MEM_ERROR;
+}
+
+/* The rounding mode is always BF_RNDZ. Return BF_ST_INVALID_OP if there
+ is an overflow and 0 otherwise. */
+int bf_get_int32(int *pres, const bf_t *a, int flags)
+{
+ uint32_t v;
+ int ret;
+ if (a->expn >= BF_EXP_INF) {
+ ret = BF_ST_INVALID_OP;
+ if (flags & BF_GET_INT_MOD) {
+ v = 0;
+ } else if (a->expn == BF_EXP_INF) {
+ v = (uint32_t)INT32_MAX + a->sign;
+ } else {
+ v = INT32_MAX;
+ }
+ } else if (a->expn <= 0) {
+ v = 0;
+ ret = 0;
+ } else if (a->expn <= 31) {
+ v = a->tab[a->len - 1] >> (LIMB_BITS - a->expn);
+ if (a->sign)
+ v = -v;
+ ret = 0;
+ } else if (!(flags & BF_GET_INT_MOD)) {
+ ret = BF_ST_INVALID_OP;
+ if (a->sign) {
+ v = (uint32_t)INT32_MAX + 1;
+ if (a->expn == 32 &&
+ (a->tab[a->len - 1] >> (LIMB_BITS - 32)) == v) {
+ ret = 0;
+ }
+ } else {
+ v = INT32_MAX;
+ }
+ } else {
+ v = get_bits(a->tab, a->len, a->len * LIMB_BITS - a->expn);
+ if (a->sign)
+ v = -v;
+ ret = 0;
+ }
+ *pres = v;
+ return ret;
+}
+
+/* The rounding mode is always BF_RNDZ. Return BF_ST_INVALID_OP if there
+ is an overflow and 0 otherwise. */
+int bf_get_int64(int64_t *pres, const bf_t *a, int flags)
+{
+ uint64_t v;
+ int ret;
+ if (a->expn >= BF_EXP_INF) {
+ ret = BF_ST_INVALID_OP;
+ if (flags & BF_GET_INT_MOD) {
+ v = 0;
+ } else if (a->expn == BF_EXP_INF) {
+ v = (uint64_t)INT64_MAX + a->sign;
+ } else {
+ v = INT64_MAX;
+ }
+ } else if (a->expn <= 0) {
+ v = 0;
+ ret = 0;
+ } else if (a->expn <= 63) {
+#if LIMB_BITS == 32
+ if (a->expn <= 32)
+ v = a->tab[a->len - 1] >> (LIMB_BITS - a->expn);
+ else
+ v = (((uint64_t)a->tab[a->len - 1] << 32) |
+ get_limbz(a, a->len - 2)) >> (64 - a->expn);
+#else
+ v = a->tab[a->len - 1] >> (LIMB_BITS - a->expn);
+#endif
+ if (a->sign)
+ v = -v;
+ ret = 0;
+ } else if (!(flags & BF_GET_INT_MOD)) {
+ ret = BF_ST_INVALID_OP;
+ if (a->sign) {
+ uint64_t v1;
+ v = (uint64_t)INT64_MAX + 1;
+ if (a->expn == 64) {
+ v1 = a->tab[a->len - 1];
+#if LIMB_BITS == 32
+ v1 = (v1 << 32) | get_limbz(a, a->len - 2);
+#endif
+ if (v1 == v)
+ ret = 0;
+ }
+ } else {
+ v = INT64_MAX;
+ }
+ } else {
+ slimb_t bit_pos = a->len * LIMB_BITS - a->expn;
+ v = get_bits(a->tab, a->len, bit_pos);
+#if LIMB_BITS == 32
+ v |= (uint64_t)get_bits(a->tab, a->len, bit_pos + 32) << 32;
+#endif
+ if (a->sign)
+ v = -v;
+ ret = 0;
+ }
+ *pres = v;
+ return ret;
+}
+
+/* The rounding mode is always BF_RNDZ. Return BF_ST_INVALID_OP if there
+ is an overflow and 0 otherwise. */
+int bf_get_uint64(uint64_t *pres, const bf_t *a)
+{
+ uint64_t v;
+ int ret;
+ if (a->expn == BF_EXP_NAN) {
+ goto overflow;
+ } else if (a->expn <= 0) {
+ v = 0;
+ ret = 0;
+ } else if (a->sign) {
+ v = 0;
+ ret = BF_ST_INVALID_OP;
+ } else if (a->expn <= 64) {
+#if LIMB_BITS == 32
+ if (a->expn <= 32)
+ v = a->tab[a->len - 1] >> (LIMB_BITS - a->expn);
+ else
+ v = (((uint64_t)a->tab[a->len - 1] << 32) |
+ get_limbz(a, a->len - 2)) >> (64 - a->expn);
+#else
+ v = a->tab[a->len - 1] >> (LIMB_BITS - a->expn);
+#endif
+ ret = 0;
+ } else {
+ overflow:
+ v = UINT64_MAX;
+ ret = BF_ST_INVALID_OP;
+ }
+ *pres = v;
+ return ret;
+}
+
+/* base conversion from radix */
+
+static const uint8_t digits_per_limb_table[BF_RADIX_MAX - 1] = {
+#if LIMB_BITS == 32
+32,20,16,13,12,11,10,10, 9, 9, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+#else
+64,40,32,27,24,22,21,20,19,18,17,17,16,16,16,15,15,15,14,14,14,14,13,13,13,13,13,13,13,12,12,12,12,12,12,
+#endif
+};
+
+static limb_t get_limb_radix(int radix)
+{
+ int i, k;
+ limb_t radixl;
+
+ k = digits_per_limb_table[radix - 2];
+ radixl = radix;
+ for(i = 1; i < k; i++)
+ radixl *= radix;
+ return radixl;
+}
+
+/* return != 0 if error */
+static int bf_integer_from_radix_rec(bf_t *r, const limb_t *tab,
+ limb_t n, int level, limb_t n0,
+ limb_t radix, bf_t *pow_tab)
+{
+ int ret;
+ if (n == 1) {
+ ret = bf_set_ui(r, tab[0]);
+ } else {
+ bf_t T_s, *T = &T_s, *B;
+ limb_t n1, n2;
+
+ n2 = (((n0 * 2) >> (level + 1)) + 1) / 2;
+ n1 = n - n2;
+ // printf("level=%d n0=%ld n1=%ld n2=%ld\n", level, n0, n1, n2);
+ B = &pow_tab[level];
+ if (B->len == 0) {
+ ret = bf_pow_ui_ui(B, radix, n2, BF_PREC_INF, BF_RNDZ);
+ if (ret)
+ return ret;
+ }
+ ret = bf_integer_from_radix_rec(r, tab + n2, n1, level + 1, n0,
+ radix, pow_tab);
+ if (ret)
+ return ret;
+ ret = bf_mul(r, r, B, BF_PREC_INF, BF_RNDZ);
+ if (ret)
+ return ret;
+ bf_init(r->ctx, T);
+ ret = bf_integer_from_radix_rec(T, tab, n2, level + 1, n0,
+ radix, pow_tab);
+ if (!ret)
+ ret = bf_add(r, r, T, BF_PREC_INF, BF_RNDZ);
+ bf_delete(T);
+ }
+ return ret;
+ // bf_print_str(" r=", r);
+}
+
+/* return 0 if OK != 0 if memory error */
+static int bf_integer_from_radix(bf_t *r, const limb_t *tab,
+ limb_t n, limb_t radix)
+{
+ bf_context_t *s = r->ctx;
+ int pow_tab_len, i, ret;
+ limb_t radixl;
+ bf_t *pow_tab;
+
+ radixl = get_limb_radix(radix);
+ pow_tab_len = ceil_log2(n) + 2; /* XXX: check */
+ pow_tab = bf_malloc(s, sizeof(pow_tab[0]) * pow_tab_len);
+ if (!pow_tab)
+ return -1;
+ for(i = 0; i < pow_tab_len; i++)
+ bf_init(r->ctx, &pow_tab[i]);
+ ret = bf_integer_from_radix_rec(r, tab, n, 0, n, radixl, pow_tab);
+ for(i = 0; i < pow_tab_len; i++) {
+ bf_delete(&pow_tab[i]);
+ }
+ bf_free(s, pow_tab);
+ return ret;
+}
+
+/* compute and round T * radix^expn. */
+int bf_mul_pow_radix(bf_t *r, const bf_t *T, limb_t radix,
+ slimb_t expn, limb_t prec, bf_flags_t flags)
+{
+ int ret, expn_sign, overflow;
+ slimb_t e, extra_bits, prec1, ziv_extra_bits;
+ bf_t B_s, *B = &B_s;
+
+ if (T->len == 0) {
+ return bf_set(r, T);
+ } else if (expn == 0) {
+ ret = bf_set(r, T);
+ ret |= bf_round(r, prec, flags);
+ return ret;
+ }
+
+ e = expn;
+ expn_sign = 0;
+ if (e < 0) {
+ e = -e;
+ expn_sign = 1;
+ }
+ bf_init(r->ctx, B);
+ if (prec == BF_PREC_INF) {
+ /* infinite precision: only used if the result is known to be exact */
+ ret = bf_pow_ui_ui(B, radix, e, BF_PREC_INF, BF_RNDN);
+ if (expn_sign) {
+ ret |= bf_div(r, T, B, T->len * LIMB_BITS, BF_RNDN);
+ } else {
+ ret |= bf_mul(r, T, B, BF_PREC_INF, BF_RNDN);
+ }
+ } else {
+ ziv_extra_bits = 16;
+ for(;;) {
+ prec1 = prec + ziv_extra_bits;
+ /* XXX: correct overflow/underflow handling */
+ /* XXX: rigorous error analysis needed */
+ extra_bits = ceil_log2(e) * 2 + 1;
+ ret = bf_pow_ui_ui(B, radix, e, prec1 + extra_bits, BF_RNDN | BF_FLAG_EXT_EXP);
+ overflow = !bf_is_finite(B);
+ /* XXX: if bf_pow_ui_ui returns an exact result, can stop
+ after the next operation */
+ if (expn_sign)
+ ret |= bf_div(r, T, B, prec1 + extra_bits, BF_RNDN | BF_FLAG_EXT_EXP);
+ else
+ ret |= bf_mul(r, T, B, prec1 + extra_bits, BF_RNDN | BF_FLAG_EXT_EXP);
+ if (ret & BF_ST_MEM_ERROR)
+ break;
+ if ((ret & BF_ST_INEXACT) &&
+ !bf_can_round(r, prec, flags & BF_RND_MASK, prec1) &&
+ !overflow) {
+ /* and more precision and retry */
+ ziv_extra_bits = ziv_extra_bits + (ziv_extra_bits / 2);
+ } else {
+ /* XXX: need to use __bf_round() to pass the inexact
+ flag for the subnormal case */
+ ret = bf_round(r, prec, flags) | (ret & BF_ST_INEXACT);
+ break;
+ }
+ }
+ }
+ bf_delete(B);
+ return ret;
+}
+
+static inline int to_digit(int c)
+{
+ if (c >= '0' && c <= '9')
+ return c - '0';
+ else if (c >= 'A' && c <= 'Z')
+ return c - 'A' + 10;
+ else if (c >= 'a' && c <= 'z')
+ return c - 'a' + 10;
+ else
+ return 36;
+}
+
+/* add a limb at 'pos' and decrement pos. new space is created if
+ needed. Return 0 if OK, -1 if memory error */
+static int bf_add_limb(bf_t *a, slimb_t *ppos, limb_t v)
+{
+ slimb_t pos;
+ pos = *ppos;
+ if (unlikely(pos < 0)) {
+ limb_t new_size, d, *new_tab;
+ new_size = bf_max(a->len + 1, a->len * 3 / 2);
+ new_tab = bf_realloc(a->ctx, a->tab, sizeof(limb_t) * new_size);
+ if (!new_tab)
+ return -1;
+ a->tab = new_tab;
+ d = new_size - a->len;
+ memmove(a->tab + d, a->tab, a->len * sizeof(limb_t));
+ a->len = new_size;
+ pos += d;
+ }
+ a->tab[pos--] = v;
+ *ppos = pos;
+ return 0;
+}
+
+static int bf_tolower(int c)
+{
+ if (c >= 'A' && c <= 'Z')
+ c = c - 'A' + 'a';
+ return c;
+}
+
+static int strcasestart(const char *str, const char *val, const char **ptr)
+{
+ const char *p, *q;
+ p = str;
+ q = val;
+ while (*q != '\0') {
+ if (bf_tolower(*p) != *q)
+ return 0;
+ p++;
+ q++;
+ }
+ if (ptr)
+ *ptr = p;
+ return 1;
+}
+
+static int bf_atof_internal(bf_t *r, slimb_t *pexponent,
+ const char *str, const char **pnext, int radix,
+ limb_t prec, bf_flags_t flags, BOOL is_dec)
+{
+ const char *p, *p_start;
+ int is_neg, radix_bits, exp_is_neg, ret, digits_per_limb, shift;
+ limb_t cur_limb;
+ slimb_t pos, expn, int_len, digit_count;
+ BOOL has_decpt, is_bin_exp;
+ bf_t a_s, *a;
+
+ *pexponent = 0;
+ p = str;
+ if (!(flags & BF_ATOF_NO_NAN_INF) && radix <= 16 &&
+ strcasestart(p, "nan", &p)) {
+ bf_set_nan(r);
+ ret = 0;
+ goto done;
+ }
+ is_neg = 0;
+
+ if (p[0] == '+') {
+ p++;
+ p_start = p;
+ } else if (p[0] == '-') {
+ is_neg = 1;
+ p++;
+ p_start = p;
+ } else {
+ p_start = p;
+ }
+ if (p[0] == '0') {
+ if ((p[1] == 'x' || p[1] == 'X') &&
+ (radix == 0 || radix == 16) &&
+ !(flags & BF_ATOF_NO_HEX)) {
+ radix = 16;
+ p += 2;
+ } else if ((p[1] == 'o' || p[1] == 'O') &&
+ radix == 0 && (flags & BF_ATOF_BIN_OCT)) {
+ p += 2;
+ radix = 8;
+ } else if ((p[1] == 'b' || p[1] == 'B') &&
+ radix == 0 && (flags & BF_ATOF_BIN_OCT)) {
+ p += 2;
+ radix = 2;
+ } else {
+ goto no_prefix;
+ }
+ /* there must be a digit after the prefix */
+ if (to_digit((uint8_t)*p) >= radix) {
+ bf_set_nan(r);
+ ret = 0;
+ goto done;
+ }
+ no_prefix: ;
+ } else {
+ if (!(flags & BF_ATOF_NO_NAN_INF) && radix <= 16 &&
+ strcasestart(p, "inf", &p)) {
+ bf_set_inf(r, is_neg);
+ ret = 0;
+ goto done;
+ }
+ }
+
+ if (radix == 0)
+ radix = 10;
+ if (is_dec) {
+ assert(radix == 10);
+ radix_bits = 0;
+ a = r;
+ } else if ((radix & (radix - 1)) != 0) {
+ radix_bits = 0; /* base is not a power of two */
+ a = &a_s;
+ bf_init(r->ctx, a);
+ } else {
+ radix_bits = ceil_log2(radix);
+ a = r;
+ }
+
+ /* skip leading zeros */
+ /* XXX: could also skip zeros after the decimal point */
+ while (*p == '0')
+ p++;
+
+ if (radix_bits) {
+ shift = digits_per_limb = LIMB_BITS;
+ } else {
+ radix_bits = 0;
+ shift = digits_per_limb = digits_per_limb_table[radix - 2];
+ }
+ cur_limb = 0;
+ bf_resize(a, 1);
+ pos = 0;
+ has_decpt = FALSE;
+ int_len = digit_count = 0;
+ for(;;) {
+ limb_t c;
+ if (*p == '.' && (p > p_start || to_digit(p[1]) < radix)) {
+ if (has_decpt)
+ break;
+ has_decpt = TRUE;
+ int_len = digit_count;
+ p++;
+ }
+ c = to_digit(*p);
+ if (c >= radix)
+ break;
+ digit_count++;
+ p++;
+ if (radix_bits) {
+ shift -= radix_bits;
+ if (shift <= 0) {
+ cur_limb |= c >> (-shift);
+ if (bf_add_limb(a, &pos, cur_limb))
+ goto mem_error;
+ if (shift < 0)
+ cur_limb = c << (LIMB_BITS + shift);
+ else
+ cur_limb = 0;
+ shift += LIMB_BITS;
+ } else {
+ cur_limb |= c << shift;
+ }
+ } else {
+ cur_limb = cur_limb * radix + c;
+ shift--;
+ if (shift == 0) {
+ if (bf_add_limb(a, &pos, cur_limb))
+ goto mem_error;
+ shift = digits_per_limb;
+ cur_limb = 0;
+ }
+ }
+ }
+ if (!has_decpt)
+ int_len = digit_count;
+
+ /* add the last limb and pad with zeros */
+ if (shift != digits_per_limb) {
+ if (radix_bits == 0) {
+ while (shift != 0) {
+ cur_limb *= radix;
+ shift--;
+ }
+ }
+ if (bf_add_limb(a, &pos, cur_limb)) {
+ mem_error:
+ ret = BF_ST_MEM_ERROR;
+ if (!radix_bits)
+ bf_delete(a);
+ bf_set_nan(r);
+ goto done;
+ }
+ }
+
+ /* reset the next limbs to zero (we prefer to reallocate in the
+ renormalization) */
+ memset(a->tab, 0, (pos + 1) * sizeof(limb_t));
+
+ if (p == p_start) {
+ ret = 0;
+ if (!radix_bits)
+ bf_delete(a);
+ bf_set_nan(r);
+ goto done;
+ }
+
+ /* parse the exponent, if any */
+ expn = 0;
+ is_bin_exp = FALSE;
+ if (((radix == 10 && (*p == 'e' || *p == 'E')) ||
+ (radix != 10 && (*p == '@' ||
+ (radix_bits && (*p == 'p' || *p == 'P'))))) &&
+ p > p_start) {
+ is_bin_exp = (*p == 'p' || *p == 'P');
+ p++;
+ exp_is_neg = 0;
+ if (*p == '+') {
+ p++;
+ } else if (*p == '-') {
+ exp_is_neg = 1;
+ p++;
+ }
+ for(;;) {
+ int c;
+ c = to_digit(*p);
+ if (c >= 10)
+ break;
+ if (unlikely(expn > ((BF_RAW_EXP_MAX - 2 - 9) / 10))) {
+ /* exponent overflow */
+ if (exp_is_neg) {
+ bf_set_zero(r, is_neg);
+ ret = BF_ST_UNDERFLOW | BF_ST_INEXACT;
+ } else {
+ bf_set_inf(r, is_neg);
+ ret = BF_ST_OVERFLOW | BF_ST_INEXACT;
+ }
+ goto done;
+ }
+ p++;
+ expn = expn * 10 + c;
+ }
+ if (exp_is_neg)
+ expn = -expn;
+ }
+ if (is_dec) {
+ a->expn = expn + int_len;
+ a->sign = is_neg;
+ ret = bfdec_normalize_and_round((bfdec_t *)a, prec, flags);
+ } else if (radix_bits) {
+ /* XXX: may overflow */
+ if (!is_bin_exp)
+ expn *= radix_bits;
+ a->expn = expn + (int_len * radix_bits);
+ a->sign = is_neg;
+ ret = bf_normalize_and_round(a, prec, flags);
+ } else {
+ limb_t l;
+ pos++;
+ l = a->len - pos; /* number of limbs */
+ if (l == 0) {
+ bf_set_zero(r, is_neg);
+ ret = 0;
+ } else {
+ bf_t T_s, *T = &T_s;
+
+ expn -= l * digits_per_limb - int_len;
+ bf_init(r->ctx, T);
+ if (bf_integer_from_radix(T, a->tab + pos, l, radix)) {
+ bf_set_nan(r);
+ ret = BF_ST_MEM_ERROR;
+ } else {
+ T->sign = is_neg;
+ if (flags & BF_ATOF_EXPONENT) {
+ /* return the exponent */
+ *pexponent = expn;
+ ret = bf_set(r, T);
+ } else {
+ ret = bf_mul_pow_radix(r, T, radix, expn, prec, flags);
+ }
+ }
+ bf_delete(T);
+ }
+ bf_delete(a);
+ }
+ done:
+ if (pnext)
+ *pnext = p;
+ return ret;
+}
+
+/*
+ Return (status, n, exp). 'status' is the floating point status. 'n'
+ is the parsed number.
+
+ If (flags & BF_ATOF_EXPONENT) and if the radix is not a power of
+ two, the parsed number is equal to r *
+ (*pexponent)^radix. Otherwise *pexponent = 0.
+*/
+int bf_atof2(bf_t *r, slimb_t *pexponent,
+ const char *str, const char **pnext, int radix,
+ limb_t prec, bf_flags_t flags)
+{
+ return bf_atof_internal(r, pexponent, str, pnext, radix, prec, flags,
+ FALSE);
+}
+
+int bf_atof(bf_t *r, const char *str, const char **pnext, int radix,
+ limb_t prec, bf_flags_t flags)
+{
+ slimb_t dummy_exp;
+ return bf_atof_internal(r, &dummy_exp, str, pnext, radix, prec, flags, FALSE);
+}
+
+/* base conversion to radix */
+
+#if LIMB_BITS == 64
+#define RADIXL_10 UINT64_C(10000000000000000000)
+#else
+#define RADIXL_10 UINT64_C(1000000000)
+#endif
+
+static const uint32_t inv_log2_radix[BF_RADIX_MAX - 1][LIMB_BITS / 32 + 1] = {
+#if LIMB_BITS == 32
+{ 0x80000000, 0x00000000,},
+{ 0x50c24e60, 0xd4d4f4a7,},
+{ 0x40000000, 0x00000000,},
+{ 0x372068d2, 0x0a1ee5ca,},
+{ 0x3184648d, 0xb8153e7a,},
+{ 0x2d983275, 0x9d5369c4,},
+{ 0x2aaaaaaa, 0xaaaaaaab,},
+{ 0x28612730, 0x6a6a7a54,},
+{ 0x268826a1, 0x3ef3fde6,},
+{ 0x25001383, 0xbac8a744,},
+{ 0x23b46706, 0x82c0c709,},
+{ 0x229729f1, 0xb2c83ded,},
+{ 0x219e7ffd, 0xa5ad572b,},
+{ 0x20c33b88, 0xda7c29ab,},
+{ 0x20000000, 0x00000000,},
+{ 0x1f50b57e, 0xac5884b3,},
+{ 0x1eb22cc6, 0x8aa6e26f,},
+{ 0x1e21e118, 0x0c5daab2,},
+{ 0x1d9dcd21, 0x439834e4,},
+{ 0x1d244c78, 0x367a0d65,},
+{ 0x1cb40589, 0xac173e0c,},
+{ 0x1c4bd95b, 0xa8d72b0d,},
+{ 0x1bead768, 0x98f8ce4c,},
+{ 0x1b903469, 0x050f72e5,},
+{ 0x1b3b433f, 0x2eb06f15,},
+{ 0x1aeb6f75, 0x9c46fc38,},
+{ 0x1aa038eb, 0x0e3bfd17,},
+{ 0x1a593062, 0xb38d8c56,},
+{ 0x1a15f4c3, 0x2b95a2e6,},
+{ 0x19d630dc, 0xcc7ddef9,},
+{ 0x19999999, 0x9999999a,},
+{ 0x195fec80, 0x8a609431,},
+{ 0x1928ee7b, 0x0b4f22f9,},
+{ 0x18f46acf, 0x8c06e318,},
+{ 0x18c23246, 0xdc0a9f3d,},
+#else
+{ 0x80000000, 0x00000000, 0x00000000,},
+{ 0x50c24e60, 0xd4d4f4a7, 0x021f57bc,},
+{ 0x40000000, 0x00000000, 0x00000000,},
+{ 0x372068d2, 0x0a1ee5ca, 0x19ea911b,},
+{ 0x3184648d, 0xb8153e7a, 0x7fc2d2e1,},
+{ 0x2d983275, 0x9d5369c4, 0x4dec1661,},
+{ 0x2aaaaaaa, 0xaaaaaaaa, 0xaaaaaaab,},
+{ 0x28612730, 0x6a6a7a53, 0x810fabde,},
+{ 0x268826a1, 0x3ef3fde6, 0x23e2566b,},
+{ 0x25001383, 0xbac8a744, 0x385a3349,},
+{ 0x23b46706, 0x82c0c709, 0x3f891718,},
+{ 0x229729f1, 0xb2c83ded, 0x15fba800,},
+{ 0x219e7ffd, 0xa5ad572a, 0xe169744b,},
+{ 0x20c33b88, 0xda7c29aa, 0x9bddee52,},
+{ 0x20000000, 0x00000000, 0x00000000,},
+{ 0x1f50b57e, 0xac5884b3, 0x70e28eee,},
+{ 0x1eb22cc6, 0x8aa6e26f, 0x06d1a2a2,},
+{ 0x1e21e118, 0x0c5daab1, 0x81b4f4bf,},
+{ 0x1d9dcd21, 0x439834e3, 0x81667575,},
+{ 0x1d244c78, 0x367a0d64, 0xc8204d6d,},
+{ 0x1cb40589, 0xac173e0c, 0x3b7b16ba,},
+{ 0x1c4bd95b, 0xa8d72b0d, 0x5879f25a,},
+{ 0x1bead768, 0x98f8ce4c, 0x66cc2858,},
+{ 0x1b903469, 0x050f72e5, 0x0cf5488e,},
+{ 0x1b3b433f, 0x2eb06f14, 0x8c89719c,},
+{ 0x1aeb6f75, 0x9c46fc37, 0xab5fc7e9,},
+{ 0x1aa038eb, 0x0e3bfd17, 0x1bd62080,},
+{ 0x1a593062, 0xb38d8c56, 0x7998ab45,},
+{ 0x1a15f4c3, 0x2b95a2e6, 0x46aed6a0,},
+{ 0x19d630dc, 0xcc7ddef9, 0x5aadd61b,},
+{ 0x19999999, 0x99999999, 0x9999999a,},
+{ 0x195fec80, 0x8a609430, 0xe1106014,},
+{ 0x1928ee7b, 0x0b4f22f9, 0x5f69791d,},
+{ 0x18f46acf, 0x8c06e318, 0x4d2aeb2c,},
+{ 0x18c23246, 0xdc0a9f3d, 0x3fe16970,},
+#endif
+};
+
+static const limb_t log2_radix[BF_RADIX_MAX - 1] = {
+#if LIMB_BITS == 32
+0x20000000,
+0x32b80347,
+0x40000000,
+0x4a4d3c26,
+0x52b80347,
+0x59d5d9fd,
+0x60000000,
+0x6570068e,
+0x6a4d3c26,
+0x6eb3a9f0,
+0x72b80347,
+0x766a008e,
+0x79d5d9fd,
+0x7d053f6d,
+0x80000000,
+0x82cc7edf,
+0x8570068e,
+0x87ef05ae,
+0x8a4d3c26,
+0x8c8ddd45,
+0x8eb3a9f0,
+0x90c10501,
+0x92b80347,
+0x949a784c,
+0x966a008e,
+0x982809d6,
+0x99d5d9fd,
+0x9b74948f,
+0x9d053f6d,
+0x9e88c6b3,
+0xa0000000,
+0xa16bad37,
+0xa2cc7edf,
+0xa4231623,
+0xa570068e,
+#else
+0x2000000000000000,
+0x32b803473f7ad0f4,
+0x4000000000000000,
+0x4a4d3c25e68dc57f,
+0x52b803473f7ad0f4,
+0x59d5d9fd5010b366,
+0x6000000000000000,
+0x6570068e7ef5a1e8,
+0x6a4d3c25e68dc57f,
+0x6eb3a9f01975077f,
+0x72b803473f7ad0f4,
+0x766a008e4788cbcd,
+0x79d5d9fd5010b366,
+0x7d053f6d26089673,
+0x8000000000000000,
+0x82cc7edf592262d0,
+0x8570068e7ef5a1e8,
+0x87ef05ae409a0289,
+0x8a4d3c25e68dc57f,
+0x8c8ddd448f8b845a,
+0x8eb3a9f01975077f,
+0x90c10500d63aa659,
+0x92b803473f7ad0f4,
+0x949a784bcd1b8afe,
+0x966a008e4788cbcd,
+0x982809d5be7072dc,
+0x99d5d9fd5010b366,
+0x9b74948f5532da4b,
+0x9d053f6d26089673,
+0x9e88c6b3626a72aa,
+0xa000000000000000,
+0xa16bad3758efd873,
+0xa2cc7edf592262d0,
+0xa4231623369e78e6,
+0xa570068e7ef5a1e8,
+#endif
+};
+
+/* compute floor(a*b) or ceil(a*b) with b = log2(radix) or
+ b=1/log2(radix). For is_inv = 0, strict accuracy is not guaranteed
+ when radix is not a power of two. */
+slimb_t bf_mul_log2_radix(slimb_t a1, unsigned int radix, int is_inv,
+ int is_ceil1)
+{
+ int is_neg;
+ limb_t a;
+ BOOL is_ceil;
+
+ is_ceil = is_ceil1;
+ a = a1;
+ if (a1 < 0) {
+ a = -a;
+ is_neg = 1;
+ } else {
+ is_neg = 0;
+ }
+ is_ceil ^= is_neg;
+ if ((radix & (radix - 1)) == 0) {
+ int radix_bits;
+ /* radix is a power of two */
+ radix_bits = ceil_log2(radix);
+ if (is_inv) {
+ if (is_ceil)
+ a += radix_bits - 1;
+ a = a / radix_bits;
+ } else {
+ a = a * radix_bits;
+ }
+ } else {
+ const uint32_t *tab;
+ limb_t b0, b1;
+ dlimb_t t;
+
+ if (is_inv) {
+ tab = inv_log2_radix[radix - 2];
+#if LIMB_BITS == 32
+ b1 = tab[0];
+ b0 = tab[1];
+#else
+ b1 = ((limb_t)tab[0] << 32) | tab[1];
+ b0 = (limb_t)tab[2] << 32;
+#endif
+ t = (dlimb_t)b0 * (dlimb_t)a;
+ t = (dlimb_t)b1 * (dlimb_t)a + (t >> LIMB_BITS);
+ a = t >> (LIMB_BITS - 1);
+ } else {
+ b0 = log2_radix[radix - 2];
+ t = (dlimb_t)b0 * (dlimb_t)a;
+ a = t >> (LIMB_BITS - 3);
+ }
+ /* a = floor(result) and 'result' cannot be an integer */
+ a += is_ceil;
+ }
+ if (is_neg)
+ a = -a;
+ return a;
+}
+
+/* 'n' is the number of output limbs */
+static int bf_integer_to_radix_rec(bf_t *pow_tab,
+ limb_t *out, const bf_t *a, limb_t n,
+ int level, limb_t n0, limb_t radixl,
+ unsigned int radixl_bits)
+{
+ limb_t n1, n2, q_prec;
+ int ret;
+
+ assert(n >= 1);
+ if (n == 1) {
+ out[0] = get_bits(a->tab, a->len, a->len * LIMB_BITS - a->expn);
+ } else if (n == 2) {
+ dlimb_t t;
+ slimb_t pos;
+ pos = a->len * LIMB_BITS - a->expn;
+ t = ((dlimb_t)get_bits(a->tab, a->len, pos + LIMB_BITS) << LIMB_BITS) |
+ get_bits(a->tab, a->len, pos);
+ if (likely(radixl == RADIXL_10)) {
+ /* use division by a constant when possible */
+ out[0] = t % RADIXL_10;
+ out[1] = t / RADIXL_10;
+ } else {
+ out[0] = t % radixl;
+ out[1] = t / radixl;
+ }
+ } else {
+ bf_t Q, R, *B, *B_inv;
+ int q_add;
+ bf_init(a->ctx, &Q);
+ bf_init(a->ctx, &R);
+ n2 = (((n0 * 2) >> (level + 1)) + 1) / 2;
+ n1 = n - n2;
+ B = &pow_tab[2 * level];
+ B_inv = &pow_tab[2 * level + 1];
+ ret = 0;
+ if (B->len == 0) {
+ /* compute BASE^n2 */
+ ret |= bf_pow_ui_ui(B, radixl, n2, BF_PREC_INF, BF_RNDZ);
+ /* we use enough bits for the maximum possible 'n1' value,
+ i.e. n2 + 1 */
+ ret |= bf_set_ui(&R, 1);
+ ret |= bf_div(B_inv, &R, B, (n2 + 1) * radixl_bits + 2, BF_RNDN);
+ }
+ // printf("%d: n1=% " PRId64 " n2=%" PRId64 "\n", level, n1, n2);
+ q_prec = n1 * radixl_bits;
+ ret |= bf_mul(&Q, a, B_inv, q_prec, BF_RNDN);
+ ret |= bf_rint(&Q, BF_RNDZ);
+
+ ret |= bf_mul(&R, &Q, B, BF_PREC_INF, BF_RNDZ);
+ ret |= bf_sub(&R, a, &R, BF_PREC_INF, BF_RNDZ);
+
+ if (ret & BF_ST_MEM_ERROR)
+ goto fail;
+ /* adjust if necessary */
+ q_add = 0;
+ while (R.sign && R.len != 0) {
+ if (bf_add(&R, &R, B, BF_PREC_INF, BF_RNDZ))
+ goto fail;
+ q_add--;
+ }
+ while (bf_cmpu(&R, B) >= 0) {
+ if (bf_sub(&R, &R, B, BF_PREC_INF, BF_RNDZ))
+ goto fail;
+ q_add++;
+ }
+ if (q_add != 0) {
+ if (bf_add_si(&Q, &Q, q_add, BF_PREC_INF, BF_RNDZ))
+ goto fail;
+ }
+ if (bf_integer_to_radix_rec(pow_tab, out + n2, &Q, n1, level + 1, n0,
+ radixl, radixl_bits))
+ goto fail;
+ if (bf_integer_to_radix_rec(pow_tab, out, &R, n2, level + 1, n0,
+ radixl, radixl_bits)) {
+ fail:
+ bf_delete(&Q);
+ bf_delete(&R);
+ return -1;
+ }
+ bf_delete(&Q);
+ bf_delete(&R);
+ }
+ return 0;
+}
+
+/* return 0 if OK != 0 if memory error */
+static int bf_integer_to_radix(bf_t *r, const bf_t *a, limb_t radixl)
+{
+ bf_context_t *s = r->ctx;
+ limb_t r_len;
+ bf_t *pow_tab;
+ int i, pow_tab_len, ret;
+
+ r_len = r->len;
+ pow_tab_len = (ceil_log2(r_len) + 2) * 2; /* XXX: check */
+ pow_tab = bf_malloc(s, sizeof(pow_tab[0]) * pow_tab_len);
+ if (!pow_tab)
+ return -1;
+ for(i = 0; i < pow_tab_len; i++)
+ bf_init(r->ctx, &pow_tab[i]);
+
+ ret = bf_integer_to_radix_rec(pow_tab, r->tab, a, r_len, 0, r_len, radixl,
+ ceil_log2(radixl));
+
+ for(i = 0; i < pow_tab_len; i++) {
+ bf_delete(&pow_tab[i]);
+ }
+ bf_free(s, pow_tab);
+ return ret;
+}
+
+/* a must be >= 0. 'P' is the wanted number of digits in radix
+ 'radix'. 'r' is the mantissa represented as an integer. *pE
+ contains the exponent. Return != 0 if memory error. */
+static int bf_convert_to_radix(bf_t *r, slimb_t *pE,
+ const bf_t *a, int radix,
+ limb_t P, bf_rnd_t rnd_mode,
+ BOOL is_fixed_exponent)
+{
+ slimb_t E, e, prec, extra_bits, ziv_extra_bits, prec0;
+ bf_t B_s, *B = &B_s;
+ int e_sign, ret, res;
+
+ if (a->len == 0) {
+ /* zero case */
+ *pE = 0;
+ return bf_set(r, a);
+ }
+
+ if (is_fixed_exponent) {
+ E = *pE;
+ } else {
+ /* compute the new exponent */
+ E = 1 + bf_mul_log2_radix(a->expn - 1, radix, TRUE, FALSE);
+ }
+ // bf_print_str("a", a);
+ // printf("E=%ld P=%ld radix=%d\n", E, P, radix);
+
+ for(;;) {
+ e = P - E;
+ e_sign = 0;
+ if (e < 0) {
+ e = -e;
+ e_sign = 1;
+ }
+ /* Note: precision for log2(radix) is not critical here */
+ prec0 = bf_mul_log2_radix(P, radix, FALSE, TRUE);
+ ziv_extra_bits = 16;
+ for(;;) {
+ prec = prec0 + ziv_extra_bits;
+ /* XXX: rigorous error analysis needed */
+ extra_bits = ceil_log2(e) * 2 + 1;
+ ret = bf_pow_ui_ui(r, radix, e, prec + extra_bits,
+ BF_RNDN | BF_FLAG_EXT_EXP);
+ if (!e_sign)
+ ret |= bf_mul(r, r, a, prec + extra_bits,
+ BF_RNDN | BF_FLAG_EXT_EXP);
+ else
+ ret |= bf_div(r, a, r, prec + extra_bits,
+ BF_RNDN | BF_FLAG_EXT_EXP);
+ if (ret & BF_ST_MEM_ERROR)
+ return BF_ST_MEM_ERROR;
+ /* if the result is not exact, check that it can be safely
+ rounded to an integer */
+ if ((ret & BF_ST_INEXACT) &&
+ !bf_can_round(r, r->expn, rnd_mode, prec)) {
+ /* and more precision and retry */
+ ziv_extra_bits = ziv_extra_bits + (ziv_extra_bits / 2);
+ continue;
+ } else {
+ ret = bf_rint(r, rnd_mode);
+ if (ret & BF_ST_MEM_ERROR)
+ return BF_ST_MEM_ERROR;
+ break;
+ }
+ }
+ if (is_fixed_exponent)
+ break;
+ /* check that the result is < B^P */
+ /* XXX: do a fast approximate test first ? */
+ bf_init(r->ctx, B);
+ ret = bf_pow_ui_ui(B, radix, P, BF_PREC_INF, BF_RNDZ);
+ if (ret) {
+ bf_delete(B);
+ return ret;
+ }
+ res = bf_cmpu(r, B);
+ bf_delete(B);
+ if (res < 0)
+ break;
+ /* try a larger exponent */
+ E++;
+ }
+ *pE = E;
+ return 0;
+}
+
+static void limb_to_a(char *buf, limb_t n, unsigned int radix, int len)
+{
+ int digit, i;
+
+ if (radix == 10) {
+ /* specific case with constant divisor */
+ for(i = len - 1; i >= 0; i--) {
+ digit = (limb_t)n % 10;
+ n = (limb_t)n / 10;
+ buf[i] = digit + '0';
+ }
+ } else {
+ for(i = len - 1; i >= 0; i--) {
+ digit = (limb_t)n % radix;
+ n = (limb_t)n / radix;
+ if (digit < 10)
+ digit += '0';
+ else
+ digit += 'a' - 10;
+ buf[i] = digit;
+ }
+ }
+}
+
+/* for power of 2 radixes */
+static void limb_to_a2(char *buf, limb_t n, unsigned int radix_bits, int len)
+{
+ int digit, i;
+ unsigned int mask;
+
+ mask = (1 << radix_bits) - 1;
+ for(i = len - 1; i >= 0; i--) {
+ digit = n & mask;
+ n >>= radix_bits;
+ if (digit < 10)
+ digit += '0';
+ else
+ digit += 'a' - 10;
+ buf[i] = digit;
+ }
+}
+
+/* 'a' must be an integer if the is_dec = FALSE or if the radix is not
+ a power of two. A dot is added before the 'dot_pos' digit. dot_pos
+ = n_digits does not display the dot. 0 <= dot_pos <=
+ n_digits. n_digits >= 1. */
+static void output_digits(DynBuf *s, const bf_t *a1, int radix, limb_t n_digits,
+ limb_t dot_pos, BOOL is_dec)
+{
+ limb_t i, v, l;
+ slimb_t pos, pos_incr;
+ int digits_per_limb, buf_pos, radix_bits, first_buf_pos;
+ char buf[65];
+ bf_t a_s, *a;
+
+ if (is_dec) {
+ digits_per_limb = LIMB_DIGITS;
+ a = (bf_t *)a1;
+ radix_bits = 0;
+ pos = a->len;
+ pos_incr = 1;
+ first_buf_pos = 0;
+ } else if ((radix & (radix - 1)) == 0) {
+ a = (bf_t *)a1;
+ radix_bits = ceil_log2(radix);
+ digits_per_limb = LIMB_BITS / radix_bits;
+ pos_incr = digits_per_limb * radix_bits;
+ /* digits are aligned relative to the radix point */
+ pos = a->len * LIMB_BITS + smod(-a->expn, radix_bits);
+ first_buf_pos = 0;
+ } else {
+ limb_t n, radixl;
+
+ digits_per_limb = digits_per_limb_table[radix - 2];
+ radixl = get_limb_radix(radix);
+ a = &a_s;
+ bf_init(a1->ctx, a);
+ n = (n_digits + digits_per_limb - 1) / digits_per_limb;
+ if (bf_resize(a, n)) {
+ dbuf_set_error(s);
+ goto done;
+ }
+ if (bf_integer_to_radix(a, a1, radixl)) {
+ dbuf_set_error(s);
+ goto done;
+ }
+ radix_bits = 0;
+ pos = n;
+ pos_incr = 1;
+ first_buf_pos = pos * digits_per_limb - n_digits;
+ }
+ buf_pos = digits_per_limb;
+ i = 0;
+ while (i < n_digits) {
+ if (buf_pos == digits_per_limb) {
+ pos -= pos_incr;
+ if (radix_bits == 0) {
+ v = get_limbz(a, pos);
+ limb_to_a(buf, v, radix, digits_per_limb);
+ } else {
+ v = get_bits(a->tab, a->len, pos);
+ limb_to_a2(buf, v, radix_bits, digits_per_limb);
+ }
+ buf_pos = first_buf_pos;
+ first_buf_pos = 0;
+ }
+ if (i < dot_pos) {
+ l = dot_pos;
+ } else {
+ if (i == dot_pos)
+ dbuf_putc(s, '.');
+ l = n_digits;
+ }
+ l = bf_min(digits_per_limb - buf_pos, l - i);
+ dbuf_put(s, (uint8_t *)(buf + buf_pos), l);
+ buf_pos += l;
+ i += l;
+ }
+ done:
+ if (a != a1)
+ bf_delete(a);
+}
+
+static void *bf_dbuf_realloc(void *opaque, void *ptr, size_t size)
+{
+ bf_context_t *s = opaque;
+ return bf_realloc(s, ptr, size);
+}
+
+/* return the length in bytes. A trailing '\0' is added */
+static char *bf_ftoa_internal(size_t *plen, const bf_t *a2, int radix,
+ limb_t prec, bf_flags_t flags, BOOL is_dec)
+{
+ bf_context_t *ctx = a2->ctx;
+ DynBuf s_s, *s = &s_s;
+ int radix_bits;
+
+ // bf_print_str("ftoa", a2);
+ // printf("radix=%d\n", radix);
+ dbuf_init2(s, ctx, bf_dbuf_realloc);
+ if (a2->expn == BF_EXP_NAN) {
+ dbuf_putstr(s, "NaN");
+ } else {
+ if (a2->sign)
+ dbuf_putc(s, '-');
+ if (a2->expn == BF_EXP_INF) {
+ if (flags & BF_FTOA_JS_QUIRKS)
+ dbuf_putstr(s, "Infinity");
+ else
+ dbuf_putstr(s, "Inf");
+ } else {
+ int fmt, ret;
+ slimb_t n_digits, n, i, n_max, n1;
+ bf_t a1_s, *a1 = &a1_s;
+
+ if ((radix & (radix - 1)) != 0)
+ radix_bits = 0;
+ else
+ radix_bits = ceil_log2(radix);
+
+ fmt = flags & BF_FTOA_FORMAT_MASK;
+ bf_init(ctx, a1);
+ if (fmt == BF_FTOA_FORMAT_FRAC) {
+ if (is_dec || radix_bits != 0) {
+ if (bf_set(a1, a2))
+ goto fail1;
+#ifdef USE_BF_DEC
+ if (is_dec) {
+ if (bfdec_round((bfdec_t *)a1, prec, (flags & BF_RND_MASK) | BF_FLAG_RADPNT_PREC) & BF_ST_MEM_ERROR)
+ goto fail1;
+ n = a1->expn;
+ } else
+#endif
+ {
+ if (bf_round(a1, prec * radix_bits, (flags & BF_RND_MASK) | BF_FLAG_RADPNT_PREC) & BF_ST_MEM_ERROR)
+ goto fail1;
+ n = ceil_div(a1->expn, radix_bits);
+ }
+ if (flags & BF_FTOA_ADD_PREFIX) {
+ if (radix == 16)
+ dbuf_putstr(s, "0x");
+ else if (radix == 8)
+ dbuf_putstr(s, "0o");
+ else if (radix == 2)
+ dbuf_putstr(s, "0b");
+ }
+ if (a1->expn == BF_EXP_ZERO) {
+ dbuf_putstr(s, "0");
+ if (prec > 0) {
+ dbuf_putstr(s, ".");
+ for(i = 0; i < prec; i++) {
+ dbuf_putc(s, '0');
+ }
+ }
+ } else {
+ n_digits = prec + n;
+ if (n <= 0) {
+ /* 0.x */
+ dbuf_putstr(s, "0.");
+ for(i = 0; i < -n; i++) {
+ dbuf_putc(s, '0');
+ }
+ if (n_digits > 0) {
+ output_digits(s, a1, radix, n_digits, n_digits, is_dec);
+ }
+ } else {
+ output_digits(s, a1, radix, n_digits, n, is_dec);
+ }
+ }
+ } else {
+ size_t pos, start;
+ bf_t a_s, *a = &a_s;
+
+ /* make a positive number */
+ a->tab = a2->tab;
+ a->len = a2->len;
+ a->expn = a2->expn;
+ a->sign = 0;
+
+ /* one more digit for the rounding */
+ n = 1 + bf_mul_log2_radix(bf_max(a->expn, 0), radix, TRUE, TRUE);
+ n_digits = n + prec;
+ n1 = n;
+ if (bf_convert_to_radix(a1, &n1, a, radix, n_digits,
+ flags & BF_RND_MASK, TRUE))
+ goto fail1;
+ start = s->size;
+ output_digits(s, a1, radix, n_digits, n, is_dec);
+ /* remove leading zeros because we allocated one more digit */
+ pos = start;
+ while ((pos + 1) < s->size && s->buf[pos] == '0' &&
+ s->buf[pos + 1] != '.')
+ pos++;
+ if (pos > start) {
+ memmove(s->buf + start, s->buf + pos, s->size - pos);
+ s->size -= (pos - start);
+ }
+ }
+ } else {
+#ifdef USE_BF_DEC
+ if (is_dec) {
+ if (bf_set(a1, a2))
+ goto fail1;
+ if (fmt == BF_FTOA_FORMAT_FIXED) {
+ n_digits = prec;
+ n_max = n_digits;
+ if (bfdec_round((bfdec_t *)a1, prec, (flags & BF_RND_MASK)) & BF_ST_MEM_ERROR)
+ goto fail1;
+ } else {
+ /* prec is ignored */
+ prec = n_digits = a1->len * LIMB_DIGITS;
+ /* remove the trailing zero digits */
+ while (n_digits > 1 &&
+ get_digit(a1->tab, a1->len, prec - n_digits) == 0) {
+ n_digits--;
+ }
+ n_max = n_digits + 4;
+ }
+ n = a1->expn;
+ } else
+#endif
+ if (radix_bits != 0) {
+ if (bf_set(a1, a2))
+ goto fail1;
+ if (fmt == BF_FTOA_FORMAT_FIXED) {
+ slimb_t prec_bits;
+ n_digits = prec;
+ n_max = n_digits;
+ /* align to the radix point */
+ prec_bits = prec * radix_bits -
+ smod(-a1->expn, radix_bits);
+ if (bf_round(a1, prec_bits,
+ (flags & BF_RND_MASK)) & BF_ST_MEM_ERROR)
+ goto fail1;
+ } else {
+ limb_t digit_mask;
+ slimb_t pos;
+ /* position of the digit before the most
+ significant digit in bits */
+ pos = a1->len * LIMB_BITS +
+ smod(-a1->expn, radix_bits);
+ n_digits = ceil_div(pos, radix_bits);
+ /* remove the trailing zero digits */
+ digit_mask = ((limb_t)1 << radix_bits) - 1;
+ while (n_digits > 1 &&
+ (get_bits(a1->tab, a1->len, pos - n_digits * radix_bits) & digit_mask) == 0) {
+ n_digits--;
+ }
+ n_max = n_digits + 4;
+ }
+ n = ceil_div(a1->expn, radix_bits);
+ } else {
+ bf_t a_s, *a = &a_s;
+
+ /* make a positive number */
+ a->tab = a2->tab;
+ a->len = a2->len;
+ a->expn = a2->expn;
+ a->sign = 0;
+
+ if (fmt == BF_FTOA_FORMAT_FIXED) {
+ n_digits = prec;
+ n_max = n_digits;
+ } else {
+ slimb_t n_digits_max, n_digits_min;
+
+ assert(prec != BF_PREC_INF);
+ n_digits = 1 + bf_mul_log2_radix(prec, radix, TRUE, TRUE);
+ /* max number of digits for non exponential
+ notation. The rational is to have the same rule
+ as JS i.e. n_max = 21 for 64 bit float in base 10. */
+ n_max = n_digits + 4;
+ if (fmt == BF_FTOA_FORMAT_FREE_MIN) {
+ bf_t b_s, *b = &b_s;
+
+ /* find the minimum number of digits by
+ dichotomy. */
+ /* XXX: inefficient */
+ n_digits_max = n_digits;
+ n_digits_min = 1;
+ bf_init(ctx, b);
+ while (n_digits_min < n_digits_max) {
+ n_digits = (n_digits_min + n_digits_max) / 2;
+ if (bf_convert_to_radix(a1, &n, a, radix, n_digits,
+ flags & BF_RND_MASK, FALSE)) {
+ bf_delete(b);
+ goto fail1;
+ }
+ /* convert back to a number and compare */
+ ret = bf_mul_pow_radix(b, a1, radix, n - n_digits,
+ prec,
+ (flags & ~BF_RND_MASK) |
+ BF_RNDN);
+ if (ret & BF_ST_MEM_ERROR) {
+ bf_delete(b);
+ goto fail1;
+ }
+ if (bf_cmpu(b, a) == 0) {
+ n_digits_max = n_digits;
+ } else {
+ n_digits_min = n_digits + 1;
+ }
+ }
+ bf_delete(b);
+ n_digits = n_digits_max;
+ }
+ }
+ if (bf_convert_to_radix(a1, &n, a, radix, n_digits,
+ flags & BF_RND_MASK, FALSE)) {
+ fail1:
+ bf_delete(a1);
+ goto fail;
+ }
+ }
+ if (a1->expn == BF_EXP_ZERO &&
+ fmt != BF_FTOA_FORMAT_FIXED &&
+ !(flags & BF_FTOA_FORCE_EXP)) {
+ /* just output zero */
+ dbuf_putstr(s, "0");
+ } else {
+ if (flags & BF_FTOA_ADD_PREFIX) {
+ if (radix == 16)
+ dbuf_putstr(s, "0x");
+ else if (radix == 8)
+ dbuf_putstr(s, "0o");
+ else if (radix == 2)
+ dbuf_putstr(s, "0b");
+ }
+ if (a1->expn == BF_EXP_ZERO)
+ n = 1;
+ if ((flags & BF_FTOA_FORCE_EXP) ||
+ n <= -6 || n > n_max) {
+ const char *fmt;
+ /* exponential notation */
+ output_digits(s, a1, radix, n_digits, 1, is_dec);
+ if (radix_bits != 0 && radix <= 16) {
+ if (flags & BF_FTOA_JS_QUIRKS)
+ fmt = "p%+" PRId_LIMB;
+ else
+ fmt = "p%" PRId_LIMB;
+ dbuf_printf(s, fmt, (n - 1) * radix_bits);
+ } else {
+ if (flags & BF_FTOA_JS_QUIRKS)
+ fmt = "%c%+" PRId_LIMB;
+ else
+ fmt = "%c%" PRId_LIMB;
+ dbuf_printf(s, fmt,
+ radix <= 10 ? 'e' : '@', n - 1);
+ }
+ } else if (n <= 0) {
+ /* 0.x */
+ dbuf_putstr(s, "0.");
+ for(i = 0; i < -n; i++) {
+ dbuf_putc(s, '0');
+ }
+ output_digits(s, a1, radix, n_digits, n_digits, is_dec);
+ } else {
+ if (n_digits <= n) {
+ /* no dot */
+ output_digits(s, a1, radix, n_digits, n_digits, is_dec);
+ for(i = 0; i < (n - n_digits); i++)
+ dbuf_putc(s, '0');
+ } else {
+ output_digits(s, a1, radix, n_digits, n, is_dec);
+ }
+ }
+ }
+ }
+ bf_delete(a1);
+ }
+ }
+ dbuf_putc(s, '\0');
+ if (dbuf_error(s))
+ goto fail;
+ if (plen)
+ *plen = s->size - 1;
+ return (char *)s->buf;
+ fail:
+ bf_free(ctx, s->buf);
+ if (plen)
+ *plen = 0;
+ return NULL;
+}
+
+char *bf_ftoa(size_t *plen, const bf_t *a, int radix, limb_t prec,
+ bf_flags_t flags)
+{
+ return bf_ftoa_internal(plen, a, radix, prec, flags, FALSE);
+}
+
+/***************************************************************/
+/* transcendental functions */
+
+/* Note: the algorithm is from MPFR */
+static void bf_const_log2_rec(bf_t *T, bf_t *P, bf_t *Q, limb_t n1,
+ limb_t n2, BOOL need_P)
+{
+ bf_context_t *s = T->ctx;
+ if ((n2 - n1) == 1) {
+ if (n1 == 0) {
+ bf_set_ui(P, 3);
+ } else {
+ bf_set_ui(P, n1);
+ P->sign = 1;
+ }
+ bf_set_ui(Q, 2 * n1 + 1);
+ Q->expn += 2;
+ bf_set(T, P);
+ } else {
+ limb_t m;
+ bf_t T1_s, *T1 = &T1_s;
+ bf_t P1_s, *P1 = &P1_s;
+ bf_t Q1_s, *Q1 = &Q1_s;
+
+ m = n1 + ((n2 - n1) >> 1);
+ bf_const_log2_rec(T, P, Q, n1, m, TRUE);
+ bf_init(s, T1);
+ bf_init(s, P1);
+ bf_init(s, Q1);
+ bf_const_log2_rec(T1, P1, Q1, m, n2, need_P);
+ bf_mul(T, T, Q1, BF_PREC_INF, BF_RNDZ);
+ bf_mul(T1, T1, P, BF_PREC_INF, BF_RNDZ);
+ bf_add(T, T, T1, BF_PREC_INF, BF_RNDZ);
+ if (need_P)
+ bf_mul(P, P, P1, BF_PREC_INF, BF_RNDZ);
+ bf_mul(Q, Q, Q1, BF_PREC_INF, BF_RNDZ);
+ bf_delete(T1);
+ bf_delete(P1);
+ bf_delete(Q1);
+ }
+}
+
+/* compute log(2) with faithful rounding at precision 'prec' */
+static void bf_const_log2_internal(bf_t *T, limb_t prec)
+{
+ limb_t w, N;
+ bf_t P_s, *P = &P_s;
+ bf_t Q_s, *Q = &Q_s;
+
+ w = prec + 15;
+ N = w / 3 + 1;
+ bf_init(T->ctx, P);
+ bf_init(T->ctx, Q);
+ bf_const_log2_rec(T, P, Q, 0, N, FALSE);
+ bf_div(T, T, Q, prec, BF_RNDN);
+ bf_delete(P);
+ bf_delete(Q);
+}
+
+/* PI constant */
+
+#define CHUD_A 13591409
+#define CHUD_B 545140134
+#define CHUD_C 640320
+#define CHUD_BITS_PER_TERM 47
+
+static void chud_bs(bf_t *P, bf_t *Q, bf_t *G, int64_t a, int64_t b, int need_g,
+ limb_t prec)
+{
+ bf_context_t *s = P->ctx;
+ int64_t c;
+
+ if (a == (b - 1)) {
+ bf_t T0, T1;
+
+ bf_init(s, &T0);
+ bf_init(s, &T1);
+ bf_set_ui(G, 2 * b - 1);
+ bf_mul_ui(G, G, 6 * b - 1, prec, BF_RNDN);
+ bf_mul_ui(G, G, 6 * b - 5, prec, BF_RNDN);
+ bf_set_ui(&T0, CHUD_B);
+ bf_mul_ui(&T0, &T0, b, prec, BF_RNDN);
+ bf_set_ui(&T1, CHUD_A);
+ bf_add(&T0, &T0, &T1, prec, BF_RNDN);
+ bf_mul(P, G, &T0, prec, BF_RNDN);
+ P->sign = b & 1;
+
+ bf_set_ui(Q, b);
+ bf_mul_ui(Q, Q, b, prec, BF_RNDN);
+ bf_mul_ui(Q, Q, b, prec, BF_RNDN);
+ bf_mul_ui(Q, Q, (uint64_t)CHUD_C * CHUD_C * CHUD_C / 24, prec, BF_RNDN);
+ bf_delete(&T0);
+ bf_delete(&T1);
+ } else {
+ bf_t P2, Q2, G2;
+
+ bf_init(s, &P2);
+ bf_init(s, &Q2);
+ bf_init(s, &G2);
+
+ c = (a + b) / 2;
+ chud_bs(P, Q, G, a, c, 1, prec);
+ chud_bs(&P2, &Q2, &G2, c, b, need_g, prec);
+
+ /* Q = Q1 * Q2 */
+ /* G = G1 * G2 */
+ /* P = P1 * Q2 + P2 * G1 */
+ bf_mul(&P2, &P2, G, prec, BF_RNDN);
+ if (!need_g)
+ bf_set_ui(G, 0);
+ bf_mul(P, P, &Q2, prec, BF_RNDN);
+ bf_add(P, P, &P2, prec, BF_RNDN);
+ bf_delete(&P2);
+
+ bf_mul(Q, Q, &Q2, prec, BF_RNDN);
+ bf_delete(&Q2);
+ if (need_g)
+ bf_mul(G, G, &G2, prec, BF_RNDN);
+ bf_delete(&G2);
+ }
+}
+
+/* compute Pi with faithful rounding at precision 'prec' using the
+ Chudnovsky formula */
+static void bf_const_pi_internal(bf_t *Q, limb_t prec)
+{
+ bf_context_t *s = Q->ctx;
+ int64_t n, prec1;
+ bf_t P, G;
+
+ /* number of serie terms */
+ n = prec / CHUD_BITS_PER_TERM + 1;
+ /* XXX: precision analysis */
+ prec1 = prec + 32;
+
+ bf_init(s, &P);
+ bf_init(s, &G);
+
+ chud_bs(&P, Q, &G, 0, n, 0, BF_PREC_INF);
+
+ bf_mul_ui(&G, Q, CHUD_A, prec1, BF_RNDN);
+ bf_add(&P, &G, &P, prec1, BF_RNDN);
+ bf_div(Q, Q, &P, prec1, BF_RNDF);
+
+ bf_set_ui(&P, CHUD_C);
+ bf_sqrt(&G, &P, prec1, BF_RNDF);
+ bf_mul_ui(&G, &G, (uint64_t)CHUD_C / 12, prec1, BF_RNDF);
+ bf_mul(Q, Q, &G, prec, BF_RNDN);
+ bf_delete(&P);
+ bf_delete(&G);
+}
+
+static int bf_const_get(bf_t *T, limb_t prec, bf_flags_t flags,
+ BFConstCache *c,
+ void (*func)(bf_t *res, limb_t prec), int sign)
+{
+ limb_t ziv_extra_bits, prec1;
+
+ ziv_extra_bits = 32;
+ for(;;) {
+ prec1 = prec + ziv_extra_bits;
+ if (c->prec < prec1) {
+ if (c->val.len == 0)
+ bf_init(T->ctx, &c->val);
+ func(&c->val, prec1);
+ c->prec = prec1;
+ } else {
+ prec1 = c->prec;
+ }
+ bf_set(T, &c->val);
+ T->sign = sign;
+ if (!bf_can_round(T, prec, flags & BF_RND_MASK, prec1)) {
+ /* and more precision and retry */
+ ziv_extra_bits = ziv_extra_bits + (ziv_extra_bits / 2);
+ } else {
+ break;
+ }
+ }
+ return bf_round(T, prec, flags);
+}
+
+static void bf_const_free(BFConstCache *c)
+{
+ bf_delete(&c->val);
+ memset(c, 0, sizeof(*c));
+}
+
+int bf_const_log2(bf_t *T, limb_t prec, bf_flags_t flags)
+{
+ bf_context_t *s = T->ctx;
+ return bf_const_get(T, prec, flags, &s->log2_cache, bf_const_log2_internal, 0);
+}
+
+/* return rounded pi * (1 - 2 * sign) */
+static int bf_const_pi_signed(bf_t *T, int sign, limb_t prec, bf_flags_t flags)
+{
+ bf_context_t *s = T->ctx;
+ return bf_const_get(T, prec, flags, &s->pi_cache, bf_const_pi_internal,
+ sign);
+}
+
+int bf_const_pi(bf_t *T, limb_t prec, bf_flags_t flags)
+{
+ return bf_const_pi_signed(T, 0, prec, flags);
+}
+
+void bf_clear_cache(bf_context_t *s)
+{
+#ifdef USE_FFT_MUL
+ fft_clear_cache(s);
+#endif
+ bf_const_free(&s->log2_cache);
+ bf_const_free(&s->pi_cache);
+}
+
+/* ZivFunc should compute the result 'r' with faithful rounding at
+ precision 'prec'. For efficiency purposes, the final bf_round()
+ does not need to be done in the function. */
+typedef int ZivFunc(bf_t *r, const bf_t *a, limb_t prec, void *opaque);
+
+static int bf_ziv_rounding(bf_t *r, const bf_t *a,
+ limb_t prec, bf_flags_t flags,
+ ZivFunc *f, void *opaque)
+{
+ int rnd_mode, ret;
+ slimb_t prec1, ziv_extra_bits;
+
+ rnd_mode = flags & BF_RND_MASK;
+ if (rnd_mode == BF_RNDF) {
+ /* no need to iterate */
+ f(r, a, prec, opaque);
+ ret = 0;
+ } else {
+ ziv_extra_bits = 32;
+ for(;;) {
+ prec1 = prec + ziv_extra_bits;
+ ret = f(r, a, prec1, opaque);
+ if (ret & (BF_ST_OVERFLOW | BF_ST_UNDERFLOW | BF_ST_MEM_ERROR)) {
+ /* overflow or underflow should never happen because
+ it indicates the rounding cannot be done correctly,
+ but we do not catch all the cases */
+ return ret;
+ }
+ /* if the result is exact, we can stop */
+ if (!(ret & BF_ST_INEXACT)) {
+ ret = 0;
+ break;
+ }
+ if (bf_can_round(r, prec, rnd_mode, prec1)) {
+ ret = BF_ST_INEXACT;
+ break;
+ }
+ ziv_extra_bits = ziv_extra_bits * 2;
+ // printf("ziv_extra_bits=%" PRId64 "\n", (int64_t)ziv_extra_bits);
+ }
+ }
+ if (r->len == 0)
+ return ret;
+ else
+ return __bf_round(r, prec, flags, r->len, ret);
+}
+
+/* add (1 - 2*e_sign) * 2^e */
+static int bf_add_epsilon(bf_t *r, const bf_t *a, slimb_t e, int e_sign,
+ limb_t prec, int flags)
+{
+ bf_t T_s, *T = &T_s;
+ int ret;
+ /* small argument case: result = 1 + epsilon * sign(x) */
+ bf_init(a->ctx, T);
+ bf_set_ui(T, 1);
+ T->sign = e_sign;
+ T->expn += e;
+ ret = bf_add(r, r, T, prec, flags);
+ bf_delete(T);
+ return ret;
+}
+
+/* Compute the exponential using faithful rounding at precision 'prec'.
+ Note: the algorithm is from MPFR */
+static int bf_exp_internal(bf_t *r, const bf_t *a, limb_t prec, void *opaque)
+{
+ bf_context_t *s = r->ctx;
+ bf_t T_s, *T = &T_s;
+ slimb_t n, K, l, i, prec1;
+
+ assert(r != a);
+
+ /* argument reduction:
+ T = a - n*log(2) with 0 <= T < log(2) and n integer.
+ */
+ bf_init(s, T);
+ if (a->expn <= -1) {
+ /* 0 <= abs(a) <= 0.5 */
+ if (a->sign)
+ n = -1;
+ else
+ n = 0;
+ } else {
+ bf_const_log2(T, LIMB_BITS, BF_RNDZ);
+ bf_div(T, a, T, LIMB_BITS, BF_RNDD);
+ bf_get_limb(&n, T, 0);
+ }
+
+ K = bf_isqrt((prec + 1) / 2);
+ l = (prec - 1) / K + 1;
+ /* XXX: precision analysis ? */
+ prec1 = prec + (K + 2 * l + 18) + K + 8;
+ if (a->expn > 0)
+ prec1 += a->expn;
+ // printf("n=%ld K=%ld prec1=%ld\n", n, K, prec1);
+
+ bf_const_log2(T, prec1, BF_RNDF);
+ bf_mul_si(T, T, n, prec1, BF_RNDN);
+ bf_sub(T, a, T, prec1, BF_RNDN);
+
+ /* reduce the range of T */
+ bf_mul_2exp(T, -K, BF_PREC_INF, BF_RNDZ);
+
+ /* Taylor expansion around zero :
+ 1 + x + x^2/2 + ... + x^n/n!
+ = (1 + x * (1 + x/2 * (1 + ... (x/n))))
+ */
+ {
+ bf_t U_s, *U = &U_s;
+
+ bf_init(s, U);
+ bf_set_ui(r, 1);
+ for(i = l ; i >= 1; i--) {
+ bf_set_ui(U, i);
+ bf_div(U, T, U, prec1, BF_RNDN);
+ bf_mul(r, r, U, prec1, BF_RNDN);
+ bf_add_si(r, r, 1, prec1, BF_RNDN);
+ }
+ bf_delete(U);
+ }
+ bf_delete(T);
+
+ /* undo the range reduction */
+ for(i = 0; i < K; i++) {
+ bf_mul(r, r, r, prec1, BF_RNDN | BF_FLAG_EXT_EXP);
+ }
+
+ /* undo the argument reduction */
+ bf_mul_2exp(r, n, BF_PREC_INF, BF_RNDZ | BF_FLAG_EXT_EXP);
+
+ return BF_ST_INEXACT;
+}
+
+/* crude overflow and underflow tests for exp(a). a_low <= a <= a_high */
+static int check_exp_underflow_overflow(bf_context_t *s, bf_t *r,
+ const bf_t *a_low, const bf_t *a_high,
+ limb_t prec, bf_flags_t flags)
+{
+ bf_t T_s, *T = &T_s;
+ bf_t log2_s, *log2 = &log2_s;
+ slimb_t e_min, e_max;
+
+ if (a_high->expn <= 0)
+ return 0;
+
+ e_max = (limb_t)1 << (bf_get_exp_bits(flags) - 1);
+ e_min = -e_max + 3;
+ if (flags & BF_FLAG_SUBNORMAL)
+ e_min -= (prec - 1);
+
+ bf_init(s, T);
+ bf_init(s, log2);
+ bf_const_log2(log2, LIMB_BITS, BF_RNDU);
+ bf_mul_ui(T, log2, e_max, LIMB_BITS, BF_RNDU);
+ /* a_low > e_max * log(2) implies exp(a) > e_max */
+ if (bf_cmp_lt(T, a_low) > 0) {
+ /* overflow */
+ bf_delete(T);
+ bf_delete(log2);
+ return bf_set_overflow(r, 0, prec, flags);
+ }
+ /* a_high < (e_min - 2) * log(2) implies exp(a) < (e_min - 2) */
+ bf_const_log2(log2, LIMB_BITS, BF_RNDD);
+ bf_mul_si(T, log2, e_min - 2, LIMB_BITS, BF_RNDD);
+ if (bf_cmp_lt(a_high, T)) {
+ int rnd_mode = flags & BF_RND_MASK;
+
+ /* underflow */
+ bf_delete(T);
+ bf_delete(log2);
+ if (rnd_mode == BF_RNDU) {
+ /* set the smallest value */
+ bf_set_ui(r, 1);
+ r->expn = e_min;
+ } else {
+ bf_set_zero(r, 0);
+ }
+ return BF_ST_UNDERFLOW | BF_ST_INEXACT;
+ }
+ bf_delete(log2);
+ bf_delete(T);
+ return 0;
+}
+
+int bf_exp(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags)
+{
+ bf_context_t *s = r->ctx;
+ int ret;
+ assert(r != a);
+ if (a->len == 0) {
+ if (a->expn == BF_EXP_NAN) {
+ bf_set_nan(r);
+ } else if (a->expn == BF_EXP_INF) {
+ if (a->sign)
+ bf_set_zero(r, 0);
+ else
+ bf_set_inf(r, 0);
+ } else {
+ bf_set_ui(r, 1);
+ }
+ return 0;
+ }
+
+ ret = check_exp_underflow_overflow(s, r, a, a, prec, flags);
+ if (ret)
+ return ret;
+ if (a->expn < 0 && (-a->expn) >= (prec + 2)) {
+ /* small argument case: result = 1 + epsilon * sign(x) */
+ bf_set_ui(r, 1);
+ return bf_add_epsilon(r, r, -(prec + 2), a->sign, prec, flags);
+ }
+
+ return bf_ziv_rounding(r, a, prec, flags, bf_exp_internal, NULL);
+}
+
+static int bf_log_internal(bf_t *r, const bf_t *a, limb_t prec, void *opaque)
+{
+ bf_context_t *s = r->ctx;
+ bf_t T_s, *T = &T_s;
+ bf_t U_s, *U = &U_s;
+ bf_t V_s, *V = &V_s;
+ slimb_t n, prec1, l, i, K;
+
+ assert(r != a);
+
+ bf_init(s, T);
+ /* argument reduction 1 */
+ /* T=a*2^n with 2/3 <= T <= 4/3 */
+ {
+ bf_t U_s, *U = &U_s;
+ bf_set(T, a);
+ n = T->expn;
+ T->expn = 0;
+ /* U= ~ 2/3 */
+ bf_init(s, U);
+ bf_set_ui(U, 0xaaaaaaaa);
+ U->expn = 0;
+ if (bf_cmp_lt(T, U)) {
+ T->expn++;
+ n--;
+ }
+ bf_delete(U);
+ }
+ // printf("n=%ld\n", n);
+ // bf_print_str("T", T);
+
+ /* XXX: precision analysis */
+ /* number of iterations for argument reduction 2 */
+ K = bf_isqrt((prec + 1) / 2);
+ /* order of Taylor expansion */
+ l = prec / (2 * K) + 1;
+ /* precision of the intermediate computations */
+ prec1 = prec + K + 2 * l + 32;
+
+ bf_init(s, U);
+ bf_init(s, V);
+
+ /* Note: cancellation occurs here, so we use more precision (XXX:
+ reduce the precision by computing the exact cancellation) */
+ bf_add_si(T, T, -1, BF_PREC_INF, BF_RNDN);
+
+ /* argument reduction 2 */
+ for(i = 0; i < K; i++) {
+ /* T = T / (1 + sqrt(1 + T)) */
+ bf_add_si(U, T, 1, prec1, BF_RNDN);
+ bf_sqrt(V, U, prec1, BF_RNDF);
+ bf_add_si(U, V, 1, prec1, BF_RNDN);
+ bf_div(T, T, U, prec1, BF_RNDN);
+ }
+
+ {
+ bf_t Y_s, *Y = &Y_s;
+ bf_t Y2_s, *Y2 = &Y2_s;
+ bf_init(s, Y);
+ bf_init(s, Y2);
+
+ /* compute ln(1+x) = ln((1+y)/(1-y)) with y=x/(2+x)
+ = y + y^3/3 + ... + y^(2*l + 1) / (2*l+1)
+ with Y=Y^2
+ = y*(1+Y/3+Y^2/5+...) = y*(1+Y*(1/3+Y*(1/5 + ...)))
+ */
+ bf_add_si(Y, T, 2, prec1, BF_RNDN);
+ bf_div(Y, T, Y, prec1, BF_RNDN);
+
+ bf_mul(Y2, Y, Y, prec1, BF_RNDN);
+ bf_set_ui(r, 0);
+ for(i = l; i >= 1; i--) {
+ bf_set_ui(U, 1);
+ bf_set_ui(V, 2 * i + 1);
+ bf_div(U, U, V, prec1, BF_RNDN);
+ bf_add(r, r, U, prec1, BF_RNDN);
+ bf_mul(r, r, Y2, prec1, BF_RNDN);
+ }
+ bf_add_si(r, r, 1, prec1, BF_RNDN);
+ bf_mul(r, r, Y, prec1, BF_RNDN);
+ bf_delete(Y);
+ bf_delete(Y2);
+ }
+ bf_delete(V);
+ bf_delete(U);
+
+ /* multiplication by 2 for the Taylor expansion and undo the
+ argument reduction 2*/
+ bf_mul_2exp(r, K + 1, BF_PREC_INF, BF_RNDZ);
+
+ /* undo the argument reduction 1 */
+ bf_const_log2(T, prec1, BF_RNDF);
+ bf_mul_si(T, T, n, prec1, BF_RNDN);
+ bf_add(r, r, T, prec1, BF_RNDN);
+
+ bf_delete(T);
+ return BF_ST_INEXACT;
+}
+
+int bf_log(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags)
+{
+ bf_context_t *s = r->ctx;
+ bf_t T_s, *T = &T_s;
+
+ assert(r != a);
+ if (a->len == 0) {
+ if (a->expn == BF_EXP_NAN) {
+ bf_set_nan(r);
+ return 0;
+ } else if (a->expn == BF_EXP_INF) {
+ if (a->sign) {
+ bf_set_nan(r);
+ return BF_ST_INVALID_OP;
+ } else {
+ bf_set_inf(r, 0);
+ return 0;
+ }
+ } else {
+ bf_set_inf(r, 1);
+ return 0;
+ }
+ }
+ if (a->sign) {
+ bf_set_nan(r);
+ return BF_ST_INVALID_OP;
+ }
+ bf_init(s, T);
+ bf_set_ui(T, 1);
+ if (bf_cmp_eq(a, T)) {
+ bf_set_zero(r, 0);
+ bf_delete(T);
+ return 0;
+ }
+ bf_delete(T);
+
+ return bf_ziv_rounding(r, a, prec, flags, bf_log_internal, NULL);
+}
+
+/* x and y finite and x > 0 */
+static int bf_pow_generic(bf_t *r, const bf_t *x, limb_t prec, void *opaque)
+{
+ bf_context_t *s = r->ctx;
+ const bf_t *y = opaque;
+ bf_t T_s, *T = &T_s;
+ limb_t prec1;
+
+ bf_init(s, T);
+ /* XXX: proof for the added precision */
+ prec1 = prec + 32;
+ bf_log(T, x, prec1, BF_RNDF | BF_FLAG_EXT_EXP);
+ bf_mul(T, T, y, prec1, BF_RNDF | BF_FLAG_EXT_EXP);
+ if (bf_is_nan(T))
+ bf_set_nan(r);
+ else
+ bf_exp_internal(r, T, prec1, NULL); /* no overflow/underlow test needed */
+ bf_delete(T);
+ return BF_ST_INEXACT;
+}
+
+/* x and y finite, x > 0, y integer and y fits on one limb */
+static int bf_pow_int(bf_t *r, const bf_t *x, limb_t prec, void *opaque)
+{
+ bf_context_t *s = r->ctx;
+ const bf_t *y = opaque;
+ bf_t T_s, *T = &T_s;
+ limb_t prec1;
+ int ret;
+ slimb_t y1;
+
+ bf_get_limb(&y1, y, 0);
+ if (y1 < 0)
+ y1 = -y1;
+ /* XXX: proof for the added precision */
+ prec1 = prec + ceil_log2(y1) * 2 + 8;
+ ret = bf_pow_ui(r, x, y1 < 0 ? -y1 : y1, prec1, BF_RNDN | BF_FLAG_EXT_EXP);
+ if (y->sign) {
+ bf_init(s, T);
+ bf_set_ui(T, 1);
+ ret |= bf_div(r, T, r, prec1, BF_RNDN | BF_FLAG_EXT_EXP);
+ bf_delete(T);
+ }
+ return ret;
+}
+
+/* x must be a finite non zero float. Return TRUE if there is a
+ floating point number r such as x=r^(2^n) and return this floating
+ point number 'r'. Otherwise return FALSE and r is undefined. */
+static BOOL check_exact_power2n(bf_t *r, const bf_t *x, slimb_t n)
+{
+ bf_context_t *s = r->ctx;
+ bf_t T_s, *T = &T_s;
+ slimb_t e, i, er;
+ limb_t v;
+
+ /* x = m*2^e with m odd integer */
+ e = bf_get_exp_min(x);
+ /* fast check on the exponent */
+ if (n > (LIMB_BITS - 1)) {
+ if (e != 0)
+ return FALSE;
+ er = 0;
+ } else {
+ if ((e & (((limb_t)1 << n) - 1)) != 0)
+ return FALSE;
+ er = e >> n;
+ }
+ /* every perfect odd square = 1 modulo 8 */
+ v = get_bits(x->tab, x->len, x->len * LIMB_BITS - x->expn + e);
+ if ((v & 7) != 1)
+ return FALSE;
+
+ bf_init(s, T);
+ bf_set(T, x);
+ T->expn -= e;
+ for(i = 0; i < n; i++) {
+ if (i != 0)
+ bf_set(T, r);
+ if (bf_sqrtrem(r, NULL, T) != 0)
+ return FALSE;
+ }
+ r->expn += er;
+ return TRUE;
+}
+
+/* prec = BF_PREC_INF is accepted for x and y integers and y >= 0 */
+int bf_pow(bf_t *r, const bf_t *x, const bf_t *y, limb_t prec, bf_flags_t flags)
+{
+ bf_context_t *s = r->ctx;
+ bf_t T_s, *T = &T_s;
+ bf_t ytmp_s;
+ BOOL y_is_int, y_is_odd;
+ int r_sign, ret, rnd_mode;
+ slimb_t y_emin;
+
+ if (x->len == 0 || y->len == 0) {
+ if (y->expn == BF_EXP_ZERO) {
+ /* pow(x, 0) = 1 */
+ bf_set_ui(r, 1);
+ } else if (x->expn == BF_EXP_NAN) {
+ bf_set_nan(r);
+ } else {
+ int cmp_x_abs_1;
+ bf_set_ui(r, 1);
+ cmp_x_abs_1 = bf_cmpu(x, r);
+ if (cmp_x_abs_1 == 0 && (flags & BF_POW_JS_QUIRKS) &&
+ (y->expn >= BF_EXP_INF)) {
+ bf_set_nan(r);
+ } else if (cmp_x_abs_1 == 0 &&
+ (!x->sign || y->expn != BF_EXP_NAN)) {
+ /* pow(1, y) = 1 even if y = NaN */
+ /* pow(-1, +/-inf) = 1 */
+ } else if (y->expn == BF_EXP_NAN) {
+ bf_set_nan(r);
+ } else if (y->expn == BF_EXP_INF) {
+ if (y->sign == (cmp_x_abs_1 > 0)) {
+ bf_set_zero(r, 0);
+ } else {
+ bf_set_inf(r, 0);
+ }
+ } else {
+ y_emin = bf_get_exp_min(y);
+ y_is_odd = (y_emin == 0);
+ if (y->sign == (x->expn == BF_EXP_ZERO)) {
+ bf_set_inf(r, y_is_odd & x->sign);
+ if (y->sign) {
+ /* pow(0, y) with y < 0 */
+ return BF_ST_DIVIDE_ZERO;
+ }
+ } else {
+ bf_set_zero(r, y_is_odd & x->sign);
+ }
+ }
+ }
+ return 0;
+ }
+ bf_init(s, T);
+ bf_set(T, x);
+ y_emin = bf_get_exp_min(y);
+ y_is_int = (y_emin >= 0);
+ rnd_mode = flags & BF_RND_MASK;
+ if (x->sign) {
+ if (!y_is_int) {
+ bf_set_nan(r);
+ bf_delete(T);
+ return BF_ST_INVALID_OP;
+ }
+ y_is_odd = (y_emin == 0);
+ r_sign = y_is_odd;
+ /* change the directed rounding mode if the sign of the result
+ is changed */
+ if (r_sign && (rnd_mode == BF_RNDD || rnd_mode == BF_RNDU))
+ flags ^= 1;
+ bf_neg(T);
+ } else {
+ r_sign = 0;
+ }
+
+ bf_set_ui(r, 1);
+ if (bf_cmp_eq(T, r)) {
+ /* abs(x) = 1: nothing more to do */
+ ret = 0;
+ } else {
+ /* check the overflow/underflow cases */
+ {
+ bf_t al_s, *al = &al_s;
+ bf_t ah_s, *ah = &ah_s;
+ limb_t precl = LIMB_BITS;
+
+ bf_init(s, al);
+ bf_init(s, ah);
+ /* compute bounds of log(abs(x)) * y with a low precision */
+ /* XXX: compute bf_log() once */
+ /* XXX: add a fast test before this slow test */
+ bf_log(al, T, precl, BF_RNDD);
+ bf_log(ah, T, precl, BF_RNDU);
+ bf_mul(al, al, y, precl, BF_RNDD ^ y->sign);
+ bf_mul(ah, ah, y, precl, BF_RNDU ^ y->sign);
+ ret = check_exp_underflow_overflow(s, r, al, ah, prec, flags);
+ bf_delete(al);
+ bf_delete(ah);
+ if (ret)
+ goto done;
+ }
+
+ if (y_is_int) {
+ slimb_t T_bits, e;
+ int_pow:
+ T_bits = T->expn - bf_get_exp_min(T);
+ if (T_bits == 1) {
+ /* pow(2^b, y) = 2^(b*y) */
+ bf_mul_si(T, y, T->expn - 1, LIMB_BITS, BF_RNDZ);
+ bf_get_limb(&e, T, 0);
+ bf_set_ui(r, 1);
+ ret = bf_mul_2exp(r, e, prec, flags);
+ } else if (prec == BF_PREC_INF) {
+ slimb_t y1;
+ /* specific case for infinite precision (integer case) */
+ bf_get_limb(&y1, y, 0);
+ assert(!y->sign);
+ /* x must be an integer, so abs(x) >= 2 */
+ if (y1 >= ((slimb_t)1 << BF_EXP_BITS_MAX)) {
+ bf_delete(T);
+ return bf_set_overflow(r, 0, BF_PREC_INF, flags);
+ }
+ ret = bf_pow_ui(r, T, y1, BF_PREC_INF, BF_RNDZ);
+ } else {
+ if (y->expn <= 31) {
+ /* small enough power: use exponentiation in all cases */
+ } else if (y->sign) {
+ /* cannot be exact */
+ goto general_case;
+ } else {
+ if (rnd_mode == BF_RNDF)
+ goto general_case; /* no need to track exact results */
+ /* see if the result has a chance to be exact:
+ if x=a*2^b (a odd), x^y=a^y*2^(b*y)
+ x^y needs a precision of at least floor_log2(a)*y bits
+ */
+ bf_mul_si(r, y, T_bits - 1, LIMB_BITS, BF_RNDZ);
+ bf_get_limb(&e, r, 0);
+ if (prec < e)
+ goto general_case;
+ }
+ ret = bf_ziv_rounding(r, T, prec, flags, bf_pow_int, (void *)y);
+ }
+ } else {
+ if (rnd_mode != BF_RNDF) {
+ bf_t *y1;
+ if (y_emin < 0 && check_exact_power2n(r, T, -y_emin)) {
+ /* the problem is reduced to a power to an integer */
+#if 0
+ printf("\nn=%" PRId64 "\n", -(int64_t)y_emin);
+ bf_print_str("T", T);
+ bf_print_str("r", r);
+#endif
+ bf_set(T, r);
+ y1 = &ytmp_s;
+ y1->tab = y->tab;
+ y1->len = y->len;
+ y1->sign = y->sign;
+ y1->expn = y->expn - y_emin;
+ y = y1;
+ goto int_pow;
+ }
+ }
+ general_case:
+ ret = bf_ziv_rounding(r, T, prec, flags, bf_pow_generic, (void *)y);
+ }
+ }
+ done:
+ bf_delete(T);
+ r->sign = r_sign;
+ return ret;
+}
+
+/* compute sqrt(-2*x-x^2) to get |sin(x)| from cos(x) - 1. */
+static void bf_sqrt_sin(bf_t *r, const bf_t *x, limb_t prec1)
+{
+ bf_context_t *s = r->ctx;
+ bf_t T_s, *T = &T_s;
+ bf_init(s, T);
+ bf_set(T, x);
+ bf_mul(r, T, T, prec1, BF_RNDN);
+ bf_mul_2exp(T, 1, BF_PREC_INF, BF_RNDZ);
+ bf_add(T, T, r, prec1, BF_RNDN);
+ bf_neg(T);
+ bf_sqrt(r, T, prec1, BF_RNDF);
+ bf_delete(T);
+}
+
+static int bf_sincos(bf_t *s, bf_t *c, const bf_t *a, limb_t prec)
+{
+ bf_context_t *s1 = a->ctx;
+ bf_t T_s, *T = &T_s;
+ bf_t U_s, *U = &U_s;
+ bf_t r_s, *r = &r_s;
+ slimb_t K, prec1, i, l, mod, prec2;
+ int is_neg;
+
+ assert(c != a && s != a);
+
+ bf_init(s1, T);
+ bf_init(s1, U);
+ bf_init(s1, r);
+
+ /* XXX: precision analysis */
+ K = bf_isqrt(prec / 2);
+ l = prec / (2 * K) + 1;
+ prec1 = prec + 2 * K + l + 8;
+
+ /* after the modulo reduction, -pi/4 <= T <= pi/4 */
+ if (a->expn <= -1) {
+ /* abs(a) <= 0.25: no modulo reduction needed */
+ bf_set(T, a);
+ mod = 0;
+ } else {
+ slimb_t cancel;
+ cancel = 0;
+ for(;;) {
+ prec2 = prec1 + a->expn + cancel;
+ bf_const_pi(U, prec2, BF_RNDF);
+ bf_mul_2exp(U, -1, BF_PREC_INF, BF_RNDZ);
+ bf_remquo(&mod, T, a, U, prec2, BF_RNDN, BF_RNDN);
+ // printf("T.expn=%ld prec2=%ld\n", T->expn, prec2);
+ if (mod == 0 || (T->expn != BF_EXP_ZERO &&
+ (T->expn + prec2) >= (prec1 - 1)))
+ break;
+ /* increase the number of bits until the precision is good enough */
+ cancel = bf_max(-T->expn, (cancel + 1) * 3 / 2);
+ }
+ mod &= 3;
+ }
+
+ is_neg = T->sign;
+
+ /* compute cosm1(x) = cos(x) - 1 */
+ bf_mul(T, T, T, prec1, BF_RNDN);
+ bf_mul_2exp(T, -2 * K, BF_PREC_INF, BF_RNDZ);
+
+ /* Taylor expansion:
+ -x^2/2 + x^4/4! - x^6/6! + ...
+ */
+ bf_set_ui(r, 1);
+ for(i = l ; i >= 1; i--) {
+ bf_set_ui(U, 2 * i - 1);
+ bf_mul_ui(U, U, 2 * i, BF_PREC_INF, BF_RNDZ);
+ bf_div(U, T, U, prec1, BF_RNDN);
+ bf_mul(r, r, U, prec1, BF_RNDN);
+ bf_neg(r);
+ if (i != 1)
+ bf_add_si(r, r, 1, prec1, BF_RNDN);
+ }
+ bf_delete(U);
+
+ /* undo argument reduction:
+ cosm1(2*x)= 2*(2*cosm1(x)+cosm1(x)^2)
+ */
+ for(i = 0; i < K; i++) {
+ bf_mul(T, r, r, prec1, BF_RNDN);
+ bf_mul_2exp(r, 1, BF_PREC_INF, BF_RNDZ);
+ bf_add(r, r, T, prec1, BF_RNDN);
+ bf_mul_2exp(r, 1, BF_PREC_INF, BF_RNDZ);
+ }
+ bf_delete(T);
+
+ if (c) {
+ if ((mod & 1) == 0) {
+ bf_add_si(c, r, 1, prec1, BF_RNDN);
+ } else {
+ bf_sqrt_sin(c, r, prec1);
+ c->sign = is_neg ^ 1;
+ }
+ c->sign ^= mod >> 1;
+ }
+ if (s) {
+ if ((mod & 1) == 0) {
+ bf_sqrt_sin(s, r, prec1);
+ s->sign = is_neg;
+ } else {
+ bf_add_si(s, r, 1, prec1, BF_RNDN);
+ }
+ s->sign ^= mod >> 1;
+ }
+ bf_delete(r);
+ return BF_ST_INEXACT;
+}
+
+static int bf_cos_internal(bf_t *r, const bf_t *a, limb_t prec, void *opaque)
+{
+ return bf_sincos(NULL, r, a, prec);
+}
+
+int bf_cos(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags)
+{
+ if (a->len == 0) {
+ if (a->expn == BF_EXP_NAN) {
+ bf_set_nan(r);
+ return 0;
+ } else if (a->expn == BF_EXP_INF) {
+ bf_set_nan(r);
+ return BF_ST_INVALID_OP;
+ } else {
+ bf_set_ui(r, 1);
+ return 0;
+ }
+ }
+
+ /* small argument case: result = 1+r(x) with r(x) = -x^2/2 +
+ O(X^4). We assume r(x) < 2^(2*EXP(x) - 1). */
+ if (a->expn < 0) {
+ slimb_t e;
+ e = 2 * a->expn - 1;
+ if (e < -(prec + 2)) {
+ bf_set_ui(r, 1);
+ return bf_add_epsilon(r, r, e, 1, prec, flags);
+ }
+ }
+
+ return bf_ziv_rounding(r, a, prec, flags, bf_cos_internal, NULL);
+}
+
+static int bf_sin_internal(bf_t *r, const bf_t *a, limb_t prec, void *opaque)
+{
+ return bf_sincos(r, NULL, a, prec);
+}
+
+int bf_sin(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags)
+{
+ if (a->len == 0) {
+ if (a->expn == BF_EXP_NAN) {
+ bf_set_nan(r);
+ return 0;
+ } else if (a->expn == BF_EXP_INF) {
+ bf_set_nan(r);
+ return BF_ST_INVALID_OP;
+ } else {
+ bf_set_zero(r, a->sign);
+ return 0;
+ }
+ }
+
+ /* small argument case: result = x+r(x) with r(x) = -x^3/6 +
+ O(X^5). We assume r(x) < 2^(3*EXP(x) - 2). */
+ if (a->expn < 0) {
+ slimb_t e;
+ e = sat_add(2 * a->expn, a->expn - 2);
+ if (e < a->expn - bf_max(prec + 2, a->len * LIMB_BITS + 2)) {
+ bf_set(r, a);
+ return bf_add_epsilon(r, r, e, 1 - a->sign, prec, flags);
+ }
+ }
+
+ return bf_ziv_rounding(r, a, prec, flags, bf_sin_internal, NULL);
+}
+
+static int bf_tan_internal(bf_t *r, const bf_t *a, limb_t prec, void *opaque)
+{
+ bf_context_t *s = r->ctx;
+ bf_t T_s, *T = &T_s;
+ limb_t prec1;
+
+ /* XXX: precision analysis */
+ prec1 = prec + 8;
+ bf_init(s, T);
+ bf_sincos(r, T, a, prec1);
+ bf_div(r, r, T, prec1, BF_RNDF);
+ bf_delete(T);
+ return BF_ST_INEXACT;
+}
+
+int bf_tan(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags)
+{
+ assert(r != a);
+ if (a->len == 0) {
+ if (a->expn == BF_EXP_NAN) {
+ bf_set_nan(r);
+ return 0;
+ } else if (a->expn == BF_EXP_INF) {
+ bf_set_nan(r);
+ return BF_ST_INVALID_OP;
+ } else {
+ bf_set_zero(r, a->sign);
+ return 0;
+ }
+ }
+
+ /* small argument case: result = x+r(x) with r(x) = x^3/3 +
+ O(X^5). We assume r(x) < 2^(3*EXP(x) - 1). */
+ if (a->expn < 0) {
+ slimb_t e;
+ e = sat_add(2 * a->expn, a->expn - 1);
+ if (e < a->expn - bf_max(prec + 2, a->len * LIMB_BITS + 2)) {
+ bf_set(r, a);
+ return bf_add_epsilon(r, r, e, a->sign, prec, flags);
+ }
+ }
+
+ return bf_ziv_rounding(r, a, prec, flags, bf_tan_internal, NULL);
+}
+
+/* if add_pi2 is true, add pi/2 to the result (used for acos(x) to
+ avoid cancellation) */
+static int bf_atan_internal(bf_t *r, const bf_t *a, limb_t prec,
+ void *opaque)
+{
+ bf_context_t *s = r->ctx;
+ BOOL add_pi2 = (BOOL)(intptr_t)opaque;
+ bf_t T_s, *T = &T_s;
+ bf_t U_s, *U = &U_s;
+ bf_t V_s, *V = &V_s;
+ bf_t X2_s, *X2 = &X2_s;
+ int cmp_1;
+ slimb_t prec1, i, K, l;
+
+ /* XXX: precision analysis */
+ K = bf_isqrt((prec + 1) / 2);
+ l = prec / (2 * K) + 1;
+ prec1 = prec + K + 2 * l + 32;
+ // printf("prec=%d K=%d l=%d prec1=%d\n", (int)prec, (int)K, (int)l, (int)prec1);
+
+ bf_init(s, T);
+ cmp_1 = (a->expn >= 1); /* a >= 1 */
+ if (cmp_1) {
+ bf_set_ui(T, 1);
+ bf_div(T, T, a, prec1, BF_RNDN);
+ } else {
+ bf_set(T, a);
+ }
+
+ /* abs(T) <= 1 */
+
+ /* argument reduction */
+
+ bf_init(s, U);
+ bf_init(s, V);
+ bf_init(s, X2);
+ for(i = 0; i < K; i++) {
+ /* T = T / (1 + sqrt(1 + T^2)) */
+ bf_mul(U, T, T, prec1, BF_RNDN);
+ bf_add_si(U, U, 1, prec1, BF_RNDN);
+ bf_sqrt(V, U, prec1, BF_RNDN);
+ bf_add_si(V, V, 1, prec1, BF_RNDN);
+ bf_div(T, T, V, prec1, BF_RNDN);
+ }
+
+ /* Taylor series:
+ x - x^3/3 + ... + (-1)^ l * y^(2*l + 1) / (2*l+1)
+ */
+ bf_mul(X2, T, T, prec1, BF_RNDN);
+ bf_set_ui(r, 0);
+ for(i = l; i >= 1; i--) {
+ bf_set_si(U, 1);
+ bf_set_ui(V, 2 * i + 1);
+ bf_div(U, U, V, prec1, BF_RNDN);
+ bf_neg(r);
+ bf_add(r, r, U, prec1, BF_RNDN);
+ bf_mul(r, r, X2, prec1, BF_RNDN);
+ }
+ bf_neg(r);
+ bf_add_si(r, r, 1, prec1, BF_RNDN);
+ bf_mul(r, r, T, prec1, BF_RNDN);
+
+ /* undo the argument reduction */
+ bf_mul_2exp(r, K, BF_PREC_INF, BF_RNDZ);
+
+ bf_delete(U);
+ bf_delete(V);
+ bf_delete(X2);
+
+ i = add_pi2;
+ if (cmp_1 > 0) {
+ /* undo the inversion : r = sign(a)*PI/2 - r */
+ bf_neg(r);
+ i += 1 - 2 * a->sign;
+ }
+ /* add i*(pi/2) with -1 <= i <= 2 */
+ if (i != 0) {
+ bf_const_pi(T, prec1, BF_RNDF);
+ if (i != 2)
+ bf_mul_2exp(T, -1, BF_PREC_INF, BF_RNDZ);
+ T->sign = (i < 0);
+ bf_add(r, T, r, prec1, BF_RNDN);
+ }
+
+ bf_delete(T);
+ return BF_ST_INEXACT;
+}
+
+int bf_atan(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags)
+{
+ bf_context_t *s = r->ctx;
+ bf_t T_s, *T = &T_s;
+ int res;
+
+ if (a->len == 0) {
+ if (a->expn == BF_EXP_NAN) {
+ bf_set_nan(r);
+ return 0;
+ } else if (a->expn == BF_EXP_INF) {
+ /* -PI/2 or PI/2 */
+ bf_const_pi_signed(r, a->sign, prec, flags);
+ bf_mul_2exp(r, -1, BF_PREC_INF, BF_RNDZ);
+ return BF_ST_INEXACT;
+ } else {
+ bf_set_zero(r, a->sign);
+ return 0;
+ }
+ }
+
+ bf_init(s, T);
+ bf_set_ui(T, 1);
+ res = bf_cmpu(a, T);
+ bf_delete(T);
+ if (res == 0) {
+ /* short cut: abs(a) == 1 -> +/-pi/4 */
+ bf_const_pi_signed(r, a->sign, prec, flags);
+ bf_mul_2exp(r, -2, BF_PREC_INF, BF_RNDZ);
+ return BF_ST_INEXACT;
+ }
+
+ /* small argument case: result = x+r(x) with r(x) = -x^3/3 +
+ O(X^5). We assume r(x) < 2^(3*EXP(x) - 1). */
+ if (a->expn < 0) {
+ slimb_t e;
+ e = sat_add(2 * a->expn, a->expn - 1);
+ if (e < a->expn - bf_max(prec + 2, a->len * LIMB_BITS + 2)) {
+ bf_set(r, a);
+ return bf_add_epsilon(r, r, e, 1 - a->sign, prec, flags);
+ }
+ }
+
+ return bf_ziv_rounding(r, a, prec, flags, bf_atan_internal, (void *)FALSE);
+}
+
+static int bf_atan2_internal(bf_t *r, const bf_t *y, limb_t prec, void *opaque)
+{
+ bf_context_t *s = r->ctx;
+ const bf_t *x = opaque;
+ bf_t T_s, *T = &T_s;
+ limb_t prec1;
+ int ret;
+
+ if (y->expn == BF_EXP_NAN || x->expn == BF_EXP_NAN) {
+ bf_set_nan(r);
+ return 0;
+ }
+
+ /* compute atan(y/x) assumming inf/inf = 1 and 0/0 = 0 */
+ bf_init(s, T);
+ prec1 = prec + 32;
+ if (y->expn == BF_EXP_INF && x->expn == BF_EXP_INF) {
+ bf_set_ui(T, 1);
+ T->sign = y->sign ^ x->sign;
+ } else if (y->expn == BF_EXP_ZERO && x->expn == BF_EXP_ZERO) {
+ bf_set_zero(T, y->sign ^ x->sign);
+ } else {
+ bf_div(T, y, x, prec1, BF_RNDF);
+ }
+ ret = bf_atan(r, T, prec1, BF_RNDF);
+
+ if (x->sign) {
+ /* if x < 0 (it includes -0), return sign(y)*pi + atan(y/x) */
+ bf_const_pi(T, prec1, BF_RNDF);
+ T->sign = y->sign;
+ bf_add(r, r, T, prec1, BF_RNDN);
+ ret |= BF_ST_INEXACT;
+ }
+
+ bf_delete(T);
+ return ret;
+}
+
+int bf_atan2(bf_t *r, const bf_t *y, const bf_t *x,
+ limb_t prec, bf_flags_t flags)
+{
+ return bf_ziv_rounding(r, y, prec, flags, bf_atan2_internal, (void *)x);
+}
+
+static int bf_asin_internal(bf_t *r, const bf_t *a, limb_t prec, void *opaque)
+{
+ bf_context_t *s = r->ctx;
+ BOOL is_acos = (BOOL)(intptr_t)opaque;
+ bf_t T_s, *T = &T_s;
+ limb_t prec1, prec2;
+
+ /* asin(x) = atan(x/sqrt(1-x^2))
+ acos(x) = pi/2 - asin(x) */
+ prec1 = prec + 8;
+ /* increase the precision in x^2 to compensate the cancellation in
+ (1-x^2) if x is close to 1 */
+ /* XXX: use less precision when possible */
+ if (a->expn >= 0)
+ prec2 = BF_PREC_INF;
+ else
+ prec2 = prec1;
+ bf_init(s, T);
+ bf_mul(T, a, a, prec2, BF_RNDN);
+ bf_neg(T);
+ bf_add_si(T, T, 1, prec2, BF_RNDN);
+
+ bf_sqrt(r, T, prec1, BF_RNDN);
+ bf_div(T, a, r, prec1, BF_RNDN);
+ if (is_acos)
+ bf_neg(T);
+ bf_atan_internal(r, T, prec1, (void *)(intptr_t)is_acos);
+ bf_delete(T);
+ return BF_ST_INEXACT;
+}
+
+int bf_asin(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags)
+{
+ bf_context_t *s = r->ctx;
+ bf_t T_s, *T = &T_s;
+ int res;
+
+ if (a->len == 0) {
+ if (a->expn == BF_EXP_NAN) {
+ bf_set_nan(r);
+ return 0;
+ } else if (a->expn == BF_EXP_INF) {
+ bf_set_nan(r);
+ return BF_ST_INVALID_OP;
+ } else {
+ bf_set_zero(r, a->sign);
+ return 0;
+ }
+ }
+ bf_init(s, T);
+ bf_set_ui(T, 1);
+ res = bf_cmpu(a, T);
+ bf_delete(T);
+ if (res > 0) {
+ bf_set_nan(r);
+ return BF_ST_INVALID_OP;
+ }
+
+ /* small argument case: result = x+r(x) with r(x) = x^3/6 +
+ O(X^5). We assume r(x) < 2^(3*EXP(x) - 2). */
+ if (a->expn < 0) {
+ slimb_t e;
+ e = sat_add(2 * a->expn, a->expn - 2);
+ if (e < a->expn - bf_max(prec + 2, a->len * LIMB_BITS + 2)) {
+ bf_set(r, a);
+ return bf_add_epsilon(r, r, e, a->sign, prec, flags);
+ }
+ }
+
+ return bf_ziv_rounding(r, a, prec, flags, bf_asin_internal, (void *)FALSE);
+}
+
+int bf_acos(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags)
+{
+ bf_context_t *s = r->ctx;
+ bf_t T_s, *T = &T_s;
+ int res;
+
+ if (a->len == 0) {
+ if (a->expn == BF_EXP_NAN) {
+ bf_set_nan(r);
+ return 0;
+ } else if (a->expn == BF_EXP_INF) {
+ bf_set_nan(r);
+ return BF_ST_INVALID_OP;
+ } else {
+ bf_const_pi(r, prec, flags);
+ bf_mul_2exp(r, -1, BF_PREC_INF, BF_RNDZ);
+ return BF_ST_INEXACT;
+ }
+ }
+ bf_init(s, T);
+ bf_set_ui(T, 1);
+ res = bf_cmpu(a, T);
+ bf_delete(T);
+ if (res > 0) {
+ bf_set_nan(r);
+ return BF_ST_INVALID_OP;
+ } else if (res == 0 && a->sign == 0) {
+ bf_set_zero(r, 0);
+ return 0;
+ }
+
+ return bf_ziv_rounding(r, a, prec, flags, bf_asin_internal, (void *)TRUE);
+}
+
+/***************************************************************/
+/* decimal floating point numbers */
+
+#ifdef USE_BF_DEC
+
+#define adddq(r1, r0, a1, a0) \
+ do { \
+ limb_t __t = r0; \
+ r0 += (a0); \
+ r1 += (a1) + (r0 < __t); \
+ } while (0)
+
+#define subdq(r1, r0, a1, a0) \
+ do { \
+ limb_t __t = r0; \
+ r0 -= (a0); \
+ r1 -= (a1) + (r0 > __t); \
+ } while (0)
+
+#if LIMB_BITS == 64
+
+/* Note: we assume __int128 is available */
+#define muldq(r1, r0, a, b) \
+ do { \
+ unsigned __int128 __t; \
+ __t = (unsigned __int128)(a) * (unsigned __int128)(b); \
+ r0 = __t; \
+ r1 = __t >> 64; \
+ } while (0)
+
+#define divdq(q, r, a1, a0, b) \
+ do { \
+ unsigned __int128 __t; \
+ limb_t __b = (b); \
+ __t = ((unsigned __int128)(a1) << 64) | (a0); \
+ q = __t / __b; \
+ r = __t % __b; \
+ } while (0)
+
+#else
+
+#define muldq(r1, r0, a, b) \
+ do { \
+ uint64_t __t; \
+ __t = (uint64_t)(a) * (uint64_t)(b); \
+ r0 = __t; \
+ r1 = __t >> 32; \
+ } while (0)
+
+#define divdq(q, r, a1, a0, b) \
+ do { \
+ uint64_t __t; \
+ limb_t __b = (b); \
+ __t = ((uint64_t)(a1) << 32) | (a0); \
+ q = __t / __b; \
+ r = __t % __b; \
+ } while (0)
+
+#endif /* LIMB_BITS != 64 */
+
+#if LIMB_DIGITS == 19
+
+/* WARNING: hardcoded for b = 1e19. It is assumed that:
+ 0 <= a1 < 2^63 */
+#define divdq_base(q, r, a1, a0)\
+do {\
+ uint64_t __a0, __a1, __t0, __t1, __b = BF_DEC_BASE; \
+ __a0 = a0;\
+ __a1 = a1;\
+ __t0 = __a1;\
+ __t0 = shld(__t0, __a0, 1);\
+ muldq(q, __t1, __t0, UINT64_C(17014118346046923173)); \
+ muldq(__t1, __t0, q, __b);\
+ subdq(__a1, __a0, __t1, __t0);\
+ subdq(__a1, __a0, 1, __b * 2); \
+ __t0 = (slimb_t)__a1 >> 1; \
+ q += 2 + __t0;\
+ adddq(__a1, __a0, 0, __b & __t0);\
+ q += __a1; \
+ __a0 += __b & __a1; \
+ r = __a0;\
+} while(0)
+
+#elif LIMB_DIGITS == 9
+
+/* WARNING: hardcoded for b = 1e9. It is assumed that:
+ 0 <= a1 < 2^29 */
+#define divdq_base(q, r, a1, a0)\
+do {\
+ uint32_t __t0, __t1, __b = BF_DEC_BASE; \
+ __t0 = a1;\
+ __t1 = a0;\
+ __t0 = (__t0 << 3) | (__t1 >> (32 - 3)); \
+ muldq(q, __t1, __t0, 2305843009U);\
+ r = a0 - q * __b;\
+ __t1 = (r >= __b);\
+ q += __t1;\
+ if (__t1)\
+ r -= __b;\
+} while(0)
+
+#endif
+
+/* fast integer division by a fixed constant */
+
+typedef struct FastDivData {
+ limb_t m1; /* multiplier */
+ int8_t shift1;
+ int8_t shift2;
+} FastDivData;
+
+/* From "Division by Invariant Integers using Multiplication" by
+ Torborn Granlund and Peter L. Montgomery */
+/* d must be != 0 */
+static inline __maybe_unused void fast_udiv_init(FastDivData *s, limb_t d)
+{
+ int l;
+ limb_t q, r, m1;
+ if (d == 1)
+ l = 0;
+ else
+ l = 64 - clz64(d - 1);
+ divdq(q, r, ((limb_t)1 << l) - d, 0, d);
+ (void)r;
+ m1 = q + 1;
+ // printf("d=%lu l=%d m1=0x%016lx\n", d, l, m1);
+ s->m1 = m1;
+ s->shift1 = l;
+ if (s->shift1 > 1)
+ s->shift1 = 1;
+ s->shift2 = l - 1;
+ if (s->shift2 < 0)
+ s->shift2 = 0;
+}
+
+static inline limb_t fast_udiv(limb_t a, const FastDivData *s)
+{
+ limb_t t0, t1;
+ muldq(t1, t0, s->m1, a);
+ t0 = (a - t1) >> s->shift1;
+ return (t1 + t0) >> s->shift2;
+}
+
+#endif // USE_BF_DEC
+/* contains 10^i */
+const limb_t mp_pow_dec[LIMB_DIGITS + 1] = {
+ 1U,
+ 10U,
+ 100U,
+ 1000U,
+ 10000U,
+ 100000U,
+ 1000000U,
+ 10000000U,
+ 100000000U,
+ 1000000000U,
+#if LIMB_BITS == 64
+ 10000000000U,
+ 100000000000U,
+ 1000000000000U,
+ 10000000000000U,
+ 100000000000000U,
+ 1000000000000000U,
+ 10000000000000000U,
+ 100000000000000000U,
+ 1000000000000000000U,
+ 10000000000000000000U,
+#endif
+};
+#ifdef USE_BF_DEC
+
+/* precomputed from fast_udiv_init(10^i) */
+static const FastDivData mp_pow_div[LIMB_DIGITS + 1] = {
+#if LIMB_BITS == 32
+ { 0x00000001, 0, 0 },
+ { 0x9999999a, 1, 3 },
+ { 0x47ae147b, 1, 6 },
+ { 0x0624dd30, 1, 9 },
+ { 0xa36e2eb2, 1, 13 },
+ { 0x4f8b588f, 1, 16 },
+ { 0x0c6f7a0c, 1, 19 },
+ { 0xad7f29ac, 1, 23 },
+ { 0x5798ee24, 1, 26 },
+ { 0x12e0be83, 1, 29 },
+#else
+ { 0x0000000000000001, 0, 0 },
+ { 0x999999999999999a, 1, 3 },
+ { 0x47ae147ae147ae15, 1, 6 },
+ { 0x0624dd2f1a9fbe77, 1, 9 },
+ { 0xa36e2eb1c432ca58, 1, 13 },
+ { 0x4f8b588e368f0847, 1, 16 },
+ { 0x0c6f7a0b5ed8d36c, 1, 19 },
+ { 0xad7f29abcaf48579, 1, 23 },
+ { 0x5798ee2308c39dfa, 1, 26 },
+ { 0x12e0be826d694b2f, 1, 29 },
+ { 0xb7cdfd9d7bdbab7e, 1, 33 },
+ { 0x5fd7fe17964955fe, 1, 36 },
+ { 0x19799812dea11198, 1, 39 },
+ { 0xc25c268497681c27, 1, 43 },
+ { 0x6849b86a12b9b01f, 1, 46 },
+ { 0x203af9ee756159b3, 1, 49 },
+ { 0xcd2b297d889bc2b7, 1, 53 },
+ { 0x70ef54646d496893, 1, 56 },
+ { 0x2725dd1d243aba0f, 1, 59 },
+ { 0xd83c94fb6d2ac34d, 1, 63 },
+#endif
+};
+
+/* divide by 10^shift with 0 <= shift <= LIMB_DIGITS */
+static inline limb_t fast_shr_dec(limb_t a, int shift)
+{
+ return fast_udiv(a, &mp_pow_div[shift]);
+}
+
+/* division and remainder by 10^shift */
+#define fast_shr_rem_dec(q, r, a, shift) q = fast_shr_dec(a, shift), r = a - q * mp_pow_dec[shift]
+
+limb_t mp_add_dec(limb_t *res, const limb_t *op1, const limb_t *op2,
+ mp_size_t n, limb_t carry)
+{
+ limb_t base = BF_DEC_BASE;
+ mp_size_t i;
+ limb_t k, a, v;
+
+ k=carry;
+ for(i=0;i<n;i++) {
+ /* XXX: reuse the trick in add_mod */
+ v = op1[i];
+ a = v + op2[i] + k - base;
+ k = a <= v;
+ if (!k)
+ a += base;
+ res[i]=a;
+ }
+ return k;
+}
+
+limb_t mp_add_ui_dec(limb_t *tab, limb_t b, mp_size_t n)
+{
+ limb_t base = BF_DEC_BASE;
+ mp_size_t i;
+ limb_t k, a, v;
+
+ k=b;
+ for(i=0;i<n;i++) {
+ v = tab[i];
+ a = v + k - base;
+ k = a <= v;
+ if (!k)
+ a += base;
+ tab[i] = a;
+ if (k == 0)
+ break;
+ }
+ return k;
+}
+
+limb_t mp_sub_dec(limb_t *res, const limb_t *op1, const limb_t *op2,
+ mp_size_t n, limb_t carry)
+{
+ limb_t base = BF_DEC_BASE;
+ mp_size_t i;
+ limb_t k, v, a;
+
+ k=carry;
+ for(i=0;i<n;i++) {
+ v = op1[i];
+ a = v - op2[i] - k;
+ k = a > v;
+ if (k)
+ a += base;
+ res[i] = a;
+ }
+ return k;
+}
+
+limb_t mp_sub_ui_dec(limb_t *tab, limb_t b, mp_size_t n)
+{
+ limb_t base = BF_DEC_BASE;
+ mp_size_t i;
+ limb_t k, v, a;
+
+ k=b;
+ for(i=0;i<n;i++) {
+ v = tab[i];
+ a = v - k;
+ k = a > v;
+ if (k)
+ a += base;
+ tab[i]=a;
+ if (k == 0)
+ break;
+ }
+ return k;
+}
+
+/* taba[] = taba[] * b + l. 0 <= b, l <= base - 1. Return the high carry */
+limb_t mp_mul1_dec(limb_t *tabr, const limb_t *taba, mp_size_t n,
+ limb_t b, limb_t l)
+{
+ mp_size_t i;
+ limb_t t0, t1, r;
+
+ for(i = 0; i < n; i++) {
+ muldq(t1, t0, taba[i], b);
+ adddq(t1, t0, 0, l);
+ divdq_base(l, r, t1, t0);
+ tabr[i] = r;
+ }
+ return l;
+}
+
+/* tabr[] += taba[] * b. 0 <= b <= base - 1. Return the value to add
+ to the high word */
+limb_t mp_add_mul1_dec(limb_t *tabr, const limb_t *taba, mp_size_t n,
+ limb_t b)
+{
+ mp_size_t i;
+ limb_t l, t0, t1, r;
+
+ l = 0;
+ for(i = 0; i < n; i++) {
+ muldq(t1, t0, taba[i], b);
+ adddq(t1, t0, 0, l);
+ adddq(t1, t0, 0, tabr[i]);
+ divdq_base(l, r, t1, t0);
+ tabr[i] = r;
+ }
+ return l;
+}
+
+/* tabr[] -= taba[] * b. 0 <= b <= base - 1. Return the value to
+ substract to the high word. */
+limb_t mp_sub_mul1_dec(limb_t *tabr, const limb_t *taba, mp_size_t n,
+ limb_t b)
+{
+ limb_t base = BF_DEC_BASE;
+ mp_size_t i;
+ limb_t l, t0, t1, r, a, v, c;
+
+ /* XXX: optimize */
+ l = 0;
+ for(i = 0; i < n; i++) {
+ muldq(t1, t0, taba[i], b);
+ adddq(t1, t0, 0, l);
+ divdq_base(l, r, t1, t0);
+ v = tabr[i];
+ a = v - r;
+ c = a > v;
+ if (c)
+ a += base;
+ /* never bigger than base because r = 0 when l = base - 1 */
+ l += c;
+ tabr[i] = a;
+ }
+ return l;
+}
+
+/* size of the result : op1_size + op2_size. */
+void mp_mul_basecase_dec(limb_t *result,
+ const limb_t *op1, mp_size_t op1_size,
+ const limb_t *op2, mp_size_t op2_size)
+{
+ mp_size_t i;
+ limb_t r;
+
+ result[op1_size] = mp_mul1_dec(result, op1, op1_size, op2[0], 0);
+
+ for(i=1;i<op2_size;i++) {
+ r = mp_add_mul1_dec(result + i, op1, op1_size, op2[i]);
+ result[i + op1_size] = r;
+ }
+}
+
+/* taba[] = (taba[] + r*base^na) / b. 0 <= b < base. 0 <= r <
+ b. Return the remainder. */
+limb_t mp_div1_dec(limb_t *tabr, const limb_t *taba, mp_size_t na,
+ limb_t b, limb_t r)
+{
+ limb_t base = BF_DEC_BASE;
+ mp_size_t i;
+ limb_t t0, t1, q;
+ int shift;
+
+#if (BF_DEC_BASE % 2) == 0
+ if (b == 2) {
+ limb_t base_div2;
+ /* Note: only works if base is even */
+ base_div2 = base >> 1;
+ if (r)
+ r = base_div2;
+ for(i = na - 1; i >= 0; i--) {
+ t0 = taba[i];
+ tabr[i] = (t0 >> 1) + r;
+ r = 0;
+ if (t0 & 1)
+ r = base_div2;
+ }
+ if (r)
+ r = 1;
+ } else
+#endif
+ if (na >= UDIV1NORM_THRESHOLD) {
+ shift = clz(b);
+ if (shift == 0) {
+ /* normalized case: b >= 2^(LIMB_BITS-1) */
+ limb_t b_inv;
+ b_inv = udiv1norm_init(b);
+ for(i = na - 1; i >= 0; i--) {
+ muldq(t1, t0, r, base);
+ adddq(t1, t0, 0, taba[i]);
+ q = udiv1norm(&r, t1, t0, b, b_inv);
+ tabr[i] = q;
+ }
+ } else {
+ limb_t b_inv;
+ b <<= shift;
+ b_inv = udiv1norm_init(b);
+ for(i = na - 1; i >= 0; i--) {
+ muldq(t1, t0, r, base);
+ adddq(t1, t0, 0, taba[i]);
+ t1 = (t1 << shift) | (t0 >> (LIMB_BITS - shift));
+ t0 <<= shift;
+ q = udiv1norm(&r, t1, t0, b, b_inv);
+ r >>= shift;
+ tabr[i] = q;
+ }
+ }
+ } else {
+ for(i = na - 1; i >= 0; i--) {
+ muldq(t1, t0, r, base);
+ adddq(t1, t0, 0, taba[i]);
+ divdq(q, r, t1, t0, b);
+ tabr[i] = q;
+ }
+ }
+ return r;
+}
+
+static __maybe_unused void mp_print_str_dec(const char *str,
+ const limb_t *tab, slimb_t n)
+{
+ slimb_t i;
+ printf("%s=", str);
+ for(i = n - 1; i >= 0; i--) {
+ if (i != n - 1)
+ printf("_");
+ printf("%0*" PRIu_LIMB, LIMB_DIGITS, tab[i]);
+ }
+ printf("\n");
+}
+
+static __maybe_unused void mp_print_str_h_dec(const char *str,
+ const limb_t *tab, slimb_t n,
+ limb_t high)
+{
+ slimb_t i;
+ printf("%s=", str);
+ printf("%0*" PRIu_LIMB, LIMB_DIGITS, high);
+ for(i = n - 1; i >= 0; i--) {
+ printf("_");
+ printf("%0*" PRIu_LIMB, LIMB_DIGITS, tab[i]);
+ }
+ printf("\n");
+}
+
+//#define DEBUG_DIV_SLOW
+
+#define DIV_STATIC_ALLOC_LEN 16
+
+/* return q = a / b and r = a % b.
+
+ taba[na] must be allocated if tabb1[nb - 1] < B / 2. tabb1[nb - 1]
+ must be != zero. na must be >= nb. 's' can be NULL if tabb1[nb - 1]
+ >= B / 2.
+
+ The remainder is is returned in taba and contains nb libms. tabq
+ contains na - nb + 1 limbs. No overlap is permitted.
+
+ Running time of the standard method: (na - nb + 1) * nb
+ Return 0 if OK, -1 if memory alloc error
+*/
+/* XXX: optimize */
+static int mp_div_dec(bf_context_t *s, limb_t *tabq,
+ limb_t *taba, mp_size_t na,
+ const limb_t *tabb1, mp_size_t nb)
+{
+ limb_t base = BF_DEC_BASE;
+ limb_t r, mult, t0, t1, a, c, q, v, *tabb;
+ mp_size_t i, j;
+ limb_t static_tabb[DIV_STATIC_ALLOC_LEN];
+
+#ifdef DEBUG_DIV_SLOW
+ mp_print_str_dec("a", taba, na);
+ mp_print_str_dec("b", tabb1, nb);
+#endif
+
+ /* normalize tabb */
+ r = tabb1[nb - 1];
+ assert(r != 0);
+ i = na - nb;
+ if (r >= BF_DEC_BASE / 2) {
+ mult = 1;
+ tabb = (limb_t *)tabb1;
+ q = 1;
+ for(j = nb - 1; j >= 0; j--) {
+ if (taba[i + j] != tabb[j]) {
+ if (taba[i + j] < tabb[j])
+ q = 0;
+ break;
+ }
+ }
+ tabq[i] = q;
+ if (q) {
+ mp_sub_dec(taba + i, taba + i, tabb, nb, 0);
+ }
+ i--;
+ } else {
+ mult = base / (r + 1);
+ if (likely(nb <= DIV_STATIC_ALLOC_LEN)) {
+ tabb = static_tabb;
+ } else {
+ tabb = bf_malloc(s, sizeof(limb_t) * nb);
+ if (!tabb)
+ return -1;
+ }
+ mp_mul1_dec(tabb, tabb1, nb, mult, 0);
+ taba[na] = mp_mul1_dec(taba, taba, na, mult, 0);
+ }
+
+#ifdef DEBUG_DIV_SLOW
+ printf("mult=" FMT_LIMB "\n", mult);
+ mp_print_str_dec("a_norm", taba, na + 1);
+ mp_print_str_dec("b_norm", tabb, nb);
+#endif
+
+ for(; i >= 0; i--) {
+ if (unlikely(taba[i + nb] >= tabb[nb - 1])) {
+ /* XXX: check if it is really possible */
+ q = base - 1;
+ } else {
+ muldq(t1, t0, taba[i + nb], base);
+ adddq(t1, t0, 0, taba[i + nb - 1]);
+ divdq(q, r, t1, t0, tabb[nb - 1]);
+ }
+ // printf("i=%d q1=%ld\n", i, q);
+
+ r = mp_sub_mul1_dec(taba + i, tabb, nb, q);
+ // mp_dump("r1", taba + i, nb, bd);
+ // printf("r2=%ld\n", r);
+
+ v = taba[i + nb];
+ a = v - r;
+ c = a > v;
+ if (c)
+ a += base;
+ taba[i + nb] = a;
+
+ if (c != 0) {
+ /* negative result */
+ for(;;) {
+ q--;
+ c = mp_add_dec(taba + i, taba + i, tabb, nb, 0);
+ /* propagate carry and test if positive result */
+ if (c != 0) {
+ if (++taba[i + nb] == base) {
+ break;
+ }
+ }
+ }
+ }
+ tabq[i] = q;
+ }
+
+#ifdef DEBUG_DIV_SLOW
+ mp_print_str_dec("q", tabq, na - nb + 1);
+ mp_print_str_dec("r", taba, nb);
+#endif
+
+ /* remove the normalization */
+ if (mult != 1) {
+ mp_div1_dec(taba, taba, nb, mult, 0);
+ if (unlikely(tabb != static_tabb))
+ bf_free(s, tabb);
+ }
+ return 0;
+}
+
+/* divide by 10^shift */
+static limb_t mp_shr_dec(limb_t *tab_r, const limb_t *tab, mp_size_t n,
+ limb_t shift, limb_t high)
+{
+ mp_size_t i;
+ limb_t l, a, q, r;
+
+ assert(shift >= 1 && shift < LIMB_DIGITS);
+ l = high;
+ for(i = n - 1; i >= 0; i--) {
+ a = tab[i];
+ fast_shr_rem_dec(q, r, a, shift);
+ tab_r[i] = q + l * mp_pow_dec[LIMB_DIGITS - shift];
+ l = r;
+ }
+ return l;
+}
+
+/* multiply by 10^shift */
+static limb_t mp_shl_dec(limb_t *tab_r, const limb_t *tab, mp_size_t n,
+ limb_t shift, limb_t low)
+{
+ mp_size_t i;
+ limb_t l, a, q, r;
+
+ assert(shift >= 1 && shift < LIMB_DIGITS);
+ l = low;
+ for(i = 0; i < n; i++) {
+ a = tab[i];
+ fast_shr_rem_dec(q, r, a, LIMB_DIGITS - shift);
+ tab_r[i] = r * mp_pow_dec[shift] + l;
+ l = q;
+ }
+ return l;
+}
+
+static limb_t mp_sqrtrem2_dec(limb_t *tabs, limb_t *taba)
+{
+ int k;
+ dlimb_t a, b, r;
+ limb_t taba1[2], s, r0, r1;
+
+ /* convert to binary and normalize */
+ a = (dlimb_t)taba[1] * BF_DEC_BASE + taba[0];
+ k = clz(a >> LIMB_BITS) & ~1;
+ b = a << k;
+ taba1[0] = b;
+ taba1[1] = b >> LIMB_BITS;
+ mp_sqrtrem2(&s, taba1);
+ s >>= (k >> 1);
+ /* convert the remainder back to decimal */
+ r = a - (dlimb_t)s * (dlimb_t)s;
+ divdq_base(r1, r0, r >> LIMB_BITS, r);
+ taba[0] = r0;
+ tabs[0] = s;
+ return r1;
+}
+
+//#define DEBUG_SQRTREM_DEC
+
+/* tmp_buf must contain (n / 2 + 1 limbs) */
+static limb_t mp_sqrtrem_rec_dec(limb_t *tabs, limb_t *taba, limb_t n,
+ limb_t *tmp_buf)
+{
+ limb_t l, h, rh, ql, qh, c, i;
+
+ if (n == 1)
+ return mp_sqrtrem2_dec(tabs, taba);
+#ifdef DEBUG_SQRTREM_DEC
+ mp_print_str_dec("a", taba, 2 * n);
+#endif
+ l = n / 2;
+ h = n - l;
+ qh = mp_sqrtrem_rec_dec(tabs + l, taba + 2 * l, h, tmp_buf);
+#ifdef DEBUG_SQRTREM_DEC
+ mp_print_str_dec("s1", tabs + l, h);
+ mp_print_str_h_dec("r1", taba + 2 * l, h, qh);
+ mp_print_str_h_dec("r2", taba + l, n, qh);
+#endif
+
+ /* the remainder is in taba + 2 * l. Its high bit is in qh */
+ if (qh) {
+ mp_sub_dec(taba + 2 * l, taba + 2 * l, tabs + l, h, 0);
+ }
+ /* instead of dividing by 2*s, divide by s (which is normalized)
+ and update q and r */
+ mp_div_dec(NULL, tmp_buf, taba + l, n, tabs + l, h);
+ qh += tmp_buf[l];
+ for(i = 0; i < l; i++)
+ tabs[i] = tmp_buf[i];
+ ql = mp_div1_dec(tabs, tabs, l, 2, qh & 1);
+ qh = qh >> 1; /* 0 or 1 */
+ if (ql)
+ rh = mp_add_dec(taba + l, taba + l, tabs + l, h, 0);
+ else
+ rh = 0;
+#ifdef DEBUG_SQRTREM_DEC
+ mp_print_str_h_dec("q", tabs, l, qh);
+ mp_print_str_h_dec("u", taba + l, h, rh);
+#endif
+
+ mp_add_ui_dec(tabs + l, qh, h);
+#ifdef DEBUG_SQRTREM_DEC
+ mp_print_str_dec("s2", tabs, n);
+#endif
+
+ /* q = qh, tabs[l - 1 ... 0], r = taba[n - 1 ... l] */
+ /* subtract q^2. if qh = 1 then q = B^l, so we can take shortcuts */
+ if (qh) {
+ c = qh;
+ } else {
+ mp_mul_basecase_dec(taba + n, tabs, l, tabs, l);
+ c = mp_sub_dec(taba, taba, taba + n, 2 * l, 0);
+ }
+ rh -= mp_sub_ui_dec(taba + 2 * l, c, n - 2 * l);
+ if ((slimb_t)rh < 0) {
+ mp_sub_ui_dec(tabs, 1, n);
+ rh += mp_add_mul1_dec(taba, tabs, n, 2);
+ rh += mp_add_ui_dec(taba, 1, n);
+ }
+ return rh;
+}
+
+/* 'taba' has 2*n limbs with n >= 1 and taba[2*n-1] >= B/4. Return (s,
+ r) with s=floor(sqrt(a)) and r=a-s^2. 0 <= r <= 2 * s. tabs has n
+ limbs. r is returned in the lower n limbs of taba. Its r[n] is the
+ returned value of the function. */
+int mp_sqrtrem_dec(bf_context_t *s, limb_t *tabs, limb_t *taba, limb_t n)
+{
+ limb_t tmp_buf1[8];
+ limb_t *tmp_buf;
+ mp_size_t n2;
+ n2 = n / 2 + 1;
+ if (n2 <= countof(tmp_buf1)) {
+ tmp_buf = tmp_buf1;
+ } else {
+ tmp_buf = bf_malloc(s, sizeof(limb_t) * n2);
+ if (!tmp_buf)
+ return -1;
+ }
+ taba[n] = mp_sqrtrem_rec_dec(tabs, taba, n, tmp_buf);
+ if (tmp_buf != tmp_buf1)
+ bf_free(s, tmp_buf);
+ return 0;
+}
+
+/* return the number of leading zero digits, from 0 to LIMB_DIGITS */
+static int clz_dec(limb_t a)
+{
+ if (a == 0)
+ return LIMB_DIGITS;
+ switch(LIMB_BITS - 1 - clz(a)) {
+ case 0: /* 1-1 */
+ return LIMB_DIGITS - 1;
+ case 1: /* 2-3 */
+ return LIMB_DIGITS - 1;
+ case 2: /* 4-7 */
+ return LIMB_DIGITS - 1;
+ case 3: /* 8-15 */
+ if (a < 10)
+ return LIMB_DIGITS - 1;
+ else
+ return LIMB_DIGITS - 2;
+ case 4: /* 16-31 */
+ return LIMB_DIGITS - 2;
+ case 5: /* 32-63 */
+ return LIMB_DIGITS - 2;
+ case 6: /* 64-127 */
+ if (a < 100)
+ return LIMB_DIGITS - 2;
+ else
+ return LIMB_DIGITS - 3;
+ case 7: /* 128-255 */
+ return LIMB_DIGITS - 3;
+ case 8: /* 256-511 */
+ return LIMB_DIGITS - 3;
+ case 9: /* 512-1023 */
+ if (a < 1000)
+ return LIMB_DIGITS - 3;
+ else
+ return LIMB_DIGITS - 4;
+ case 10: /* 1024-2047 */
+ return LIMB_DIGITS - 4;
+ case 11: /* 2048-4095 */
+ return LIMB_DIGITS - 4;
+ case 12: /* 4096-8191 */
+ return LIMB_DIGITS - 4;
+ case 13: /* 8192-16383 */
+ if (a < 10000)
+ return LIMB_DIGITS - 4;
+ else
+ return LIMB_DIGITS - 5;
+ case 14: /* 16384-32767 */
+ return LIMB_DIGITS - 5;
+ case 15: /* 32768-65535 */
+ return LIMB_DIGITS - 5;
+ case 16: /* 65536-131071 */
+ if (a < 100000)
+ return LIMB_DIGITS - 5;
+ else
+ return LIMB_DIGITS - 6;
+ case 17: /* 131072-262143 */
+ return LIMB_DIGITS - 6;
+ case 18: /* 262144-524287 */
+ return LIMB_DIGITS - 6;
+ case 19: /* 524288-1048575 */
+ if (a < 1000000)
+ return LIMB_DIGITS - 6;
+ else
+ return LIMB_DIGITS - 7;
+ case 20: /* 1048576-2097151 */
+ return LIMB_DIGITS - 7;
+ case 21: /* 2097152-4194303 */
+ return LIMB_DIGITS - 7;
+ case 22: /* 4194304-8388607 */
+ return LIMB_DIGITS - 7;
+ case 23: /* 8388608-16777215 */
+ if (a < 10000000)
+ return LIMB_DIGITS - 7;
+ else
+ return LIMB_DIGITS - 8;
+ case 24: /* 16777216-33554431 */
+ return LIMB_DIGITS - 8;
+ case 25: /* 33554432-67108863 */
+ return LIMB_DIGITS - 8;
+ case 26: /* 67108864-134217727 */
+ if (a < 100000000)
+ return LIMB_DIGITS - 8;
+ else
+ return LIMB_DIGITS - 9;
+#if LIMB_BITS == 64
+ case 27: /* 134217728-268435455 */
+ return LIMB_DIGITS - 9;
+ case 28: /* 268435456-536870911 */
+ return LIMB_DIGITS - 9;
+ case 29: /* 536870912-1073741823 */
+ if (a < 1000000000)
+ return LIMB_DIGITS - 9;
+ else
+ return LIMB_DIGITS - 10;
+ case 30: /* 1073741824-2147483647 */
+ return LIMB_DIGITS - 10;
+ case 31: /* 2147483648-4294967295 */
+ return LIMB_DIGITS - 10;
+ case 32: /* 4294967296-8589934591 */
+ return LIMB_DIGITS - 10;
+ case 33: /* 8589934592-17179869183 */
+ if (a < 10000000000)
+ return LIMB_DIGITS - 10;
+ else
+ return LIMB_DIGITS - 11;
+ case 34: /* 17179869184-34359738367 */
+ return LIMB_DIGITS - 11;
+ case 35: /* 34359738368-68719476735 */
+ return LIMB_DIGITS - 11;
+ case 36: /* 68719476736-137438953471 */
+ if (a < 100000000000)
+ return LIMB_DIGITS - 11;
+ else
+ return LIMB_DIGITS - 12;
+ case 37: /* 137438953472-274877906943 */
+ return LIMB_DIGITS - 12;
+ case 38: /* 274877906944-549755813887 */
+ return LIMB_DIGITS - 12;
+ case 39: /* 549755813888-1099511627775 */
+ if (a < 1000000000000)
+ return LIMB_DIGITS - 12;
+ else
+ return LIMB_DIGITS - 13;
+ case 40: /* 1099511627776-2199023255551 */
+ return LIMB_DIGITS - 13;
+ case 41: /* 2199023255552-4398046511103 */
+ return LIMB_DIGITS - 13;
+ case 42: /* 4398046511104-8796093022207 */
+ return LIMB_DIGITS - 13;
+ case 43: /* 8796093022208-17592186044415 */
+ if (a < 10000000000000)
+ return LIMB_DIGITS - 13;
+ else
+ return LIMB_DIGITS - 14;
+ case 44: /* 17592186044416-35184372088831 */
+ return LIMB_DIGITS - 14;
+ case 45: /* 35184372088832-70368744177663 */
+ return LIMB_DIGITS - 14;
+ case 46: /* 70368744177664-140737488355327 */
+ if (a < 100000000000000)
+ return LIMB_DIGITS - 14;
+ else
+ return LIMB_DIGITS - 15;
+ case 47: /* 140737488355328-281474976710655 */
+ return LIMB_DIGITS - 15;
+ case 48: /* 281474976710656-562949953421311 */
+ return LIMB_DIGITS - 15;
+ case 49: /* 562949953421312-1125899906842623 */
+ if (a < 1000000000000000)
+ return LIMB_DIGITS - 15;
+ else
+ return LIMB_DIGITS - 16;
+ case 50: /* 1125899906842624-2251799813685247 */
+ return LIMB_DIGITS - 16;
+ case 51: /* 2251799813685248-4503599627370495 */
+ return LIMB_DIGITS - 16;
+ case 52: /* 4503599627370496-9007199254740991 */
+ return LIMB_DIGITS - 16;
+ case 53: /* 9007199254740992-18014398509481983 */
+ if (a < 10000000000000000)
+ return LIMB_DIGITS - 16;
+ else
+ return LIMB_DIGITS - 17;
+ case 54: /* 18014398509481984-36028797018963967 */
+ return LIMB_DIGITS - 17;
+ case 55: /* 36028797018963968-72057594037927935 */
+ return LIMB_DIGITS - 17;
+ case 56: /* 72057594037927936-144115188075855871 */
+ if (a < 100000000000000000)
+ return LIMB_DIGITS - 17;
+ else
+ return LIMB_DIGITS - 18;
+ case 57: /* 144115188075855872-288230376151711743 */
+ return LIMB_DIGITS - 18;
+ case 58: /* 288230376151711744-576460752303423487 */
+ return LIMB_DIGITS - 18;
+ case 59: /* 576460752303423488-1152921504606846975 */
+ if (a < 1000000000000000000)
+ return LIMB_DIGITS - 18;
+ else
+ return LIMB_DIGITS - 19;
+#endif
+ default:
+ return 0;
+ }
+}
+
+/* for debugging */
+void bfdec_print_str(const char *str, const bfdec_t *a)
+{
+ slimb_t i;
+ printf("%s=", str);
+
+ if (a->expn == BF_EXP_NAN) {
+ printf("NaN");
+ } else {
+ if (a->sign)
+ putchar('-');
+ if (a->expn == BF_EXP_ZERO) {
+ putchar('0');
+ } else if (a->expn == BF_EXP_INF) {
+ printf("Inf");
+ } else {
+ printf("0.");
+ for(i = a->len - 1; i >= 0; i--)
+ printf("%0*" PRIu_LIMB, LIMB_DIGITS, a->tab[i]);
+ printf("e%" PRId_LIMB, a->expn);
+ }
+ }
+ printf("\n");
+}
+
+/* return != 0 if one digit between 0 and bit_pos inclusive is not zero. */
+static inline limb_t scan_digit_nz(const bfdec_t *r, slimb_t bit_pos)
+{
+ slimb_t pos;
+ limb_t v, q;
+ int shift;
+
+ if (bit_pos < 0)
+ return 0;
+ pos = (limb_t)bit_pos / LIMB_DIGITS;
+ shift = (limb_t)bit_pos % LIMB_DIGITS;
+ fast_shr_rem_dec(q, v, r->tab[pos], shift + 1);
+ (void)q;
+ if (v != 0)
+ return 1;
+ pos--;
+ while (pos >= 0) {
+ if (r->tab[pos] != 0)
+ return 1;
+ pos--;
+ }
+ return 0;
+}
+
+static limb_t get_digit(const limb_t *tab, limb_t len, slimb_t pos)
+{
+ slimb_t i;
+ int shift;
+ i = floor_div(pos, LIMB_DIGITS);
+ if (i < 0 || i >= len)
+ return 0;
+ shift = pos - i * LIMB_DIGITS;
+ return fast_shr_dec(tab[i], shift) % 10;
+}
+
+#if 0
+static limb_t get_digits(const limb_t *tab, limb_t len, slimb_t pos)
+{
+ limb_t a0, a1;
+ int shift;
+ slimb_t i;
+
+ i = floor_div(pos, LIMB_DIGITS);
+ shift = pos - i * LIMB_DIGITS;
+ if (i >= 0 && i < len)
+ a0 = tab[i];
+ else
+ a0 = 0;
+ if (shift == 0) {
+ return a0;
+ } else {
+ i++;
+ if (i >= 0 && i < len)
+ a1 = tab[i];
+ else
+ a1 = 0;
+ return fast_shr_dec(a0, shift) +
+ fast_urem(a1, &mp_pow_div[LIMB_DIGITS - shift]) *
+ mp_pow_dec[shift];
+ }
+}
+#endif
+
+/* return the addend for rounding. Note that prec can be <= 0 for bf_rint() */
+static int bfdec_get_rnd_add(int *pret, const bfdec_t *r, limb_t l,
+ slimb_t prec, int rnd_mode)
+{
+ int add_one, inexact;
+ limb_t digit1, digit0;
+
+ // bfdec_print_str("get_rnd_add", r);
+ if (rnd_mode == BF_RNDF) {
+ digit0 = 1; /* faithful rounding does not honor the INEXACT flag */
+ } else {
+ /* starting limb for bit 'prec + 1' */
+ digit0 = scan_digit_nz(r, l * LIMB_DIGITS - 1 - bf_max(0, prec + 1));
+ }
+
+ /* get the digit at 'prec' */
+ digit1 = get_digit(r->tab, l, l * LIMB_DIGITS - 1 - prec);
+ inexact = (digit1 | digit0) != 0;
+
+ add_one = 0;
+ switch(rnd_mode) {
+ case BF_RNDZ:
+ break;
+ case BF_RNDN:
+ if (digit1 == 5) {
+ if (digit0) {
+ add_one = 1;
+ } else {
+ /* round to even */
+ add_one =
+ get_digit(r->tab, l, l * LIMB_DIGITS - 1 - (prec - 1)) & 1;
+ }
+ } else if (digit1 > 5) {
+ add_one = 1;
+ }
+ break;
+ case BF_RNDD:
+ case BF_RNDU:
+ if (r->sign == (rnd_mode == BF_RNDD))
+ add_one = inexact;
+ break;
+ case BF_RNDNA:
+ case BF_RNDF:
+ add_one = (digit1 >= 5);
+ break;
+ case BF_RNDA:
+ add_one = inexact;
+ break;
+ default:
+ abort();
+ }
+
+ if (inexact)
+ *pret |= BF_ST_INEXACT;
+ return add_one;
+}
+
+/* round to prec1 bits assuming 'r' is non zero and finite. 'r' is
+ assumed to have length 'l' (1 <= l <= r->len). prec1 can be
+ BF_PREC_INF. BF_FLAG_SUBNORMAL is not supported. Cannot fail with
+ BF_ST_MEM_ERROR.
+ */
+static int __bfdec_round(bfdec_t *r, limb_t prec1, bf_flags_t flags, limb_t l)
+{
+ int shift, add_one, rnd_mode, ret;
+ slimb_t i, bit_pos, pos, e_min, e_max, e_range, prec;
+
+ /* XXX: align to IEEE 754 2008 for decimal numbers ? */
+ e_range = (limb_t)1 << (bf_get_exp_bits(flags) - 1);
+ e_min = -e_range + 3;
+ e_max = e_range;
+
+ if (flags & BF_FLAG_RADPNT_PREC) {
+ /* 'prec' is the precision after the decimal point */
+ if (prec1 != BF_PREC_INF)
+ prec = r->expn + prec1;
+ else
+ prec = prec1;
+ } else if (unlikely(r->expn < e_min) && (flags & BF_FLAG_SUBNORMAL)) {
+ /* restrict the precision in case of potentially subnormal
+ result */
+ assert(prec1 != BF_PREC_INF);
+ prec = prec1 - (e_min - r->expn);
+ } else {
+ prec = prec1;
+ }
+
+ /* round to prec bits */
+ rnd_mode = flags & BF_RND_MASK;
+ ret = 0;
+ add_one = bfdec_get_rnd_add(&ret, r, l, prec, rnd_mode);
+
+ if (prec <= 0) {
+ if (add_one) {
+ bfdec_resize(r, 1); /* cannot fail because r is non zero */
+ r->tab[0] = BF_DEC_BASE / 10;
+ r->expn += 1 - prec;
+ ret |= BF_ST_UNDERFLOW | BF_ST_INEXACT;
+ return ret;
+ } else {
+ goto underflow;
+ }
+ } else if (add_one) {
+ limb_t carry;
+
+ /* add one starting at digit 'prec - 1' */
+ bit_pos = l * LIMB_DIGITS - 1 - (prec - 1);
+ pos = bit_pos / LIMB_DIGITS;
+ carry = mp_pow_dec[bit_pos % LIMB_DIGITS];
+ carry = mp_add_ui_dec(r->tab + pos, carry, l - pos);
+ if (carry) {
+ /* shift right by one digit */
+ mp_shr_dec(r->tab + pos, r->tab + pos, l - pos, 1, 1);
+ r->expn++;
+ }
+ }
+
+ /* check underflow */
+ if (unlikely(r->expn < e_min)) {
+ if (flags & BF_FLAG_SUBNORMAL) {
+ /* if inexact, also set the underflow flag */
+ if (ret & BF_ST_INEXACT)
+ ret |= BF_ST_UNDERFLOW;
+ } else {
+ underflow:
+ bfdec_set_zero(r, r->sign);
+ ret |= BF_ST_UNDERFLOW | BF_ST_INEXACT;
+ return ret;
+ }
+ }
+
+ /* check overflow */
+ if (unlikely(r->expn > e_max)) {
+ bfdec_set_inf(r, r->sign);
+ ret |= BF_ST_OVERFLOW | BF_ST_INEXACT;
+ return ret;
+ }
+
+ /* keep the bits starting at 'prec - 1' */
+ bit_pos = l * LIMB_DIGITS - 1 - (prec - 1);
+ i = floor_div(bit_pos, LIMB_DIGITS);
+ if (i >= 0) {
+ shift = smod(bit_pos, LIMB_DIGITS);
+ if (shift != 0) {
+ r->tab[i] = fast_shr_dec(r->tab[i], shift) *
+ mp_pow_dec[shift];
+ }
+ } else {
+ i = 0;
+ }
+ /* remove trailing zeros */
+ while (r->tab[i] == 0)
+ i++;
+ if (i > 0) {
+ l -= i;
+ memmove(r->tab, r->tab + i, l * sizeof(limb_t));
+ }
+ bfdec_resize(r, l); /* cannot fail */
+ return ret;
+}
+
+/* Cannot fail with BF_ST_MEM_ERROR. */
+int bfdec_round(bfdec_t *r, limb_t prec, bf_flags_t flags)
+{
+ if (r->len == 0)
+ return 0;
+ return __bfdec_round(r, prec, flags, r->len);
+}
+
+/* 'r' must be a finite number. Cannot fail with BF_ST_MEM_ERROR. */
+int bfdec_normalize_and_round(bfdec_t *r, limb_t prec1, bf_flags_t flags)
+{
+ limb_t l, v;
+ int shift, ret;
+
+ // bfdec_print_str("bf_renorm", r);
+ l = r->len;
+ while (l > 0 && r->tab[l - 1] == 0)
+ l--;
+ if (l == 0) {
+ /* zero */
+ r->expn = BF_EXP_ZERO;
+ bfdec_resize(r, 0); /* cannot fail */
+ ret = 0;
+ } else {
+ r->expn -= (r->len - l) * LIMB_DIGITS;
+ /* shift to have the MSB set to '1' */
+ v = r->tab[l - 1];
+ shift = clz_dec(v);
+ if (shift != 0) {
+ mp_shl_dec(r->tab, r->tab, l, shift, 0);
+ r->expn -= shift;
+ }
+ ret = __bfdec_round(r, prec1, flags, l);
+ }
+ // bf_print_str("r_final", r);
+ return ret;
+}
+
+int bfdec_set_ui(bfdec_t *r, uint64_t v)
+{
+#if LIMB_BITS == 32
+ if (v >= BF_DEC_BASE * BF_DEC_BASE) {
+ if (bfdec_resize(r, 3))
+ goto fail;
+ r->tab[0] = v % BF_DEC_BASE;
+ v /= BF_DEC_BASE;
+ r->tab[1] = v % BF_DEC_BASE;
+ r->tab[2] = v / BF_DEC_BASE;
+ r->expn = 3 * LIMB_DIGITS;
+ } else
+#endif
+ if (v >= BF_DEC_BASE) {
+ if (bfdec_resize(r, 2))
+ goto fail;
+ r->tab[0] = v % BF_DEC_BASE;
+ r->tab[1] = v / BF_DEC_BASE;
+ r->expn = 2 * LIMB_DIGITS;
+ } else {
+ if (bfdec_resize(r, 1))
+ goto fail;
+ r->tab[0] = v;
+ r->expn = LIMB_DIGITS;
+ }
+ r->sign = 0;
+ return bfdec_normalize_and_round(r, BF_PREC_INF, 0);
+ fail:
+ bfdec_set_nan(r);
+ return BF_ST_MEM_ERROR;
+}
+
+int bfdec_set_si(bfdec_t *r, int64_t v)
+{
+ int ret;
+ if (v < 0) {
+ ret = bfdec_set_ui(r, -v);
+ r->sign = 1;
+ } else {
+ ret = bfdec_set_ui(r, v);
+ }
+ return ret;
+}
+
+static int bfdec_add_internal(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec, bf_flags_t flags, int b_neg)
+{
+ bf_context_t *s = r->ctx;
+ int is_sub, cmp_res, a_sign, b_sign, ret;
+
+ a_sign = a->sign;
+ b_sign = b->sign ^ b_neg;
+ is_sub = a_sign ^ b_sign;
+ cmp_res = bfdec_cmpu(a, b);
+ if (cmp_res < 0) {
+ const bfdec_t *tmp;
+ tmp = a;
+ a = b;
+ b = tmp;
+ a_sign = b_sign; /* b_sign is never used later */
+ }
+ /* abs(a) >= abs(b) */
+ if (cmp_res == 0 && is_sub && a->expn < BF_EXP_INF) {
+ /* zero result */
+ bfdec_set_zero(r, (flags & BF_RND_MASK) == BF_RNDD);
+ ret = 0;
+ } else if (a->len == 0 || b->len == 0) {
+ ret = 0;
+ if (a->expn >= BF_EXP_INF) {
+ if (a->expn == BF_EXP_NAN) {
+ /* at least one operand is NaN */
+ bfdec_set_nan(r);
+ ret = 0;
+ } else if (b->expn == BF_EXP_INF && is_sub) {
+ /* infinities with different signs */
+ bfdec_set_nan(r);
+ ret = BF_ST_INVALID_OP;
+ } else {
+ bfdec_set_inf(r, a_sign);
+ }
+ } else {
+ /* at least one zero and not subtract */
+ if (bfdec_set(r, a))
+ return BF_ST_MEM_ERROR;
+ r->sign = a_sign;
+ goto renorm;
+ }
+ } else {
+ slimb_t d, a_offset, b_offset, i, r_len;
+ limb_t carry;
+ limb_t *b1_tab;
+ int b_shift;
+ mp_size_t b1_len;
+
+ d = a->expn - b->expn;
+
+ /* XXX: not efficient in time and memory if the precision is
+ not infinite */
+ r_len = bf_max(a->len, b->len + (d + LIMB_DIGITS - 1) / LIMB_DIGITS);
+ if (bfdec_resize(r, r_len))
+ goto fail;
+ r->sign = a_sign;
+ r->expn = a->expn;
+
+ a_offset = r_len - a->len;
+ for(i = 0; i < a_offset; i++)
+ r->tab[i] = 0;
+ for(i = 0; i < a->len; i++)
+ r->tab[a_offset + i] = a->tab[i];
+
+ b_shift = d % LIMB_DIGITS;
+ if (b_shift == 0) {
+ b1_len = b->len;
+ b1_tab = (limb_t *)b->tab;
+ } else {
+ b1_len = b->len + 1;
+ b1_tab = bf_malloc(s, sizeof(limb_t) * b1_len);
+ if (!b1_tab)
+ goto fail;
+ b1_tab[0] = mp_shr_dec(b1_tab + 1, b->tab, b->len, b_shift, 0) *
+ mp_pow_dec[LIMB_DIGITS - b_shift];
+ }
+ b_offset = r_len - (b->len + (d + LIMB_DIGITS - 1) / LIMB_DIGITS);
+
+ if (is_sub) {
+ carry = mp_sub_dec(r->tab + b_offset, r->tab + b_offset,
+ b1_tab, b1_len, 0);
+ if (carry != 0) {
+ carry = mp_sub_ui_dec(r->tab + b_offset + b1_len, carry,
+ r_len - (b_offset + b1_len));
+ assert(carry == 0);
+ }
+ } else {
+ carry = mp_add_dec(r->tab + b_offset, r->tab + b_offset,
+ b1_tab, b1_len, 0);
+ if (carry != 0) {
+ carry = mp_add_ui_dec(r->tab + b_offset + b1_len, carry,
+ r_len - (b_offset + b1_len));
+ }
+ if (carry != 0) {
+ if (bfdec_resize(r, r_len + 1)) {
+ if (b_shift != 0)
+ bf_free(s, b1_tab);
+ goto fail;
+ }
+ r->tab[r_len] = 1;
+ r->expn += LIMB_DIGITS;
+ }
+ }
+ if (b_shift != 0)
+ bf_free(s, b1_tab);
+ renorm:
+ ret = bfdec_normalize_and_round(r, prec, flags);
+ }
+ return ret;
+ fail:
+ bfdec_set_nan(r);
+ return BF_ST_MEM_ERROR;
+}
+
+static int __bfdec_add(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
+ bf_flags_t flags)
+{
+ return bfdec_add_internal(r, a, b, prec, flags, 0);
+}
+
+static int __bfdec_sub(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
+ bf_flags_t flags)
+{
+ return bfdec_add_internal(r, a, b, prec, flags, 1);
+}
+
+int bfdec_add(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
+ bf_flags_t flags)
+{
+ return bf_op2((bf_t *)r, (bf_t *)a, (bf_t *)b, prec, flags,
+ (bf_op2_func_t *)__bfdec_add);
+}
+
+int bfdec_sub(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
+ bf_flags_t flags)
+{
+ return bf_op2((bf_t *)r, (bf_t *)a, (bf_t *)b, prec, flags,
+ (bf_op2_func_t *)__bfdec_sub);
+}
+
+int bfdec_mul(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
+ bf_flags_t flags)
+{
+ int ret, r_sign;
+
+ if (a->len < b->len) {
+ const bfdec_t *tmp = a;
+ a = b;
+ b = tmp;
+ }
+ r_sign = a->sign ^ b->sign;
+ /* here b->len <= a->len */
+ if (b->len == 0) {
+ if (a->expn == BF_EXP_NAN || b->expn == BF_EXP_NAN) {
+ bfdec_set_nan(r);
+ ret = 0;
+ } else if (a->expn == BF_EXP_INF || b->expn == BF_EXP_INF) {
+ if ((a->expn == BF_EXP_INF && b->expn == BF_EXP_ZERO) ||
+ (a->expn == BF_EXP_ZERO && b->expn == BF_EXP_INF)) {
+ bfdec_set_nan(r);
+ ret = BF_ST_INVALID_OP;
+ } else {
+ bfdec_set_inf(r, r_sign);
+ ret = 0;
+ }
+ } else {
+ bfdec_set_zero(r, r_sign);
+ ret = 0;
+ }
+ } else {
+ bfdec_t tmp, *r1 = NULL;
+ limb_t a_len, b_len;
+ limb_t *a_tab, *b_tab;
+
+ a_len = a->len;
+ b_len = b->len;
+ a_tab = a->tab;
+ b_tab = b->tab;
+
+ if (r == a || r == b) {
+ bfdec_init(r->ctx, &tmp);
+ r1 = r;
+ r = &tmp;
+ }
+ if (bfdec_resize(r, a_len + b_len)) {
+ bfdec_set_nan(r);
+ ret = BF_ST_MEM_ERROR;
+ goto done;
+ }
+ mp_mul_basecase_dec(r->tab, a_tab, a_len, b_tab, b_len);
+ r->sign = r_sign;
+ r->expn = a->expn + b->expn;
+ ret = bfdec_normalize_and_round(r, prec, flags);
+ done:
+ if (r == &tmp)
+ bfdec_move(r1, &tmp);
+ }
+ return ret;
+}
+
+int bfdec_mul_si(bfdec_t *r, const bfdec_t *a, int64_t b1, limb_t prec,
+ bf_flags_t flags)
+{
+ bfdec_t b;
+ int ret;
+ bfdec_init(r->ctx, &b);
+ ret = bfdec_set_si(&b, b1);
+ ret |= bfdec_mul(r, a, &b, prec, flags);
+ bfdec_delete(&b);
+ return ret;
+}
+
+int bfdec_add_si(bfdec_t *r, const bfdec_t *a, int64_t b1, limb_t prec,
+ bf_flags_t flags)
+{
+ bfdec_t b;
+ int ret;
+
+ bfdec_init(r->ctx, &b);
+ ret = bfdec_set_si(&b, b1);
+ ret |= bfdec_add(r, a, &b, prec, flags);
+ bfdec_delete(&b);
+ return ret;
+}
+
+static int __bfdec_div(bfdec_t *r, const bfdec_t *a, const bfdec_t *b,
+ limb_t prec, bf_flags_t flags)
+{
+ int ret, r_sign;
+ limb_t n, nb, precl;
+
+ r_sign = a->sign ^ b->sign;
+ if (a->expn >= BF_EXP_INF || b->expn >= BF_EXP_INF) {
+ if (a->expn == BF_EXP_NAN || b->expn == BF_EXP_NAN) {
+ bfdec_set_nan(r);
+ return 0;
+ } else if (a->expn == BF_EXP_INF && b->expn == BF_EXP_INF) {
+ bfdec_set_nan(r);
+ return BF_ST_INVALID_OP;
+ } else if (a->expn == BF_EXP_INF) {
+ bfdec_set_inf(r, r_sign);
+ return 0;
+ } else {
+ bfdec_set_zero(r, r_sign);
+ return 0;
+ }
+ } else if (a->expn == BF_EXP_ZERO) {
+ if (b->expn == BF_EXP_ZERO) {
+ bfdec_set_nan(r);
+ return BF_ST_INVALID_OP;
+ } else {
+ bfdec_set_zero(r, r_sign);
+ return 0;
+ }
+ } else if (b->expn == BF_EXP_ZERO) {
+ bfdec_set_inf(r, r_sign);
+ return BF_ST_DIVIDE_ZERO;
+ }
+
+ nb = b->len;
+ if (prec == BF_PREC_INF) {
+ /* infinite precision: return BF_ST_INVALID_OP if not an exact
+ result */
+ /* XXX: check */
+ precl = nb + 1;
+ } else if (flags & BF_FLAG_RADPNT_PREC) {
+ /* number of digits after the decimal point */
+ /* XXX: check (2 extra digits for rounding + 2 digits) */
+ precl = (bf_max(a->expn - b->expn, 0) + 2 +
+ prec + 2 + LIMB_DIGITS - 1) / LIMB_DIGITS;
+ } else {
+ /* number of limbs of the quotient (2 extra digits for rounding) */
+ precl = (prec + 2 + LIMB_DIGITS - 1) / LIMB_DIGITS;
+ }
+ n = bf_max(a->len, precl);
+
+ {
+ limb_t *taba, na, i;
+ slimb_t d;
+
+ na = n + nb;
+ taba = bf_malloc(r->ctx, (na + 1) * sizeof(limb_t));
+ if (!taba)
+ goto fail;
+ d = na - a->len;
+ memset(taba, 0, d * sizeof(limb_t));
+ memcpy(taba + d, a->tab, a->len * sizeof(limb_t));
+ if (bfdec_resize(r, n + 1))
+ goto fail1;
+ if (mp_div_dec(r->ctx, r->tab, taba, na, b->tab, nb)) {
+ fail1:
+ bf_free(r->ctx, taba);
+ goto fail;
+ }
+ /* see if non zero remainder */
+ for(i = 0; i < nb; i++) {
+ if (taba[i] != 0)
+ break;
+ }
+ bf_free(r->ctx, taba);
+ if (i != nb) {
+ if (prec == BF_PREC_INF) {
+ bfdec_set_nan(r);
+ return BF_ST_INVALID_OP;
+ } else {
+ r->tab[0] |= 1;
+ }
+ }
+ r->expn = a->expn - b->expn + LIMB_DIGITS;
+ r->sign = r_sign;
+ ret = bfdec_normalize_and_round(r, prec, flags);
+ }
+ return ret;
+ fail:
+ bfdec_set_nan(r);
+ return BF_ST_MEM_ERROR;
+}
+
+int bfdec_div(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
+ bf_flags_t flags)
+{
+ return bf_op2((bf_t *)r, (bf_t *)a, (bf_t *)b, prec, flags,
+ (bf_op2_func_t *)__bfdec_div);
+}
+
+/* a and b must be finite numbers with a >= 0 and b > 0. 'q' is the
+ integer defined as floor(a/b) and r = a - q * b. */
+static void bfdec_tdivremu(bf_context_t *s, bfdec_t *q, bfdec_t *r,
+ const bfdec_t *a, const bfdec_t *b)
+{
+ if (bfdec_cmpu(a, b) < 0) {
+ bfdec_set_ui(q, 0);
+ bfdec_set(r, a);
+ } else {
+ bfdec_div(q, a, b, 0, BF_RNDZ | BF_FLAG_RADPNT_PREC);
+ bfdec_mul(r, q, b, BF_PREC_INF, BF_RNDZ);
+ bfdec_sub(r, a, r, BF_PREC_INF, BF_RNDZ);
+ }
+}
+
+/* division and remainder.
+
+ rnd_mode is the rounding mode for the quotient. The additional
+ rounding mode BF_RND_EUCLIDIAN is supported.
+
+ 'q' is an integer. 'r' is rounded with prec and flags (prec can be
+ BF_PREC_INF).
+*/
+int bfdec_divrem(bfdec_t *q, bfdec_t *r, const bfdec_t *a, const bfdec_t *b,
+ limb_t prec, bf_flags_t flags, int rnd_mode)
+{
+ bf_context_t *s = q->ctx;
+ bfdec_t a1_s, *a1 = &a1_s;
+ bfdec_t b1_s, *b1 = &b1_s;
+ bfdec_t r1_s, *r1 = &r1_s;
+ int q_sign, res;
+ BOOL is_ceil, is_rndn;
+
+ assert(q != a && q != b);
+ assert(r != a && r != b);
+ assert(q != r);
+
+ if (a->len == 0 || b->len == 0) {
+ bfdec_set_zero(q, 0);
+ if (a->expn == BF_EXP_NAN || b->expn == BF_EXP_NAN) {
+ bfdec_set_nan(r);
+ return 0;
+ } else if (a->expn == BF_EXP_INF || b->expn == BF_EXP_ZERO) {
+ bfdec_set_nan(r);
+ return BF_ST_INVALID_OP;
+ } else {
+ bfdec_set(r, a);
+ return bfdec_round(r, prec, flags);
+ }
+ }
+
+ q_sign = a->sign ^ b->sign;
+ is_rndn = (rnd_mode == BF_RNDN || rnd_mode == BF_RNDNA);
+ switch(rnd_mode) {
+ default:
+ case BF_RNDZ:
+ case BF_RNDN:
+ case BF_RNDNA:
+ is_ceil = FALSE;
+ break;
+ case BF_RNDD:
+ is_ceil = q_sign;
+ break;
+ case BF_RNDU:
+ is_ceil = q_sign ^ 1;
+ break;
+ case BF_RNDA:
+ is_ceil = TRUE;
+ break;
+ case BF_DIVREM_EUCLIDIAN:
+ is_ceil = a->sign;
+ break;
+ }
+
+ a1->expn = a->expn;
+ a1->tab = a->tab;
+ a1->len = a->len;
+ a1->sign = 0;
+
+ b1->expn = b->expn;
+ b1->tab = b->tab;
+ b1->len = b->len;
+ b1->sign = 0;
+
+ // bfdec_print_str("a1", a1);
+ // bfdec_print_str("b1", b1);
+ /* XXX: could improve to avoid having a large 'q' */
+ bfdec_tdivremu(s, q, r, a1, b1);
+ if (bfdec_is_nan(q) || bfdec_is_nan(r))
+ goto fail;
+ // bfdec_print_str("q", q);
+ // bfdec_print_str("r", r);
+
+ if (r->len != 0) {
+ if (is_rndn) {
+ bfdec_init(s, r1);
+ if (bfdec_set(r1, r))
+ goto fail;
+ if (bfdec_mul_si(r1, r1, 2, BF_PREC_INF, BF_RNDZ)) {
+ bfdec_delete(r1);
+ goto fail;
+ }
+ res = bfdec_cmpu(r1, b);
+ bfdec_delete(r1);
+ if (res > 0 ||
+ (res == 0 &&
+ (rnd_mode == BF_RNDNA ||
+ (get_digit(q->tab, q->len, q->len * LIMB_DIGITS - q->expn) & 1) != 0))) {
+ goto do_sub_r;
+ }
+ } else if (is_ceil) {
+ do_sub_r:
+ res = bfdec_add_si(q, q, 1, BF_PREC_INF, BF_RNDZ);
+ res |= bfdec_sub(r, r, b1, BF_PREC_INF, BF_RNDZ);
+ if (res & BF_ST_MEM_ERROR)
+ goto fail;
+ }
+ }
+
+ r->sign ^= a->sign;
+ q->sign = q_sign;
+ return bfdec_round(r, prec, flags);
+ fail:
+ bfdec_set_nan(q);
+ bfdec_set_nan(r);
+ return BF_ST_MEM_ERROR;
+}
+
+int bfdec_rem(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
+ bf_flags_t flags, int rnd_mode)
+{
+ bfdec_t q_s, *q = &q_s;
+ int ret;
+
+ bfdec_init(r->ctx, q);
+ ret = bfdec_divrem(q, r, a, b, prec, flags, rnd_mode);
+ bfdec_delete(q);
+ return ret;
+}
+
+/* convert to integer (infinite precision) */
+int bfdec_rint(bfdec_t *r, int rnd_mode)
+{
+ return bfdec_round(r, 0, rnd_mode | BF_FLAG_RADPNT_PREC);
+}
+
+int bfdec_sqrt(bfdec_t *r, const bfdec_t *a, limb_t prec, bf_flags_t flags)
+{
+ bf_context_t *s = a->ctx;
+ int ret, k;
+ limb_t *a1, v;
+ slimb_t n, n1, prec1;
+ limb_t res;
+
+ assert(r != a);
+
+ if (a->len == 0) {
+ if (a->expn == BF_EXP_NAN) {
+ bfdec_set_nan(r);
+ } else if (a->expn == BF_EXP_INF && a->sign) {
+ goto invalid_op;
+ } else {
+ bfdec_set(r, a);
+ }
+ ret = 0;
+ } else if (a->sign || prec == BF_PREC_INF) {
+ invalid_op:
+ bfdec_set_nan(r);
+ ret = BF_ST_INVALID_OP;
+ } else {
+ if (flags & BF_FLAG_RADPNT_PREC) {
+ prec1 = bf_max(floor_div(a->expn + 1, 2) + prec, 1);
+ } else {
+ prec1 = prec;
+ }
+ /* convert the mantissa to an integer with at least 2 *
+ prec + 4 digits */
+ n = (2 * (prec1 + 2) + 2 * LIMB_DIGITS - 1) / (2 * LIMB_DIGITS);
+ if (bfdec_resize(r, n))
+ goto fail;
+ a1 = bf_malloc(s, sizeof(limb_t) * 2 * n);
+ if (!a1)
+ goto fail;
+ n1 = bf_min(2 * n, a->len);
+ memset(a1, 0, (2 * n - n1) * sizeof(limb_t));
+ memcpy(a1 + 2 * n - n1, a->tab + a->len - n1, n1 * sizeof(limb_t));
+ if (a->expn & 1) {
+ res = mp_shr_dec(a1, a1, 2 * n, 1, 0);
+ } else {
+ res = 0;
+ }
+ /* normalize so that a1 >= B^(2*n)/4. Not need for n = 1
+ because mp_sqrtrem2_dec already does it */
+ k = 0;
+ if (n > 1) {
+ v = a1[2 * n - 1];
+ while (v < BF_DEC_BASE / 4) {
+ k++;
+ v *= 4;
+ }
+ if (k != 0)
+ mp_mul1_dec(a1, a1, 2 * n, 1 << (2 * k), 0);
+ }
+ if (mp_sqrtrem_dec(s, r->tab, a1, n)) {
+ bf_free(s, a1);
+ goto fail;
+ }
+ if (k != 0)
+ mp_div1_dec(r->tab, r->tab, n, 1 << k, 0);
+ if (!res) {
+ res = mp_scan_nz(a1, n + 1);
+ }
+ bf_free(s, a1);
+ if (!res) {
+ res = mp_scan_nz(a->tab, a->len - n1);
+ }
+ if (res != 0)
+ r->tab[0] |= 1;
+ r->sign = 0;
+ r->expn = (a->expn + 1) >> 1;
+ ret = bfdec_round(r, prec, flags);
+ }
+ return ret;
+ fail:
+ bfdec_set_nan(r);
+ return BF_ST_MEM_ERROR;
+}
+
+/* The rounding mode is always BF_RNDZ. Return BF_ST_OVERFLOW if there
+ is an overflow and 0 otherwise. No memory error is possible. */
+int bfdec_get_int32(int *pres, const bfdec_t *a)
+{
+ uint32_t v;
+ int ret;
+ if (a->expn >= BF_EXP_INF) {
+ ret = 0;
+ if (a->expn == BF_EXP_INF) {
+ v = (uint32_t)INT32_MAX + a->sign;
+ /* XXX: return overflow ? */
+ } else {
+ v = INT32_MAX;
+ }
+ } else if (a->expn <= 0) {
+ v = 0;
+ ret = 0;
+ } else if (a->expn <= 9) {
+ v = fast_shr_dec(a->tab[a->len - 1], LIMB_DIGITS - a->expn);
+ if (a->sign)
+ v = -v;
+ ret = 0;
+ } else if (a->expn == 10) {
+ uint64_t v1;
+ uint32_t v_max;
+#if LIMB_BITS == 64
+ v1 = fast_shr_dec(a->tab[a->len - 1], LIMB_DIGITS - a->expn);
+#else
+ v1 = (uint64_t)a->tab[a->len - 1] * 10 +
+ get_digit(a->tab, a->len, (a->len - 1) * LIMB_DIGITS - 1);
+#endif
+ v_max = (uint32_t)INT32_MAX + a->sign;
+ if (v1 > v_max) {
+ v = v_max;
+ ret = BF_ST_OVERFLOW;
+ } else {
+ v = v1;
+ if (a->sign)
+ v = -v;
+ ret = 0;
+ }
+ } else {
+ v = (uint32_t)INT32_MAX + a->sign;
+ ret = BF_ST_OVERFLOW;
+ }
+ *pres = v;
+ return ret;
+}
+
+/* power to an integer with infinite precision */
+int bfdec_pow_ui(bfdec_t *r, const bfdec_t *a, limb_t b)
+{
+ int ret, n_bits, i;
+
+ assert(r != a);
+ if (b == 0)
+ return bfdec_set_ui(r, 1);
+ ret = bfdec_set(r, a);
+ n_bits = LIMB_BITS - clz(b);
+ for(i = n_bits - 2; i >= 0; i--) {
+ ret |= bfdec_mul(r, r, r, BF_PREC_INF, BF_RNDZ);
+ if ((b >> i) & 1)
+ ret |= bfdec_mul(r, r, a, BF_PREC_INF, BF_RNDZ);
+ }
+ return ret;
+}
+
+char *bfdec_ftoa(size_t *plen, const bfdec_t *a, limb_t prec, bf_flags_t flags)
+{
+ return bf_ftoa_internal(plen, (const bf_t *)a, 10, prec, flags, TRUE);
+}
+
+int bfdec_atof(bfdec_t *r, const char *str, const char **pnext,
+ limb_t prec, bf_flags_t flags)
+{
+ slimb_t dummy_exp;
+ return bf_atof_internal((bf_t *)r, &dummy_exp, str, pnext, 10, prec,
+ flags, TRUE);
+}
+
+#endif /* USE_BF_DEC */
+
+#ifdef USE_FFT_MUL
+/***************************************************************/
+/* Integer multiplication with FFT */
+
+/* or LIMB_BITS at bit position 'pos' in tab */
+static inline void put_bits(limb_t *tab, limb_t len, slimb_t pos, limb_t val)
+{
+ limb_t i;
+ int p;
+
+ i = pos >> LIMB_LOG2_BITS;
+ p = pos & (LIMB_BITS - 1);
+ if (i < len)
+ tab[i] |= val << p;
+ if (p != 0) {
+ i++;
+ if (i < len) {
+ tab[i] |= val >> (LIMB_BITS - p);
+ }
+ }
+}
+
+#if defined(__AVX2__)
+
+typedef double NTTLimb;
+
+/* we must have: modulo >= 1 << NTT_MOD_LOG2_MIN */
+#define NTT_MOD_LOG2_MIN 50
+#define NTT_MOD_LOG2_MAX 51
+#define NB_MODS 5
+#define NTT_PROOT_2EXP 39
+static const int ntt_int_bits[NB_MODS] = { 254, 203, 152, 101, 50, };
+
+static const limb_t ntt_mods[NB_MODS] = { 0x00073a8000000001, 0x0007858000000001, 0x0007a38000000001, 0x0007a68000000001, 0x0007fd8000000001,
+};
+
+static const limb_t ntt_proot[2][NB_MODS] = {
+ { 0x00056198d44332c8, 0x0002eb5d640aad39, 0x00047e31eaa35fd0, 0x0005271ac118a150, 0x00075e0ce8442bd5, },
+ { 0x000461169761bcc5, 0x0002dac3cb2da688, 0x0004abc97751e3bf, 0x000656778fc8c485, 0x0000dc6469c269fa, },
+};
+
+static const limb_t ntt_mods_cr[NB_MODS * (NB_MODS - 1) / 2] = {
+ 0x00020e4da740da8e, 0x0004c3dc09c09c1d, 0x000063bd097b4271, 0x000799d8f18f18fd,
+ 0x0005384222222264, 0x000572b07c1f07fe, 0x00035cd08888889a,
+ 0x00066015555557e3, 0x000725960b60b623,
+ 0x0002fc1fa1d6ce12,
+};
+
+#else
+
+typedef limb_t NTTLimb;
+
+#if LIMB_BITS == 64
+
+#define NTT_MOD_LOG2_MIN 61
+#define NTT_MOD_LOG2_MAX 62
+#define NB_MODS 5
+#define NTT_PROOT_2EXP 51
+static const int ntt_int_bits[NB_MODS] = { 307, 246, 185, 123, 61, };
+
+static const limb_t ntt_mods[NB_MODS] = { 0x28d8000000000001, 0x2a88000000000001, 0x2ed8000000000001, 0x3508000000000001, 0x3aa8000000000001,
+};
+
+static const limb_t ntt_proot[2][NB_MODS] = {
+ { 0x1b8ea61034a2bea7, 0x21a9762de58206fb, 0x02ca782f0756a8ea, 0x278384537a3e50a1, 0x106e13fee74ce0ab, },
+ { 0x233513af133e13b8, 0x1d13140d1c6f75f1, 0x12cde57f97e3eeda, 0x0d6149e23cbe654f, 0x36cd204f522a1379, },
+};
+
+static const limb_t ntt_mods_cr[NB_MODS * (NB_MODS - 1) / 2] = {
+ 0x08a9ed097b425eea, 0x18a44aaaaaaaaab3, 0x2493f57f57f57f5d, 0x126b8d0649a7f8d4,
+ 0x09d80ed7303b5ccc, 0x25b8bcf3cf3cf3d5, 0x2ce6ce63398ce638,
+ 0x0e31fad40a57eb59, 0x02a3529fd4a7f52f,
+ 0x3a5493e93e93e94a,
+};
+
+#elif LIMB_BITS == 32
+
+/* we must have: modulo >= 1 << NTT_MOD_LOG2_MIN */
+#define NTT_MOD_LOG2_MIN 29
+#define NTT_MOD_LOG2_MAX 30
+#define NB_MODS 5
+#define NTT_PROOT_2EXP 20
+static const int ntt_int_bits[NB_MODS] = { 148, 119, 89, 59, 29, };
+
+static const limb_t ntt_mods[NB_MODS] = { 0x0000000032b00001, 0x0000000033700001, 0x0000000036d00001, 0x0000000037300001, 0x000000003e500001,
+};
+
+static const limb_t ntt_proot[2][NB_MODS] = {
+ { 0x0000000032525f31, 0x0000000005eb3b37, 0x00000000246eda9f, 0x0000000035f25901, 0x00000000022f5768, },
+ { 0x00000000051eba1a, 0x00000000107be10e, 0x000000001cd574e0, 0x00000000053806e6, 0x000000002cd6bf98, },
+};
+
+static const limb_t ntt_mods_cr[NB_MODS * (NB_MODS - 1) / 2] = {
+ 0x000000000449559a, 0x000000001eba6ca9, 0x000000002ec18e46, 0x000000000860160b,
+ 0x000000000d321307, 0x000000000bf51120, 0x000000000f662938,
+ 0x000000000932ab3e, 0x000000002f40eef8,
+ 0x000000002e760905,
+};
+
+#endif /* LIMB_BITS */
+
+#endif /* !AVX2 */
+
+#if defined(__AVX2__)
+#define NTT_TRIG_K_MAX 18
+#else
+#define NTT_TRIG_K_MAX 19
+#endif
+
+typedef struct BFNTTState {
+ bf_context_t *ctx;
+
+ /* used for mul_mod_fast() */
+ limb_t ntt_mods_div[NB_MODS];
+
+ limb_t ntt_proot_pow[NB_MODS][2][NTT_PROOT_2EXP + 1];
+ limb_t ntt_proot_pow_inv[NB_MODS][2][NTT_PROOT_2EXP + 1];
+ NTTLimb *ntt_trig[NB_MODS][2][NTT_TRIG_K_MAX + 1];
+ /* 1/2^n mod m */
+ limb_t ntt_len_inv[NB_MODS][NTT_PROOT_2EXP + 1][2];
+#if defined(__AVX2__)
+ __m256d ntt_mods_cr_vec[NB_MODS * (NB_MODS - 1) / 2];
+ __m256d ntt_mods_vec[NB_MODS];
+ __m256d ntt_mods_inv_vec[NB_MODS];
+#else
+ limb_t ntt_mods_cr_inv[NB_MODS * (NB_MODS - 1) / 2];
+#endif
+} BFNTTState;
+
+static NTTLimb *get_trig(BFNTTState *s, int k, int inverse, int m_idx);
+
+/* add modulo with up to (LIMB_BITS-1) bit modulo */
+static inline limb_t add_mod(limb_t a, limb_t b, limb_t m)
+{
+ limb_t r;
+ r = a + b;
+ if (r >= m)
+ r -= m;
+ return r;
+}
+
+/* sub modulo with up to LIMB_BITS bit modulo */
+static inline limb_t sub_mod(limb_t a, limb_t b, limb_t m)
+{
+ limb_t r;
+ r = a - b;
+ if (r > a)
+ r += m;
+ return r;
+}
+
+/* return (r0+r1*B) mod m
+ precondition: 0 <= r0+r1*B < 2^(64+NTT_MOD_LOG2_MIN)
+*/
+static inline limb_t mod_fast(dlimb_t r,
+ limb_t m, limb_t m_inv)
+{
+ limb_t a1, q, t0, r1, r0;
+
+ a1 = r >> NTT_MOD_LOG2_MIN;
+
+ q = ((dlimb_t)a1 * m_inv) >> LIMB_BITS;
+ r = r - (dlimb_t)q * m - m * 2;
+ r1 = r >> LIMB_BITS;
+ t0 = (slimb_t)r1 >> 1;
+ r += m & t0;
+ r0 = r;
+ r1 = r >> LIMB_BITS;
+ r0 += m & r1;
+ return r0;
+}
+
+/* faster version using precomputed modulo inverse.
+ precondition: 0 <= a * b < 2^(64+NTT_MOD_LOG2_MIN) */
+static inline limb_t mul_mod_fast(limb_t a, limb_t b,
+ limb_t m, limb_t m_inv)
+{
+ dlimb_t r;
+ r = (dlimb_t)a * (dlimb_t)b;
+ return mod_fast(r, m, m_inv);
+}
+
+static inline limb_t init_mul_mod_fast(limb_t m)
+{
+ dlimb_t t;
+ assert(m < (limb_t)1 << NTT_MOD_LOG2_MAX);
+ assert(m >= (limb_t)1 << NTT_MOD_LOG2_MIN);
+ t = (dlimb_t)1 << (LIMB_BITS + NTT_MOD_LOG2_MIN);
+ return t / m;
+}
+
+/* Faster version used when the multiplier is constant. 0 <= a < 2^64,
+ 0 <= b < m. */
+static inline limb_t mul_mod_fast2(limb_t a, limb_t b,
+ limb_t m, limb_t b_inv)
+{
+ limb_t r, q;
+
+ q = ((dlimb_t)a * (dlimb_t)b_inv) >> LIMB_BITS;
+ r = a * b - q * m;
+ if (r >= m)
+ r -= m;
+ return r;
+}
+
+/* Faster version used when the multiplier is constant. 0 <= a < 2^64,
+ 0 <= b < m. Let r = a * b mod m. The return value is 'r' or 'r +
+ m'. */
+static inline limb_t mul_mod_fast3(limb_t a, limb_t b,
+ limb_t m, limb_t b_inv)
+{
+ limb_t r, q;
+
+ q = ((dlimb_t)a * (dlimb_t)b_inv) >> LIMB_BITS;
+ r = a * b - q * m;
+ return r;
+}
+
+static inline limb_t init_mul_mod_fast2(limb_t b, limb_t m)
+{
+ return ((dlimb_t)b << LIMB_BITS) / m;
+}
+
+#ifdef __AVX2__
+
+static inline limb_t ntt_limb_to_int(NTTLimb a, limb_t m)
+{
+ slimb_t v;
+ v = a;
+ if (v < 0)
+ v += m;
+ if (v >= m)
+ v -= m;
+ return v;
+}
+
+static inline NTTLimb int_to_ntt_limb(limb_t a, limb_t m)
+{
+ return (slimb_t)a;
+}
+
+static inline NTTLimb int_to_ntt_limb2(limb_t a, limb_t m)
+{
+ if (a >= (m / 2))
+ a -= m;
+ return (slimb_t)a;
+}
+
+/* return r + m if r < 0 otherwise r. */
+static inline __m256d ntt_mod1(__m256d r, __m256d m)
+{
+ return _mm256_blendv_pd(r, r + m, r);
+}
+
+/* input: abs(r) < 2 * m. Output: abs(r) < m */
+static inline __m256d ntt_mod(__m256d r, __m256d mf, __m256d m2f)
+{
+ return _mm256_blendv_pd(r, r + m2f, r) - mf;
+}
+
+/* input: abs(a*b) < 2 * m^2, output: abs(r) < m */
+static inline __m256d ntt_mul_mod(__m256d a, __m256d b, __m256d mf,
+ __m256d m_inv)
+{
+ __m256d r, q, ab1, ab0, qm0, qm1;
+ ab1 = a * b;
+ q = _mm256_round_pd(ab1 * m_inv, 0); /* round to nearest */
+ qm1 = q * mf;
+ qm0 = _mm256_fmsub_pd(q, mf, qm1); /* low part */
+ ab0 = _mm256_fmsub_pd(a, b, ab1); /* low part */
+ r = (ab1 - qm1) + (ab0 - qm0);
+ return r;
+}
+
+static void *bf_aligned_malloc(bf_context_t *s, size_t size, size_t align)
+{
+ void *ptr;
+ void **ptr1;
+ ptr = bf_malloc(s, size + sizeof(void *) + align - 1);
+ if (!ptr)
+ return NULL;
+ ptr1 = (void **)(((uintptr_t)ptr + sizeof(void *) + align - 1) &
+ ~(align - 1));
+ ptr1[-1] = ptr;
+ return ptr1;
+}
+
+static void bf_aligned_free(bf_context_t *s, void *ptr)
+{
+ if (!ptr)
+ return;
+ bf_free(s, ((void **)ptr)[-1]);
+}
+
+static void *ntt_malloc(BFNTTState *s, size_t size)
+{
+ return bf_aligned_malloc(s->ctx, size, 64);
+}
+
+static void ntt_free(BFNTTState *s, void *ptr)
+{
+ bf_aligned_free(s->ctx, ptr);
+}
+
+static no_inline int ntt_fft(BFNTTState *s,
+ NTTLimb *out_buf, NTTLimb *in_buf,
+ NTTLimb *tmp_buf, int fft_len_log2,
+ int inverse, int m_idx)
+{
+ limb_t nb_blocks, fft_per_block, p, k, n, stride_in, i, j;
+ NTTLimb *tab_in, *tab_out, *tmp, *trig;
+ __m256d m_inv, mf, m2f, c, a0, a1, b0, b1;
+ limb_t m;
+ int l;
+
+ m = ntt_mods[m_idx];
+
+ m_inv = _mm256_set1_pd(1.0 / (double)m);
+ mf = _mm256_set1_pd(m);
+ m2f = _mm256_set1_pd(m * 2);
+
+ n = (limb_t)1 << fft_len_log2;
+ assert(n >= 8);
+ stride_in = n / 2;
+
+ tab_in = in_buf;
+ tab_out = tmp_buf;
+ trig = get_trig(s, fft_len_log2, inverse, m_idx);
+ if (!trig)
+ return -1;
+ p = 0;
+ for(k = 0; k < stride_in; k += 4) {
+ a0 = _mm256_load_pd(&tab_in[k]);
+ a1 = _mm256_load_pd(&tab_in[k + stride_in]);
+ c = _mm256_load_pd(trig);
+ trig += 4;
+ b0 = ntt_mod(a0 + a1, mf, m2f);
+ b1 = ntt_mul_mod(a0 - a1, c, mf, m_inv);
+ a0 = _mm256_permute2f128_pd(b0, b1, 0x20);
+ a1 = _mm256_permute2f128_pd(b0, b1, 0x31);
+ a0 = _mm256_permute4x64_pd(a0, 0xd8);
+ a1 = _mm256_permute4x64_pd(a1, 0xd8);
+ _mm256_store_pd(&tab_out[p], a0);
+ _mm256_store_pd(&tab_out[p + 4], a1);
+ p += 2 * 4;
+ }
+ tmp = tab_in;
+ tab_in = tab_out;
+ tab_out = tmp;
+
+ trig = get_trig(s, fft_len_log2 - 1, inverse, m_idx);
+ if (!trig)
+ return -1;
+ p = 0;
+ for(k = 0; k < stride_in; k += 4) {
+ a0 = _mm256_load_pd(&tab_in[k]);
+ a1 = _mm256_load_pd(&tab_in[k + stride_in]);
+ c = _mm256_setr_pd(trig[0], trig[0], trig[1], trig[1]);
+ trig += 2;
+ b0 = ntt_mod(a0 + a1, mf, m2f);
+ b1 = ntt_mul_mod(a0 - a1, c, mf, m_inv);
+ a0 = _mm256_permute2f128_pd(b0, b1, 0x20);
+ a1 = _mm256_permute2f128_pd(b0, b1, 0x31);
+ _mm256_store_pd(&tab_out[p], a0);
+ _mm256_store_pd(&tab_out[p + 4], a1);
+ p += 2 * 4;
+ }
+ tmp = tab_in;
+ tab_in = tab_out;
+ tab_out = tmp;
+
+ nb_blocks = n / 4;
+ fft_per_block = 4;
+
+ l = fft_len_log2 - 2;
+ while (nb_blocks != 2) {
+ nb_blocks >>= 1;
+ p = 0;
+ k = 0;
+ trig = get_trig(s, l, inverse, m_idx);
+ if (!trig)
+ return -1;
+ for(i = 0; i < nb_blocks; i++) {
+ c = _mm256_set1_pd(trig[0]);
+ trig++;
+ for(j = 0; j < fft_per_block; j += 4) {
+ a0 = _mm256_load_pd(&tab_in[k + j]);
+ a1 = _mm256_load_pd(&tab_in[k + j + stride_in]);
+ b0 = ntt_mod(a0 + a1, mf, m2f);
+ b1 = ntt_mul_mod(a0 - a1, c, mf, m_inv);
+ _mm256_store_pd(&tab_out[p + j], b0);
+ _mm256_store_pd(&tab_out[p + j + fft_per_block], b1);
+ }
+ k += fft_per_block;
+ p += 2 * fft_per_block;
+ }
+ fft_per_block <<= 1;
+ l--;
+ tmp = tab_in;
+ tab_in = tab_out;
+ tab_out = tmp;
+ }
+
+ tab_out = out_buf;
+ for(k = 0; k < stride_in; k += 4) {
+ a0 = _mm256_load_pd(&tab_in[k]);
+ a1 = _mm256_load_pd(&tab_in[k + stride_in]);
+ b0 = ntt_mod(a0 + a1, mf, m2f);
+ b1 = ntt_mod(a0 - a1, mf, m2f);
+ _mm256_store_pd(&tab_out[k], b0);
+ _mm256_store_pd(&tab_out[k + stride_in], b1);
+ }
+ return 0;
+}
+
+static void ntt_vec_mul(BFNTTState *s,
+ NTTLimb *tab1, NTTLimb *tab2, limb_t fft_len_log2,
+ int k_tot, int m_idx)
+{
+ limb_t i, c_inv, n, m;
+ __m256d m_inv, mf, a, b, c;
+
+ m = ntt_mods[m_idx];
+ c_inv = s->ntt_len_inv[m_idx][k_tot][0];
+ m_inv = _mm256_set1_pd(1.0 / (double)m);
+ mf = _mm256_set1_pd(m);
+ c = _mm256_set1_pd(int_to_ntt_limb(c_inv, m));
+ n = (limb_t)1 << fft_len_log2;
+ for(i = 0; i < n; i += 4) {
+ a = _mm256_load_pd(&tab1[i]);
+ b = _mm256_load_pd(&tab2[i]);
+ a = ntt_mul_mod(a, b, mf, m_inv);
+ a = ntt_mul_mod(a, c, mf, m_inv);
+ _mm256_store_pd(&tab1[i], a);
+ }
+}
+
+static no_inline void mul_trig(NTTLimb *buf,
+ limb_t n, limb_t c1, limb_t m, limb_t m_inv1)
+{
+ limb_t i, c2, c3, c4;
+ __m256d c, c_mul, a0, mf, m_inv;
+ assert(n >= 2);
+
+ mf = _mm256_set1_pd(m);
+ m_inv = _mm256_set1_pd(1.0 / (double)m);
+
+ c2 = mul_mod_fast(c1, c1, m, m_inv1);
+ c3 = mul_mod_fast(c2, c1, m, m_inv1);
+ c4 = mul_mod_fast(c2, c2, m, m_inv1);
+ c = _mm256_setr_pd(1, int_to_ntt_limb(c1, m),
+ int_to_ntt_limb(c2, m), int_to_ntt_limb(c3, m));
+ c_mul = _mm256_set1_pd(int_to_ntt_limb(c4, m));
+ for(i = 0; i < n; i += 4) {
+ a0 = _mm256_load_pd(&buf[i]);
+ a0 = ntt_mul_mod(a0, c, mf, m_inv);
+ _mm256_store_pd(&buf[i], a0);
+ c = ntt_mul_mod(c, c_mul, mf, m_inv);
+ }
+}
+
+#else
+
+static void *ntt_malloc(BFNTTState *s, size_t size)
+{
+ return bf_malloc(s->ctx, size);
+}
+
+static void ntt_free(BFNTTState *s, void *ptr)
+{
+ bf_free(s->ctx, ptr);
+}
+
+static inline limb_t ntt_limb_to_int(NTTLimb a, limb_t m)
+{
+ if (a >= m)
+ a -= m;
+ return a;
+}
+
+static inline NTTLimb int_to_ntt_limb(slimb_t a, limb_t m)
+{
+ return a;
+}
+
+static no_inline int ntt_fft(BFNTTState *s, NTTLimb *out_buf, NTTLimb *in_buf,
+ NTTLimb *tmp_buf, int fft_len_log2,
+ int inverse, int m_idx)
+{
+ limb_t nb_blocks, fft_per_block, p, k, n, stride_in, i, j, m, m2;
+ NTTLimb *tab_in, *tab_out, *tmp, a0, a1, b0, b1, c, *trig, c_inv;
+ int l;
+
+ m = ntt_mods[m_idx];
+ m2 = 2 * m;
+ n = (limb_t)1 << fft_len_log2;
+ nb_blocks = n;
+ fft_per_block = 1;
+ stride_in = n / 2;
+ tab_in = in_buf;
+ tab_out = tmp_buf;
+ l = fft_len_log2;
+ while (nb_blocks != 2) {
+ nb_blocks >>= 1;
+ p = 0;
+ k = 0;
+ trig = get_trig(s, l, inverse, m_idx);
+ if (!trig)
+ return -1;
+ for(i = 0; i < nb_blocks; i++) {
+ c = trig[0];
+ c_inv = trig[1];
+ trig += 2;
+ for(j = 0; j < fft_per_block; j++) {
+ a0 = tab_in[k + j];
+ a1 = tab_in[k + j + stride_in];
+ b0 = add_mod(a0, a1, m2);
+ b1 = a0 - a1 + m2;
+ b1 = mul_mod_fast3(b1, c, m, c_inv);
+ tab_out[p + j] = b0;
+ tab_out[p + j + fft_per_block] = b1;
+ }
+ k += fft_per_block;
+ p += 2 * fft_per_block;
+ }
+ fft_per_block <<= 1;
+ l--;
+ tmp = tab_in;
+ tab_in = tab_out;
+ tab_out = tmp;
+ }
+ /* no twiddle in last step */
+ tab_out = out_buf;
+ for(k = 0; k < stride_in; k++) {
+ a0 = tab_in[k];
+ a1 = tab_in[k + stride_in];
+ b0 = add_mod(a0, a1, m2);
+ b1 = sub_mod(a0, a1, m2);
+ tab_out[k] = b0;
+ tab_out[k + stride_in] = b1;
+ }
+ return 0;
+}
+
+static void ntt_vec_mul(BFNTTState *s,
+ NTTLimb *tab1, NTTLimb *tab2, int fft_len_log2,
+ int k_tot, int m_idx)
+{
+ limb_t i, norm, norm_inv, a, n, m, m_inv;
+
+ m = ntt_mods[m_idx];
+ m_inv = s->ntt_mods_div[m_idx];
+ norm = s->ntt_len_inv[m_idx][k_tot][0];
+ norm_inv = s->ntt_len_inv[m_idx][k_tot][1];
+ n = (limb_t)1 << fft_len_log2;
+ for(i = 0; i < n; i++) {
+ a = tab1[i];
+ /* need to reduce the range so that the product is <
+ 2^(LIMB_BITS+NTT_MOD_LOG2_MIN) */
+ if (a >= m)
+ a -= m;
+ a = mul_mod_fast(a, tab2[i], m, m_inv);
+ a = mul_mod_fast3(a, norm, m, norm_inv);
+ tab1[i] = a;
+ }
+}
+
+static no_inline void mul_trig(NTTLimb *buf,
+ limb_t n, limb_t c_mul, limb_t m, limb_t m_inv)
+{
+ limb_t i, c0, c_mul_inv;
+
+ c0 = 1;
+ c_mul_inv = init_mul_mod_fast2(c_mul, m);
+ for(i = 0; i < n; i++) {
+ buf[i] = mul_mod_fast(buf[i], c0, m, m_inv);
+ c0 = mul_mod_fast2(c0, c_mul, m, c_mul_inv);
+ }
+}
+
+#endif /* !AVX2 */
+
+static no_inline NTTLimb *get_trig(BFNTTState *s,
+ int k, int inverse, int m_idx)
+{
+ NTTLimb *tab;
+ limb_t i, n2, c, c_mul, m, c_mul_inv;
+
+ if (k > NTT_TRIG_K_MAX)
+ return NULL;
+
+ tab = s->ntt_trig[m_idx][inverse][k];
+ if (tab)
+ return tab;
+ n2 = (limb_t)1 << (k - 1);
+ m = ntt_mods[m_idx];
+#ifdef __AVX2__
+ tab = ntt_malloc(s, sizeof(NTTLimb) * n2);
+#else
+ tab = ntt_malloc(s, sizeof(NTTLimb) * n2 * 2);
+#endif
+ if (!tab)
+ return NULL;
+ c = 1;
+ c_mul = s->ntt_proot_pow[m_idx][inverse][k];
+ c_mul_inv = s->ntt_proot_pow_inv[m_idx][inverse][k];
+ for(i = 0; i < n2; i++) {
+#ifdef __AVX2__
+ tab[i] = int_to_ntt_limb2(c, m);
+#else
+ tab[2 * i] = int_to_ntt_limb(c, m);
+ tab[2 * i + 1] = init_mul_mod_fast2(c, m);
+#endif
+ c = mul_mod_fast2(c, c_mul, m, c_mul_inv);
+ }
+ s->ntt_trig[m_idx][inverse][k] = tab;
+ return tab;
+}
+
+void fft_clear_cache(bf_context_t *s1)
+{
+ int m_idx, inverse, k;
+ BFNTTState *s = s1->ntt_state;
+ if (s) {
+ for(m_idx = 0; m_idx < NB_MODS; m_idx++) {
+ for(inverse = 0; inverse < 2; inverse++) {
+ for(k = 0; k < NTT_TRIG_K_MAX + 1; k++) {
+ if (s->ntt_trig[m_idx][inverse][k]) {
+ ntt_free(s, s->ntt_trig[m_idx][inverse][k]);
+ s->ntt_trig[m_idx][inverse][k] = NULL;
+ }
+ }
+ }
+ }
+#if defined(__AVX2__)
+ bf_aligned_free(s1, s);
+#else
+ bf_free(s1, s);
+#endif
+ s1->ntt_state = NULL;
+ }
+}
+
+#define STRIP_LEN 16
+
+/* dst = buf1, src = buf2 */
+static int ntt_fft_partial(BFNTTState *s, NTTLimb *buf1,
+ int k1, int k2, limb_t n1, limb_t n2, int inverse,
+ limb_t m_idx)
+{
+ limb_t i, j, c_mul, c0, m, m_inv, strip_len, l;
+ NTTLimb *buf2, *buf3;
+
+ buf2 = NULL;
+ buf3 = ntt_malloc(s, sizeof(NTTLimb) * n1);
+ if (!buf3)
+ goto fail;
+ if (k2 == 0) {
+ if (ntt_fft(s, buf1, buf1, buf3, k1, inverse, m_idx))
+ goto fail;
+ } else {
+ strip_len = STRIP_LEN;
+ buf2 = ntt_malloc(s, sizeof(NTTLimb) * n1 * strip_len);
+ if (!buf2)
+ goto fail;
+ m = ntt_mods[m_idx];
+ m_inv = s->ntt_mods_div[m_idx];
+ c0 = s->ntt_proot_pow[m_idx][inverse][k1 + k2];
+ c_mul = 1;
+ assert((n2 % strip_len) == 0);
+ for(j = 0; j < n2; j += strip_len) {
+ for(i = 0; i < n1; i++) {
+ for(l = 0; l < strip_len; l++) {
+ buf2[i + l * n1] = buf1[i * n2 + (j + l)];
+ }
+ }
+ for(l = 0; l < strip_len; l++) {
+ if (inverse)
+ mul_trig(buf2 + l * n1, n1, c_mul, m, m_inv);
+ if (ntt_fft(s, buf2 + l * n1, buf2 + l * n1, buf3, k1, inverse, m_idx))
+ goto fail;
+ if (!inverse)
+ mul_trig(buf2 + l * n1, n1, c_mul, m, m_inv);
+ c_mul = mul_mod_fast(c_mul, c0, m, m_inv);
+ }
+
+ for(i = 0; i < n1; i++) {
+ for(l = 0; l < strip_len; l++) {
+ buf1[i * n2 + (j + l)] = buf2[i + l *n1];
+ }
+ }
+ }
+ ntt_free(s, buf2);
+ }
+ ntt_free(s, buf3);
+ return 0;
+ fail:
+ ntt_free(s, buf2);
+ ntt_free(s, buf3);
+ return -1;
+}
+
+
+/* dst = buf1, src = buf2, tmp = buf3 */
+static int ntt_conv(BFNTTState *s, NTTLimb *buf1, NTTLimb *buf2,
+ int k, int k_tot, limb_t m_idx)
+{
+ limb_t n1, n2, i;
+ int k1, k2;
+
+ if (k <= NTT_TRIG_K_MAX) {
+ k1 = k;
+ } else {
+ /* recursive split of the FFT */
+ k1 = bf_min(k / 2, NTT_TRIG_K_MAX);
+ }
+ k2 = k - k1;
+ n1 = (limb_t)1 << k1;
+ n2 = (limb_t)1 << k2;
+
+ if (ntt_fft_partial(s, buf1, k1, k2, n1, n2, 0, m_idx))
+ return -1;
+ if (ntt_fft_partial(s, buf2, k1, k2, n1, n2, 0, m_idx))
+ return -1;
+ if (k2 == 0) {
+ ntt_vec_mul(s, buf1, buf2, k, k_tot, m_idx);
+ } else {
+ for(i = 0; i < n1; i++) {
+ ntt_conv(s, buf1 + i * n2, buf2 + i * n2, k2, k_tot, m_idx);
+ }
+ }
+ if (ntt_fft_partial(s, buf1, k1, k2, n1, n2, 1, m_idx))
+ return -1;
+ return 0;
+}
+
+
+static no_inline void limb_to_ntt(BFNTTState *s,
+ NTTLimb *tabr, limb_t fft_len,
+ const limb_t *taba, limb_t a_len, int dpl,
+ int first_m_idx, int nb_mods)
+{
+ slimb_t i, n;
+ dlimb_t a, b;
+ int j, shift;
+ limb_t base_mask1, a0, a1, a2, r, m, m_inv;
+
+#if 0
+ for(i = 0; i < a_len; i++) {
+ printf("%" PRId64 ": " FMT_LIMB "\n",
+ (int64_t)i, taba[i]);
+ }
+#endif
+ memset(tabr, 0, sizeof(NTTLimb) * fft_len * nb_mods);
+ shift = dpl & (LIMB_BITS - 1);
+ if (shift == 0)
+ base_mask1 = -1;
+ else
+ base_mask1 = ((limb_t)1 << shift) - 1;
+ n = bf_min(fft_len, (a_len * LIMB_BITS + dpl - 1) / dpl);
+ for(i = 0; i < n; i++) {
+ a0 = get_bits(taba, a_len, i * dpl);
+ if (dpl <= LIMB_BITS) {
+ a0 &= base_mask1;
+ a = a0;
+ } else {
+ a1 = get_bits(taba, a_len, i * dpl + LIMB_BITS);
+ if (dpl <= (LIMB_BITS + NTT_MOD_LOG2_MIN)) {
+ a = a0 | ((dlimb_t)(a1 & base_mask1) << LIMB_BITS);
+ } else {
+ if (dpl > 2 * LIMB_BITS) {
+ a2 = get_bits(taba, a_len, i * dpl + LIMB_BITS * 2) &
+ base_mask1;
+ } else {
+ a1 &= base_mask1;
+ a2 = 0;
+ }
+ // printf("a=0x%016lx%016lx%016lx\n", a2, a1, a0);
+ a = (a0 >> (LIMB_BITS - NTT_MOD_LOG2_MAX + NTT_MOD_LOG2_MIN)) |
+ ((dlimb_t)a1 << (NTT_MOD_LOG2_MAX - NTT_MOD_LOG2_MIN)) |
+ ((dlimb_t)a2 << (LIMB_BITS + NTT_MOD_LOG2_MAX - NTT_MOD_LOG2_MIN));
+ a0 &= ((limb_t)1 << (LIMB_BITS - NTT_MOD_LOG2_MAX + NTT_MOD_LOG2_MIN)) - 1;
+ }
+ }
+ for(j = 0; j < nb_mods; j++) {
+ m = ntt_mods[first_m_idx + j];
+ m_inv = s->ntt_mods_div[first_m_idx + j];
+ r = mod_fast(a, m, m_inv);
+ if (dpl > (LIMB_BITS + NTT_MOD_LOG2_MIN)) {
+ b = ((dlimb_t)r << (LIMB_BITS - NTT_MOD_LOG2_MAX + NTT_MOD_LOG2_MIN)) | a0;
+ r = mod_fast(b, m, m_inv);
+ }
+ tabr[i + j * fft_len] = int_to_ntt_limb(r, m);
+ }
+ }
+}
+
+#if defined(__AVX2__)
+
+#define VEC_LEN 4
+
+typedef union {
+ __m256d v;
+ double d[4];
+} VecUnion;
+
+static no_inline void ntt_to_limb(BFNTTState *s, limb_t *tabr, limb_t r_len,
+ const NTTLimb *buf, int fft_len_log2, int dpl,
+ int nb_mods)
+{
+ const limb_t *mods = ntt_mods + NB_MODS - nb_mods;
+ const __m256d *mods_cr_vec, *mf, *m_inv;
+ VecUnion y[NB_MODS];
+ limb_t u[NB_MODS], carry[NB_MODS], fft_len, base_mask1, r;
+ slimb_t i, len, pos;
+ int j, k, l, shift, n_limb1, p;
+ dlimb_t t;
+
+ j = NB_MODS * (NB_MODS - 1) / 2 - nb_mods * (nb_mods - 1) / 2;
+ mods_cr_vec = s->ntt_mods_cr_vec + j;
+ mf = s->ntt_mods_vec + NB_MODS - nb_mods;
+ m_inv = s->ntt_mods_inv_vec + NB_MODS - nb_mods;
+
+ shift = dpl & (LIMB_BITS - 1);
+ if (shift == 0)
+ base_mask1 = -1;
+ else
+ base_mask1 = ((limb_t)1 << shift) - 1;
+ n_limb1 = ((unsigned)dpl - 1) / LIMB_BITS;
+ for(j = 0; j < NB_MODS; j++)
+ carry[j] = 0;
+ for(j = 0; j < NB_MODS; j++)
+ u[j] = 0; /* avoid warnings */
+ memset(tabr, 0, sizeof(limb_t) * r_len);
+ fft_len = (limb_t)1 << fft_len_log2;
+ len = bf_min(fft_len, (r_len * LIMB_BITS + dpl - 1) / dpl);
+ len = (len + VEC_LEN - 1) & ~(VEC_LEN - 1);
+ i = 0;
+ while (i < len) {
+ for(j = 0; j < nb_mods; j++)
+ y[j].v = *(__m256d *)&buf[i + fft_len * j];
+
+ /* Chinese remainder to get mixed radix representation */
+ l = 0;
+ for(j = 0; j < nb_mods - 1; j++) {
+ y[j].v = ntt_mod1(y[j].v, mf[j]);
+ for(k = j + 1; k < nb_mods; k++) {
+ y[k].v = ntt_mul_mod(y[k].v - y[j].v,
+ mods_cr_vec[l], mf[k], m_inv[k]);
+ l++;
+ }
+ }
+ y[j].v = ntt_mod1(y[j].v, mf[j]);
+
+ for(p = 0; p < VEC_LEN; p++) {
+ /* back to normal representation */
+ u[0] = (int64_t)y[nb_mods - 1].d[p];
+ l = 1;
+ for(j = nb_mods - 2; j >= 1; j--) {
+ r = (int64_t)y[j].d[p];
+ for(k = 0; k < l; k++) {
+ t = (dlimb_t)u[k] * mods[j] + r;
+ r = t >> LIMB_BITS;
+ u[k] = t;
+ }
+ u[l] = r;
+ l++;
+ }
+ /* XXX: for nb_mods = 5, l should be 4 */
+
+ /* last step adds the carry */
+ r = (int64_t)y[0].d[p];
+ for(k = 0; k < l; k++) {
+ t = (dlimb_t)u[k] * mods[j] + r + carry[k];
+ r = t >> LIMB_BITS;
+ u[k] = t;
+ }
+ u[l] = r + carry[l];
+
+#if 0
+ printf("%" PRId64 ": ", i);
+ for(j = nb_mods - 1; j >= 0; j--) {
+ printf(" %019" PRIu64, u[j]);
+ }
+ printf("\n");
+#endif
+
+ /* write the digits */
+ pos = i * dpl;
+ for(j = 0; j < n_limb1; j++) {
+ put_bits(tabr, r_len, pos, u[j]);
+ pos += LIMB_BITS;
+ }
+ put_bits(tabr, r_len, pos, u[n_limb1] & base_mask1);
+ /* shift by dpl digits and set the carry */
+ if (shift == 0) {
+ for(j = n_limb1 + 1; j < nb_mods; j++)
+ carry[j - (n_limb1 + 1)] = u[j];
+ } else {
+ for(j = n_limb1; j < nb_mods - 1; j++) {
+ carry[j - n_limb1] = (u[j] >> shift) |
+ (u[j + 1] << (LIMB_BITS - shift));
+ }
+ carry[nb_mods - 1 - n_limb1] = u[nb_mods - 1] >> shift;
+ }
+ i++;
+ }
+ }
+}
+#else
+static no_inline void ntt_to_limb(BFNTTState *s, limb_t *tabr, limb_t r_len,
+ const NTTLimb *buf, int fft_len_log2, int dpl,
+ int nb_mods)
+{
+ const limb_t *mods = ntt_mods + NB_MODS - nb_mods;
+ const limb_t *mods_cr, *mods_cr_inv;
+ limb_t y[NB_MODS], u[NB_MODS], carry[NB_MODS], fft_len, base_mask1, r;
+ slimb_t i, len, pos;
+ int j, k, l, shift, n_limb1;
+ dlimb_t t;
+
+ j = NB_MODS * (NB_MODS - 1) / 2 - nb_mods * (nb_mods - 1) / 2;
+ mods_cr = ntt_mods_cr + j;
+ mods_cr_inv = s->ntt_mods_cr_inv + j;
+
+ shift = dpl & (LIMB_BITS - 1);
+ if (shift == 0)
+ base_mask1 = -1;
+ else
+ base_mask1 = ((limb_t)1 << shift) - 1;
+ n_limb1 = ((unsigned)dpl - 1) / LIMB_BITS;
+ for(j = 0; j < NB_MODS; j++)
+ carry[j] = 0;
+ for(j = 0; j < NB_MODS; j++)
+ u[j] = 0; /* avoid warnings */
+ memset(tabr, 0, sizeof(limb_t) * r_len);
+ fft_len = (limb_t)1 << fft_len_log2;
+ len = bf_min(fft_len, (r_len * LIMB_BITS + dpl - 1) / dpl);
+ for(i = 0; i < len; i++) {
+ for(j = 0; j < nb_mods; j++) {
+ y[j] = ntt_limb_to_int(buf[i + fft_len * j], mods[j]);
+ }
+
+ /* Chinese remainder to get mixed radix representation */
+ l = 0;
+ for(j = 0; j < nb_mods - 1; j++) {
+ for(k = j + 1; k < nb_mods; k++) {
+ limb_t m;
+ m = mods[k];
+ /* Note: there is no overflow in the sub_mod() because
+ the modulos are sorted by increasing order */
+ y[k] = mul_mod_fast2(y[k] - y[j] + m,
+ mods_cr[l], m, mods_cr_inv[l]);
+ l++;
+ }
+ }
+
+ /* back to normal representation */
+ u[0] = y[nb_mods - 1];
+ l = 1;
+ for(j = nb_mods - 2; j >= 1; j--) {
+ r = y[j];
+ for(k = 0; k < l; k++) {
+ t = (dlimb_t)u[k] * mods[j] + r;
+ r = t >> LIMB_BITS;
+ u[k] = t;
+ }
+ u[l] = r;
+ l++;
+ }
+
+ /* last step adds the carry */
+ r = y[0];
+ for(k = 0; k < l; k++) {
+ t = (dlimb_t)u[k] * mods[j] + r + carry[k];
+ r = t >> LIMB_BITS;
+ u[k] = t;
+ }
+ u[l] = r + carry[l];
+
+#if 0
+ printf("%" PRId64 ": ", (int64_t)i);
+ for(j = nb_mods - 1; j >= 0; j--) {
+ printf(" " FMT_LIMB, u[j]);
+ }
+ printf("\n");
+#endif
+
+ /* write the digits */
+ pos = i * dpl;
+ for(j = 0; j < n_limb1; j++) {
+ put_bits(tabr, r_len, pos, u[j]);
+ pos += LIMB_BITS;
+ }
+ put_bits(tabr, r_len, pos, u[n_limb1] & base_mask1);
+ /* shift by dpl digits and set the carry */
+ if (shift == 0) {
+ for(j = n_limb1 + 1; j < nb_mods; j++)
+ carry[j - (n_limb1 + 1)] = u[j];
+ } else {
+ for(j = n_limb1; j < nb_mods - 1; j++) {
+ carry[j - n_limb1] = (u[j] >> shift) |
+ (u[j + 1] << (LIMB_BITS - shift));
+ }
+ carry[nb_mods - 1 - n_limb1] = u[nb_mods - 1] >> shift;
+ }
+ }
+}
+#endif
+
+static int ntt_static_init(bf_context_t *s1)
+{
+ BFNTTState *s;
+ int inverse, i, j, k, l;
+ limb_t c, c_inv, c_inv2, m, m_inv;
+
+ if (s1->ntt_state)
+ return 0;
+#if defined(__AVX2__)
+ s = bf_aligned_malloc(s1, sizeof(*s), 64);
+#else
+ s = bf_malloc(s1, sizeof(*s));
+#endif
+ if (!s)
+ return -1;
+ memset(s, 0, sizeof(*s));
+ s1->ntt_state = s;
+ s->ctx = s1;
+
+ for(j = 0; j < NB_MODS; j++) {
+ m = ntt_mods[j];
+ m_inv = init_mul_mod_fast(m);
+ s->ntt_mods_div[j] = m_inv;
+#if defined(__AVX2__)
+ s->ntt_mods_vec[j] = _mm256_set1_pd(m);
+ s->ntt_mods_inv_vec[j] = _mm256_set1_pd(1.0 / (double)m);
+#endif
+ c_inv2 = (m + 1) / 2; /* 1/2 */
+ c_inv = 1;
+ for(i = 0; i <= NTT_PROOT_2EXP; i++) {
+ s->ntt_len_inv[j][i][0] = c_inv;
+ s->ntt_len_inv[j][i][1] = init_mul_mod_fast2(c_inv, m);
+ c_inv = mul_mod_fast(c_inv, c_inv2, m, m_inv);
+ }
+
+ for(inverse = 0; inverse < 2; inverse++) {
+ c = ntt_proot[inverse][j];
+ for(i = 0; i < NTT_PROOT_2EXP; i++) {
+ s->ntt_proot_pow[j][inverse][NTT_PROOT_2EXP - i] = c;
+ s->ntt_proot_pow_inv[j][inverse][NTT_PROOT_2EXP - i] =
+ init_mul_mod_fast2(c, m);
+ c = mul_mod_fast(c, c, m, m_inv);
+ }
+ }
+ }
+
+ l = 0;
+ for(j = 0; j < NB_MODS - 1; j++) {
+ for(k = j + 1; k < NB_MODS; k++) {
+#if defined(__AVX2__)
+ s->ntt_mods_cr_vec[l] = _mm256_set1_pd(int_to_ntt_limb2(ntt_mods_cr[l],
+ ntt_mods[k]));
+#else
+ s->ntt_mods_cr_inv[l] = init_mul_mod_fast2(ntt_mods_cr[l],
+ ntt_mods[k]);
+#endif
+ l++;
+ }
+ }
+ return 0;
+}
+
+int bf_get_fft_size(int *pdpl, int *pnb_mods, limb_t len)
+{
+ int dpl, fft_len_log2, n_bits, nb_mods, dpl_found, fft_len_log2_found;
+ int int_bits, nb_mods_found;
+ limb_t cost, min_cost;
+
+ min_cost = -1;
+ dpl_found = 0;
+ nb_mods_found = 4;
+ fft_len_log2_found = 0;
+ for(nb_mods = 3; nb_mods <= NB_MODS; nb_mods++) {
+ int_bits = ntt_int_bits[NB_MODS - nb_mods];
+ dpl = bf_min((int_bits - 4) / 2,
+ 2 * LIMB_BITS + 2 * NTT_MOD_LOG2_MIN - NTT_MOD_LOG2_MAX);
+ for(;;) {
+ fft_len_log2 = ceil_log2((len * LIMB_BITS + dpl - 1) / dpl);
+ if (fft_len_log2 > NTT_PROOT_2EXP)
+ goto next;
+ n_bits = fft_len_log2 + 2 * dpl;
+ if (n_bits <= int_bits) {
+ cost = ((limb_t)(fft_len_log2 + 1) << fft_len_log2) * nb_mods;
+ // printf("n=%d dpl=%d: cost=%" PRId64 "\n", nb_mods, dpl, (int64_t)cost);
+ if (cost < min_cost) {
+ min_cost = cost;
+ dpl_found = dpl;
+ nb_mods_found = nb_mods;
+ fft_len_log2_found = fft_len_log2;
+ }
+ break;
+ }
+ dpl--;
+ if (dpl == 0)
+ break;
+ }
+ next: ;
+ }
+ if (!dpl_found)
+ abort();
+ /* limit dpl if possible to reduce fixed cost of limb/NTT conversion */
+ if (dpl_found > (LIMB_BITS + NTT_MOD_LOG2_MIN) &&
+ ((limb_t)(LIMB_BITS + NTT_MOD_LOG2_MIN) << fft_len_log2_found) >=
+ len * LIMB_BITS) {
+ dpl_found = LIMB_BITS + NTT_MOD_LOG2_MIN;
+ }
+ *pnb_mods = nb_mods_found;
+ *pdpl = dpl_found;
+ return fft_len_log2_found;
+}
+
+/* return 0 if OK, -1 if memory error */
+static no_inline int fft_mul(bf_context_t *s1,
+ bf_t *res, limb_t *a_tab, limb_t a_len,
+ limb_t *b_tab, limb_t b_len, int mul_flags)
+{
+ BFNTTState *s;
+ int dpl, fft_len_log2, j, nb_mods, reduced_mem;
+ slimb_t len, fft_len;
+ NTTLimb *buf1, *buf2, *ptr;
+#if defined(USE_MUL_CHECK)
+ limb_t ha, hb, hr, h_ref;
+#endif
+
+ if (ntt_static_init(s1))
+ return -1;
+ s = s1->ntt_state;
+
+ /* find the optimal number of digits per limb (dpl) */
+ len = a_len + b_len;
+ fft_len_log2 = bf_get_fft_size(&dpl, &nb_mods, len);
+ fft_len = (uint64_t)1 << fft_len_log2;
+ // printf("len=%" PRId64 " fft_len_log2=%d dpl=%d\n", len, fft_len_log2, dpl);
+#if defined(USE_MUL_CHECK)
+ ha = mp_mod1(a_tab, a_len, BF_CHKSUM_MOD, 0);
+ hb = mp_mod1(b_tab, b_len, BF_CHKSUM_MOD, 0);
+#endif
+ if ((mul_flags & (FFT_MUL_R_OVERLAP_A | FFT_MUL_R_OVERLAP_B)) == 0) {
+ if (!(mul_flags & FFT_MUL_R_NORESIZE))
+ bf_resize(res, 0);
+ } else if (mul_flags & FFT_MUL_R_OVERLAP_B) {
+ limb_t *tmp_tab, tmp_len;
+ /* it is better to free 'b' first */
+ tmp_tab = a_tab;
+ a_tab = b_tab;
+ b_tab = tmp_tab;
+ tmp_len = a_len;
+ a_len = b_len;
+ b_len = tmp_len;
+ }
+ buf1 = ntt_malloc(s, sizeof(NTTLimb) * fft_len * nb_mods);
+ if (!buf1)
+ return -1;
+ limb_to_ntt(s, buf1, fft_len, a_tab, a_len, dpl,
+ NB_MODS - nb_mods, nb_mods);
+ if ((mul_flags & (FFT_MUL_R_OVERLAP_A | FFT_MUL_R_OVERLAP_B)) ==
+ FFT_MUL_R_OVERLAP_A) {
+ if (!(mul_flags & FFT_MUL_R_NORESIZE))
+ bf_resize(res, 0);
+ }
+ reduced_mem = (fft_len_log2 >= 14);
+ if (!reduced_mem) {
+ buf2 = ntt_malloc(s, sizeof(NTTLimb) * fft_len * nb_mods);
+ if (!buf2)
+ goto fail;
+ limb_to_ntt(s, buf2, fft_len, b_tab, b_len, dpl,
+ NB_MODS - nb_mods, nb_mods);
+ if (!(mul_flags & FFT_MUL_R_NORESIZE))
+ bf_resize(res, 0); /* in case res == b */
+ } else {
+ buf2 = ntt_malloc(s, sizeof(NTTLimb) * fft_len);
+ if (!buf2)
+ goto fail;
+ }
+ for(j = 0; j < nb_mods; j++) {
+ if (reduced_mem) {
+ limb_to_ntt(s, buf2, fft_len, b_tab, b_len, dpl,
+ NB_MODS - nb_mods + j, 1);
+ ptr = buf2;
+ } else {
+ ptr = buf2 + fft_len * j;
+ }
+ if (ntt_conv(s, buf1 + fft_len * j, ptr,
+ fft_len_log2, fft_len_log2, j + NB_MODS - nb_mods))
+ goto fail;
+ }
+ if (!(mul_flags & FFT_MUL_R_NORESIZE))
+ bf_resize(res, 0); /* in case res == b and reduced mem */
+ ntt_free(s, buf2);
+ buf2 = NULL;
+ if (!(mul_flags & FFT_MUL_R_NORESIZE)) {
+ if (bf_resize(res, len))
+ goto fail;
+ }
+ ntt_to_limb(s, res->tab, len, buf1, fft_len_log2, dpl, nb_mods);
+ ntt_free(s, buf1);
+#if defined(USE_MUL_CHECK)
+ hr = mp_mod1(res->tab, len, BF_CHKSUM_MOD, 0);
+ h_ref = mul_mod(ha, hb, BF_CHKSUM_MOD);
+ if (hr != h_ref) {
+ printf("ntt_mul_error: len=%" PRId_LIMB " fft_len_log2=%d dpl=%d nb_mods=%d\n",
+ len, fft_len_log2, dpl, nb_mods);
+ // printf("ha=0x" FMT_LIMB" hb=0x" FMT_LIMB " hr=0x" FMT_LIMB " expected=0x" FMT_LIMB "\n", ha, hb, hr, h_ref);
+ exit(1);
+ }
+#endif
+ return 0;
+ fail:
+ ntt_free(s, buf1);
+ ntt_free(s, buf2);
+ return -1;
+}
+
+#else /* USE_FFT_MUL */
+
+int bf_get_fft_size(int *pdpl, int *pnb_mods, limb_t len)
+{
+ return 0;
+}
+
+#endif /* !USE_FFT_MUL */
diff --git a/src/shared/quickjs/libbf.h b/src/shared/quickjs/libbf.h
new file mode 100644
index 000000000..b247952b1
--- /dev/null
+++ b/src/shared/quickjs/libbf.h
@@ -0,0 +1,543 @@
+/*
+ * Tiny arbitrary precision floating point library
+ *
+ * Copyright (c) 2017-2021 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#ifndef LIBBF_H
+#define LIBBF_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(__SIZEOF_INT128__) && (INTPTR_MAX >= INT64_MAX)
+#define LIMB_LOG2_BITS 6
+#else
+#define LIMB_LOG2_BITS 5
+#endif
+
+#define LIMB_BITS (1 << LIMB_LOG2_BITS)
+
+#if LIMB_BITS == 64
+typedef __int128 int128_t;
+typedef unsigned __int128 uint128_t;
+typedef int64_t slimb_t;
+typedef uint64_t limb_t;
+typedef uint128_t dlimb_t;
+#define BF_RAW_EXP_MIN INT64_MIN
+#define BF_RAW_EXP_MAX INT64_MAX
+
+#define LIMB_DIGITS 19
+#define BF_DEC_BASE UINT64_C(10000000000000000000)
+
+#else
+
+typedef int32_t slimb_t;
+typedef uint32_t limb_t;
+typedef uint64_t dlimb_t;
+#define BF_RAW_EXP_MIN INT32_MIN
+#define BF_RAW_EXP_MAX INT32_MAX
+
+#define LIMB_DIGITS 9
+#define BF_DEC_BASE 1000000000U
+
+#endif
+
+/* in bits */
+/* minimum number of bits for the exponent */
+#define BF_EXP_BITS_MIN 3
+/* maximum number of bits for the exponent */
+#define BF_EXP_BITS_MAX (LIMB_BITS - 3)
+/* extended range for exponent, used internally */
+#define BF_EXT_EXP_BITS_MAX (BF_EXP_BITS_MAX + 1)
+/* minimum possible precision */
+#define BF_PREC_MIN 2
+/* minimum possible precision */
+#define BF_PREC_MAX (((limb_t)1 << (LIMB_BITS - 2)) - 2)
+/* some operations support infinite precision */
+#define BF_PREC_INF (BF_PREC_MAX + 1) /* infinite precision */
+
+#if LIMB_BITS == 64
+#define BF_CHKSUM_MOD (UINT64_C(975620677) * UINT64_C(9795002197))
+#else
+#define BF_CHKSUM_MOD 975620677U
+#endif
+
+#define BF_EXP_ZERO BF_RAW_EXP_MIN
+#define BF_EXP_INF (BF_RAW_EXP_MAX - 1)
+#define BF_EXP_NAN BF_RAW_EXP_MAX
+
+/* +/-zero is represented with expn = BF_EXP_ZERO and len = 0,
+ +/-infinity is represented with expn = BF_EXP_INF and len = 0,
+ NaN is represented with expn = BF_EXP_NAN and len = 0 (sign is ignored)
+ */
+typedef struct {
+ struct bf_context_t *ctx;
+ int sign;
+ slimb_t expn;
+ limb_t len;
+ limb_t *tab;
+} bf_t;
+
+typedef struct {
+ /* must be kept identical to bf_t */
+ struct bf_context_t *ctx;
+ int sign;
+ slimb_t expn;
+ limb_t len;
+ limb_t *tab;
+} bfdec_t;
+
+typedef enum {
+ BF_RNDN, /* round to nearest, ties to even */
+ BF_RNDZ, /* round to zero */
+ BF_RNDD, /* round to -inf (the code relies on (BF_RNDD xor BF_RNDU) = 1) */
+ BF_RNDU, /* round to +inf */
+ BF_RNDNA, /* round to nearest, ties away from zero */
+ BF_RNDA, /* round away from zero */
+ BF_RNDF, /* faithful rounding (nondeterministic, either RNDD or RNDU,
+ inexact flag is always set) */
+} bf_rnd_t;
+
+/* allow subnormal numbers. Only available if the number of exponent
+ bits is <= BF_EXP_BITS_USER_MAX and prec != BF_PREC_INF. */
+#define BF_FLAG_SUBNORMAL (1 << 3)
+/* 'prec' is the precision after the radix point instead of the whole
+ mantissa. Can only be used with bf_round() and
+ bfdec_[add|sub|mul|div|sqrt|round](). */
+#define BF_FLAG_RADPNT_PREC (1 << 4)
+
+#define BF_RND_MASK 0x7
+#define BF_EXP_BITS_SHIFT 5
+#define BF_EXP_BITS_MASK 0x3f
+
+/* shortcut for bf_set_exp_bits(BF_EXT_EXP_BITS_MAX) */
+#define BF_FLAG_EXT_EXP (BF_EXP_BITS_MASK << BF_EXP_BITS_SHIFT)
+
+/* contains the rounding mode and number of exponents bits */
+typedef uint32_t bf_flags_t;
+
+typedef void *bf_realloc_func_t(void *opaque, void *ptr, size_t size);
+
+typedef struct {
+ bf_t val;
+ limb_t prec;
+} BFConstCache;
+
+typedef struct bf_context_t {
+ void *realloc_opaque;
+ bf_realloc_func_t *realloc_func;
+ BFConstCache log2_cache;
+ BFConstCache pi_cache;
+ struct BFNTTState *ntt_state;
+} bf_context_t;
+
+static inline int bf_get_exp_bits(bf_flags_t flags)
+{
+ int e;
+ e = (flags >> BF_EXP_BITS_SHIFT) & BF_EXP_BITS_MASK;
+ if (e == BF_EXP_BITS_MASK)
+ return BF_EXP_BITS_MAX + 1;
+ else
+ return BF_EXP_BITS_MAX - e;
+}
+
+static inline bf_flags_t bf_set_exp_bits(int n)
+{
+ return ((BF_EXP_BITS_MAX - n) & BF_EXP_BITS_MASK) << BF_EXP_BITS_SHIFT;
+}
+
+/* returned status */
+#define BF_ST_INVALID_OP (1 << 0)
+#define BF_ST_DIVIDE_ZERO (1 << 1)
+#define BF_ST_OVERFLOW (1 << 2)
+#define BF_ST_UNDERFLOW (1 << 3)
+#define BF_ST_INEXACT (1 << 4)
+/* indicate that a memory allocation error occured. NaN is returned */
+#define BF_ST_MEM_ERROR (1 << 5)
+
+#define BF_RADIX_MAX 36 /* maximum radix for bf_atof() and bf_ftoa() */
+
+static inline slimb_t bf_max(slimb_t a, slimb_t b)
+{
+ if (a > b)
+ return a;
+ else
+ return b;
+}
+
+static inline slimb_t bf_min(slimb_t a, slimb_t b)
+{
+ if (a < b)
+ return a;
+ else
+ return b;
+}
+
+void bf_context_init(bf_context_t *s, bf_realloc_func_t *realloc_func,
+ void *realloc_opaque);
+void bf_context_end(bf_context_t *s);
+/* free memory allocated for the bf cache data */
+void bf_clear_cache(bf_context_t *s);
+
+static inline void *bf_realloc(bf_context_t *s, void *ptr, size_t size)
+{
+ return s->realloc_func(s->realloc_opaque, ptr, size);
+}
+
+/* 'size' must be != 0 */
+static inline void *bf_malloc(bf_context_t *s, size_t size)
+{
+ return bf_realloc(s, NULL, size);
+}
+
+static inline void bf_free(bf_context_t *s, void *ptr)
+{
+ /* must test ptr otherwise equivalent to malloc(0) */
+ if (ptr)
+ bf_realloc(s, ptr, 0);
+}
+
+void bf_init(bf_context_t *s, bf_t *r);
+
+static inline void bf_delete(bf_t *r)
+{
+ bf_context_t *s = r->ctx;
+ /* we accept to delete a zeroed bf_t structure */
+ if (s && r->tab) {
+ bf_realloc(s, r->tab, 0);
+ }
+}
+
+static inline void bf_neg(bf_t *r)
+{
+ r->sign ^= 1;
+}
+
+static inline int bf_is_finite(const bf_t *a)
+{
+ return (a->expn < BF_EXP_INF);
+}
+
+static inline int bf_is_nan(const bf_t *a)
+{
+ return (a->expn == BF_EXP_NAN);
+}
+
+static inline int bf_is_zero(const bf_t *a)
+{
+ return (a->expn == BF_EXP_ZERO);
+}
+
+static inline void bf_memcpy(bf_t *r, const bf_t *a)
+{
+ *r = *a;
+}
+
+int bf_set_ui(bf_t *r, uint64_t a);
+int bf_set_si(bf_t *r, int64_t a);
+void bf_set_nan(bf_t *r);
+void bf_set_zero(bf_t *r, int is_neg);
+void bf_set_inf(bf_t *r, int is_neg);
+int bf_set(bf_t *r, const bf_t *a);
+void bf_move(bf_t *r, bf_t *a);
+int bf_get_float64(const bf_t *a, double *pres, bf_rnd_t rnd_mode);
+int bf_set_float64(bf_t *a, double d);
+
+int bf_cmpu(const bf_t *a, const bf_t *b);
+int bf_cmp_full(const bf_t *a, const bf_t *b);
+int bf_cmp(const bf_t *a, const bf_t *b);
+static inline int bf_cmp_eq(const bf_t *a, const bf_t *b)
+{
+ return bf_cmp(a, b) == 0;
+}
+
+static inline int bf_cmp_le(const bf_t *a, const bf_t *b)
+{
+ return bf_cmp(a, b) <= 0;
+}
+
+static inline int bf_cmp_lt(const bf_t *a, const bf_t *b)
+{
+ return bf_cmp(a, b) < 0;
+}
+
+int bf_add(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags);
+int bf_sub(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags);
+int bf_add_si(bf_t *r, const bf_t *a, int64_t b1, limb_t prec, bf_flags_t flags);
+int bf_mul(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags);
+int bf_mul_ui(bf_t *r, const bf_t *a, uint64_t b1, limb_t prec, bf_flags_t flags);
+int bf_mul_si(bf_t *r, const bf_t *a, int64_t b1, limb_t prec,
+ bf_flags_t flags);
+int bf_mul_2exp(bf_t *r, slimb_t e, limb_t prec, bf_flags_t flags);
+int bf_div(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags);
+#define BF_DIVREM_EUCLIDIAN BF_RNDF
+int bf_divrem(bf_t *q, bf_t *r, const bf_t *a, const bf_t *b,
+ limb_t prec, bf_flags_t flags, int rnd_mode);
+int bf_rem(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
+ bf_flags_t flags, int rnd_mode);
+int bf_remquo(slimb_t *pq, bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
+ bf_flags_t flags, int rnd_mode);
+/* round to integer with infinite precision */
+int bf_rint(bf_t *r, int rnd_mode);
+int bf_round(bf_t *r, limb_t prec, bf_flags_t flags);
+int bf_sqrtrem(bf_t *r, bf_t *rem1, const bf_t *a);
+int bf_sqrt(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
+slimb_t bf_get_exp_min(const bf_t *a);
+int bf_logic_or(bf_t *r, const bf_t *a, const bf_t *b);
+int bf_logic_xor(bf_t *r, const bf_t *a, const bf_t *b);
+int bf_logic_and(bf_t *r, const bf_t *a, const bf_t *b);
+
+/* additional flags for bf_atof */
+/* do not accept hex radix prefix (0x or 0X) if radix = 0 or radix = 16 */
+#define BF_ATOF_NO_HEX (1 << 16)
+/* accept binary (0b or 0B) or octal (0o or 0O) radix prefix if radix = 0 */
+#define BF_ATOF_BIN_OCT (1 << 17)
+/* Do not parse NaN or Inf */
+#define BF_ATOF_NO_NAN_INF (1 << 18)
+/* return the exponent separately */
+#define BF_ATOF_EXPONENT (1 << 19)
+
+int bf_atof(bf_t *a, const char *str, const char **pnext, int radix,
+ limb_t prec, bf_flags_t flags);
+/* this version accepts prec = BF_PREC_INF and returns the radix
+ exponent */
+int bf_atof2(bf_t *r, slimb_t *pexponent,
+ const char *str, const char **pnext, int radix,
+ limb_t prec, bf_flags_t flags);
+int bf_mul_pow_radix(bf_t *r, const bf_t *T, limb_t radix,
+ slimb_t expn, limb_t prec, bf_flags_t flags);
+
+
+/* Conversion of floating point number to string. Return a null
+ terminated string or NULL if memory error. *plen contains its
+ length if plen != NULL. The exponent letter is "e" for base 10,
+ "p" for bases 2, 8, 16 with a binary exponent and "@" for the other
+ bases. */
+
+#define BF_FTOA_FORMAT_MASK (3 << 16)
+
+/* fixed format: prec significant digits rounded with (flags &
+ BF_RND_MASK). Exponential notation is used if too many zeros are
+ needed.*/
+#define BF_FTOA_FORMAT_FIXED (0 << 16)
+/* fractional format: prec digits after the decimal point rounded with
+ (flags & BF_RND_MASK) */
+#define BF_FTOA_FORMAT_FRAC (1 << 16)
+/* free format:
+
+ For binary radices with bf_ftoa() and for bfdec_ftoa(): use the minimum
+ number of digits to represent 'a'. The precision and the rounding
+ mode are ignored.
+
+ For the non binary radices with bf_ftoa(): use as many digits as
+ necessary so that bf_atof() return the same number when using
+ precision 'prec', rounding to nearest and the subnormal
+ configuration of 'flags'. The result is meaningful only if 'a' is
+ already rounded to 'prec' bits. If the subnormal flag is set, the
+ exponent in 'flags' must also be set to the desired exponent range.
+*/
+#define BF_FTOA_FORMAT_FREE (2 << 16)
+/* same as BF_FTOA_FORMAT_FREE but uses the minimum number of digits
+ (takes more computation time). Identical to BF_FTOA_FORMAT_FREE for
+ binary radices with bf_ftoa() and for bfdec_ftoa(). */
+#define BF_FTOA_FORMAT_FREE_MIN (3 << 16)
+
+/* force exponential notation for fixed or free format */
+#define BF_FTOA_FORCE_EXP (1 << 20)
+/* add 0x prefix for base 16, 0o prefix for base 8 or 0b prefix for
+ base 2 if non zero value */
+#define BF_FTOA_ADD_PREFIX (1 << 21)
+/* return "Infinity" instead of "Inf" and add a "+" for positive
+ exponents */
+#define BF_FTOA_JS_QUIRKS (1 << 22)
+
+char *bf_ftoa(size_t *plen, const bf_t *a, int radix, limb_t prec,
+ bf_flags_t flags);
+
+/* modulo 2^n instead of saturation. NaN and infinity return 0 */
+#define BF_GET_INT_MOD (1 << 0)
+int bf_get_int32(int *pres, const bf_t *a, int flags);
+int bf_get_int64(int64_t *pres, const bf_t *a, int flags);
+int bf_get_uint64(uint64_t *pres, const bf_t *a);
+
+/* the following functions are exported for testing only. */
+void mp_print_str(const char *str, const limb_t *tab, limb_t n);
+void bf_print_str(const char *str, const bf_t *a);
+int bf_resize(bf_t *r, limb_t len);
+int bf_get_fft_size(int *pdpl, int *pnb_mods, limb_t len);
+int bf_normalize_and_round(bf_t *r, limb_t prec1, bf_flags_t flags);
+int bf_can_round(const bf_t *a, slimb_t prec, bf_rnd_t rnd_mode, slimb_t k);
+slimb_t bf_mul_log2_radix(slimb_t a1, unsigned int radix, int is_inv,
+ int is_ceil1);
+int mp_mul(bf_context_t *s, limb_t *result,
+ const limb_t *op1, limb_t op1_size,
+ const limb_t *op2, limb_t op2_size);
+limb_t mp_add(limb_t *res, const limb_t *op1, const limb_t *op2,
+ limb_t n, limb_t carry);
+limb_t mp_add_ui(limb_t *tab, limb_t b, size_t n);
+int mp_sqrtrem(bf_context_t *s, limb_t *tabs, limb_t *taba, limb_t n);
+int mp_recip(bf_context_t *s, limb_t *tabr, const limb_t *taba, limb_t n);
+limb_t bf_isqrt(limb_t a);
+
+/* transcendental functions */
+int bf_const_log2(bf_t *T, limb_t prec, bf_flags_t flags);
+int bf_const_pi(bf_t *T, limb_t prec, bf_flags_t flags);
+int bf_exp(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
+int bf_log(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
+#define BF_POW_JS_QUIRKS (1 << 16) /* (+/-1)^(+/-Inf) = NaN, 1^NaN = NaN */
+int bf_pow(bf_t *r, const bf_t *x, const bf_t *y, limb_t prec, bf_flags_t flags);
+int bf_cos(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
+int bf_sin(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
+int bf_tan(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
+int bf_atan(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
+int bf_atan2(bf_t *r, const bf_t *y, const bf_t *x,
+ limb_t prec, bf_flags_t flags);
+int bf_asin(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
+int bf_acos(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
+
+/* decimal floating point */
+
+static inline void bfdec_init(bf_context_t *s, bfdec_t *r)
+{
+ bf_init(s, (bf_t *)r);
+}
+static inline void bfdec_delete(bfdec_t *r)
+{
+ bf_delete((bf_t *)r);
+}
+
+static inline void bfdec_neg(bfdec_t *r)
+{
+ r->sign ^= 1;
+}
+
+static inline int bfdec_is_finite(const bfdec_t *a)
+{
+ return (a->expn < BF_EXP_INF);
+}
+
+static inline int bfdec_is_nan(const bfdec_t *a)
+{
+ return (a->expn == BF_EXP_NAN);
+}
+
+static inline int bfdec_is_zero(const bfdec_t *a)
+{
+ return (a->expn == BF_EXP_ZERO);
+}
+
+static inline void bfdec_memcpy(bfdec_t *r, const bfdec_t *a)
+{
+ bf_memcpy((bf_t *)r, (const bf_t *)a);
+}
+
+int bfdec_set_ui(bfdec_t *r, uint64_t a);
+int bfdec_set_si(bfdec_t *r, int64_t a);
+
+static inline void bfdec_set_nan(bfdec_t *r)
+{
+ bf_set_nan((bf_t *)r);
+}
+static inline void bfdec_set_zero(bfdec_t *r, int is_neg)
+{
+ bf_set_zero((bf_t *)r, is_neg);
+}
+static inline void bfdec_set_inf(bfdec_t *r, int is_neg)
+{
+ bf_set_inf((bf_t *)r, is_neg);
+}
+static inline int bfdec_set(bfdec_t *r, const bfdec_t *a)
+{
+ return bf_set((bf_t *)r, (bf_t *)a);
+}
+static inline void bfdec_move(bfdec_t *r, bfdec_t *a)
+{
+ bf_move((bf_t *)r, (bf_t *)a);
+}
+static inline int bfdec_cmpu(const bfdec_t *a, const bfdec_t *b)
+{
+ return bf_cmpu((const bf_t *)a, (const bf_t *)b);
+}
+static inline int bfdec_cmp_full(const bfdec_t *a, const bfdec_t *b)
+{
+ return bf_cmp_full((const bf_t *)a, (const bf_t *)b);
+}
+static inline int bfdec_cmp(const bfdec_t *a, const bfdec_t *b)
+{
+ return bf_cmp((const bf_t *)a, (const bf_t *)b);
+}
+static inline int bfdec_cmp_eq(const bfdec_t *a, const bfdec_t *b)
+{
+ return bfdec_cmp(a, b) == 0;
+}
+static inline int bfdec_cmp_le(const bfdec_t *a, const bfdec_t *b)
+{
+ return bfdec_cmp(a, b) <= 0;
+}
+static inline int bfdec_cmp_lt(const bfdec_t *a, const bfdec_t *b)
+{
+ return bfdec_cmp(a, b) < 0;
+}
+
+int bfdec_add(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
+ bf_flags_t flags);
+int bfdec_sub(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
+ bf_flags_t flags);
+int bfdec_add_si(bfdec_t *r, const bfdec_t *a, int64_t b1, limb_t prec,
+ bf_flags_t flags);
+int bfdec_mul(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
+ bf_flags_t flags);
+int bfdec_mul_si(bfdec_t *r, const bfdec_t *a, int64_t b1, limb_t prec,
+ bf_flags_t flags);
+int bfdec_div(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
+ bf_flags_t flags);
+int bfdec_divrem(bfdec_t *q, bfdec_t *r, const bfdec_t *a, const bfdec_t *b,
+ limb_t prec, bf_flags_t flags, int rnd_mode);
+int bfdec_rem(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
+ bf_flags_t flags, int rnd_mode);
+int bfdec_rint(bfdec_t *r, int rnd_mode);
+int bfdec_sqrt(bfdec_t *r, const bfdec_t *a, limb_t prec, bf_flags_t flags);
+int bfdec_round(bfdec_t *r, limb_t prec, bf_flags_t flags);
+int bfdec_get_int32(int *pres, const bfdec_t *a);
+int bfdec_pow_ui(bfdec_t *r, const bfdec_t *a, limb_t b);
+
+char *bfdec_ftoa(size_t *plen, const bfdec_t *a, limb_t prec, bf_flags_t flags);
+int bfdec_atof(bfdec_t *r, const char *str, const char **pnext,
+ limb_t prec, bf_flags_t flags);
+
+/* the following functions are exported for testing only. */
+extern const limb_t mp_pow_dec[LIMB_DIGITS + 1];
+void bfdec_print_str(const char *str, const bfdec_t *a);
+static inline int bfdec_resize(bfdec_t *r, limb_t len)
+{
+ return bf_resize((bf_t *)r, len);
+}
+int bfdec_normalize_and_round(bfdec_t *r, limb_t prec1, bf_flags_t flags);
+
+#ifdef __cplusplus
+} /* extern "C" { */
+#endif
+
+#endif /* LIBBF_H */
diff --git a/src/shared/quickjs/libregexp-opcode.h b/src/shared/quickjs/libregexp-opcode.h
index f90c23b34..f255e09f2 100644
--- a/src/shared/quickjs/libregexp-opcode.h
+++ b/src/shared/quickjs/libregexp-opcode.h
@@ -1,6 +1,6 @@
/*
* Regular Expression Engine
- *
+ *
* Copyright (c) 2017-2018 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -50,8 +50,7 @@ DEF(range32, 3) /* variable length */
DEF(lookahead, 5)
DEF(negative_lookahead, 5)
DEF(push_char_pos, 1) /* push the character position on the stack */
-DEF(bne_char_pos, 5) /* pop one stack element and jump if equal to the character
- position */
+DEF(check_advance, 1) /* pop one stack element and check that it is different from the character position */
DEF(prev, 1) /* go to the previous char */
DEF(simple_greedy_quant, 17)
diff --git a/src/shared/quickjs/libregexp.c b/src/shared/quickjs/libregexp.c
index ad91f781a..4db042941 100644
--- a/src/shared/quickjs/libregexp.c
+++ b/src/shared/quickjs/libregexp.c
@@ -30,13 +30,11 @@
#include "cutils.h"
#include "libregexp.h"
+#include "libunicode.h"
/*
TODO:
- - Add full unicode canonicalize rules for character ranges (not
- really useful but needed for exact "ignorecase" compatibility).
-
- Add a lock step execution mode (=linear time execution guaranteed)
when the regular expression is "simple" i.e. no backreference nor
complicated lookahead. The opcodes are designed for this execution
@@ -69,7 +67,7 @@ typedef struct {
const uint8_t *buf_end;
const uint8_t *buf_start;
int re_flags;
- BOOL is_utf16;
+ BOOL is_unicode;
BOOL ignore_case;
BOOL dotall;
int capture_count;
@@ -103,6 +101,7 @@ static const REOpCode reopcode_info[REOP_COUNT] = {
#define RE_HEADER_FLAGS 0
#define RE_HEADER_CAPTURE_COUNT 1
#define RE_HEADER_STACK_SIZE 2
+#define RE_HEADER_BYTECODE_LEN 3
#define RE_HEADER_LEN 7
@@ -120,33 +119,6 @@ static int dbuf_insert(DynBuf *s, int pos, int len)
return 0;
}
-/* canonicalize with the specific JS regexp rules */
-static uint32_t lre_canonicalize(uint32_t c, BOOL is_utf16)
-{
- uint32_t res[LRE_CC_RES_LEN_MAX];
- int len;
- if (is_utf16) {
- if (likely(c < 128)) {
- if (c >= 'A' && c <= 'Z')
- c = c - 'A' + 'a';
- } else {
- lre_case_conv(res, c, 2);
- c = res[0];
- }
- } else {
- if (likely(c < 128)) {
- if (c >= 'a' && c <= 'z')
- c = c - 'a' + 'A';
- } else {
- /* legacy regexp: to upper case if single char >= 128 */
- len = lre_case_conv(res, c, FALSE);
- if (len == 1 && res[0] >= 128)
- c = res[0];
- }
- }
- return c;
-}
-
static const uint16_t char_range_d[] = {
1,
0x0030, 0x0039 + 1,
@@ -170,32 +142,6 @@ static const uint16_t char_range_s[] = {
0xFEFF, 0xFEFF + 1,
};
-BOOL lre_is_space(int c)
-{
- int i, n, low, high;
- n = (countof(char_range_s) - 1) / 2;
- for(i = 0; i < n; i++) {
- low = char_range_s[2 * i + 1];
- if (c < low)
- return FALSE;
- high = char_range_s[2 * i + 2];
- if (c < high)
- return TRUE;
- }
- return FALSE;
-}
-
-uint32_t const lre_id_start_table_ascii[4] = {
- /* $ A-Z _ a-z */
- 0x00000000, 0x00000010, 0x87FFFFFE, 0x07FFFFFE
-};
-
-uint32_t const lre_id_continue_table_ascii[4] = {
- /* $ 0-9 A-Z _ a-z */
- 0x00000000, 0x03FF0010, 0x87FFFFFE, 0x07FFFFFE
-};
-
-
static const uint16_t char_range_w[] = {
4,
0x0030, 0x0039 + 1,
@@ -215,7 +161,7 @@ typedef enum {
CHAR_RANGE_W,
} CharRangeEnum;
-static const uint16_t *char_range_table[] = {
+static const uint16_t * const char_range_table[] = {
char_range_d,
char_range_s,
char_range_w,
@@ -245,33 +191,8 @@ static int cr_init_char_range(REParseState *s, CharRange *cr, uint32_t c)
return -1;
}
-static int cr_canonicalize(CharRange *cr)
-{
- CharRange a;
- uint32_t pt[2];
- int i, ret;
-
- cr_init(&a, cr->mem_opaque, lre_realloc);
- pt[0] = 'a';
- pt[1] = 'z' + 1;
- ret = cr_op(&a, cr->points, cr->len, pt, 2, CR_OP_INTER);
- if (ret)
- goto fail;
- /* convert to upper case */
- /* XXX: the generic unicode case would be much more complicated
- and not really useful */
- for(i = 0; i < a.len; i++) {
- a.points[i] += 'A' - 'a';
- }
- /* Note: for simplicity we keep the lower case ranges */
- ret = cr_union1(cr, a.points, a.len);
- fail:
- cr_free(&a);
- return ret;
-}
-
#ifdef DUMP_REOP
-static MAYBE_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;
@@ -279,16 +200,16 @@ static MAYBE_UNUSED void lre_dump_bytecode(const uint8_t *buf,
assert(buf_len >= RE_HEADER_LEN);
- re_flags= buf[0];
- bc_len = get_u32(buf + 3);
+ re_flags = lre_get_flags(buf);
+ bc_len = get_u32(buf + RE_HEADER_BYTECODE_LEN);
assert(bc_len + RE_HEADER_LEN <= buf_len);
printf("flags: 0x%x capture_count=%d stack_size=%d\n",
- re_flags, buf[1], buf[2]);
+ re_flags, buf[RE_HEADER_CAPTURE_COUNT], buf[RE_HEADER_STACK_SIZE]);
if (re_flags & LRE_FLAG_NAMED_GROUPS) {
const char *p;
p = (char *)buf + RE_HEADER_LEN + bc_len;
printf("named groups: ");
- for(i = 1; i < buf[1]; i++) {
+ for(i = 1; i < buf[RE_HEADER_CAPTURE_COUNT]; i++) {
if (i != 1)
printf(",");
printf("<%s>", p);
@@ -335,7 +256,6 @@ static MAYBE_UNUSED void lre_dump_bytecode(const uint8_t *buf,
case REOP_loop:
case REOP_lookahead:
case REOP_negative_lookahead:
- case REOP_bne_char_pos:
val = get_u32(buf + pos + 1);
val += (pos + 5);
printf(" %u", val);
@@ -550,7 +470,7 @@ int lre_parse_escape(const uint8_t **pp, int allow_utf16)
}
c = (c << 4) | h;
}
- if (c >= 0xd800 && c < 0xdc00 &&
+ if (is_hi_surrogate(c) &&
allow_utf16 == 2 && p[0] == '\\' && p[1] == 'u') {
/* convert an escaped surrogate pair into a
unicode char */
@@ -561,9 +481,9 @@ int lre_parse_escape(const uint8_t **pp, int allow_utf16)
break;
c1 = (c1 << 4) | h;
}
- if (i == 4 && c1 >= 0xdc00 && c1 < 0xe000) {
+ if (i == 4 && is_lo_surrogate(c1)) {
p += 6;
- c = (((c & 0x3ff) << 10) | (c1 & 0x3ff)) + 0x10000;
+ c = from_surrogate(c, c1);
}
}
}
@@ -752,10 +672,10 @@ static int get_class_atom(REParseState *s, CharRange *cr,
if ((c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') ||
(((c >= '0' && c <= '9') || c == '_') &&
- inclass && !s->is_utf16)) { /* Annex B.1.4 */
+ inclass && !s->is_unicode)) { /* Annex B.1.4 */
c &= 0x1f;
p++;
- } else if (s->is_utf16) {
+ } else if (s->is_unicode) {
goto invalid_escape;
} else {
/* otherwise return '\' and 'c' */
@@ -766,7 +686,7 @@ static int get_class_atom(REParseState *s, CharRange *cr,
#ifdef CONFIG_ALL_UNICODE
case 'p':
case 'P':
- if (s->is_utf16) {
+ if (s->is_unicode) {
if (parse_unicode_property(s, cr, &p, (c == 'P')))
return -1;
c = CLASS_RANGE_BASE;
@@ -776,14 +696,14 @@ static int get_class_atom(REParseState *s, CharRange *cr,
#endif
default:
p--;
- ret = lre_parse_escape(&p, s->is_utf16 * 2);
+ ret = lre_parse_escape(&p, s->is_unicode * 2);
if (ret >= 0) {
c = ret;
} else {
if (ret == -2 && *p != '\0' && strchr("^$\\.*+?()[]{}|/", *p)) {
/* always valid to escape these characters */
goto normal_char;
- } else if (s->is_utf16) {
+ } else if (s->is_unicode) {
invalid_escape:
return re_parse_error(s, "invalid escape sequence in regular expression");
} else {
@@ -805,7 +725,7 @@ static int get_class_atom(REParseState *s, CharRange *cr,
/* normal char */
if (c >= 128) {
c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p);
- if ((unsigned)c > 0xffff && !s->is_utf16) {
+ if ((unsigned)c > 0xffff && !s->is_unicode) {
/* XXX: should handle non BMP-1 code points */
return re_parse_error(s, "malformed unicode char");
}
@@ -867,11 +787,13 @@ static int re_parse_char_class(REParseState *s, const uint8_t **pp)
cr_init(cr, s->opaque, lre_realloc);
p = *pp;
p++; /* skip '[' */
+
invert = FALSE;
if (*p == '^') {
p++;
invert = TRUE;
}
+
for(;;) {
if (*p == ']')
break;
@@ -881,7 +803,7 @@ static int re_parse_char_class(REParseState *s, const uint8_t **pp)
if (*p == '-' && p[1] != ']') {
const uint8_t *p0 = p + 1;
if (c1 >= CLASS_RANGE_BASE) {
- if (s->is_utf16) {
+ if (s->is_unicode) {
cr_free(cr1);
goto invalid_class_range;
}
@@ -893,7 +815,7 @@ static int re_parse_char_class(REParseState *s, const uint8_t **pp)
goto fail;
if (c2 >= CLASS_RANGE_BASE) {
cr_free(cr1);
- if (s->is_utf16) {
+ if (s->is_unicode) {
goto invalid_class_range;
}
/* Annex B: match '-' character */
@@ -922,7 +844,7 @@ static int re_parse_char_class(REParseState *s, const uint8_t **pp)
}
}
if (s->ignore_case) {
- if (cr_canonicalize(cr))
+ if (cr_regexp_canonicalize(cr, s->is_unicode))
goto memory_error;
}
if (invert) {
@@ -943,22 +865,17 @@ static int re_parse_char_class(REParseState *s, const uint8_t **pp)
}
/* Return:
- 1 if the opcodes in bc_buf[] always advance the character pointer.
- 0 if the character pointer may not be advanced.
- -1 if the code may depend on side effects of its previous execution (backreference)
+ - true if the opcodes may not advance the char pointer
+ - false if the opcodes always advance the char pointer
*/
-static int re_check_advance(const uint8_t *bc_buf, int bc_buf_len)
+static BOOL re_need_check_advance(const uint8_t *bc_buf, int bc_buf_len)
{
- int pos, opcode, ret, len, i;
- uint32_t val, last;
- BOOL has_back_reference;
- uint8_t capture_bitmap[CAPTURE_COUNT_MAX];
+ int pos, opcode, len;
+ uint32_t val;
+ BOOL ret;
- ret = -2; /* not known yet */
+ ret = TRUE;
pos = 0;
- has_back_reference = FALSE;
- memset(capture_bitmap, 0, sizeof(capture_bitmap));
-
while (pos < bc_buf_len) {
opcode = bc_buf[pos];
len = reopcode_info[opcode].size;
@@ -976,8 +893,7 @@ static int re_check_advance(const uint8_t *bc_buf, int bc_buf_len)
case REOP_dot:
case REOP_any:
simple_char:
- if (ret == -2)
- ret = 1;
+ ret = FALSE;
break;
case REOP_line_start:
case REOP_line_end:
@@ -991,41 +907,16 @@ static int re_check_advance(const uint8_t *bc_buf, int bc_buf_len)
break;
case REOP_save_start:
case REOP_save_end:
- val = bc_buf[pos + 1];
- capture_bitmap[val] |= 1;
- break;
case REOP_save_reset:
- {
- val = bc_buf[pos + 1];
- last = bc_buf[pos + 2];
- while (val < last)
- capture_bitmap[val++] |= 1;
- }
- break;
case REOP_back_reference:
case REOP_backward_back_reference:
- val = bc_buf[pos + 1];
- capture_bitmap[val] |= 2;
- has_back_reference = TRUE;
break;
default:
- /* safe behvior: we cannot predict the outcome */
- if (ret == -2)
- ret = 0;
- break;
+ /* safe behavior: we cannot predict the outcome */
+ return TRUE;
}
pos += len;
}
- if (has_back_reference) {
- /* check if there is back reference which references a capture
- made in the some code */
- for(i = 0; i < CAPTURE_COUNT_MAX; i++) {
- if (capture_bitmap[i] == 3)
- return -1;
- }
- }
- if (ret == -2)
- ret = 0;
return ret;
}
@@ -1071,11 +962,10 @@ static int re_is_simple_quantifier(const uint8_t *bc_buf, int bc_buf_len)
}
/* '*pp' is the first char after '<' */
-static int re_parse_group_name(char *buf, int buf_size,
- const uint8_t **pp, BOOL is_utf16)
+static int re_parse_group_name(char *buf, int buf_size, const uint8_t **pp)
{
- const uint8_t *p;
- uint32_t c;
+ const uint8_t *p, *p1;
+ uint32_t c, d;
char *q;
p = *pp;
@@ -1086,11 +976,18 @@ static int re_parse_group_name(char *buf, int buf_size,
p++;
if (*p != 'u')
return -1;
- c = lre_parse_escape(&p, is_utf16 * 2);
+ c = lre_parse_escape(&p, 2); // accept surrogate pairs
} else if (c == '>') {
break;
} else if (c >= 128) {
c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p);
+ if (is_hi_surrogate(c)) {
+ d = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p1);
+ if (is_lo_surrogate(d)) {
+ c = from_surrogate(c, d);
+ p = p1;
+ }
+ }
} else {
p++;
}
@@ -1140,8 +1037,7 @@ static int re_parse_captures(REParseState *s, int *phas_named_captures,
/* potential named capture */
if (capture_name) {
p += 3;
- if (re_parse_group_name(name, sizeof(name), &p,
- s->is_utf16) == 0) {
+ if (re_parse_group_name(name, sizeof(name), &p) == 0) {
if (!strcmp(name, capture_name))
return capture_index;
}
@@ -1196,9 +1092,10 @@ static int find_group_name(REParseState *s, const char *name)
size_t len, name_len;
int capture_index;
- name_len = strlen(name);
p = (char *)s->group_names.buf;
+ if (!p) return -1;
buf_end = (char *)s->group_names.buf + s->group_names.size;
+ name_len = strlen(name);
capture_index = 1;
while (p < buf_end) {
len = strlen(p);
@@ -1243,7 +1140,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
re_emit_op(s, REOP_prev);
break;
case '{':
- if (s->is_utf16) {
+ if (s->is_unicode) {
return re_parse_error(s, "syntax error");
} else if (!is_digit(p[1])) {
/* Annex B: we accept '{' not followed by digits as a
@@ -1295,7 +1192,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
lookahead:
/* Annex B allows lookahead to be used as an atom for
the quantifiers */
- if (!s->is_utf16 && !is_backward_lookahead) {
+ if (!s->is_unicode && !is_backward_lookahead) {
last_atom_start = s->byte_code.size;
last_capture_count = s->capture_count;
}
@@ -1314,7 +1211,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
} else if (p[2] == '<') {
p += 3;
if (re_parse_group_name(s->u.tmp_buf, sizeof(s->u.tmp_buf),
- &p, s->is_utf16)) {
+ &p)) {
return re_parse_error(s, "invalid group name");
}
if (find_group_name(s, s->u.tmp_buf) > 0) {
@@ -1371,15 +1268,15 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
/* annex B: we tolerate invalid group names in non
unicode mode if there is no named capture
definition */
- if (s->is_utf16 || re_has_named_captures(s))
+ if (s->is_unicode || re_has_named_captures(s))
return re_parse_error(s, "expecting group name");
else
goto parse_class_atom;
}
p1 += 3;
if (re_parse_group_name(s->u.tmp_buf, sizeof(s->u.tmp_buf),
- &p1, s->is_utf16)) {
- if (s->is_utf16 || re_has_named_captures(s))
+ &p1)) {
+ if (s->is_unicode || re_has_named_captures(s))
return re_parse_error(s, "invalid group name");
else
goto parse_class_atom;
@@ -1390,7 +1287,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
after (inefficient, but hopefully not common */
c = re_parse_captures(s, &dummy_res, s->u.tmp_buf);
if (c < 0) {
- if (s->is_utf16 || re_has_named_captures(s))
+ if (s->is_unicode || re_has_named_captures(s))
return re_parse_error(s, "group name not defined");
else
goto parse_class_atom;
@@ -1402,7 +1299,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
case '0':
p += 2;
c = 0;
- if (s->is_utf16) {
+ if (s->is_unicode) {
if (is_digit(*p)) {
return re_parse_error(s, "invalid decimal escape in regular expression");
}
@@ -1424,7 +1321,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
c = parse_digits(&p, FALSE);
if (c < 0 || (c >= s->capture_count && c >= re_count_captures(s))) {
- if (!s->is_utf16) {
+ if (!s->is_unicode) {
/* Annex B.1.4: accept legacy octal */
p = q;
if (*p <= '7') {
@@ -1466,13 +1363,13 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
break;
case ']':
case '}':
- if (s->is_utf16)
+ if (s->is_unicode)
return re_parse_error(s, "syntax error");
goto parse_class_atom;
default:
parse_class_atom:
c = get_class_atom(s, cr, &p, FALSE);
- if (c < 0)
+ if ((int)c < 0)
return -1;
normal_char:
last_atom_start = s->byte_code.size;
@@ -1488,7 +1385,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
return -1;
} else {
if (s->ignore_case)
- c = lre_canonicalize(c, s->is_utf16);
+ c = lre_canonicalize(c, s->is_unicode);
if (c <= 0xffff)
re_emit_op_u16(s, REOP_char, c);
else
@@ -1524,7 +1421,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
/* As an extension (see ES6 annex B), we accept '{' not
followed by digits as a normal atom */
if (!is_digit(p[1])) {
- if (s->is_utf16)
+ if (s->is_unicode)
goto invalid_quant_count;
break;
}
@@ -1543,7 +1440,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
quant_max = INT32_MAX; /* infinity */
}
}
- if (*p != '}' && !s->is_utf16) {
+ if (*p != '}' && !s->is_unicode) {
/* Annex B: normal atom if invalid '{' syntax */
p = p1;
break;
@@ -1591,8 +1488,12 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
if (dbuf_error(&s->byte_code))
goto out_of_memory;
- add_zero_advance_check = (re_check_advance(s->byte_code.buf + last_atom_start,
- s->byte_code.size - last_atom_start) == 0);
+ /* the spec tells that if there is no advance when
+ running the atom after the first quant_min times,
+ then there is no match. We remove this test when we
+ are sure the atom always advances the position. */
+ add_zero_advance_check = re_need_check_advance(s->byte_code.buf + last_atom_start,
+ s->byte_code.size - last_atom_start);
} else {
add_zero_advance_check = FALSE;
}
@@ -1612,38 +1513,34 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
}
if (quant_max == 0) {
s->byte_code.size = last_atom_start;
- } else if (quant_max == 1) {
- if (dbuf_insert(&s->byte_code, last_atom_start, 5))
- goto out_of_memory;
- s->byte_code.buf[last_atom_start] = REOP_split_goto_first +
- greedy;
- put_u32(s->byte_code.buf + last_atom_start + 1, len);
- } else if (quant_max == INT32_MAX) {
+ } else if (quant_max == 1 || quant_max == INT32_MAX) {
+ BOOL has_goto = (quant_max == INT32_MAX);
if (dbuf_insert(&s->byte_code, last_atom_start, 5 + add_zero_advance_check))
goto out_of_memory;
s->byte_code.buf[last_atom_start] = REOP_split_goto_first +
greedy;
put_u32(s->byte_code.buf + last_atom_start + 1,
- len + 5 + add_zero_advance_check);
+ len + 5 * has_goto + add_zero_advance_check * 2);
if (add_zero_advance_check) {
- /* avoid infinite loop by stoping the
- recursion if no advance was made in the
- atom (only works if the atom has no
- side effect) */
s->byte_code.buf[last_atom_start + 1 + 4] = REOP_push_char_pos;
- re_emit_goto(s, REOP_bne_char_pos, last_atom_start);
- } else {
- re_emit_goto(s, REOP_goto, last_atom_start);
+ re_emit_op(s, REOP_check_advance);
}
+ if (has_goto)
+ re_emit_goto(s, REOP_goto, last_atom_start);
} else {
- if (dbuf_insert(&s->byte_code, last_atom_start, 10))
+ if (dbuf_insert(&s->byte_code, last_atom_start, 10 + add_zero_advance_check))
goto out_of_memory;
pos = last_atom_start;
s->byte_code.buf[pos++] = REOP_push_i32;
put_u32(s->byte_code.buf + pos, quant_max);
pos += 4;
s->byte_code.buf[pos++] = REOP_split_goto_first + greedy;
- put_u32(s->byte_code.buf + pos, len + 5);
+ put_u32(s->byte_code.buf + pos, len + 5 + add_zero_advance_check * 2);
+ pos += 4;
+ if (add_zero_advance_check) {
+ s->byte_code.buf[pos++] = REOP_push_char_pos;
+ re_emit_op(s, REOP_check_advance);
+ }
re_emit_goto(s, REOP_loop, last_atom_start + 5);
re_emit_op(s, REOP_drop);
}
@@ -1667,22 +1564,25 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
if (quant_max == INT32_MAX) {
pos = s->byte_code.size;
re_emit_op_u32(s, REOP_split_goto_first + greedy,
- len + 5 + add_zero_advance_check);
+ len + 5 + add_zero_advance_check * 2);
if (add_zero_advance_check)
re_emit_op(s, REOP_push_char_pos);
/* copy the atom */
dbuf_put_self(&s->byte_code, last_atom_start, len);
if (add_zero_advance_check)
- re_emit_goto(s, REOP_bne_char_pos, pos);
- else
- re_emit_goto(s, REOP_goto, pos);
+ re_emit_op(s, REOP_check_advance);
+ re_emit_goto(s, REOP_goto, pos);
} else if (quant_max > quant_min) {
re_emit_op_u32(s, REOP_push_i32, quant_max - quant_min);
pos = s->byte_code.size;
- re_emit_op_u32(s, REOP_split_goto_first + greedy, len + 5);
+ re_emit_op_u32(s, REOP_split_goto_first + greedy,
+ len + 5 + add_zero_advance_check * 2);
+ if (add_zero_advance_check)
+ re_emit_op(s, REOP_push_char_pos);
/* copy the atom */
dbuf_put_self(&s->byte_code, last_atom_start, len);
-
+ if (add_zero_advance_check)
+ re_emit_op(s, REOP_check_advance);
re_emit_goto(s, REOP_loop, pos);
re_emit_op(s, REOP_drop);
}
@@ -1796,7 +1696,7 @@ static int compute_stack_size(const uint8_t *bc_buf, int bc_buf_len)
}
break;
case REOP_drop:
- case REOP_bne_char_pos:
+ case REOP_check_advance:
assert(stack_size > 0);
stack_size--;
break;
@@ -1832,7 +1732,7 @@ uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size,
s->buf_end = s->buf_ptr + buf_len;
s->buf_start = s->buf_ptr;
s->re_flags = re_flags;
- s->is_utf16 = ((re_flags & LRE_FLAG_UTF16) != 0);
+ s->is_unicode = ((re_flags & LRE_FLAG_UNICODE) != 0);
is_sticky = ((re_flags & LRE_FLAG_STICKY) != 0);
s->ignore_case = ((re_flags & LRE_FLAG_IGNORECASE) != 0);
s->dotall = ((re_flags & LRE_FLAG_DOTALL) != 0);
@@ -1890,7 +1790,8 @@ uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size,
s->byte_code.buf[RE_HEADER_CAPTURE_COUNT] = s->capture_count;
s->byte_code.buf[RE_HEADER_STACK_SIZE] = stack_size;
- put_u32(s->byte_code.buf + 3, s->byte_code.size - RE_HEADER_LEN);
+ put_u32(s->byte_code.buf + RE_HEADER_BYTECODE_LEN,
+ s->byte_code.size - RE_HEADER_LEN);
/* add the named groups if needed */
if (s->group_names.size > (s->capture_count - 1)) {
@@ -1921,93 +1822,86 @@ static BOOL is_word_char(uint32_t c)
(c == '_'));
}
-#define GET_CHAR(c, cptr, cbuf_end) \
+#define GET_CHAR(c, cptr, cbuf_end, cbuf_type) \
do { \
if (cbuf_type == 0) { \
- (c) = *(cptr)++; \
+ c = *cptr++; \
} else { \
- uint32_t __c1; \
- (c) = *(uint16_t *)(cptr); \
- (cptr) += 2; \
- if ((c) >= 0xd800 && (c) < 0xdc00 && \
- cbuf_type == 2 && (cptr) < (cbuf_end)) { \
- __c1 = *(uint16_t *)(cptr); \
- if (__c1 >= 0xdc00 && __c1 < 0xe000) { \
- (c) = ((((c) & 0x3ff) << 10) | (__c1 & 0x3ff)) + 0x10000; \
- (cptr) += 2; \
+ const uint16_t *_p = (const uint16_t *)cptr; \
+ const uint16_t *_end = (const uint16_t *)cbuf_end; \
+ c = *_p++; \
+ if (is_hi_surrogate(c) && cbuf_type == 2) { \
+ if (_p < _end && is_lo_surrogate(*_p)) { \
+ c = from_surrogate(c, *_p++); \
} \
} \
+ cptr = (const void *)_p; \
} \
} while (0)
-#define PEEK_CHAR(c, cptr, cbuf_end) \
- do { \
- if (cbuf_type == 0) { \
- (c) = (cptr)[0]; \
- } else { \
- uint32_t __c1; \
- (c) = ((uint16_t *)(cptr))[0]; \
- if ((c) >= 0xd800 && (c) < 0xdc00 && \
- cbuf_type == 2 && ((cptr) + 2) < (cbuf_end)) { \
- __c1 = ((uint16_t *)(cptr))[1]; \
- if (__c1 >= 0xdc00 && __c1 < 0xe000) { \
- (c) = ((((c) & 0x3ff) << 10) | (__c1 & 0x3ff)) + 0x10000; \
+#define PEEK_CHAR(c, cptr, cbuf_end, cbuf_type) \
+ do { \
+ if (cbuf_type == 0) { \
+ c = cptr[0]; \
+ } else { \
+ const uint16_t *_p = (const uint16_t *)cptr; \
+ const uint16_t *_end = (const uint16_t *)cbuf_end; \
+ c = *_p++; \
+ if (is_hi_surrogate(c) && cbuf_type == 2) { \
+ if (_p < _end && is_lo_surrogate(*_p)) { \
+ c = from_surrogate(c, *_p); \
} \
} \
- } \
+ } \
} while (0)
-#define PEEK_PREV_CHAR(c, cptr, cbuf_start) \
- do { \
- if (cbuf_type == 0) { \
- (c) = (cptr)[-1]; \
- } else { \
- uint32_t __c1; \
- (c) = ((uint16_t *)(cptr))[-1]; \
- if ((c) >= 0xdc00 && (c) < 0xe000 && \
- cbuf_type == 2 && ((cptr) - 4) >= (cbuf_start)) { \
- __c1 = ((uint16_t *)(cptr))[-2]; \
- if (__c1 >= 0xd800 && __c1 < 0xdc00 ) { \
- (c) = (((__c1 & 0x3ff) << 10) | ((c) & 0x3ff)) + 0x10000; \
+#define PEEK_PREV_CHAR(c, cptr, cbuf_start, cbuf_type) \
+ do { \
+ if (cbuf_type == 0) { \
+ c = cptr[-1]; \
+ } else { \
+ const uint16_t *_p = (const uint16_t *)cptr - 1; \
+ const uint16_t *_start = (const uint16_t *)cbuf_start; \
+ c = *_p; \
+ if (is_lo_surrogate(c) && cbuf_type == 2) { \
+ if (_p > _start && is_hi_surrogate(_p[-1])) { \
+ c = from_surrogate(*--_p, c); \
} \
} \
} \
} while (0)
-#define GET_PREV_CHAR(c, cptr, cbuf_start) \
- do { \
- if (cbuf_type == 0) { \
- (cptr)--; \
- (c) = (cptr)[0]; \
- } else { \
- uint32_t __c1; \
- (cptr) -= 2; \
- (c) = ((uint16_t *)(cptr))[0]; \
- if ((c) >= 0xdc00 && (c) < 0xe000 && \
- cbuf_type == 2 && (cptr) > (cbuf_start)) { \
- __c1 = ((uint16_t *)(cptr))[-1]; \
- if (__c1 >= 0xd800 && __c1 < 0xdc00 ) { \
- (cptr) -= 2; \
- (c) = (((__c1 & 0x3ff) << 10) | ((c) & 0x3ff)) + 0x10000; \
+#define GET_PREV_CHAR(c, cptr, cbuf_start, cbuf_type) \
+ do { \
+ if (cbuf_type == 0) { \
+ cptr--; \
+ c = cptr[0]; \
+ } else { \
+ const uint16_t *_p = (const uint16_t *)cptr - 1; \
+ const uint16_t *_start = (const uint16_t *)cbuf_start; \
+ c = *_p; \
+ if (is_lo_surrogate(c) && cbuf_type == 2) { \
+ if (_p > _start && is_hi_surrogate(_p[-1])) { \
+ c = from_surrogate(*--_p, c); \
} \
} \
+ cptr = (const void *)_p; \
} \
} while (0)
-#define PREV_CHAR(cptr, cbuf_start) \
- do { \
- if (cbuf_type == 0) { \
- (cptr)--; \
- } else { \
- (cptr) -= 2; \
- if (cbuf_type == 2) { \
- c = ((uint16_t *)(cptr))[0]; \
- if (c >= 0xdc00 && c < 0xe000 && (cptr) > (cbuf_start)) { \
- c = ((uint16_t *)(cptr))[-1]; \
- if (c >= 0xd800 && c < 0xdc00) \
- (cptr) -= 2; \
+#define PREV_CHAR(cptr, cbuf_start, cbuf_type) \
+ do { \
+ if (cbuf_type == 0) { \
+ cptr--; \
+ } else { \
+ const uint16_t *_p = (const uint16_t *)cptr - 1; \
+ const uint16_t *_start = (const uint16_t *)cbuf_start; \
+ if (is_lo_surrogate(*_p) && cbuf_type == 2) { \
+ if (_p > _start && is_hi_surrogate(_p[-1])) { \
+ --_p; \
} \
} \
+ cptr = (const void *)_p; \
} \
} while (0)
@@ -2038,7 +1932,7 @@ typedef struct {
int stack_size_max;
BOOL multi_line;
BOOL ignore_case;
- BOOL is_utf16;
+ BOOL is_unicode;
void *opaque; /* used for stack overflow check */
size_t state_size;
@@ -2049,7 +1943,7 @@ typedef struct {
static int push_state(REExecContext *s,
uint8_t **capture,
- const StackInt *stack, size_t stack_len,
+ StackInt *stack, size_t stack_len,
const uint8_t *pc, const uint8_t *cptr,
REExecStateEnum type, size_t count)
{
@@ -2147,7 +2041,7 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture,
/* go backward */
char_count = get_u32(pc + 12);
for(i = 0; i < char_count; i++) {
- PREV_CHAR(cptr, s->cbuf);
+ PREV_CHAR(cptr, s->cbuf, cbuf_type);
}
pc = (pc + 16) + (int)get_u32(pc);
rs->cptr = cptr;
@@ -2182,9 +2076,9 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture,
test_char:
if (cptr >= cbuf_end)
goto no_match;
- GET_CHAR(c, cptr, cbuf_end);
+ GET_CHAR(c, cptr, cbuf_end, cbuf_type);
if (s->ignore_case) {
- c = lre_canonicalize(c, s->is_utf16);
+ c = lre_canonicalize(c, s->is_unicode);
}
if (val != c)
goto no_match;
@@ -2229,7 +2123,7 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture,
break;
if (!s->multi_line)
goto no_match;
- PEEK_PREV_CHAR(c, cptr, s->cbuf);
+ PEEK_PREV_CHAR(c, cptr, s->cbuf, cbuf_type);
if (!is_line_terminator(c))
goto no_match;
break;
@@ -2238,21 +2132,21 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture,
break;
if (!s->multi_line)
goto no_match;
- PEEK_CHAR(c, cptr, cbuf_end);
+ PEEK_CHAR(c, cptr, cbuf_end, cbuf_type);
if (!is_line_terminator(c))
goto no_match;
break;
case REOP_dot:
if (cptr == cbuf_end)
goto no_match;
- GET_CHAR(c, cptr, cbuf_end);
+ GET_CHAR(c, cptr, cbuf_end, cbuf_type);
if (is_line_terminator(c))
goto no_match;
break;
case REOP_any:
if (cptr == cbuf_end)
goto no_match;
- GET_CHAR(c, cptr, cbuf_end);
+ GET_CHAR(c, cptr, cbuf_end, cbuf_type);
break;
case REOP_save_start:
case REOP_save_end:
@@ -2292,11 +2186,9 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture,
case REOP_push_char_pos:
stack[stack_len++] = (uintptr_t)cptr;
break;
- case REOP_bne_char_pos:
- val = get_u32(pc);
- pc += 4;
- if (stack[--stack_len] != (uintptr_t)cptr)
- pc += (int)val;
+ case REOP_check_advance:
+ if (stack[--stack_len] == (uintptr_t)cptr)
+ goto no_match;
break;
case REOP_word_boundary:
case REOP_not_word_boundary:
@@ -2306,14 +2198,14 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture,
if (cptr == s->cbuf) {
v1 = FALSE;
} else {
- PEEK_PREV_CHAR(c, cptr, s->cbuf);
+ PEEK_PREV_CHAR(c, cptr, s->cbuf, cbuf_type);
v1 = is_word_char(c);
}
/* current char */
if (cptr >= cbuf_end) {
v2 = FALSE;
} else {
- PEEK_CHAR(c, cptr, cbuf_end);
+ PEEK_CHAR(c, cptr, cbuf_end, cbuf_type);
v2 = is_word_char(c);
}
if (v1 ^ v2 ^ (REOP_not_word_boundary - opcode))
@@ -2338,11 +2230,11 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture,
while (cptr1 < cptr1_end) {
if (cptr >= cbuf_end)
goto no_match;
- GET_CHAR(c1, cptr1, cptr1_end);
- GET_CHAR(c2, cptr, cbuf_end);
+ GET_CHAR(c1, cptr1, cptr1_end, cbuf_type);
+ GET_CHAR(c2, cptr, cbuf_end, cbuf_type);
if (s->ignore_case) {
- c1 = lre_canonicalize(c1, s->is_utf16);
- c2 = lre_canonicalize(c2, s->is_utf16);
+ c1 = lre_canonicalize(c1, s->is_unicode);
+ c2 = lre_canonicalize(c2, s->is_unicode);
}
if (c1 != c2)
goto no_match;
@@ -2352,11 +2244,11 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture,
while (cptr1 > cptr1_start) {
if (cptr == s->cbuf)
goto no_match;
- GET_PREV_CHAR(c1, cptr1, cptr1_start);
- GET_PREV_CHAR(c2, cptr, s->cbuf);
+ GET_PREV_CHAR(c1, cptr1, cptr1_start, cbuf_type);
+ GET_PREV_CHAR(c2, cptr, s->cbuf, cbuf_type);
if (s->ignore_case) {
- c1 = lre_canonicalize(c1, s->is_utf16);
- c2 = lre_canonicalize(c2, s->is_utf16);
+ c1 = lre_canonicalize(c1, s->is_unicode);
+ c2 = lre_canonicalize(c2, s->is_unicode);
}
if (c1 != c2)
goto no_match;
@@ -2373,9 +2265,9 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture,
pc += 2;
if (cptr >= cbuf_end)
goto no_match;
- GET_CHAR(c, cptr, cbuf_end);
+ GET_CHAR(c, cptr, cbuf_end, cbuf_type);
if (s->ignore_case) {
- c = lre_canonicalize(c, s->is_utf16);
+ c = lre_canonicalize(c, s->is_unicode);
}
idx_min = 0;
low = get_u16(pc + 0 * 4);
@@ -2413,9 +2305,9 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture,
pc += 2;
if (cptr >= cbuf_end)
goto no_match;
- GET_CHAR(c, cptr, cbuf_end);
+ GET_CHAR(c, cptr, cbuf_end, cbuf_type);
if (s->ignore_case) {
- c = lre_canonicalize(c, s->is_utf16);
+ c = lre_canonicalize(c, s->is_unicode);
}
idx_min = 0;
low = get_u32(pc + 0 * 8);
@@ -2445,7 +2337,7 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture,
/* go to the previous char */
if (cptr == s->cbuf)
goto no_match;
- PREV_CHAR(cptr, s->cbuf);
+ PREV_CHAR(cptr, s->cbuf, cbuf_type);
break;
case REOP_simple_greedy_quant:
{
@@ -2504,16 +2396,16 @@ int lre_exec(uint8_t **capture,
int re_flags, i, alloca_size, ret;
StackInt *stack_buf;
- re_flags = bc_buf[RE_HEADER_FLAGS];
+ re_flags = lre_get_flags(bc_buf);
s->multi_line = (re_flags & LRE_FLAG_MULTILINE) != 0;
s->ignore_case = (re_flags & LRE_FLAG_IGNORECASE) != 0;
- s->is_utf16 = (re_flags & LRE_FLAG_UTF16) != 0;
+ s->is_unicode = (re_flags & LRE_FLAG_UNICODE) != 0;
s->capture_count = bc_buf[RE_HEADER_CAPTURE_COUNT];
s->stack_size_max = bc_buf[RE_HEADER_STACK_SIZE];
s->cbuf = cbuf;
s->cbuf_end = cbuf + (clen << cbuf_type);
s->cbuf_type = cbuf_type;
- if (s->cbuf_type == 1 && s->is_utf16)
+ if (s->cbuf_type == 1 && s->is_unicode)
s->cbuf_type = 2;
s->opaque = opaque;
@@ -2551,8 +2443,8 @@ const char *lre_get_groupnames(const uint8_t *bc_buf)
uint32_t re_bytecode_len;
if ((lre_get_flags(bc_buf) & LRE_FLAG_NAMED_GROUPS) == 0)
return NULL;
- re_bytecode_len = get_u32(bc_buf + 3);
- return (const char *)(bc_buf + 7 + re_bytecode_len);
+ re_bytecode_len = get_u32(bc_buf + RE_HEADER_BYTECODE_LEN);
+ return (const char *)(bc_buf + RE_HEADER_LEN + re_bytecode_len);
}
#ifdef TEST
@@ -2569,25 +2461,26 @@ void *lre_realloc(void *opaque, void *ptr, size_t size)
int main(int argc, char **argv)
{
- int len, ret, i;
+ int len, flags, ret, i;
uint8_t *bc;
char error_msg[64];
uint8_t *capture[CAPTURE_COUNT_MAX * 2];
const char *input;
int input_len, capture_count;
- if (argc < 3) {
- printf("usage: %s regexp input\n", argv[0]);
- exit(1);
+ if (argc < 4) {
+ printf("usage: %s regexp flags input\n", argv[0]);
+ return 1;
}
+ flags = atoi(argv[2]);
bc = lre_compile(&len, error_msg, sizeof(error_msg), argv[1],
- strlen(argv[1]), 0, NULL);
+ strlen(argv[1]), flags, NULL);
if (!bc) {
fprintf(stderr, "error: %s\n", error_msg);
exit(1);
}
- input = argv[2];
+ input = argv[3];
input_len = strlen(input);
ret = lre_exec(capture, bc, (uint8_t *)input, 0, input_len, 0, NULL);
diff --git a/src/shared/quickjs/libregexp.h b/src/shared/quickjs/libregexp.h
index 9aedb7e93..7af7ece0f 100644
--- a/src/shared/quickjs/libregexp.h
+++ b/src/shared/quickjs/libregexp.h
@@ -1,6 +1,6 @@
/*
* Regular Expression Engine
- *
+ *
* Copyright (c) 2017-2018 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -25,18 +25,15 @@
#define LIBREGEXP_H
#include <stddef.h>
-
-#include "libunicode.h"
-
-#define LRE_BOOL int /* for documentation purposes */
+#include <stdint.h>
#define LRE_FLAG_GLOBAL (1 << 0)
#define LRE_FLAG_IGNORECASE (1 << 1)
#define LRE_FLAG_MULTILINE (1 << 2)
#define LRE_FLAG_DOTALL (1 << 3)
-#define LRE_FLAG_UTF16 (1 << 4)
+#define LRE_FLAG_UNICODE (1 << 4)
#define LRE_FLAG_STICKY (1 << 5)
-
+#define LRE_FLAG_INDICES (1 << 6) /* Unused by libregexp, just recorded. */
#define LRE_FLAG_NAMED_GROUPS (1 << 7) /* named groups are present in the regexp */
uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size,
@@ -50,43 +47,9 @@ int lre_exec(uint8_t **capture,
int cbuf_type, void *opaque);
int lre_parse_escape(const uint8_t **pp, int allow_utf16);
-LRE_BOOL lre_is_space(int c);
-/* must be provided by the user */
-LRE_BOOL lre_check_stack_overflow(void *opaque, size_t alloca_size);
+/* must be provided by the user, return non zero if overflow */
+int lre_check_stack_overflow(void *opaque, size_t alloca_size);
void *lre_realloc(void *opaque, void *ptr, size_t size);
-/* JS identifier test */
-extern uint32_t const lre_id_start_table_ascii[4];
-extern uint32_t const lre_id_continue_table_ascii[4];
-
-static inline int lre_js_is_ident_first(int c)
-{
- if ((uint32_t)c < 128) {
- return (lre_id_start_table_ascii[c >> 5] >> (c & 31)) & 1;
- } else {
-#ifdef CONFIG_ALL_UNICODE
- return lre_is_id_start(c);
-#else
- return !lre_is_space(c);
-#endif
- }
-}
-
-static inline int lre_js_is_ident_next(int c)
-{
- if ((uint32_t)c < 128) {
- return (lre_id_continue_table_ascii[c >> 5] >> (c & 31)) & 1;
- } else {
- /* ZWNJ and ZWJ are accepted in identifiers */
-#ifdef CONFIG_ALL_UNICODE
- return lre_is_id_continue(c) || c == 0x200C || c == 0x200D;
-#else
- return !lre_is_space(c) || c == 0x200C || c == 0x200D;
-#endif
- }
-}
-
-#undef LRE_BOOL
-
#endif /* LIBREGEXP_H */
diff --git a/src/shared/quickjs/libunicode-table.h b/src/shared/quickjs/libunicode-table.h
index 1727525fb..72d495e78 100644
--- a/src/shared/quickjs/libunicode-table.h
+++ b/src/shared/quickjs/libunicode-table.h
@@ -160,40 +160,45 @@ static const uint16_t case_conv_ext[58] = {
0x006b, 0x00e5,
};
-static const uint8_t unicode_prop_Cased1_table[188] = {
+static const uint8_t unicode_prop_Cased1_table[196] = {
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, 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, 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, 0xa2, 0x00, 0x80, 0xa1,
- 0x82, 0x43, 0x34, 0xa2, 0x06, 0x80, 0x8c, 0x60,
- 0x5c, 0x16, 0x01, 0x10, 0xa9, 0x80, 0x88, 0x60,
- 0xcc, 0x44, 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,
+ 0x80, 0x41, 0x62, 0x80, 0xa6, 0x80, 0x4b, 0x72,
+ 0x80, 0x4c, 0x02, 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, 0xa2,
+ 0x00, 0x80, 0x9b, 0x12, 0x82, 0x43, 0x34, 0xa2,
+ 0x06, 0x80, 0x8d, 0x60, 0x5c, 0x15, 0x01, 0x10,
+ 0xa9, 0x80, 0x88, 0x60, 0xcc, 0x44, 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, 0x80, 0x9e, 0x80, 0x98, 0x07,
- 0x47, 0x33, 0x89, 0x80, 0x93, 0x52, 0x10, 0x99,
+ 0x9e, 0x80, 0x98, 0x07, 0x47, 0x33, 0x89, 0x80,
+ 0x93, 0x2d, 0x41, 0x04, 0xbd, 0x50, 0xc1, 0x99,
0x85, 0x99, 0x85, 0x99,
};
-static const uint8_t unicode_prop_Cased1_index[18] = {
- 0xb9, 0x02, 0xe0, 0xa0, 0x1e, 0x40, 0x9e, 0xa6,
- 0x40, 0x55, 0xd4, 0x61, 0xfb, 0xd6, 0x21, 0x8a,
- 0xf1, 0x01,
+static const uint8_t unicode_prop_Cased1_index[21] = {
+ 0xb9, 0x02, 0xe0, // 002B9 at 39
+ 0xc0, 0x1d, 0x20, // 01DC0 at 65
+ 0xe5, 0x2c, 0x20, // 02CE5 at 97
+ 0xb1, 0x07, 0x21, // 107B1 at 129
+ 0xc1, 0xd6, 0x21, // 1D6C1 at 161
+ 0x4a, 0xf1, 0x01, // 1F14A at 192
+ 0x8a, 0xf1, 0x01, // 1F18A at 224 (upper bound)
};
-static const uint8_t unicode_prop_Case_Ignorable_table[720] = {
+static const uint8_t unicode_prop_Case_Ignorable_table[737] = {
0xa6, 0x05, 0x80, 0x8a, 0x80, 0xa2, 0x00, 0x80,
0xc6, 0x03, 0x00, 0x03, 0x01, 0x81, 0x41, 0xf6,
0x40, 0xbf, 0x19, 0x18, 0x88, 0x08, 0x80, 0x40,
@@ -215,7 +220,7 @@ static const uint8_t unicode_prop_Case_Ignorable_table[720] = {
0x01, 0x05, 0x04, 0x81, 0x93, 0x81, 0x9b, 0x81,
0xb8, 0x0b, 0x1f, 0x80, 0x93, 0x81, 0x9c, 0x80,
0xc7, 0x06, 0x10, 0x80, 0xd9, 0x01, 0x86, 0x8a,
- 0x88, 0xe1, 0x01, 0x88, 0x88, 0x00, 0x85, 0xc9,
+ 0x88, 0xe1, 0x01, 0x88, 0x88, 0x00, 0x86, 0xc8,
0x81, 0x9a, 0x00, 0x00, 0x80, 0xb6, 0x8d, 0x04,
0x01, 0x84, 0x8a, 0x80, 0xa3, 0x88, 0x80, 0xe5,
0x18, 0x28, 0x09, 0x81, 0x98, 0x0b, 0x82, 0x8f,
@@ -256,49 +261,66 @@ static const uint8_t unicode_prop_Case_Ignorable_table[720] = {
0x80, 0x40, 0x94, 0x84, 0x44, 0x04, 0x28, 0xa9,
0x80, 0x88, 0x42, 0x45, 0x10, 0x0c, 0x83, 0xa7,
0x13, 0x80, 0x40, 0xa4, 0x81, 0x42, 0x3c, 0x83,
- 0x41, 0x82, 0x81, 0x40, 0x98, 0x8a, 0xb0, 0x83,
- 0xfa, 0x80, 0xb5, 0x8e, 0xa8, 0x01, 0x81, 0x89,
- 0x82, 0xb0, 0x19, 0x09, 0x03, 0x80, 0x89, 0x80,
- 0xb1, 0x82, 0xa3, 0x20, 0x87, 0xbd, 0x80, 0x8b,
- 0x81, 0xb3, 0x88, 0x89, 0x19, 0x80, 0xde, 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, 0x40, 0xff, 0x08, 0x03, 0x80,
- 0x40, 0x8f, 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, 0x81, 0x60, 0x40, 0x0a, 0x18, 0x30,
- 0x81, 0x4c, 0x9d, 0x08, 0x83, 0x52, 0x5b, 0xad,
- 0x81, 0x96, 0x42, 0x1f, 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, 0x6f, 0x80, 0xbc, 0x83, 0x45,
- 0xdf, 0x86, 0xec, 0x87, 0x4a, 0xae, 0x84, 0x6c,
- 0x0c, 0x00, 0x80, 0x9d, 0xdf, 0xff, 0x40, 0xef,
+ 0x41, 0x82, 0x81, 0xcf, 0x82, 0xc5, 0x8a, 0xb0,
+ 0x83, 0xfa, 0x80, 0xb5, 0x8e, 0xa8, 0x01, 0x81,
+ 0x89, 0x82, 0xb0, 0x19, 0x09, 0x03, 0x80, 0x89,
+ 0x80, 0xb1, 0x82, 0xa3, 0x20, 0x87, 0xbd, 0x80,
+ 0x8b, 0x81, 0xb3, 0x88, 0x89, 0x19, 0x80, 0xde,
+ 0x11, 0x00, 0x0d, 0x01, 0x80, 0x40, 0x9c, 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, 0x40, 0xff, 0x08,
+ 0x03, 0x80, 0x40, 0x8f, 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, 0x8a, 0x81, 0xb3, 0x24, 0x00, 0x80,
+ 0x54, 0xec, 0x90, 0x85, 0x8e, 0x60, 0x36, 0x99,
+ 0x84, 0xba, 0x86, 0x88, 0x83, 0x44, 0x0a, 0x80,
+ 0xbe, 0x90, 0xbf, 0x08, 0x81, 0x60, 0x40, 0x0a,
+ 0x18, 0x30, 0x81, 0x4c, 0x9d, 0x08, 0x83, 0x52,
+ 0x5b, 0xad, 0x81, 0x96, 0x42, 0x1f, 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, 0x84, 0xbd, 0xa0, 0x80, 0x40, 0x9f, 0x8d,
+ 0x41, 0x6f, 0x80, 0xbc, 0x83, 0x41, 0xfa, 0x84,
+ 0x43, 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[69] = {
- 0xbe, 0x05, 0x00, 0xfe, 0x07, 0x00, 0x52, 0x0a,
- 0xa0, 0xc1, 0x0b, 0x00, 0x82, 0x0d, 0x00, 0x3f,
- 0x10, 0x80, 0xd4, 0x17, 0x40, 0xcf, 0x1a, 0x20,
- 0xf5, 0x1c, 0x00, 0x80, 0x20, 0x00, 0x16, 0xa0,
- 0x00, 0xc6, 0xa8, 0x00, 0xc2, 0xaa, 0x60, 0x56,
- 0xfe, 0x20, 0xb1, 0x07, 0x01, 0x82, 0x10, 0x21,
- 0x02, 0x13, 0x21, 0xb8, 0x16, 0x61, 0x97, 0x1a,
- 0x01, 0x37, 0x6b, 0x21, 0x8c, 0xd1, 0x01, 0xd7,
- 0xe8, 0x41, 0xf0, 0x01, 0x0e,
+ 0xbe, 0x05, 0x00, // 005BE at 32
+ 0xfe, 0x07, 0x00, // 007FE at 64
+ 0x52, 0x0a, 0xa0, // 00A52 at 101
+ 0xc1, 0x0b, 0x00, // 00BC1 at 128
+ 0x82, 0x0d, 0x00, // 00D82 at 160
+ 0x3f, 0x10, 0x80, // 0103F at 196
+ 0xd4, 0x17, 0x40, // 017D4 at 226
+ 0xcf, 0x1a, 0x20, // 01ACF at 257
+ 0xf5, 0x1c, 0x00, // 01CF5 at 288
+ 0x80, 0x20, 0x00, // 02080 at 320
+ 0x16, 0xa0, 0x00, // 0A016 at 352
+ 0xc6, 0xa8, 0x00, // 0A8C6 at 384
+ 0xc2, 0xaa, 0x60, // 0AAC2 at 419
+ 0x56, 0xfe, 0x20, // 0FE56 at 449
+ 0xb1, 0x07, 0x01, // 107B1 at 480
+ 0x75, 0x10, 0x01, // 11075 at 512
+ 0xeb, 0x12, 0x21, // 112EB at 545
+ 0x41, 0x16, 0x01, // 11641 at 576
+ 0x5c, 0x1a, 0x01, // 11A5C at 608
+ 0x43, 0x1f, 0x01, // 11F43 at 640
+ 0x2e, 0xcf, 0x41, // 1CF2E at 674
+ 0x25, 0xe0, 0x01, // 1E025 at 704
+ 0xf0, 0x01, 0x0e, // E01F0 at 736 (upper bound)
};
-static const uint8_t unicode_prop_ID_Start_table[1079] = {
+static const uint8_t unicode_prop_ID_Start_table[1100] = {
0xc0, 0x99, 0x85, 0x99, 0xae, 0x80, 0x89, 0x03,
0x04, 0x96, 0x80, 0x9e, 0x80, 0x41, 0xc9, 0x83,
0x8b, 0x8d, 0x26, 0x00, 0x80, 0x40, 0x80, 0x20,
@@ -392,67 +414,92 @@ static const uint8_t unicode_prop_ID_Start_table[1079] = {
0xad, 0x94, 0x9a, 0x96, 0x8b, 0xb4, 0xb8, 0x09,
0x80, 0x8c, 0xac, 0x9f, 0x98, 0x99, 0xa3, 0x9c,
0x01, 0x07, 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, 0x82, 0x9d, 0xaf, 0x93, 0x08, 0x80,
- 0x40, 0xb7, 0xae, 0xa8, 0x83, 0xa3, 0xaf, 0x93,
- 0x80, 0xba, 0xaa, 0x8c, 0x80, 0xc6, 0x9a, 0xa4,
- 0x86, 0x40, 0xb8, 0xab, 0xf3, 0xbf, 0x9e, 0x39,
- 0x01, 0x38, 0x08, 0x97, 0x8e, 0x00, 0x80, 0xdd,
- 0x39, 0xa6, 0x8f, 0x00, 0x80, 0x9b, 0x80, 0x89,
- 0xa7, 0x30, 0x94, 0x80, 0x8a, 0xad, 0x92, 0x80,
- 0x91, 0xc8, 0x41, 0x06, 0x88, 0x80, 0xa4, 0x90,
- 0x80, 0xb0, 0x9d, 0xef, 0x30, 0x08, 0xa5, 0x94,
- 0x80, 0x98, 0x28, 0x08, 0x9f, 0x8d, 0x80, 0x41,
- 0x46, 0x92, 0x40, 0xbc, 0x80, 0xce, 0x43, 0x99,
- 0xe5, 0xee, 0x90, 0x40, 0xc3, 0x4a, 0x4b, 0xe0,
- 0x8e, 0x44, 0x2e, 0x4f, 0xd0, 0x42, 0x46, 0x60,
+ 0x94, 0x00, 0x80, 0xa2, 0x91, 0x80, 0x98, 0x92,
+ 0x81, 0xbe, 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, 0x82, 0x9d, 0xaf, 0x93,
+ 0x08, 0x80, 0x40, 0xb7, 0xae, 0xa8, 0x83, 0xa3,
+ 0xaf, 0x93, 0x80, 0xba, 0xaa, 0x8c, 0x80, 0xc6,
+ 0x9a, 0xa4, 0x86, 0x40, 0xb8, 0xab, 0xf3, 0xbf,
+ 0x9e, 0x39, 0x01, 0x38, 0x08, 0x97, 0x8e, 0x00,
+ 0x80, 0xdd, 0x39, 0xa6, 0x8f, 0x00, 0x80, 0x9b,
+ 0x80, 0x89, 0xa7, 0x30, 0x94, 0x80, 0x8a, 0xad,
+ 0x92, 0x80, 0x91, 0xc8, 0x41, 0x06, 0x88, 0x80,
+ 0xa4, 0x90, 0x80, 0xb0, 0x9d, 0xef, 0x30, 0x08,
+ 0xa5, 0x94, 0x80, 0x98, 0x28, 0x08, 0x9f, 0x8d,
+ 0x80, 0x41, 0x46, 0x92, 0x8e, 0x00, 0x8c, 0x80,
+ 0xa1, 0xfb, 0x80, 0xce, 0x43, 0x99, 0xe5, 0xee,
+ 0x90, 0x40, 0xc3, 0x4a, 0x4b, 0xe0, 0x8e, 0x44,
+ 0x2f, 0x90, 0x85, 0x4f, 0xb8, 0x42, 0x46, 0x60,
0x21, 0xb8, 0x42, 0x38, 0x86, 0x9e, 0x90, 0xce,
0x90, 0x9d, 0x91, 0xaf, 0x8f, 0x83, 0x9e, 0x94,
0x84, 0x92, 0x42, 0xaf, 0xbf, 0xff, 0xca, 0x20,
0xc1, 0x8c, 0xbf, 0x08, 0x80, 0x9b, 0x57, 0xf7,
0x87, 0x44, 0xd5, 0xa9, 0x88, 0x60, 0x22, 0xe6,
- 0x18, 0x30, 0x08, 0x41, 0x22, 0xac, 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, 0x47, 0x33, 0x9e, 0x41,
- 0xe0, 0xac, 0x89, 0x86, 0x8f, 0x80, 0x41, 0x40,
- 0x9d, 0x91, 0xab, 0x44, 0xf3, 0x30, 0x18, 0x08,
- 0x8e, 0x80, 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, 0xdf, 0x9f, 0x50, 0x38, 0x86, 0x40,
- 0xdd, 0x81, 0x56, 0x81, 0x8d, 0x5d, 0x30, 0x4c,
- 0x1e, 0x42, 0x1d, 0x45, 0xe1, 0x53, 0x4a,
+ 0x18, 0x30, 0x08, 0x41, 0x22, 0x8e, 0x80, 0x9c,
+ 0x11, 0x80, 0x8d, 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, 0x47,
+ 0x33, 0x9e, 0x2d, 0x41, 0x04, 0xbd, 0x40, 0x91,
+ 0xac, 0x89, 0x86, 0x8f, 0x80, 0x41, 0x40, 0x9d,
+ 0x91, 0xab, 0x41, 0xe3, 0x9b, 0x42, 0xf3, 0x30,
+ 0x18, 0x08, 0x8e, 0x80, 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, 0xdf, 0x9f, 0x50, 0x39,
+ 0x85, 0x40, 0xdd, 0x81, 0x56, 0x81, 0x8d, 0x5d,
+ 0x30, 0x4c, 0x1e, 0x42, 0x1d, 0x45, 0xe1, 0x53,
+ 0x4a, 0x84, 0x50, 0x5f,
};
-static const uint8_t unicode_prop_ID_Start_index[102] = {
- 0xf6, 0x03, 0x20, 0xa6, 0x07, 0x00, 0xa9, 0x09,
- 0x20, 0xb1, 0x0a, 0x00, 0xba, 0x0b, 0x20, 0x3b,
- 0x0d, 0x20, 0xc7, 0x0e, 0x20, 0x49, 0x12, 0x00,
- 0x9b, 0x16, 0x00, 0xac, 0x19, 0x00, 0xc0, 0x1d,
- 0x80, 0x80, 0x20, 0x20, 0x70, 0x2d, 0x00, 0x00,
- 0x32, 0x00, 0xda, 0xa7, 0x00, 0x4c, 0xaa, 0x20,
- 0xc7, 0xd7, 0x20, 0xfc, 0xfd, 0x20, 0x9d, 0x02,
- 0x21, 0x96, 0x05, 0x01, 0xf3, 0x08, 0x01, 0xb3,
- 0x0c, 0x21, 0x73, 0x11, 0x61, 0x3e, 0x13, 0x01,
- 0x47, 0x17, 0x21, 0x9e, 0x1a, 0x01, 0x9a, 0x23,
- 0x01, 0x78, 0x6b, 0x01, 0xfc, 0xb2, 0x61, 0x3a,
- 0xd5, 0x01, 0x2d, 0xe1, 0x41, 0x33, 0xee, 0x01,
- 0xe0, 0xa6, 0x62, 0x4b, 0x13, 0x03,
+static const uint8_t unicode_prop_ID_Start_index[105] = {
+ 0xf6, 0x03, 0x20, // 003F6 at 33
+ 0xa6, 0x07, 0x00, // 007A6 at 64
+ 0xa9, 0x09, 0x20, // 009A9 at 97
+ 0xb1, 0x0a, 0x00, // 00AB1 at 128
+ 0xba, 0x0b, 0x20, // 00BBA at 161
+ 0x3b, 0x0d, 0x20, // 00D3B at 193
+ 0xc7, 0x0e, 0x20, // 00EC7 at 225
+ 0x49, 0x12, 0x00, // 01249 at 256
+ 0x9b, 0x16, 0x00, // 0169B at 288
+ 0xac, 0x19, 0x00, // 019AC at 320
+ 0xc0, 0x1d, 0x80, // 01DC0 at 356
+ 0x80, 0x20, 0x20, // 02080 at 385
+ 0x70, 0x2d, 0x00, // 02D70 at 416
+ 0x00, 0x32, 0x00, // 03200 at 448
+ 0xda, 0xa7, 0x00, // 0A7DA at 480
+ 0x4c, 0xaa, 0x20, // 0AA4C at 513
+ 0xc7, 0xd7, 0x20, // 0D7C7 at 545
+ 0xfc, 0xfd, 0x20, // 0FDFC at 577
+ 0x9d, 0x02, 0x21, // 1029D at 609
+ 0x96, 0x05, 0x01, // 10596 at 640
+ 0xf3, 0x08, 0x01, // 108F3 at 672
+ 0xb3, 0x0c, 0x21, // 10CB3 at 705
+ 0x73, 0x11, 0x61, // 11173 at 739
+ 0x34, 0x13, 0x01, // 11334 at 768
+ 0x1b, 0x17, 0x21, // 1171B at 801
+ 0x8a, 0x1a, 0x01, // 11A8A at 832
+ 0x34, 0x1f, 0x21, // 11F34 at 865
+ 0xbf, 0x6a, 0x01, // 16ABF at 896
+ 0x23, 0xb1, 0xa1, // 1B123 at 933
+ 0xad, 0xd4, 0x01, // 1D4AD at 960
+ 0x6f, 0xd7, 0x01, // 1D76F at 992
+ 0xff, 0xe7, 0x61, // 1E7FF at 1027
+ 0x5e, 0xee, 0x01, // 1EE5E at 1056
+ 0xe1, 0xeb, 0x22, // 2EBE1 at 1089
+ 0xb0, 0x23, 0x03, // 323B0 at 1120 (upper bound)
};
-static const uint8_t unicode_prop_ID_Continue1_table[640] = {
+static const uint8_t unicode_prop_ID_Continue1_table[660] = {
0xaf, 0x89, 0xa4, 0x80, 0xd6, 0x80, 0x42, 0x47,
0xef, 0x96, 0x80, 0x40, 0xfa, 0x84, 0x41, 0x08,
0xac, 0x00, 0x01, 0x01, 0x00, 0xc7, 0x8a, 0xaf,
@@ -470,85 +517,101 @@ static const uint8_t unicode_prop_ID_Continue1_table[640] = {
0xba, 0x22, 0x10, 0x83, 0x88, 0x80, 0x8d, 0x89,
0x8f, 0x84, 0xb6, 0x00, 0x30, 0x10, 0x1e, 0x81,
0x8a, 0x09, 0x89, 0x90, 0x82, 0xb7, 0x00, 0x30,
- 0x10, 0x1e, 0x81, 0x8a, 0x09, 0x89, 0x8f, 0x83,
- 0xb6, 0x08, 0x30, 0x10, 0x83, 0x88, 0x80, 0x89,
- 0x09, 0x89, 0x90, 0x82, 0xc5, 0x03, 0x28, 0x00,
- 0x3d, 0x89, 0x09, 0xbc, 0x01, 0x86, 0x8b, 0x38,
- 0x89, 0xd6, 0x01, 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, 0x83, 0x9b, 0x82,
- 0x9c, 0x81, 0x9d, 0x81, 0xbf, 0x9f, 0x88, 0x01,
- 0x89, 0xa0, 0x10, 0x8a, 0x40, 0x8e, 0x80, 0xf5,
- 0x8b, 0x83, 0x8b, 0x89, 0x89, 0xff, 0x8a, 0xbb,
- 0x84, 0xb8, 0x89, 0x80, 0x9c, 0x81, 0x8a, 0x85,
- 0x89, 0x95, 0x8d, 0x80, 0x8f, 0xb0, 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, 0xbf, 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, 0x23, 0x80, 0xd2, 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,
- 0x41, 0x70, 0x81, 0x40, 0x98, 0x8a, 0xb0, 0x83,
- 0xf9, 0x82, 0xb4, 0x8e, 0x9e, 0x8a, 0x09, 0x89,
- 0x83, 0xac, 0x8a, 0x30, 0xac, 0x89, 0x2a, 0xa3,
- 0x8d, 0x80, 0x89, 0x21, 0xab, 0x80, 0x8b, 0x82,
- 0xaf, 0x8d, 0x3b, 0x80, 0x8b, 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, 0xc5, 0x28, 0x09, 0x18, 0x00,
- 0x81, 0x8b, 0x89, 0xf6, 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, 0xd5, 0x89,
- 0xa5, 0x84, 0xba, 0x86, 0x98, 0x89, 0x43, 0xf4,
- 0x00, 0xb6, 0x33, 0xd0, 0x80, 0x8a, 0x81, 0x60,
- 0x4c, 0xaa, 0x81, 0x52, 0x60, 0xad, 0x81, 0x96,
- 0x42, 0x1d, 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, 0x63, 0x80,
- 0xbc, 0x8d, 0x45, 0xd5, 0x86, 0xec, 0x34, 0x89,
- 0x52, 0x95, 0x89, 0x6c, 0x05, 0x05, 0x40, 0xef,
+ 0x10, 0x1e, 0x81, 0x8a, 0x09, 0x89, 0x10, 0x8b,
+ 0x83, 0xb6, 0x08, 0x30, 0x10, 0x83, 0x88, 0x80,
+ 0x89, 0x09, 0x89, 0x90, 0x82, 0xc5, 0x03, 0x28,
+ 0x00, 0x3d, 0x89, 0x09, 0xbc, 0x01, 0x86, 0x8b,
+ 0x38, 0x89, 0xd6, 0x01, 0x88, 0x8a, 0x30, 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, 0x83, 0x9b,
+ 0x82, 0x9c, 0x81, 0x9d, 0x81, 0xbf, 0x9f, 0x88,
+ 0x01, 0x89, 0xa0, 0x10, 0x8a, 0x40, 0x8e, 0x80,
+ 0xf5, 0x8b, 0x83, 0x8b, 0x89, 0x89, 0xff, 0x8a,
+ 0xbb, 0x84, 0xb8, 0x89, 0x80, 0x9c, 0x81, 0x8a,
+ 0x85, 0x89, 0x95, 0x8d, 0x80, 0x8f, 0xb0, 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, 0xbf, 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, 0x23, 0x80, 0xd2,
+ 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, 0x41, 0x70, 0x81, 0xcf, 0x82, 0xc5, 0x8a,
+ 0xb0, 0x83, 0xf9, 0x82, 0xb4, 0x8e, 0x9e, 0x8a,
+ 0x09, 0x89, 0x83, 0xac, 0x8a, 0x30, 0xac, 0x89,
+ 0x2a, 0xa3, 0x8d, 0x80, 0x89, 0x21, 0xab, 0x80,
+ 0x8b, 0x82, 0xaf, 0x8d, 0x3b, 0x80, 0x8b, 0xd1,
+ 0x8b, 0x28, 0x08, 0x40, 0x9c, 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, 0xc5, 0x28,
+ 0x09, 0x18, 0x00, 0x81, 0x8b, 0x89, 0xf6, 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, 0x88, 0x08, 0x80,
+ 0xaf, 0x32, 0x84, 0x8c, 0x89, 0x54, 0xe5, 0x05,
+ 0x8e, 0x60, 0x36, 0x09, 0x89, 0xd5, 0x89, 0xa5,
+ 0x84, 0xba, 0x86, 0x98, 0x89, 0x43, 0xf4, 0x00,
+ 0xb6, 0x33, 0xd0, 0x80, 0x8a, 0x81, 0x60, 0x4c,
+ 0xaa, 0x81, 0x52, 0x60, 0xad, 0x81, 0x96, 0x42,
+ 0x1d, 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, 0xe3,
+ 0x80, 0x40, 0x9f, 0x86, 0x88, 0x89, 0x41, 0x63,
+ 0x80, 0xbc, 0x8d, 0x41, 0xf1, 0x8d, 0x43, 0xd5,
+ 0x86, 0xec, 0x34, 0x89, 0x52, 0x95, 0x89, 0x6c,
+ 0x05, 0x05, 0x40, 0xef,
};
-static const uint8_t unicode_prop_ID_Continue1_index[60] = {
- 0xfa, 0x06, 0x00, 0x70, 0x09, 0x00, 0xf0, 0x0a,
- 0x40, 0x57, 0x0c, 0x00, 0xf0, 0x0d, 0x40, 0xc7,
- 0x0f, 0x00, 0xea, 0x17, 0x20, 0x45, 0x1b, 0x20,
- 0x55, 0x20, 0x20, 0x0c, 0xa8, 0x60, 0x37, 0xaa,
- 0x00, 0x50, 0xfe, 0x00, 0x3a, 0x0d, 0x01, 0x83,
- 0x11, 0x01, 0xc4, 0x14, 0x21, 0x44, 0x19, 0x21,
- 0x5a, 0x1d, 0x41, 0x9f, 0xbc, 0x61, 0xb0, 0xda,
- 0x21, 0xf0, 0x01, 0x0e,
+static const uint8_t unicode_prop_ID_Continue1_index[63] = {
+ 0xfa, 0x06, 0x00, // 006FA at 32
+ 0x70, 0x09, 0x00, // 00970 at 64
+ 0xf0, 0x0a, 0x40, // 00AF0 at 98
+ 0x57, 0x0c, 0x00, // 00C57 at 128
+ 0xf0, 0x0d, 0x60, // 00DF0 at 163
+ 0xc7, 0x0f, 0x20, // 00FC7 at 193
+ 0xea, 0x17, 0x40, // 017EA at 226
+ 0x05, 0x1b, 0x00, // 01B05 at 256
+ 0x41, 0x20, 0x00, // 02041 at 288
+ 0x0c, 0xa8, 0x80, // 0A80C at 324
+ 0x37, 0xaa, 0x20, // 0AA37 at 353
+ 0x50, 0xfe, 0x20, // 0FE50 at 385
+ 0x3a, 0x0d, 0x21, // 10D3A at 417
+ 0x74, 0x11, 0x01, // 11174 at 448
+ 0x5a, 0x14, 0x21, // 1145A at 481
+ 0x44, 0x19, 0x81, // 11944 at 516
+ 0x5a, 0x1d, 0xa1, // 11D5A at 549
+ 0xf5, 0x6a, 0x21, // 16AF5 at 577
+ 0x45, 0xd2, 0x41, // 1D245 at 610
+ 0xaf, 0xe2, 0x21, // 1E2AF at 641
+ 0xf0, 0x01, 0x0e, // E01F0 at 672 (upper bound)
};
#ifdef CONFIG_ALL_UNICODE
-static const uint8_t unicode_cc_table[881] = {
+static const uint8_t unicode_cc_table[899] = {
0xb2, 0xcf, 0xd4, 0x00, 0xe8, 0x03, 0xdc, 0x00,
0xe8, 0x00, 0xd8, 0x04, 0xdc, 0x01, 0xca, 0x03,
0xdc, 0x01, 0xca, 0x0a, 0xdc, 0x04, 0x01, 0x03,
@@ -631,52 +694,72 @@ static const uint8_t unicode_cc_table[881] = {
0xb6, 0x61, 0x00, 0xdc, 0x80, 0xc0, 0xa7, 0xc0,
0x00, 0x01, 0x00, 0xdc, 0x83, 0x00, 0x09, 0xb0,
0x74, 0xc0, 0x00, 0xdc, 0xb2, 0x0c, 0xc3, 0xb1,
- 0x52, 0xc1, 0xb0, 0x68, 0x01, 0xdc, 0xc2, 0x00,
- 0xdc, 0xc0, 0x03, 0xdc, 0xb0, 0x00, 0xc0, 0x00,
- 0xdc, 0xc0, 0x00, 0xdc, 0xb0, 0x8f, 0x00, 0x09,
- 0xa8, 0x00, 0x09, 0x8d, 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, 0xb0, 0xd1, 0x01,
- 0x09, 0x83, 0x00, 0x07, 0xb0, 0x6b, 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,
+ 0x52, 0xc1, 0xb0, 0x1f, 0x02, 0xdc, 0xb0, 0x15,
+ 0x01, 0xdc, 0xc2, 0x00, 0xdc, 0xc0, 0x03, 0xdc,
+ 0xb0, 0x00, 0xc0, 0x00, 0xdc, 0xc0, 0x00, 0xdc,
+ 0xb0, 0x8f, 0x00, 0x09, 0xa8, 0x00, 0x09, 0x8d,
+ 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, 0xb0, 0xd1, 0x01, 0x09, 0x83, 0x00, 0x07,
+ 0xb0, 0x6b, 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, 0xb1, 0x78,
+ 0x01, 0x09, 0xb8, 0x43, 0x7c, 0x04, 0x01, 0xb0,
0x0a, 0xc6, 0xb4, 0x88, 0x01, 0x06, 0xb8, 0x44,
0x7b, 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, 0x46, 0xc0, 0xb0, 0x0c, 0xc3,
- 0xb5, 0xaf, 0x06, 0xdc, 0xb0, 0x3c, 0xc5, 0x00,
- 0x07,
+ 0x33, 0xc0, 0xb0, 0x6f, 0xc6, 0xb1, 0x46, 0xc0,
+ 0xb0, 0x0c, 0xc3, 0xb1, 0xcb, 0x01, 0xe8, 0x00,
+ 0xdc, 0xc0, 0xb3, 0xaf, 0x06, 0xdc, 0xb0, 0x3c,
+ 0xc5, 0x00, 0x07,
};
-static const uint8_t unicode_cc_index[84] = {
- 0x4d, 0x03, 0x00, 0x97, 0x05, 0x20, 0xc6, 0x05,
- 0x00, 0xe7, 0x06, 0x00, 0x45, 0x07, 0x00, 0x9c,
- 0x08, 0x00, 0x4d, 0x09, 0x00, 0x3c, 0x0b, 0x00,
- 0x3d, 0x0d, 0x00, 0x36, 0x0f, 0x00, 0x38, 0x10,
- 0x20, 0x3a, 0x19, 0x00, 0xcb, 0x1a, 0x20, 0xd3,
- 0x1c, 0x00, 0xcf, 0x1d, 0x00, 0xe2, 0x20, 0x00,
- 0x2e, 0x30, 0x20, 0x2b, 0xa9, 0x20, 0xed, 0xab,
- 0x00, 0x39, 0x0a, 0x01, 0x84, 0x0f, 0x21, 0xc0,
- 0x11, 0x01, 0x43, 0x14, 0x01, 0x39, 0x18, 0x21,
- 0x42, 0x1d, 0x21, 0x67, 0xd1, 0x01, 0x30, 0xe1,
- 0x21, 0x4b, 0xe9, 0x01,
+static const uint8_t unicode_cc_index[87] = {
+ 0x4d, 0x03, 0x00, // 0034D at 32
+ 0x97, 0x05, 0x20, // 00597 at 65
+ 0xc6, 0x05, 0x00, // 005C6 at 96
+ 0xe7, 0x06, 0x00, // 006E7 at 128
+ 0x45, 0x07, 0x00, // 00745 at 160
+ 0x9c, 0x08, 0x00, // 0089C at 192
+ 0x4d, 0x09, 0x00, // 0094D at 224
+ 0x3c, 0x0b, 0x00, // 00B3C at 256
+ 0x3d, 0x0d, 0x00, // 00D3D at 288
+ 0x36, 0x0f, 0x00, // 00F36 at 320
+ 0x38, 0x10, 0x20, // 01038 at 353
+ 0x3a, 0x19, 0x00, // 0193A at 384
+ 0xcb, 0x1a, 0x20, // 01ACB at 417
+ 0xd3, 0x1c, 0x00, // 01CD3 at 448
+ 0xcf, 0x1d, 0x00, // 01DCF at 480
+ 0xe2, 0x20, 0x00, // 020E2 at 512
+ 0x2e, 0x30, 0x20, // 0302E at 545
+ 0x2b, 0xa9, 0x20, // 0A92B at 577
+ 0xed, 0xab, 0x00, // 0ABED at 608
+ 0x39, 0x0a, 0x01, // 10A39 at 640
+ 0x51, 0x0f, 0x01, // 10F51 at 672
+ 0x73, 0x11, 0x01, // 11173 at 704
+ 0x75, 0x13, 0x01, // 11375 at 736
+ 0x2b, 0x17, 0x21, // 1172B at 769
+ 0x3f, 0x1c, 0x21, // 11C3F at 801
+ 0x9e, 0xbc, 0x21, // 1BC9E at 833
+ 0x08, 0xe0, 0x01, // 1E008 at 864
+ 0x44, 0xe9, 0x01, // 1E944 at 896
+ 0x4b, 0xe9, 0x01, // 1E94B at 928 (upper bound)
};
-static const uint32_t unicode_decomp_table1[693] = {
+static const uint32_t unicode_decomp_table1[699] = {
0x00280081, 0x002a0097, 0x002a8081, 0x002bc097,
0x002c8115, 0x002d0097, 0x002d4081, 0x002e0097,
0x002e4115, 0x002f0199, 0x00302016, 0x00400842,
@@ -840,20 +923,21 @@ static const uint32_t unicode_decomp_table1[693] = {
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, 0x7efc051f,
- 0xbe0001ac, 0xbe00d110, 0xbe0947ac, 0xbe0d3910,
- 0xbe29872c, 0xbe2d022c, 0xbe2e3790, 0xbe49ff90,
- 0xbe69bc10,
+ 0x75fb051f, 0x75fd851f, 0x780c049f, 0x780e419f,
+ 0x780f059f, 0x7811c203, 0x7812d0ad, 0x781b0103,
+ 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, 0x7efc051f, 0xbe0001ac, 0xbe00d110,
+ 0xbe0947ac, 0xbe0d3910, 0xbe29872c, 0xbe2d022c,
+ 0xbe2e3790, 0xbe49ff90, 0xbe69bc10,
};
-static const uint16_t unicode_decomp_table2[693] = {
+static const uint16_t unicode_decomp_table2[699] = {
0x0020, 0x0000, 0x0061, 0x0002, 0x0004, 0x0006, 0x03bc, 0x0008,
0x000a, 0x000c, 0x0015, 0x0095, 0x00a5, 0x00b9, 0x00c1, 0x00c3,
0x00c7, 0x00cb, 0x00d1, 0x00d7, 0x00dd, 0x00e0, 0x00e6, 0x00f8,
@@ -935,15 +1019,16 @@ static const uint16_t unicode_decomp_table2[693] = {
0x2207, 0x1dc8, 0x2202, 0x1dca, 0x1dd2, 0x03f4, 0x1dd4, 0x2207,
0x1dd6, 0x2202, 0x1dd8, 0x1de0, 0x03f4, 0x1de2, 0x2207, 0x1de4,
0x2202, 0x1de6, 0x1dee, 0x03f4, 0x1df0, 0x2207, 0x1df2, 0x2202,
- 0x1df4, 0x1dfe, 0x1e00, 0x1e02, 0x1e04, 0x1e06, 0x1e08, 0x1e0e,
- 0x1e2b, 0x062d, 0x1e33, 0x1e3f, 0x062c, 0x1e4f, 0x1ebf, 0x1ecb,
- 0x1ede, 0x1ef0, 0x1f03, 0x1f05, 0x1f09, 0x1f0f, 0x1f15, 0x1f17,
- 0x1f1b, 0x1f1d, 0x1f25, 0x1f28, 0x1f2a, 0x1f30, 0x1f32, 0x30b5,
- 0x1f38, 0x1f90, 0x1fa6, 0x1faa, 0x1fac, 0x1fb1, 0x1ffe, 0x200f,
- 0x2110, 0x2120, 0x2126, 0x2220, 0x233e,
+ 0x1df4, 0x1dfe, 0x1e00, 0x1e02, 0x1e04, 0x1e06, 0x1e08, 0x1e0a,
+ 0x1e0c, 0x1e0e, 0x1e16, 0x1e39, 0x1e3d, 0x1e43, 0x1e60, 0x062d,
+ 0x1e68, 0x1e74, 0x062c, 0x1e84, 0x1ef4, 0x1f00, 0x1f13, 0x1f25,
+ 0x1f38, 0x1f3a, 0x1f3e, 0x1f44, 0x1f4a, 0x1f4c, 0x1f50, 0x1f52,
+ 0x1f5a, 0x1f5d, 0x1f5f, 0x1f65, 0x1f67, 0x30b5, 0x1f6d, 0x1fc5,
+ 0x1fdb, 0x1fdf, 0x1fe1, 0x1fe6, 0x2033, 0x2044, 0x2145, 0x2155,
+ 0x215b, 0x2255, 0x2373,
};
-static const uint8_t unicode_decomp_data[9292] = {
+static const uint8_t unicode_decomp_data[9345] = {
0x20, 0x88, 0x20, 0x84, 0x32, 0x33, 0x20, 0x81,
0x20, 0xa7, 0x31, 0x6f, 0x31, 0xd0, 0x34, 0x31,
0xd0, 0x32, 0x33, 0xd0, 0x34, 0x41, 0x80, 0x41,
@@ -1905,207 +1990,214 @@ static const uint8_t unicode_decomp_data[9292] = {
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,
+ 0x30, 0x04, 0x3a, 0x04, 0x3e, 0x04, 0x4b, 0x04,
+ 0x4d, 0x04, 0x4e, 0x04, 0x89, 0xa6, 0x30, 0x04,
+ 0xa9, 0x26, 0x28, 0xb9, 0x7f, 0x9f, 0x00, 0x01,
+ 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0a,
+ 0x0b, 0x0e, 0x0f, 0x11, 0x13, 0x14, 0x15, 0x16,
+ 0x17, 0x18, 0x1a, 0x1b, 0x61, 0x26, 0x25, 0x2f,
+ 0x7b, 0x51, 0xa6, 0xb1, 0x04, 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, 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, 0x30, 0x00, 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, 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, 0x30,
+ 0x00, 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[945] = {
@@ -2313,7 +2405,7 @@ static const char unicode_gc_name_table[] =
"C,Other" "\0"
;
-static const uint8_t unicode_gc_table[3897] = {
+static const uint8_t unicode_gc_table[3948] = {
0xfa, 0x18, 0x17, 0x56, 0x0d, 0x56, 0x12, 0x13,
0x16, 0x0c, 0x16, 0x11, 0x36, 0xe9, 0x02, 0x36,
0x4c, 0x36, 0xe1, 0x12, 0x12, 0x16, 0x13, 0x0e,
@@ -2399,409 +2491,415 @@ static const uint8_t unicode_gc_table[3897] = {
0x85, 0x20, 0x06, 0x05, 0x07, 0x06, 0x87, 0x00,
0x06, 0x27, 0x00, 0x27, 0x26, 0xc0, 0x27, 0xa0,
0x25, 0x00, 0x25, 0x26, 0x20, 0xe9, 0x02, 0x00,
- 0x25, 0xe0, 0x05, 0x26, 0x27, 0xe5, 0x01, 0x00,
- 0x45, 0x00, 0xe5, 0x21, 0x26, 0x05, 0x47, 0x66,
- 0x00, 0x47, 0x00, 0x47, 0x06, 0x05, 0x0f, 0x60,
- 0x45, 0x07, 0xcb, 0x45, 0x26, 0x20, 0xe9, 0x02,
- 0xeb, 0x01, 0x0f, 0xa5, 0x00, 0x06, 0x27, 0x00,
- 0xe5, 0x0a, 0x40, 0xe5, 0x10, 0x00, 0xe5, 0x01,
- 0x00, 0x05, 0x20, 0xc5, 0x40, 0x06, 0x60, 0x47,
- 0x46, 0x00, 0x06, 0x00, 0xe7, 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, 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, 0x0a, 0x46, 0x07, 0xe0,
- 0x01, 0xe5, 0x0b, 0x26, 0x07, 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, 0x06, 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, 0xe6, 0x08, 0xe0, 0x29, 0x66, 0x07, 0xe5,
- 0x27, 0x06, 0x07, 0x86, 0x07, 0x06, 0x87, 0x06,
- 0x27, 0xe5, 0x00, 0x40, 0xe9, 0x02, 0xd6, 0xef,
- 0x02, 0xe6, 0x01, 0xef, 0x01, 0x36, 0x00, 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, 0x38, 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, 0x19, 0xe0, 0x07,
- 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, 0xec,
- 0x08, 0xef, 0x80, 0x78, 0xec, 0x7b, 0x12, 0x13,
+ 0x25, 0x07, 0xe0, 0x04, 0x26, 0x27, 0xe5, 0x01,
+ 0x00, 0x45, 0x00, 0xe5, 0x21, 0x26, 0x05, 0x47,
+ 0x66, 0x00, 0x47, 0x00, 0x47, 0x06, 0x05, 0x0f,
+ 0x60, 0x45, 0x07, 0xcb, 0x45, 0x26, 0x20, 0xe9,
+ 0x02, 0xeb, 0x01, 0x0f, 0xa5, 0x00, 0x06, 0x27,
+ 0x00, 0xe5, 0x0a, 0x40, 0xe5, 0x10, 0x00, 0xe5,
+ 0x01, 0x00, 0x05, 0x20, 0xc5, 0x40, 0x06, 0x60,
+ 0x47, 0x46, 0x00, 0x06, 0x00, 0xe7, 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, 0x00, 0x85, 0x00, 0xe5, 0x10,
+ 0x00, 0x05, 0x00, 0xe5, 0x02, 0x06, 0x25, 0xe6,
+ 0x01, 0x05, 0x20, 0x85, 0x00, 0x04, 0x00, 0xc6,
+ 0x00, 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, 0x0a, 0x46, 0x07,
+ 0xe0, 0x01, 0xe5, 0x0b, 0x26, 0x07, 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, 0x06, 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, 0xe6, 0x08, 0xe0, 0x29, 0x66, 0x07,
+ 0xe5, 0x27, 0x06, 0x07, 0x86, 0x07, 0x06, 0x87,
+ 0x06, 0x27, 0xe5, 0x00, 0x40, 0xe9, 0x02, 0xd6,
+ 0xef, 0x02, 0xe6, 0x01, 0xef, 0x01, 0x36, 0x00,
+ 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, 0x38, 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, 0x19, 0xe0,
+ 0x07, 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, 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, 0x00, 0xef, 0x61, 0xe1,
- 0x28, 0xe2, 0x28, 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, 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, 0x2f, 0x56, 0x12, 0x13, 0x12, 0x13, 0x12,
- 0x13, 0x12, 0x13, 0x11, 0xe0, 0x1a, 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,
- 0x18, 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,
- 0x38, 0xef, 0x38, 0xe5, 0xc0, 0x11, 0x8d, 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, 0x07, 0x41, 0x02, 0x3f, 0x80,
- 0x3f, 0x00, 0x02, 0x00, 0x02, 0x7f, 0xe0, 0x10,
- 0x44, 0x3f, 0x05, 0x24, 0x02, 0xc5, 0x06, 0x45,
- 0x06, 0x65, 0x06, 0xe5, 0x0f, 0x27, 0x26, 0x07,
- 0x6f, 0x06, 0x40, 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,
- 0x01, 0x04, 0x2e, 0x60, 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, 0x09, 0xe0, 0x08,
- 0xe5, 0x80, 0xe3, 0x13, 0x12, 0xef, 0x08, 0xe5,
- 0x38, 0x20, 0xe5, 0x2e, 0xc0, 0x0f, 0xe0, 0x18,
- 0xe5, 0x04, 0x0d, 0x4f, 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,
- 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, 0x05, 0x40,
- 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, 0xe1, 0x03, 0x00, 0xe1, 0x07, 0x00, 0xc1,
- 0x00, 0x21, 0x00, 0xe2, 0x03, 0x00, 0xe2, 0x07,
- 0x00, 0xc2, 0x00, 0x22, 0xe0, 0x3b, 0xe5, 0x80,
- 0xaf, 0xe0, 0x01, 0xe5, 0x0e, 0xe0, 0x02, 0xe5,
- 0x00, 0xe0, 0x10, 0xa4, 0x00, 0xe4, 0x22, 0x00,
- 0xe4, 0x01, 0xe0, 0x3d, 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, 0x00, 0xe5, 0x22,
- 0x00, 0x26, 0x11, 0x20, 0x25, 0xe0, 0x46, 0xe5,
- 0x15, 0xeb, 0x02, 0x05, 0xe0, 0x00, 0xe5, 0x0e,
- 0xe6, 0x03, 0x6b, 0x96, 0xe0, 0x0e, 0xe5, 0x0a,
- 0x66, 0x76, 0xe0, 0x1e, 0xe5, 0x0d, 0xcb, 0xe0,
- 0x0c, 0xe5, 0x0f, 0xe0, 0x01, 0x07, 0x06, 0x07,
- 0xe5, 0x2d, 0xe6, 0x07, 0xd6, 0x60, 0xeb, 0x0c,
- 0xe9, 0x02, 0x06, 0x25, 0x26, 0x05, 0xe0, 0x01,
- 0x46, 0x07, 0xe5, 0x25, 0x47, 0x66, 0x27, 0x26,
- 0x36, 0x1b, 0x76, 0x06, 0xe0, 0x02, 0x1b, 0x20,
- 0xe5, 0x11, 0xc0, 0xe9, 0x02, 0xa0, 0x46, 0xe5,
- 0x1c, 0x86, 0x07, 0xe6, 0x00, 0x00, 0xe9, 0x02,
- 0x76, 0x05, 0x27, 0x05, 0xe0, 0x00, 0xe5, 0x1b,
- 0x06, 0x36, 0x05, 0xe0, 0x01, 0x26, 0x07, 0xe5,
- 0x28, 0x47, 0xe6, 0x01, 0x27, 0x65, 0x76, 0x66,
- 0x16, 0x07, 0x06, 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, 0x36, 0x00, 0x16, 0x06, 0x45, 0xe0, 0x16,
- 0xe5, 0x28, 0x47, 0xa6, 0x07, 0x06, 0x67, 0x26,
- 0x07, 0x26, 0x25, 0x16, 0x05, 0xe0, 0x00, 0xe9,
- 0x02, 0xe0, 0x80, 0x1e, 0xe5, 0x27, 0x47, 0x66,
- 0x20, 0x67, 0x26, 0x07, 0x26, 0xf6, 0x0f, 0x65,
- 0x26, 0xe0, 0x1a, 0xe5, 0x28, 0x47, 0xe6, 0x00,
- 0x27, 0x06, 0x07, 0x26, 0x56, 0x05, 0xe0, 0x03,
- 0xe9, 0x02, 0xa0, 0xf6, 0x05, 0xe0, 0x0b, 0xe5,
- 0x23, 0x06, 0x07, 0x06, 0x27, 0xa6, 0x07, 0x06,
- 0x05, 0x16, 0xa0, 0xe9, 0x02, 0xe0, 0x2e, 0xe5,
- 0x13, 0x20, 0x46, 0x27, 0x66, 0x07, 0x86, 0x60,
- 0xe9, 0x02, 0x2b, 0x56, 0x0f, 0xc5, 0xe0, 0x80,
- 0x31, 0xe5, 0x24, 0x47, 0xe6, 0x01, 0x07, 0x26,
- 0x16, 0xe0, 0x5c, 0xe1, 0x18, 0xe2, 0x18, 0xe9,
- 0x02, 0xeb, 0x01, 0xe0, 0x04, 0xe5, 0x00, 0x20,
- 0x05, 0x20, 0xe5, 0x00, 0x00, 0x25, 0x00, 0xe5,
- 0x10, 0xa7, 0x00, 0x27, 0x20, 0x26, 0x07, 0x06,
- 0x05, 0x07, 0x05, 0x07, 0x06, 0x56, 0xe0, 0x01,
- 0xe9, 0x02, 0xe0, 0x3e, 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, 0x05, 0xe5, 0x41, 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, 0x2f, 0x05, 0xe0, 0x07, 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, 0x89,
- 0xc4, 0xe5, 0x59, 0x36, 0xe0, 0x05, 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,
- 0xe5, 0x47, 0x00, 0xe9, 0x02, 0xa0, 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, 0x06, 0xe0, 0x03,
- 0x27, 0xe0, 0x06, 0xe5, 0x97, 0x70, 0xe0, 0x00,
- 0xe5, 0x84, 0x4e, 0xe0, 0x22, 0xe5, 0x01, 0xe0,
- 0xa2, 0x5f, 0x64, 0x00, 0xc4, 0x00, 0x24, 0x00,
- 0xe5, 0x80, 0x9b, 0xe0, 0x25, 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, 0x91, 0xd4, 0xe6, 0x26, 0x20, 0xe6,
- 0x0f, 0xe0, 0x01, 0xef, 0x6c, 0xe0, 0x34, 0xef,
- 0x80, 0x6e, 0xe0, 0x02, 0xef, 0x1f, 0x20, 0xef,
- 0x34, 0x27, 0x46, 0x4f, 0xa7, 0xfb, 0x00, 0xe6,
- 0x00, 0x2f, 0xc6, 0xef, 0x16, 0x66, 0xef, 0x35,
- 0xe0, 0x0d, 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,
+ 0xec, 0x08, 0xef, 0x80, 0x78, 0xec, 0x7b, 0x12,
+ 0x13, 0x12, 0x13, 0x12, 0x13, 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, 0x00, 0xef, 0x61,
+ 0xe1, 0x28, 0xe2, 0x28, 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, 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, 0x2f, 0x56, 0x12, 0x13, 0x12, 0x13,
+ 0x12, 0x13, 0x12, 0x13, 0x11, 0xe0, 0x1a, 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, 0x18, 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, 0x38, 0xef, 0x38, 0xe5, 0xc0, 0x11, 0x8d,
+ 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, 0x07, 0x41, 0x02, 0x3f,
+ 0x80, 0x3f, 0x00, 0x02, 0x00, 0x02, 0x7f, 0xe0,
+ 0x10, 0x44, 0x3f, 0x05, 0x24, 0x02, 0xc5, 0x06,
+ 0x45, 0x06, 0x65, 0x06, 0xe5, 0x0f, 0x27, 0x26,
+ 0x07, 0x6f, 0x06, 0x40, 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, 0x01, 0x04, 0x2e, 0x60, 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, 0x09, 0xe0,
+ 0x08, 0xe5, 0x80, 0xe3, 0x13, 0x12, 0xef, 0x08,
+ 0xe5, 0x38, 0x20, 0xe5, 0x2e, 0xc0, 0x0f, 0xe0,
+ 0x18, 0xe5, 0x04, 0x0d, 0x4f, 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, 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, 0x05,
+ 0x40, 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, 0xe1, 0x03, 0x00, 0xe1, 0x07, 0x00,
+ 0xc1, 0x00, 0x21, 0x00, 0xe2, 0x03, 0x00, 0xe2,
+ 0x07, 0x00, 0xc2, 0x00, 0x22, 0xe0, 0x3b, 0xe5,
+ 0x80, 0xaf, 0xe0, 0x01, 0xe5, 0x0e, 0xe0, 0x02,
+ 0xe5, 0x00, 0xe0, 0x10, 0xa4, 0x00, 0xe4, 0x22,
+ 0x00, 0xe4, 0x01, 0xe0, 0x3d, 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, 0x00, 0xe5,
+ 0x22, 0x00, 0x26, 0x11, 0x20, 0x25, 0xe0, 0x43,
+ 0x46, 0xe5, 0x15, 0xeb, 0x02, 0x05, 0xe0, 0x00,
+ 0xe5, 0x0e, 0xe6, 0x03, 0x6b, 0x96, 0xe0, 0x0e,
+ 0xe5, 0x0a, 0x66, 0x76, 0xe0, 0x1e, 0xe5, 0x0d,
+ 0xcb, 0xe0, 0x0c, 0xe5, 0x0f, 0xe0, 0x01, 0x07,
+ 0x06, 0x07, 0xe5, 0x2d, 0xe6, 0x07, 0xd6, 0x60,
+ 0xeb, 0x0c, 0xe9, 0x02, 0x06, 0x25, 0x26, 0x05,
+ 0xe0, 0x01, 0x46, 0x07, 0xe5, 0x25, 0x47, 0x66,
+ 0x27, 0x26, 0x36, 0x1b, 0x76, 0x06, 0xe0, 0x02,
+ 0x1b, 0x20, 0xe5, 0x11, 0xc0, 0xe9, 0x02, 0xa0,
+ 0x46, 0xe5, 0x1c, 0x86, 0x07, 0xe6, 0x00, 0x00,
+ 0xe9, 0x02, 0x76, 0x05, 0x27, 0x05, 0xe0, 0x00,
+ 0xe5, 0x1b, 0x06, 0x36, 0x05, 0xe0, 0x01, 0x26,
+ 0x07, 0xe5, 0x28, 0x47, 0xe6, 0x01, 0x27, 0x65,
+ 0x76, 0x66, 0x16, 0x07, 0x06, 0xe9, 0x02, 0x05,
+ 0x16, 0x05, 0x56, 0x00, 0xeb, 0x0c, 0xe0, 0x03,
+ 0xe5, 0x0a, 0x00, 0xe5, 0x11, 0x47, 0x46, 0x27,
+ 0x06, 0x07, 0x26, 0xb6, 0x06, 0x25, 0x06, 0xe0,
+ 0x36, 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, 0x36, 0x00, 0x16,
+ 0x06, 0x45, 0xe0, 0x16, 0xe5, 0x28, 0x47, 0xa6,
+ 0x07, 0x06, 0x67, 0x26, 0x07, 0x26, 0x25, 0x16,
+ 0x05, 0xe0, 0x00, 0xe9, 0x02, 0xe0, 0x80, 0x1e,
+ 0xe5, 0x27, 0x47, 0x66, 0x20, 0x67, 0x26, 0x07,
+ 0x26, 0xf6, 0x0f, 0x65, 0x26, 0xe0, 0x1a, 0xe5,
+ 0x28, 0x47, 0xe6, 0x00, 0x27, 0x06, 0x07, 0x26,
+ 0x56, 0x05, 0xe0, 0x03, 0xe9, 0x02, 0xa0, 0xf6,
+ 0x05, 0xe0, 0x0b, 0xe5, 0x23, 0x06, 0x07, 0x06,
+ 0x27, 0xa6, 0x07, 0x06, 0x05, 0x16, 0xa0, 0xe9,
+ 0x02, 0xe0, 0x2e, 0xe5, 0x13, 0x20, 0x46, 0x27,
+ 0x66, 0x07, 0x86, 0x60, 0xe9, 0x02, 0x2b, 0x56,
+ 0x0f, 0xc5, 0xe0, 0x80, 0x31, 0xe5, 0x24, 0x47,
+ 0xe6, 0x01, 0x07, 0x26, 0x16, 0xe0, 0x5c, 0xe1,
+ 0x18, 0xe2, 0x18, 0xe9, 0x02, 0xeb, 0x01, 0xe0,
+ 0x04, 0xe5, 0x00, 0x20, 0x05, 0x20, 0xe5, 0x00,
+ 0x00, 0x25, 0x00, 0xe5, 0x10, 0xa7, 0x00, 0x27,
+ 0x20, 0x26, 0x07, 0x06, 0x05, 0x07, 0x05, 0x07,
+ 0x06, 0x56, 0xe0, 0x01, 0xe9, 0x02, 0xe0, 0x3e,
+ 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, 0x05, 0xe5, 0x41,
+ 0xc0, 0xf6, 0x02, 0xe0, 0x80, 0x6e, 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, 0xc0,
+ 0x26, 0x05, 0x07, 0xe5, 0x05, 0x00, 0xe5, 0x1a,
+ 0x27, 0x86, 0x40, 0x27, 0x06, 0x07, 0x06, 0xf6,
+ 0x05, 0xe9, 0x02, 0xe0, 0x4e, 0x05, 0xe0, 0x07,
+ 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, 0x89, 0xc4, 0xe5, 0x59, 0x36, 0xe0, 0x05,
+ 0xe5, 0x83, 0xa8, 0xfb, 0x08, 0x06, 0xa5, 0xe6,
+ 0x07, 0xe0, 0x8f, 0x22, 0xe5, 0x81, 0xbf, 0xe0,
+ 0xa1, 0x31, 0xe5, 0x81, 0xb1, 0xc0, 0xe5, 0x17,
+ 0x00, 0xe9, 0x02, 0x60, 0x36, 0xe5, 0x47, 0x00,
+ 0xe9, 0x02, 0xa0, 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, 0x06, 0xe0, 0x03, 0x27, 0xe0, 0x06,
+ 0xe5, 0x97, 0x70, 0xe0, 0x00, 0xe5, 0x84, 0x4e,
+ 0xe0, 0x22, 0xe5, 0x01, 0xe0, 0xa2, 0x5f, 0x64,
+ 0x00, 0xc4, 0x00, 0x24, 0x00, 0xe5, 0x80, 0x9b,
+ 0xe0, 0x07, 0x05, 0xe0, 0x15, 0x45, 0x20, 0x05,
+ 0xe0, 0x06, 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, 0x91, 0xd4, 0xe6, 0x26,
+ 0x20, 0xe6, 0x0f, 0xe0, 0x01, 0xef, 0x6c, 0xe0,
+ 0x34, 0xef, 0x80, 0x6e, 0xe0, 0x02, 0xef, 0x1f,
+ 0x20, 0xef, 0x34, 0x27, 0x46, 0x4f, 0xa7, 0xfb,
+ 0x00, 0xe6, 0x00, 0x2f, 0xc6, 0xef, 0x16, 0x66,
+ 0xef, 0x35, 0xe0, 0x0d, 0xef, 0x3a, 0x46, 0x0f,
+ 0xe0, 0x72, 0xeb, 0x0c, 0xe0, 0x04, 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, 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, 0x83, 0xc8, 0xe2, 0x02, 0x05, 0xe2, 0x0c,
- 0xe0, 0x80, 0x59, 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, 0xb8, 0xe5, 0x16,
- 0x06, 0xe0, 0x09, 0xe5, 0x24, 0x66, 0xe9, 0x02,
- 0x80, 0x0d, 0xe0, 0x84, 0x58, 0xc5, 0x00, 0x65,
- 0x00, 0x25, 0x00, 0xe5, 0x07, 0x00, 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, 0xef,
- 0x80, 0x19, 0xe0, 0x30, 0xef, 0x15, 0xe0, 0x05,
- 0xef, 0x24, 0x60, 0xef, 0x01, 0xc0, 0x2f, 0xe0,
- 0x06, 0xaf, 0xe0, 0x80, 0x12, 0xef, 0x80, 0x73,
- 0x8e, 0xef, 0x82, 0x50, 0x80, 0xef, 0x08, 0x40,
- 0xef, 0x05, 0x40, 0xef, 0x6c, 0xe0, 0x04, 0xef,
- 0x51, 0xc0, 0xef, 0x04, 0x60, 0x0f, 0xe0, 0x07,
- 0xef, 0x04, 0x60, 0xef, 0x30, 0xe0, 0x00, 0xef,
- 0x02, 0xa0, 0xef, 0x20, 0xe0, 0x00, 0xef, 0x16,
- 0x20, 0x2f, 0xe0, 0x46, 0xef, 0x80, 0xcc, 0xe0,
- 0x04, 0xef, 0x06, 0x20, 0x8f, 0x40, 0x8f, 0x40,
- 0xcf, 0xe0, 0x01, 0xef, 0x15, 0x40, 0xef, 0x03,
- 0x80, 0xaf, 0xe0, 0x02, 0xef, 0x02, 0xa0, 0xef,
- 0x00, 0xe0, 0x00, 0xcf, 0xe0, 0x01, 0xef, 0x80,
- 0x0b, 0x00, 0xef, 0x2f, 0xe0, 0x1d, 0xe9, 0x02,
- 0xe0, 0x83, 0x7e, 0xe5, 0xc0, 0x66, 0x58, 0xe0,
- 0x18, 0xe5, 0x8f, 0xb1, 0xc0, 0xe5, 0x80, 0x56,
- 0x20, 0xe5, 0x95, 0xfa, 0xe0, 0x06, 0xe5, 0x9c,
- 0xa9, 0xe0, 0x8b, 0x97, 0xe5, 0x81, 0x96, 0xe0,
- 0x85, 0x5a, 0xe5, 0x92, 0xc3, 0xe0, 0xca, 0xac,
- 0x2e, 0x1b, 0xe0, 0x16, 0xfb, 0x58, 0xe0, 0x78,
- 0xe6, 0x80, 0x68, 0xe0, 0xc0, 0xbd, 0x88, 0xfd,
- 0xc0, 0xbf, 0x76, 0x20, 0xfd, 0xc0, 0xbf, 0x76,
- 0x20,
+ 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, 0x83, 0xc8,
+ 0xe2, 0x02, 0x05, 0xe2, 0x0c, 0xa0, 0xa2, 0xe0,
+ 0x80, 0x4d, 0xc6, 0x00, 0xe6, 0x09, 0x20, 0xc6,
+ 0x00, 0x26, 0x00, 0x86, 0x80, 0xe4, 0x36, 0xe0,
+ 0x19, 0x06, 0xe0, 0x68, 0xe5, 0x25, 0x40, 0xc6,
+ 0xc4, 0x20, 0xe9, 0x02, 0x60, 0x05, 0x0f, 0xe0,
+ 0x80, 0xb8, 0xe5, 0x16, 0x06, 0xe0, 0x09, 0xe5,
+ 0x24, 0x66, 0xe9, 0x02, 0x80, 0x0d, 0xe0, 0x81,
+ 0x48, 0xe5, 0x13, 0x04, 0x66, 0xe9, 0x02, 0xe0,
+ 0x82, 0x5e, 0xc5, 0x00, 0x65, 0x00, 0x25, 0x00,
+ 0xe5, 0x07, 0x00, 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, 0xef, 0x80, 0x19, 0xe0,
+ 0x30, 0xef, 0x15, 0xe0, 0x05, 0xef, 0x24, 0x60,
+ 0xef, 0x01, 0xc0, 0x2f, 0xe0, 0x06, 0xaf, 0xe0,
+ 0x80, 0x12, 0xef, 0x80, 0x73, 0x8e, 0xef, 0x82,
+ 0x50, 0x60, 0xef, 0x09, 0x40, 0xef, 0x05, 0x40,
+ 0xef, 0x6f, 0x60, 0xef, 0x57, 0xa0, 0xef, 0x04,
+ 0x60, 0x0f, 0xe0, 0x07, 0xef, 0x04, 0x60, 0xef,
+ 0x30, 0xe0, 0x00, 0xef, 0x02, 0xa0, 0xef, 0x20,
+ 0xe0, 0x00, 0xef, 0x16, 0x20, 0x2f, 0xe0, 0x46,
+ 0xef, 0x80, 0xcc, 0xe0, 0x04, 0xef, 0x06, 0x20,
+ 0xef, 0x05, 0x40, 0xef, 0x01, 0xc0, 0xef, 0x26,
+ 0x00, 0xcf, 0xe0, 0x00, 0xef, 0x06, 0x60, 0xef,
+ 0x01, 0xc0, 0xef, 0x01, 0xc0, 0xef, 0x80, 0x0b,
+ 0x00, 0xef, 0x2f, 0xe0, 0x1d, 0xe9, 0x02, 0xe0,
+ 0x83, 0x7e, 0xe5, 0xc0, 0x66, 0x58, 0xe0, 0x18,
+ 0xe5, 0x8f, 0xb2, 0xa0, 0xe5, 0x80, 0x56, 0x20,
+ 0xe5, 0x95, 0xfa, 0xe0, 0x06, 0xe5, 0x9c, 0xa9,
+ 0xe0, 0x8b, 0x97, 0xe5, 0x81, 0x96, 0xe0, 0x85,
+ 0x5a, 0xe5, 0x92, 0xc3, 0x80, 0xe5, 0x8f, 0xd8,
+ 0xe0, 0xca, 0x9b, 0xc9, 0x1b, 0xe0, 0x16, 0xfb,
+ 0x58, 0xe0, 0x78, 0xe6, 0x80, 0x68, 0xe0, 0xc0,
+ 0xbd, 0x88, 0xfd, 0xc0, 0xbf, 0x76, 0x20, 0xfd,
+ 0xc0, 0xbf, 0x76, 0x20,
};
typedef enum {
@@ -2868,6 +2966,7 @@ typedef enum {
UNICODE_SCRIPT_Kaithi,
UNICODE_SCRIPT_Kannada,
UNICODE_SCRIPT_Katakana,
+ UNICODE_SCRIPT_Kawi,
UNICODE_SCRIPT_Kayah_Li,
UNICODE_SCRIPT_Kharoshthi,
UNICODE_SCRIPT_Khmer,
@@ -2902,6 +3001,7 @@ typedef enum {
UNICODE_SCRIPT_Multani,
UNICODE_SCRIPT_Myanmar,
UNICODE_SCRIPT_Nabataean,
+ UNICODE_SCRIPT_Nag_Mundari,
UNICODE_SCRIPT_Nandinagari,
UNICODE_SCRIPT_New_Tai_Lue,
UNICODE_SCRIPT_Newa,
@@ -3033,6 +3133,7 @@ static const char unicode_script_name_table[] =
"Kaithi,Kthi" "\0"
"Kannada,Knda" "\0"
"Katakana,Kana" "\0"
+ "Kawi,Kawi" "\0"
"Kayah_Li,Kali" "\0"
"Kharoshthi,Khar" "\0"
"Khmer,Khmr" "\0"
@@ -3067,6 +3168,7 @@ static const char unicode_script_name_table[] =
"Multani,Mult" "\0"
"Myanmar,Mymr" "\0"
"Nabataean,Nbat" "\0"
+ "Nag_Mundari,Nagm" "\0"
"Nandinagari,Nand" "\0"
"New_Tai_Lue,Talu" "\0"
"Newa,Newa" "\0"
@@ -3134,12 +3236,12 @@ static const char unicode_script_name_table[] =
"Zanabazar_Square,Zanb" "\0"
;
-static const uint8_t unicode_script_table[2690] = {
- 0xc0, 0x19, 0x99, 0x46, 0x85, 0x19, 0x99, 0x46,
- 0xae, 0x19, 0x80, 0x46, 0x8e, 0x19, 0x80, 0x46,
- 0x84, 0x19, 0x96, 0x46, 0x80, 0x19, 0x9e, 0x46,
- 0x80, 0x19, 0xe1, 0x60, 0x46, 0xa6, 0x19, 0x84,
- 0x46, 0x84, 0x19, 0x81, 0x0d, 0x93, 0x19, 0xe0,
+static const uint8_t unicode_script_table[2720] = {
+ 0xc0, 0x19, 0x99, 0x47, 0x85, 0x19, 0x99, 0x47,
+ 0xae, 0x19, 0x80, 0x47, 0x8e, 0x19, 0x80, 0x47,
+ 0x84, 0x19, 0x96, 0x47, 0x80, 0x19, 0x9e, 0x47,
+ 0x80, 0x19, 0xe1, 0x60, 0x47, 0xa6, 0x19, 0x84,
+ 0x47, 0x84, 0x19, 0x81, 0x0d, 0x93, 0x19, 0xe0,
0x0f, 0x38, 0x83, 0x2c, 0x80, 0x19, 0x82, 0x2c,
0x01, 0x83, 0x2c, 0x80, 0x19, 0x80, 0x2c, 0x03,
0x80, 0x2c, 0x80, 0x19, 0x80, 0x2c, 0x80, 0x19,
@@ -3152,11 +3254,11 @@ static const uint8_t unicode_script_table[2690] = {
0x80, 0x19, 0x8d, 0x04, 0x80, 0x19, 0x82, 0x04,
0x80, 0x19, 0x9f, 0x04, 0x80, 0x19, 0x89, 0x04,
0x8a, 0x38, 0x99, 0x04, 0x80, 0x38, 0xe0, 0x0b,
- 0x04, 0x80, 0x19, 0xa1, 0x04, 0x8d, 0x89, 0x00,
- 0xbb, 0x89, 0x01, 0x82, 0x89, 0xaf, 0x04, 0xb1,
- 0x93, 0x0d, 0xba, 0x64, 0x01, 0x82, 0x64, 0xad,
- 0x7d, 0x01, 0x8e, 0x7d, 0x00, 0x9b, 0x51, 0x01,
- 0x80, 0x51, 0x00, 0x8a, 0x89, 0x04, 0x9e, 0x04,
+ 0x04, 0x80, 0x19, 0xa1, 0x04, 0x8d, 0x8b, 0x00,
+ 0xbb, 0x8b, 0x01, 0x82, 0x8b, 0xaf, 0x04, 0xb1,
+ 0x95, 0x0d, 0xba, 0x66, 0x01, 0x82, 0x66, 0xad,
+ 0x7f, 0x01, 0x8e, 0x7f, 0x00, 0x9b, 0x52, 0x01,
+ 0x80, 0x52, 0x00, 0x8a, 0x8b, 0x04, 0x9e, 0x04,
0x00, 0x81, 0x04, 0x05, 0xc9, 0x04, 0x80, 0x19,
0x9c, 0x04, 0xd0, 0x20, 0x83, 0x38, 0x8e, 0x20,
0x81, 0x19, 0x99, 0x20, 0x83, 0x0b, 0x00, 0x87,
@@ -3176,43 +3278,43 @@ static const uint8_t unicode_script_table[2690] = {
0x84, 0x2d, 0x01, 0x89, 0x2d, 0x00, 0x82, 0x2d,
0x00, 0x82, 0x2d, 0x01, 0x80, 0x2d, 0x0e, 0x83,
0x2d, 0x01, 0x8b, 0x2d, 0x06, 0x86, 0x2d, 0x00,
- 0x82, 0x72, 0x00, 0x87, 0x72, 0x01, 0x81, 0x72,
- 0x01, 0x95, 0x72, 0x00, 0x86, 0x72, 0x00, 0x81,
- 0x72, 0x00, 0x84, 0x72, 0x01, 0x88, 0x72, 0x01,
- 0x81, 0x72, 0x01, 0x82, 0x72, 0x06, 0x82, 0x72,
- 0x03, 0x81, 0x72, 0x00, 0x84, 0x72, 0x01, 0x91,
- 0x72, 0x09, 0x81, 0x90, 0x00, 0x85, 0x90, 0x02,
- 0x82, 0x90, 0x00, 0x83, 0x90, 0x02, 0x81, 0x90,
- 0x00, 0x80, 0x90, 0x00, 0x81, 0x90, 0x02, 0x81,
- 0x90, 0x02, 0x82, 0x90, 0x02, 0x8b, 0x90, 0x03,
- 0x84, 0x90, 0x02, 0x82, 0x90, 0x00, 0x83, 0x90,
- 0x01, 0x80, 0x90, 0x05, 0x80, 0x90, 0x0d, 0x94,
- 0x90, 0x04, 0x8c, 0x92, 0x00, 0x82, 0x92, 0x00,
- 0x96, 0x92, 0x00, 0x8f, 0x92, 0x01, 0x88, 0x92,
- 0x00, 0x82, 0x92, 0x00, 0x83, 0x92, 0x06, 0x81,
- 0x92, 0x00, 0x82, 0x92, 0x01, 0x80, 0x92, 0x01,
- 0x83, 0x92, 0x01, 0x89, 0x92, 0x06, 0x88, 0x92,
+ 0x82, 0x74, 0x00, 0x87, 0x74, 0x01, 0x81, 0x74,
+ 0x01, 0x95, 0x74, 0x00, 0x86, 0x74, 0x00, 0x81,
+ 0x74, 0x00, 0x84, 0x74, 0x01, 0x88, 0x74, 0x01,
+ 0x81, 0x74, 0x01, 0x82, 0x74, 0x06, 0x82, 0x74,
+ 0x03, 0x81, 0x74, 0x00, 0x84, 0x74, 0x01, 0x91,
+ 0x74, 0x09, 0x81, 0x92, 0x00, 0x85, 0x92, 0x02,
+ 0x82, 0x92, 0x00, 0x83, 0x92, 0x02, 0x81, 0x92,
+ 0x00, 0x80, 0x92, 0x00, 0x81, 0x92, 0x02, 0x81,
+ 0x92, 0x02, 0x82, 0x92, 0x02, 0x8b, 0x92, 0x03,
+ 0x84, 0x92, 0x02, 0x82, 0x92, 0x00, 0x83, 0x92,
+ 0x01, 0x80, 0x92, 0x05, 0x80, 0x92, 0x0d, 0x94,
+ 0x92, 0x04, 0x8c, 0x94, 0x00, 0x82, 0x94, 0x00,
+ 0x96, 0x94, 0x00, 0x8f, 0x94, 0x01, 0x88, 0x94,
+ 0x00, 0x82, 0x94, 0x00, 0x83, 0x94, 0x06, 0x81,
+ 0x94, 0x00, 0x82, 0x94, 0x01, 0x80, 0x94, 0x01,
+ 0x83, 0x94, 0x01, 0x89, 0x94, 0x06, 0x88, 0x94,
0x8c, 0x3d, 0x00, 0x82, 0x3d, 0x00, 0x96, 0x3d,
0x00, 0x89, 0x3d, 0x00, 0x84, 0x3d, 0x01, 0x88,
0x3d, 0x00, 0x82, 0x3d, 0x00, 0x83, 0x3d, 0x06,
0x81, 0x3d, 0x05, 0x81, 0x3d, 0x00, 0x83, 0x3d,
- 0x01, 0x89, 0x3d, 0x00, 0x81, 0x3d, 0x0c, 0x8c,
- 0x50, 0x00, 0x82, 0x50, 0x00, 0xb2, 0x50, 0x00,
- 0x82, 0x50, 0x00, 0x85, 0x50, 0x03, 0x8f, 0x50,
- 0x01, 0x99, 0x50, 0x00, 0x82, 0x83, 0x00, 0x91,
- 0x83, 0x02, 0x97, 0x83, 0x00, 0x88, 0x83, 0x00,
- 0x80, 0x83, 0x01, 0x86, 0x83, 0x02, 0x80, 0x83,
- 0x03, 0x85, 0x83, 0x00, 0x80, 0x83, 0x00, 0x87,
- 0x83, 0x05, 0x89, 0x83, 0x01, 0x82, 0x83, 0x0b,
- 0xb9, 0x94, 0x03, 0x80, 0x19, 0x9b, 0x94, 0x24,
- 0x81, 0x45, 0x00, 0x80, 0x45, 0x00, 0x84, 0x45,
- 0x00, 0x97, 0x45, 0x00, 0x80, 0x45, 0x00, 0x96,
- 0x45, 0x01, 0x84, 0x45, 0x00, 0x80, 0x45, 0x00,
- 0x85, 0x45, 0x01, 0x89, 0x45, 0x01, 0x83, 0x45,
- 0x1f, 0xc7, 0x95, 0x00, 0xa3, 0x95, 0x03, 0xa6,
- 0x95, 0x00, 0xa3, 0x95, 0x00, 0x8e, 0x95, 0x00,
- 0x86, 0x95, 0x83, 0x19, 0x81, 0x95, 0x24, 0xe0,
- 0x3f, 0x5f, 0xa5, 0x28, 0x00, 0x80, 0x28, 0x04,
+ 0x01, 0x89, 0x3d, 0x00, 0x82, 0x3d, 0x0b, 0x8c,
+ 0x51, 0x00, 0x82, 0x51, 0x00, 0xb2, 0x51, 0x00,
+ 0x82, 0x51, 0x00, 0x85, 0x51, 0x03, 0x8f, 0x51,
+ 0x01, 0x99, 0x51, 0x00, 0x82, 0x85, 0x00, 0x91,
+ 0x85, 0x02, 0x97, 0x85, 0x00, 0x88, 0x85, 0x00,
+ 0x80, 0x85, 0x01, 0x86, 0x85, 0x02, 0x80, 0x85,
+ 0x03, 0x85, 0x85, 0x00, 0x80, 0x85, 0x00, 0x87,
+ 0x85, 0x05, 0x89, 0x85, 0x01, 0x82, 0x85, 0x0b,
+ 0xb9, 0x96, 0x03, 0x80, 0x19, 0x9b, 0x96, 0x24,
+ 0x81, 0x46, 0x00, 0x80, 0x46, 0x00, 0x84, 0x46,
+ 0x00, 0x97, 0x46, 0x00, 0x80, 0x46, 0x00, 0x96,
+ 0x46, 0x01, 0x84, 0x46, 0x00, 0x80, 0x46, 0x00,
+ 0x86, 0x46, 0x00, 0x89, 0x46, 0x01, 0x83, 0x46,
+ 0x1f, 0xc7, 0x97, 0x00, 0xa3, 0x97, 0x03, 0xa6,
+ 0x97, 0x00, 0xa3, 0x97, 0x00, 0x8e, 0x97, 0x00,
+ 0x86, 0x97, 0x83, 0x19, 0x81, 0x97, 0x24, 0xe0,
+ 0x3f, 0x60, 0xa5, 0x28, 0x00, 0x80, 0x28, 0x04,
0x80, 0x28, 0x01, 0xaa, 0x28, 0x80, 0x19, 0x83,
0x28, 0xe0, 0x9f, 0x31, 0xc8, 0x27, 0x00, 0x83,
0x27, 0x01, 0x86, 0x27, 0x00, 0x80, 0x27, 0x00,
@@ -3222,32 +3324,32 @@ static const uint8_t unicode_script_table[2690] = {
0x8e, 0x27, 0x00, 0xb8, 0x27, 0x00, 0x83, 0x27,
0x01, 0xc2, 0x27, 0x01, 0x9f, 0x27, 0x02, 0x99,
0x27, 0x05, 0xd5, 0x17, 0x01, 0x85, 0x17, 0x01,
- 0xe2, 0x1f, 0x12, 0x9c, 0x67, 0x02, 0xca, 0x7c,
- 0x82, 0x19, 0x8a, 0x7c, 0x06, 0x95, 0x8a, 0x08,
- 0x80, 0x8a, 0x94, 0x33, 0x81, 0x19, 0x08, 0x93,
- 0x11, 0x0b, 0x8c, 0x8b, 0x00, 0x82, 0x8b, 0x00,
- 0x81, 0x8b, 0x0b, 0xdd, 0x41, 0x01, 0x89, 0x41,
- 0x05, 0x89, 0x41, 0x05, 0x81, 0x5c, 0x81, 0x19,
- 0x80, 0x5c, 0x80, 0x19, 0x93, 0x5c, 0x05, 0xd8,
- 0x5c, 0x06, 0xaa, 0x5c, 0x04, 0xc5, 0x12, 0x09,
- 0x9e, 0x48, 0x00, 0x8b, 0x48, 0x03, 0x8b, 0x48,
- 0x03, 0x80, 0x48, 0x02, 0x8b, 0x48, 0x9d, 0x8c,
- 0x01, 0x84, 0x8c, 0x0a, 0xab, 0x62, 0x03, 0x99,
- 0x62, 0x05, 0x8a, 0x62, 0x02, 0x81, 0x62, 0x9f,
- 0x41, 0x9b, 0x10, 0x01, 0x81, 0x10, 0xbe, 0x8d,
- 0x00, 0x9c, 0x8d, 0x01, 0x8a, 0x8d, 0x05, 0x89,
- 0x8d, 0x05, 0x8d, 0x8d, 0x01, 0x9e, 0x38, 0x30,
- 0xcc, 0x07, 0x02, 0xae, 0x07, 0x00, 0xbf, 0x87,
- 0xb3, 0x0a, 0x07, 0x83, 0x0a, 0xb7, 0x47, 0x02,
- 0x8e, 0x47, 0x02, 0x82, 0x47, 0xaf, 0x68, 0x88,
+ 0xe2, 0x1f, 0x12, 0x9c, 0x69, 0x02, 0xca, 0x7e,
+ 0x82, 0x19, 0x8a, 0x7e, 0x06, 0x95, 0x8c, 0x08,
+ 0x80, 0x8c, 0x94, 0x33, 0x81, 0x19, 0x08, 0x93,
+ 0x11, 0x0b, 0x8c, 0x8d, 0x00, 0x82, 0x8d, 0x00,
+ 0x81, 0x8d, 0x0b, 0xdd, 0x42, 0x01, 0x89, 0x42,
+ 0x05, 0x89, 0x42, 0x05, 0x81, 0x5d, 0x81, 0x19,
+ 0x80, 0x5d, 0x80, 0x19, 0x93, 0x5d, 0x05, 0xd8,
+ 0x5d, 0x06, 0xaa, 0x5d, 0x04, 0xc5, 0x12, 0x09,
+ 0x9e, 0x49, 0x00, 0x8b, 0x49, 0x03, 0x8b, 0x49,
+ 0x03, 0x80, 0x49, 0x02, 0x8b, 0x49, 0x9d, 0x8e,
+ 0x01, 0x84, 0x8e, 0x0a, 0xab, 0x64, 0x03, 0x99,
+ 0x64, 0x05, 0x8a, 0x64, 0x02, 0x81, 0x64, 0x9f,
+ 0x42, 0x9b, 0x10, 0x01, 0x81, 0x10, 0xbe, 0x8f,
+ 0x00, 0x9c, 0x8f, 0x01, 0x8a, 0x8f, 0x05, 0x89,
+ 0x8f, 0x05, 0x8d, 0x8f, 0x01, 0x9e, 0x38, 0x30,
+ 0xcc, 0x07, 0x02, 0xae, 0x07, 0x00, 0xbf, 0x89,
+ 0xb3, 0x0a, 0x07, 0x83, 0x0a, 0xb7, 0x48, 0x02,
+ 0x8e, 0x48, 0x02, 0x82, 0x48, 0xaf, 0x6a, 0x88,
0x1d, 0x06, 0xaa, 0x28, 0x01, 0x82, 0x28, 0x87,
- 0x87, 0x07, 0x82, 0x38, 0x80, 0x19, 0x8c, 0x38,
+ 0x89, 0x07, 0x82, 0x38, 0x80, 0x19, 0x8c, 0x38,
0x80, 0x19, 0x86, 0x38, 0x83, 0x19, 0x80, 0x38,
0x85, 0x19, 0x80, 0x38, 0x82, 0x19, 0x81, 0x38,
- 0x80, 0x19, 0x04, 0xa5, 0x46, 0x84, 0x2c, 0x80,
- 0x1d, 0xb0, 0x46, 0x84, 0x2c, 0x83, 0x46, 0x84,
- 0x2c, 0x8c, 0x46, 0x80, 0x1d, 0xc5, 0x46, 0x80,
- 0x2c, 0xbf, 0x38, 0xe0, 0x9f, 0x46, 0x95, 0x2c,
+ 0x80, 0x19, 0x04, 0xa5, 0x47, 0x84, 0x2c, 0x80,
+ 0x1d, 0xb0, 0x47, 0x84, 0x2c, 0x83, 0x47, 0x84,
+ 0x2c, 0x8c, 0x47, 0x80, 0x1d, 0xc5, 0x47, 0x80,
+ 0x2c, 0xbf, 0x38, 0xe0, 0x9f, 0x47, 0x95, 0x2c,
0x01, 0x85, 0x2c, 0x01, 0xa5, 0x2c, 0x01, 0x85,
0x2c, 0x01, 0x87, 0x2c, 0x00, 0x80, 0x2c, 0x00,
0x80, 0x2c, 0x00, 0x80, 0x2c, 0x00, 0x9e, 0x2c,
@@ -3255,18 +3357,18 @@ static const uint8_t unicode_script_table[2690] = {
0x2c, 0x01, 0x85, 0x2c, 0x00, 0x92, 0x2c, 0x01,
0x82, 0x2c, 0x00, 0x88, 0x2c, 0x00, 0x8b, 0x19,
0x81, 0x38, 0xd6, 0x19, 0x00, 0x8a, 0x19, 0x80,
- 0x46, 0x01, 0x8a, 0x19, 0x80, 0x46, 0x8e, 0x19,
- 0x00, 0x8c, 0x46, 0x02, 0xa0, 0x19, 0x0e, 0xa0,
+ 0x47, 0x01, 0x8a, 0x19, 0x80, 0x47, 0x8e, 0x19,
+ 0x00, 0x8c, 0x47, 0x02, 0xa0, 0x19, 0x0e, 0xa0,
0x38, 0x0e, 0xa5, 0x19, 0x80, 0x2c, 0x82, 0x19,
- 0x81, 0x46, 0x85, 0x19, 0x80, 0x46, 0x9a, 0x19,
- 0x80, 0x46, 0x90, 0x19, 0xa8, 0x46, 0x82, 0x19,
+ 0x81, 0x47, 0x85, 0x19, 0x80, 0x47, 0x9a, 0x19,
+ 0x80, 0x47, 0x90, 0x19, 0xa8, 0x47, 0x82, 0x19,
0x03, 0xe2, 0x36, 0x19, 0x18, 0x8a, 0x19, 0x14,
0xe3, 0x3f, 0x19, 0xe0, 0x9f, 0x0f, 0xe2, 0x13,
0x19, 0x01, 0x9f, 0x19, 0x00, 0xe0, 0x08, 0x19,
- 0xdf, 0x29, 0x9f, 0x46, 0xe0, 0x13, 0x1a, 0x04,
+ 0xdf, 0x29, 0x9f, 0x47, 0xe0, 0x13, 0x1a, 0x04,
0x86, 0x1a, 0xa5, 0x28, 0x00, 0x80, 0x28, 0x04,
- 0x80, 0x28, 0x01, 0xb7, 0x96, 0x06, 0x81, 0x96,
- 0x0d, 0x80, 0x96, 0x96, 0x27, 0x08, 0x86, 0x27,
+ 0x80, 0x28, 0x01, 0xb7, 0x98, 0x06, 0x81, 0x98,
+ 0x0d, 0x80, 0x98, 0x96, 0x27, 0x08, 0x86, 0x27,
0x00, 0x86, 0x27, 0x00, 0x86, 0x27, 0x00, 0x86,
0x27, 0x00, 0x86, 0x27, 0x00, 0x86, 0x27, 0x00,
0x86, 0x27, 0x00, 0x86, 0x27, 0x00, 0x9f, 0x1d,
@@ -3282,27 +3384,27 @@ static const uint8_t unicode_script_table[2690] = {
0x9e, 0x31, 0x00, 0xbf, 0x19, 0x9e, 0x31, 0xd0,
0x19, 0xae, 0x3e, 0x80, 0x19, 0xd7, 0x3e, 0xe0,
0x47, 0x19, 0xf0, 0x09, 0x5f, 0x30, 0xbf, 0x19,
- 0xf0, 0x41, 0x9f, 0x30, 0xe4, 0x2c, 0xa0, 0x02,
- 0xb6, 0xa0, 0x08, 0xaf, 0x4b, 0xe0, 0xcb, 0x9b,
+ 0xf0, 0x41, 0x9f, 0x30, 0xe4, 0x2c, 0xa2, 0x02,
+ 0xb6, 0xa2, 0x08, 0xaf, 0x4c, 0xe0, 0xcb, 0x9d,
0x13, 0xdf, 0x1d, 0xd7, 0x08, 0x07, 0xa1, 0x19,
- 0xe0, 0x05, 0x46, 0x82, 0x19, 0xbf, 0x46, 0x04,
- 0x81, 0x46, 0x00, 0x80, 0x46, 0x00, 0x84, 0x46,
- 0x17, 0x8d, 0x46, 0xac, 0x88, 0x02, 0x89, 0x19,
- 0x05, 0xb7, 0x78, 0x07, 0xc5, 0x7e, 0x07, 0x8b,
- 0x7e, 0x05, 0x9f, 0x20, 0xad, 0x3f, 0x80, 0x19,
- 0x80, 0x3f, 0xa3, 0x7b, 0x0a, 0x80, 0x7b, 0x9c,
+ 0xe0, 0x05, 0x47, 0x82, 0x19, 0xbf, 0x47, 0x04,
+ 0x81, 0x47, 0x00, 0x80, 0x47, 0x00, 0x84, 0x47,
+ 0x17, 0x8d, 0x47, 0xac, 0x8a, 0x02, 0x89, 0x19,
+ 0x05, 0xb7, 0x7a, 0x07, 0xc5, 0x80, 0x07, 0x8b,
+ 0x80, 0x05, 0x9f, 0x20, 0xad, 0x40, 0x80, 0x19,
+ 0x80, 0x40, 0xa3, 0x7d, 0x0a, 0x80, 0x7d, 0x9c,
0x31, 0x02, 0xcd, 0x3b, 0x00, 0x80, 0x19, 0x89,
- 0x3b, 0x03, 0x81, 0x3b, 0x9e, 0x5f, 0x00, 0xb6,
+ 0x3b, 0x03, 0x81, 0x3b, 0x9e, 0x60, 0x00, 0xb6,
0x16, 0x08, 0x8d, 0x16, 0x01, 0x89, 0x16, 0x01,
- 0x83, 0x16, 0x9f, 0x5f, 0xc2, 0x8e, 0x17, 0x84,
- 0x8e, 0x96, 0x56, 0x09, 0x85, 0x27, 0x01, 0x85,
+ 0x83, 0x16, 0x9f, 0x60, 0xc2, 0x90, 0x17, 0x84,
+ 0x90, 0x96, 0x57, 0x09, 0x85, 0x27, 0x01, 0x85,
0x27, 0x01, 0x85, 0x27, 0x08, 0x86, 0x27, 0x00,
- 0x86, 0x27, 0x00, 0xaa, 0x46, 0x80, 0x19, 0x88,
- 0x46, 0x80, 0x2c, 0x83, 0x46, 0x81, 0x19, 0x03,
- 0xcf, 0x17, 0xad, 0x56, 0x01, 0x89, 0x56, 0x05,
+ 0x86, 0x27, 0x00, 0xaa, 0x47, 0x80, 0x19, 0x88,
+ 0x47, 0x80, 0x2c, 0x83, 0x47, 0x81, 0x19, 0x03,
+ 0xcf, 0x17, 0xad, 0x57, 0x01, 0x89, 0x57, 0x05,
0xf0, 0x1b, 0x43, 0x31, 0x0b, 0x96, 0x31, 0x03,
0xb0, 0x31, 0x70, 0x10, 0xa3, 0xe1, 0x0d, 0x30,
- 0x01, 0xe0, 0x09, 0x30, 0x25, 0x86, 0x46, 0x0b,
+ 0x01, 0xe0, 0x09, 0x30, 0x25, 0x86, 0x47, 0x0b,
0x84, 0x05, 0x04, 0x99, 0x35, 0x00, 0x84, 0x35,
0x00, 0x80, 0x35, 0x00, 0x81, 0x35, 0x00, 0x81,
0x35, 0x00, 0x89, 0x35, 0xe0, 0x12, 0x04, 0x0f,
@@ -3311,130 +3413,134 @@ static const uint8_t unicode_script_table[2690] = {
0x8f, 0x38, 0x89, 0x19, 0x05, 0x8d, 0x38, 0x81,
0x1d, 0xa2, 0x19, 0x00, 0x92, 0x19, 0x00, 0x83,
0x19, 0x03, 0x84, 0x04, 0x00, 0xe0, 0x26, 0x04,
- 0x01, 0x80, 0x19, 0x00, 0x9f, 0x19, 0x99, 0x46,
- 0x85, 0x19, 0x99, 0x46, 0x8a, 0x19, 0x89, 0x3e,
+ 0x01, 0x80, 0x19, 0x00, 0x9f, 0x19, 0x99, 0x47,
+ 0x85, 0x19, 0x99, 0x47, 0x8a, 0x19, 0x89, 0x3e,
0x80, 0x19, 0xac, 0x3e, 0x81, 0x19, 0x9e, 0x31,
0x02, 0x85, 0x31, 0x01, 0x85, 0x31, 0x01, 0x85,
0x31, 0x01, 0x82, 0x31, 0x02, 0x86, 0x19, 0x00,
- 0x86, 0x19, 0x09, 0x84, 0x19, 0x01, 0x8b, 0x4a,
- 0x00, 0x99, 0x4a, 0x00, 0x92, 0x4a, 0x00, 0x81,
- 0x4a, 0x00, 0x8e, 0x4a, 0x01, 0x8d, 0x4a, 0x21,
- 0xe0, 0x1a, 0x4a, 0x04, 0x82, 0x19, 0x03, 0xac,
+ 0x86, 0x19, 0x09, 0x84, 0x19, 0x01, 0x8b, 0x4b,
+ 0x00, 0x99, 0x4b, 0x00, 0x92, 0x4b, 0x00, 0x81,
+ 0x4b, 0x00, 0x8e, 0x4b, 0x01, 0x8d, 0x4b, 0x21,
+ 0xe0, 0x1a, 0x4b, 0x04, 0x82, 0x19, 0x03, 0xac,
0x19, 0x02, 0x88, 0x19, 0xce, 0x2c, 0x00, 0x8c,
0x19, 0x02, 0x80, 0x2c, 0x2e, 0xac, 0x19, 0x80,
- 0x38, 0x60, 0x21, 0x9c, 0x4c, 0x02, 0xb0, 0x13,
- 0x0e, 0x80, 0x38, 0x9a, 0x19, 0x03, 0xa3, 0x6a,
- 0x08, 0x82, 0x6a, 0x9a, 0x2a, 0x04, 0xaa, 0x6c,
- 0x04, 0x9d, 0x9a, 0x00, 0x80, 0x9a, 0xa3, 0x6d,
- 0x03, 0x8d, 0x6d, 0x29, 0xcf, 0x1f, 0xaf, 0x80,
- 0x9d, 0x74, 0x01, 0x89, 0x74, 0x05, 0xa3, 0x73,
- 0x03, 0xa3, 0x73, 0x03, 0xa7, 0x25, 0x07, 0xb3,
- 0x14, 0x0a, 0x80, 0x14, 0x8a, 0x9c, 0x00, 0x8e,
- 0x9c, 0x00, 0x86, 0x9c, 0x00, 0x81, 0x9c, 0x00,
- 0x8a, 0x9c, 0x00, 0x8e, 0x9c, 0x00, 0x86, 0x9c,
- 0x00, 0x81, 0x9c, 0x42, 0xe0, 0xd6, 0x49, 0x08,
- 0x95, 0x49, 0x09, 0x87, 0x49, 0x17, 0x85, 0x46,
- 0x00, 0xa9, 0x46, 0x00, 0x88, 0x46, 0x44, 0x85,
+ 0x38, 0x60, 0x21, 0x9c, 0x4d, 0x02, 0xb0, 0x13,
+ 0x0e, 0x80, 0x38, 0x9a, 0x19, 0x03, 0xa3, 0x6c,
+ 0x08, 0x82, 0x6c, 0x9a, 0x2a, 0x04, 0xaa, 0x6e,
+ 0x04, 0x9d, 0x9c, 0x00, 0x80, 0x9c, 0xa3, 0x6f,
+ 0x03, 0x8d, 0x6f, 0x29, 0xcf, 0x1f, 0xaf, 0x82,
+ 0x9d, 0x76, 0x01, 0x89, 0x76, 0x05, 0xa3, 0x75,
+ 0x03, 0xa3, 0x75, 0x03, 0xa7, 0x25, 0x07, 0xb3,
+ 0x14, 0x0a, 0x80, 0x14, 0x8a, 0x9e, 0x00, 0x8e,
+ 0x9e, 0x00, 0x86, 0x9e, 0x00, 0x81, 0x9e, 0x00,
+ 0x8a, 0x9e, 0x00, 0x8e, 0x9e, 0x00, 0x86, 0x9e,
+ 0x00, 0x81, 0x9e, 0x42, 0xe0, 0xd6, 0x4a, 0x08,
+ 0x95, 0x4a, 0x09, 0x87, 0x4a, 0x17, 0x85, 0x47,
+ 0x00, 0xa9, 0x47, 0x00, 0x88, 0x47, 0x44, 0x85,
0x1c, 0x01, 0x80, 0x1c, 0x00, 0xab, 0x1c, 0x00,
0x81, 0x1c, 0x02, 0x80, 0x1c, 0x01, 0x80, 0x1c,
- 0x95, 0x37, 0x00, 0x88, 0x37, 0x9f, 0x76, 0x9e,
- 0x60, 0x07, 0x88, 0x60, 0x2f, 0x92, 0x34, 0x00,
- 0x81, 0x34, 0x04, 0x84, 0x34, 0x9b, 0x79, 0x02,
- 0x80, 0x79, 0x99, 0x4d, 0x04, 0x80, 0x4d, 0x3f,
- 0x9f, 0x59, 0x97, 0x58, 0x03, 0x93, 0x58, 0x01,
- 0xad, 0x58, 0x83, 0x40, 0x00, 0x81, 0x40, 0x04,
- 0x87, 0x40, 0x00, 0x82, 0x40, 0x00, 0x9c, 0x40,
- 0x01, 0x82, 0x40, 0x03, 0x89, 0x40, 0x06, 0x88,
- 0x40, 0x06, 0x9f, 0x6f, 0x9f, 0x6b, 0x1f, 0xa6,
- 0x52, 0x03, 0x8b, 0x52, 0x08, 0xb5, 0x06, 0x02,
+ 0x95, 0x37, 0x00, 0x88, 0x37, 0x9f, 0x78, 0x9e,
+ 0x61, 0x07, 0x88, 0x61, 0x2f, 0x92, 0x34, 0x00,
+ 0x81, 0x34, 0x04, 0x84, 0x34, 0x9b, 0x7b, 0x02,
+ 0x80, 0x7b, 0x99, 0x4e, 0x04, 0x80, 0x4e, 0x3f,
+ 0x9f, 0x5a, 0x97, 0x59, 0x03, 0x93, 0x59, 0x01,
+ 0xad, 0x59, 0x83, 0x41, 0x00, 0x81, 0x41, 0x04,
+ 0x87, 0x41, 0x00, 0x82, 0x41, 0x00, 0x9c, 0x41,
+ 0x01, 0x82, 0x41, 0x03, 0x89, 0x41, 0x06, 0x88,
+ 0x41, 0x06, 0x9f, 0x71, 0x9f, 0x6d, 0x1f, 0xa6,
+ 0x53, 0x03, 0x8b, 0x53, 0x08, 0xb5, 0x06, 0x02,
0x86, 0x06, 0x95, 0x3a, 0x01, 0x87, 0x3a, 0x92,
- 0x39, 0x04, 0x87, 0x39, 0x91, 0x7a, 0x06, 0x83,
- 0x7a, 0x0b, 0x86, 0x7a, 0x4f, 0xc8, 0x70, 0x36,
- 0xb2, 0x69, 0x0c, 0xb2, 0x69, 0x06, 0x85, 0x69,
+ 0x39, 0x04, 0x87, 0x39, 0x91, 0x7c, 0x06, 0x83,
+ 0x7c, 0x0b, 0x86, 0x7c, 0x4f, 0xc8, 0x72, 0x36,
+ 0xb2, 0x6b, 0x0c, 0xb2, 0x6b, 0x06, 0x85, 0x6b,
0xa7, 0x32, 0x07, 0x89, 0x32, 0x60, 0xc5, 0x9e,
- 0x04, 0x00, 0xa9, 0x9f, 0x00, 0x82, 0x9f, 0x01,
- 0x81, 0x9f, 0x4d, 0xa7, 0x6e, 0x07, 0xa9, 0x84,
- 0x15, 0x99, 0x71, 0x25, 0x9b, 0x18, 0x13, 0x96,
- 0x26, 0x08, 0xcd, 0x0e, 0x03, 0xa3, 0x0e, 0x08,
- 0x80, 0x0e, 0xc2, 0x3c, 0x09, 0x80, 0x3c, 0x01,
- 0x98, 0x85, 0x06, 0x89, 0x85, 0x05, 0xb4, 0x15,
- 0x00, 0x91, 0x15, 0x07, 0xa6, 0x4f, 0x08, 0xdf,
- 0x7f, 0x00, 0x93, 0x83, 0x0a, 0x91, 0x42, 0x00,
- 0xab, 0x42, 0x40, 0x86, 0x5e, 0x00, 0x80, 0x5e,
- 0x00, 0x83, 0x5e, 0x00, 0x8e, 0x5e, 0x00, 0x8a,
- 0x5e, 0x05, 0xba, 0x44, 0x04, 0x89, 0x44, 0x05,
- 0x83, 0x2b, 0x00, 0x87, 0x2b, 0x01, 0x81, 0x2b,
- 0x01, 0x95, 0x2b, 0x00, 0x86, 0x2b, 0x00, 0x81,
- 0x2b, 0x00, 0x84, 0x2b, 0x00, 0x80, 0x38, 0x88,
- 0x2b, 0x01, 0x81, 0x2b, 0x01, 0x82, 0x2b, 0x01,
- 0x80, 0x2b, 0x05, 0x80, 0x2b, 0x04, 0x86, 0x2b,
- 0x01, 0x86, 0x2b, 0x02, 0x84, 0x2b, 0x60, 0x2a,
- 0xdb, 0x63, 0x00, 0x84, 0x63, 0x1d, 0xc7, 0x97,
- 0x07, 0x89, 0x97, 0x60, 0x45, 0xb5, 0x81, 0x01,
- 0xa5, 0x81, 0x21, 0xc4, 0x5b, 0x0a, 0x89, 0x5b,
- 0x05, 0x8c, 0x5c, 0x12, 0xb9, 0x8f, 0x05, 0x89,
- 0x8f, 0x35, 0x9a, 0x02, 0x01, 0x8e, 0x02, 0x03,
- 0x96, 0x02, 0x60, 0x58, 0xbb, 0x22, 0x60, 0x03,
- 0xd2, 0x9e, 0x0b, 0x80, 0x9e, 0x86, 0x21, 0x01,
- 0x80, 0x21, 0x01, 0x87, 0x21, 0x00, 0x81, 0x21,
- 0x00, 0x9d, 0x21, 0x00, 0x81, 0x21, 0x01, 0x8b,
- 0x21, 0x08, 0x89, 0x21, 0x45, 0x87, 0x61, 0x01,
- 0xad, 0x61, 0x01, 0x8a, 0x61, 0x1a, 0xc7, 0xa1,
- 0x07, 0xd2, 0x86, 0x0c, 0x8f, 0x12, 0xb8, 0x77,
- 0x60, 0xa6, 0x88, 0x0c, 0x00, 0xac, 0x0c, 0x00,
- 0x8d, 0x0c, 0x09, 0x9c, 0x0c, 0x02, 0x9f, 0x53,
- 0x01, 0x95, 0x53, 0x00, 0x8d, 0x53, 0x48, 0x86,
- 0x54, 0x00, 0x81, 0x54, 0x00, 0xab, 0x54, 0x02,
- 0x80, 0x54, 0x00, 0x81, 0x54, 0x00, 0x88, 0x54,
- 0x07, 0x89, 0x54, 0x05, 0x85, 0x2e, 0x00, 0x81,
- 0x2e, 0x00, 0xa4, 0x2e, 0x00, 0x81, 0x2e, 0x00,
- 0x85, 0x2e, 0x06, 0x89, 0x2e, 0x60, 0xd5, 0x98,
- 0x4e, 0x60, 0x56, 0x80, 0x4b, 0x0e, 0xb1, 0x90,
- 0x0c, 0x80, 0x90, 0xe3, 0x39, 0x1b, 0x60, 0x05,
- 0xe0, 0x0e, 0x1b, 0x00, 0x84, 0x1b, 0x0a, 0xe0,
- 0x63, 0x1b, 0x69, 0xeb, 0xe0, 0x02, 0x1e, 0x0c,
- 0xe3, 0xce, 0x24, 0x00, 0x88, 0x24, 0x6f, 0x66,
- 0xe1, 0xe6, 0x03, 0x70, 0x11, 0x58, 0xe1, 0xd8,
- 0x08, 0x06, 0x9e, 0x5d, 0x00, 0x89, 0x5d, 0x03,
- 0x81, 0x5d, 0xce, 0x98, 0x00, 0x89, 0x98, 0x05,
- 0x9d, 0x09, 0x01, 0x85, 0x09, 0x09, 0xc5, 0x75,
- 0x09, 0x89, 0x75, 0x00, 0x86, 0x75, 0x00, 0x94,
- 0x75, 0x04, 0x92, 0x75, 0x62, 0x4f, 0xda, 0x55,
- 0x60, 0x04, 0xca, 0x5a, 0x03, 0xb8, 0x5a, 0x06,
- 0x90, 0x5a, 0x3f, 0x80, 0x91, 0x80, 0x65, 0x81,
- 0x30, 0x80, 0x43, 0x0a, 0x81, 0x30, 0x0d, 0xf0,
- 0x07, 0x97, 0x91, 0x07, 0xe2, 0x9f, 0x91, 0xe1,
- 0x75, 0x43, 0x29, 0x88, 0x91, 0x70, 0x12, 0x86,
- 0x83, 0x3e, 0x00, 0x86, 0x3e, 0x00, 0x81, 0x3e,
- 0x00, 0x80, 0x3e, 0xe0, 0xbe, 0x36, 0x82, 0x3e,
- 0x2c, 0x82, 0x36, 0x10, 0x83, 0x3e, 0x07, 0xe1,
- 0x2b, 0x65, 0x68, 0xa3, 0xe0, 0x0a, 0x23, 0x04,
+ 0x04, 0x00, 0xa9, 0xa1, 0x00, 0x82, 0xa1, 0x01,
+ 0x81, 0xa1, 0x4a, 0x82, 0x04, 0xa7, 0x70, 0x07,
+ 0xa9, 0x86, 0x15, 0x99, 0x73, 0x25, 0x9b, 0x18,
+ 0x13, 0x96, 0x26, 0x08, 0xcd, 0x0e, 0x03, 0xa3,
+ 0x0e, 0x08, 0x80, 0x0e, 0xc2, 0x3c, 0x09, 0x80,
+ 0x3c, 0x01, 0x98, 0x87, 0x06, 0x89, 0x87, 0x05,
+ 0xb4, 0x15, 0x00, 0x91, 0x15, 0x07, 0xa6, 0x50,
+ 0x08, 0xdf, 0x81, 0x00, 0x93, 0x85, 0x0a, 0x91,
+ 0x43, 0x00, 0xae, 0x43, 0x3d, 0x86, 0x5f, 0x00,
+ 0x80, 0x5f, 0x00, 0x83, 0x5f, 0x00, 0x8e, 0x5f,
+ 0x00, 0x8a, 0x5f, 0x05, 0xba, 0x45, 0x04, 0x89,
+ 0x45, 0x05, 0x83, 0x2b, 0x00, 0x87, 0x2b, 0x01,
+ 0x81, 0x2b, 0x01, 0x95, 0x2b, 0x00, 0x86, 0x2b,
+ 0x00, 0x81, 0x2b, 0x00, 0x84, 0x2b, 0x00, 0x80,
+ 0x38, 0x88, 0x2b, 0x01, 0x81, 0x2b, 0x01, 0x82,
+ 0x2b, 0x01, 0x80, 0x2b, 0x05, 0x80, 0x2b, 0x04,
+ 0x86, 0x2b, 0x01, 0x86, 0x2b, 0x02, 0x84, 0x2b,
+ 0x60, 0x2a, 0xdb, 0x65, 0x00, 0x84, 0x65, 0x1d,
+ 0xc7, 0x99, 0x07, 0x89, 0x99, 0x60, 0x45, 0xb5,
+ 0x83, 0x01, 0xa5, 0x83, 0x21, 0xc4, 0x5c, 0x0a,
+ 0x89, 0x5c, 0x05, 0x8c, 0x5d, 0x12, 0xb9, 0x91,
+ 0x05, 0x89, 0x91, 0x35, 0x9a, 0x02, 0x01, 0x8e,
+ 0x02, 0x03, 0x96, 0x02, 0x60, 0x58, 0xbb, 0x22,
+ 0x60, 0x03, 0xd2, 0xa0, 0x0b, 0x80, 0xa0, 0x86,
+ 0x21, 0x01, 0x80, 0x21, 0x01, 0x87, 0x21, 0x00,
+ 0x81, 0x21, 0x00, 0x9d, 0x21, 0x00, 0x81, 0x21,
+ 0x01, 0x8b, 0x21, 0x08, 0x89, 0x21, 0x45, 0x87,
+ 0x63, 0x01, 0xad, 0x63, 0x01, 0x8a, 0x63, 0x1a,
+ 0xc7, 0xa3, 0x07, 0xd2, 0x88, 0x0c, 0x8f, 0x12,
+ 0xb8, 0x79, 0x06, 0x89, 0x20, 0x60, 0x95, 0x88,
+ 0x0c, 0x00, 0xac, 0x0c, 0x00, 0x8d, 0x0c, 0x09,
+ 0x9c, 0x0c, 0x02, 0x9f, 0x54, 0x01, 0x95, 0x54,
+ 0x00, 0x8d, 0x54, 0x48, 0x86, 0x55, 0x00, 0x81,
+ 0x55, 0x00, 0xab, 0x55, 0x02, 0x80, 0x55, 0x00,
+ 0x81, 0x55, 0x00, 0x88, 0x55, 0x07, 0x89, 0x55,
+ 0x05, 0x85, 0x2e, 0x00, 0x81, 0x2e, 0x00, 0xa4,
+ 0x2e, 0x00, 0x81, 0x2e, 0x00, 0x85, 0x2e, 0x06,
+ 0x89, 0x2e, 0x60, 0xd5, 0x98, 0x4f, 0x06, 0x90,
+ 0x3f, 0x00, 0xa8, 0x3f, 0x02, 0x9b, 0x3f, 0x55,
+ 0x80, 0x4c, 0x0e, 0xb1, 0x92, 0x0c, 0x80, 0x92,
+ 0xe3, 0x39, 0x1b, 0x60, 0x05, 0xe0, 0x0e, 0x1b,
+ 0x00, 0x84, 0x1b, 0x0a, 0xe0, 0x63, 0x1b, 0x69,
+ 0xeb, 0xe0, 0x02, 0x1e, 0x0c, 0xe3, 0xf5, 0x24,
+ 0x6f, 0x49, 0xe1, 0xe6, 0x03, 0x70, 0x11, 0x58,
+ 0xe1, 0xd8, 0x08, 0x06, 0x9e, 0x5e, 0x00, 0x89,
+ 0x5e, 0x03, 0x81, 0x5e, 0xce, 0x9a, 0x00, 0x89,
+ 0x9a, 0x05, 0x9d, 0x09, 0x01, 0x85, 0x09, 0x09,
+ 0xc5, 0x77, 0x09, 0x89, 0x77, 0x00, 0x86, 0x77,
+ 0x00, 0x94, 0x77, 0x04, 0x92, 0x77, 0x62, 0x4f,
+ 0xda, 0x56, 0x60, 0x04, 0xca, 0x5b, 0x03, 0xb8,
+ 0x5b, 0x06, 0x90, 0x5b, 0x3f, 0x80, 0x93, 0x80,
+ 0x67, 0x81, 0x30, 0x80, 0x44, 0x0a, 0x81, 0x30,
+ 0x0d, 0xf0, 0x07, 0x97, 0x93, 0x07, 0xe2, 0x9f,
+ 0x93, 0xe1, 0x75, 0x44, 0x29, 0x88, 0x93, 0x70,
+ 0x12, 0x86, 0x83, 0x3e, 0x00, 0x86, 0x3e, 0x00,
+ 0x81, 0x3e, 0x00, 0x80, 0x3e, 0xe0, 0xbe, 0x36,
+ 0x82, 0x3e, 0x0e, 0x80, 0x36, 0x1c, 0x82, 0x36,
+ 0x01, 0x80, 0x3e, 0x0d, 0x83, 0x3e, 0x07, 0xe1,
+ 0x2b, 0x67, 0x68, 0xa3, 0xe0, 0x0a, 0x23, 0x04,
0x8c, 0x23, 0x02, 0x88, 0x23, 0x06, 0x89, 0x23,
0x01, 0x83, 0x23, 0x83, 0x19, 0x70, 0x01, 0xfb,
0xad, 0x38, 0x01, 0x96, 0x38, 0x08, 0xe0, 0x13,
0x19, 0x3b, 0xe0, 0x95, 0x19, 0x09, 0xa6, 0x19,
0x01, 0xbd, 0x19, 0x82, 0x38, 0x90, 0x19, 0x87,
0x38, 0x81, 0x19, 0x86, 0x38, 0x9d, 0x19, 0x83,
- 0x38, 0xbc, 0x19, 0x14, 0xc5, 0x2c, 0x60, 0x39,
- 0x93, 0x19, 0x0b, 0xd6, 0x19, 0x08, 0x98, 0x19,
- 0x60, 0x26, 0xd4, 0x19, 0x00, 0xc6, 0x19, 0x00,
- 0x81, 0x19, 0x01, 0x80, 0x19, 0x01, 0x81, 0x19,
- 0x01, 0x83, 0x19, 0x00, 0x8b, 0x19, 0x00, 0x80,
- 0x19, 0x00, 0x86, 0x19, 0x00, 0xc0, 0x19, 0x00,
- 0x83, 0x19, 0x01, 0x87, 0x19, 0x00, 0x86, 0x19,
- 0x00, 0x9b, 0x19, 0x00, 0x83, 0x19, 0x00, 0x84,
- 0x19, 0x00, 0x80, 0x19, 0x02, 0x86, 0x19, 0x00,
- 0xe0, 0xf3, 0x19, 0x01, 0xe0, 0xc3, 0x19, 0x01,
- 0xb1, 0x19, 0xe2, 0x2b, 0x82, 0x0e, 0x84, 0x82,
- 0x00, 0x8e, 0x82, 0x63, 0xef, 0x9e, 0x46, 0x60,
- 0x80, 0x86, 0x29, 0x00, 0x90, 0x29, 0x01, 0x86,
- 0x29, 0x00, 0x81, 0x29, 0x00, 0x84, 0x29, 0x60,
- 0x74, 0xac, 0x66, 0x02, 0x8d, 0x66, 0x01, 0x89,
- 0x66, 0x03, 0x81, 0x66, 0x60, 0xdf, 0x9e, 0x99,
- 0x10, 0xb9, 0x9d, 0x04, 0x80, 0x9d, 0x64, 0x7f,
+ 0x38, 0xbc, 0x19, 0x14, 0xc5, 0x2c, 0x60, 0x19,
+ 0x93, 0x19, 0x0b, 0x93, 0x19, 0x0b, 0xd6, 0x19,
+ 0x08, 0x98, 0x19, 0x60, 0x26, 0xd4, 0x19, 0x00,
+ 0xc6, 0x19, 0x00, 0x81, 0x19, 0x01, 0x80, 0x19,
+ 0x01, 0x81, 0x19, 0x01, 0x83, 0x19, 0x00, 0x8b,
+ 0x19, 0x00, 0x80, 0x19, 0x00, 0x86, 0x19, 0x00,
+ 0xc0, 0x19, 0x00, 0x83, 0x19, 0x01, 0x87, 0x19,
+ 0x00, 0x86, 0x19, 0x00, 0x9b, 0x19, 0x00, 0x83,
+ 0x19, 0x00, 0x84, 0x19, 0x00, 0x80, 0x19, 0x02,
+ 0x86, 0x19, 0x00, 0xe0, 0xf3, 0x19, 0x01, 0xe0,
+ 0xc3, 0x19, 0x01, 0xb1, 0x19, 0xe2, 0x2b, 0x84,
+ 0x0e, 0x84, 0x84, 0x00, 0x8e, 0x84, 0x63, 0xef,
+ 0x9e, 0x47, 0x05, 0x85, 0x47, 0x60, 0x74, 0x86,
+ 0x29, 0x00, 0x90, 0x29, 0x01, 0x86, 0x29, 0x00,
+ 0x81, 0x29, 0x00, 0x84, 0x29, 0x04, 0xbd, 0x1d,
+ 0x20, 0x80, 0x1d, 0x60, 0x0f, 0xac, 0x68, 0x02,
+ 0x8d, 0x68, 0x01, 0x89, 0x68, 0x03, 0x81, 0x68,
+ 0x60, 0xdf, 0x9e, 0x9b, 0x10, 0xb9, 0x9f, 0x04,
+ 0x80, 0x9f, 0x61, 0x6f, 0xa9, 0x62, 0x62, 0x85,
0x86, 0x27, 0x00, 0x83, 0x27, 0x00, 0x81, 0x27,
- 0x00, 0x8e, 0x27, 0x00, 0xe0, 0x64, 0x57, 0x01,
- 0x8f, 0x57, 0x28, 0xcb, 0x01, 0x03, 0x89, 0x01,
+ 0x00, 0x8e, 0x27, 0x00, 0xe0, 0x64, 0x58, 0x01,
+ 0x8f, 0x58, 0x28, 0xcb, 0x01, 0x03, 0x89, 0x01,
0x03, 0x81, 0x01, 0x62, 0xb0, 0xc3, 0x19, 0x4b,
0xbc, 0x19, 0x60, 0x61, 0x83, 0x04, 0x00, 0x9a,
0x04, 0x00, 0x81, 0x04, 0x00, 0x80, 0x04, 0x01,
@@ -3455,86 +3561,85 @@ static const uint8_t unicode_script_table[2690] = {
0x19, 0x37, 0x99, 0x19, 0x80, 0x36, 0x81, 0x19,
0x0c, 0xab, 0x19, 0x03, 0x88, 0x19, 0x06, 0x81,
0x19, 0x0d, 0x85, 0x19, 0x60, 0x39, 0xe3, 0x77,
- 0x19, 0x04, 0x8f, 0x19, 0x02, 0x8c, 0x19, 0x02,
- 0xe0, 0x13, 0x19, 0x0b, 0xd8, 0x19, 0x06, 0x8b,
+ 0x19, 0x03, 0x90, 0x19, 0x02, 0x8c, 0x19, 0x02,
+ 0xe0, 0x16, 0x19, 0x03, 0xde, 0x19, 0x05, 0x8b,
0x19, 0x03, 0x80, 0x19, 0x0e, 0x8b, 0x19, 0x03,
0xb7, 0x19, 0x07, 0x89, 0x19, 0x05, 0xa7, 0x19,
0x07, 0x9d, 0x19, 0x01, 0x81, 0x19, 0x4d, 0xe0,
- 0xf3, 0x19, 0x0b, 0x8d, 0x19, 0x01, 0x84, 0x19,
- 0x02, 0x84, 0x19, 0x02, 0x86, 0x19, 0x08, 0x9c,
- 0x19, 0x02, 0x8a, 0x19, 0x04, 0x85, 0x19, 0x09,
- 0x89, 0x19, 0x05, 0x87, 0x19, 0x07, 0x86, 0x19,
- 0x08, 0xe0, 0x32, 0x19, 0x00, 0xb6, 0x19, 0x24,
- 0x89, 0x19, 0x63, 0xa5, 0xf0, 0x96, 0x7f, 0x30,
- 0x1f, 0xef, 0xd8, 0x30, 0x06, 0xe0, 0x7d, 0x30,
- 0x01, 0xf0, 0x06, 0x21, 0x30, 0x0d, 0xf0, 0x0c,
- 0xd0, 0x30, 0x6b, 0xbe, 0xe1, 0xbd, 0x30, 0x65,
- 0x81, 0xf0, 0x02, 0xea, 0x30, 0x7a, 0xdc, 0x55,
- 0x80, 0x19, 0x1d, 0xdf, 0x19, 0x60, 0x1f, 0xe0,
- 0x8f, 0x38,
+ 0xf3, 0x19, 0x0b, 0x8d, 0x19, 0x01, 0x8c, 0x19,
+ 0x02, 0x88, 0x19, 0x06, 0xad, 0x19, 0x00, 0x86,
+ 0x19, 0x07, 0x8d, 0x19, 0x03, 0x88, 0x19, 0x06,
+ 0x88, 0x19, 0x06, 0xe0, 0x32, 0x19, 0x00, 0xb6,
+ 0x19, 0x24, 0x89, 0x19, 0x63, 0xa5, 0xf0, 0x96,
+ 0x7f, 0x30, 0x1f, 0xef, 0xd9, 0x30, 0x05, 0xe0,
+ 0x7d, 0x30, 0x01, 0xf0, 0x06, 0x21, 0x30, 0x0d,
+ 0xf0, 0x0c, 0xd0, 0x30, 0x6b, 0xbe, 0xe1, 0xbd,
+ 0x30, 0x65, 0x81, 0xf0, 0x02, 0xea, 0x30, 0x04,
+ 0xef, 0xff, 0x30, 0x7a, 0xcb, 0xf0, 0x80, 0x19,
+ 0x1d, 0xdf, 0x19, 0x60, 0x1f, 0xe0, 0x8f, 0x38,
};
static const uint8_t unicode_script_ext_table[828] = {
0x82, 0xc1, 0x00, 0x00, 0x01, 0x2c, 0x01, 0x00,
- 0x00, 0x01, 0x2c, 0x1c, 0x00, 0x0c, 0x01, 0x46,
- 0x80, 0x92, 0x00, 0x00, 0x02, 0x1d, 0x6c, 0x00,
- 0x02, 0x1d, 0x29, 0x01, 0x02, 0x1d, 0x46, 0x00,
+ 0x00, 0x01, 0x2c, 0x1c, 0x00, 0x0c, 0x01, 0x47,
+ 0x80, 0x92, 0x00, 0x00, 0x02, 0x1d, 0x6e, 0x00,
+ 0x02, 0x1d, 0x29, 0x01, 0x02, 0x1d, 0x47, 0x00,
0x02, 0x1d, 0x29, 0x81, 0x03, 0x00, 0x00, 0x06,
- 0x04, 0x64, 0x32, 0x89, 0x93, 0x9f, 0x0d, 0x00,
- 0x00, 0x06, 0x04, 0x64, 0x32, 0x89, 0x93, 0x9f,
- 0x00, 0x03, 0x04, 0x89, 0x93, 0x01, 0x00, 0x00,
- 0x07, 0x01, 0x04, 0x64, 0x32, 0x89, 0x93, 0x9f,
- 0x1f, 0x00, 0x00, 0x09, 0x01, 0x04, 0x51, 0x52,
- 0x71, 0x7a, 0x32, 0x84, 0x89, 0x09, 0x00, 0x0a,
- 0x02, 0x04, 0x89, 0x09, 0x00, 0x09, 0x03, 0x04,
- 0x93, 0x9f, 0x05, 0x00, 0x00, 0x02, 0x04, 0x89,
+ 0x04, 0x66, 0x32, 0x8b, 0x95, 0xa1, 0x0d, 0x00,
+ 0x00, 0x06, 0x04, 0x66, 0x32, 0x8b, 0x95, 0xa1,
+ 0x00, 0x03, 0x04, 0x8b, 0x95, 0x01, 0x00, 0x00,
+ 0x07, 0x01, 0x04, 0x66, 0x32, 0x8b, 0x95, 0xa1,
+ 0x1f, 0x00, 0x00, 0x09, 0x01, 0x04, 0x52, 0x53,
+ 0x73, 0x7c, 0x32, 0x86, 0x8b, 0x09, 0x00, 0x0a,
+ 0x02, 0x04, 0x8b, 0x09, 0x00, 0x09, 0x03, 0x04,
+ 0x95, 0xa1, 0x05, 0x00, 0x00, 0x02, 0x04, 0x8b,
0x62, 0x00, 0x00, 0x02, 0x04, 0x32, 0x81, 0xfb,
0x00, 0x00, 0x0d, 0x0b, 0x20, 0x2b, 0x2d, 0x2f,
- 0x3d, 0x46, 0x50, 0x72, 0x7f, 0x90, 0x92, 0x97,
+ 0x3d, 0x47, 0x51, 0x74, 0x81, 0x92, 0x94, 0x99,
0x00, 0x0c, 0x0b, 0x20, 0x2b, 0x2d, 0x2f, 0x3d,
- 0x46, 0x50, 0x72, 0x90, 0x92, 0x97, 0x10, 0x00,
- 0x00, 0x14, 0x0b, 0x20, 0x22, 0x2e, 0x54, 0x2b,
- 0x2d, 0x2f, 0x3d, 0x4f, 0x50, 0x61, 0x72, 0x44,
- 0x83, 0x88, 0x8f, 0x90, 0x92, 0x97, 0x00, 0x15,
- 0x0b, 0x20, 0x22, 0x2e, 0x54, 0x2b, 0x2d, 0x2f,
- 0x3d, 0x48, 0x4f, 0x50, 0x61, 0x72, 0x44, 0x83,
- 0x88, 0x8f, 0x90, 0x92, 0x97, 0x09, 0x04, 0x20,
- 0x22, 0x3c, 0x4f, 0x75, 0x00, 0x09, 0x03, 0x0b,
- 0x15, 0x88, 0x75, 0x00, 0x09, 0x02, 0x2f, 0x5e,
- 0x75, 0x00, 0x09, 0x02, 0x2d, 0x42, 0x80, 0x75,
- 0x00, 0x0d, 0x02, 0x2b, 0x90, 0x80, 0x71, 0x00,
- 0x09, 0x02, 0x3d, 0x61, 0x82, 0xcf, 0x00, 0x09,
- 0x03, 0x15, 0x5f, 0x8c, 0x80, 0x30, 0x00, 0x00,
- 0x02, 0x28, 0x46, 0x85, 0xb8, 0x00, 0x01, 0x04,
- 0x11, 0x33, 0x8b, 0x8a, 0x80, 0x4a, 0x00, 0x01,
- 0x02, 0x5c, 0x78, 0x00, 0x00, 0x00, 0x02, 0x5c,
- 0x78, 0x84, 0x49, 0x00, 0x00, 0x04, 0x0b, 0x20,
+ 0x47, 0x51, 0x74, 0x92, 0x94, 0x99, 0x10, 0x00,
+ 0x00, 0x14, 0x0b, 0x20, 0x22, 0x2e, 0x55, 0x2b,
+ 0x2d, 0x2f, 0x3d, 0x50, 0x51, 0x63, 0x74, 0x45,
+ 0x85, 0x8a, 0x91, 0x92, 0x94, 0x99, 0x00, 0x15,
+ 0x0b, 0x20, 0x22, 0x2e, 0x55, 0x2b, 0x2d, 0x2f,
+ 0x3d, 0x49, 0x50, 0x51, 0x63, 0x74, 0x45, 0x85,
+ 0x8a, 0x91, 0x92, 0x94, 0x99, 0x09, 0x04, 0x20,
+ 0x22, 0x3c, 0x50, 0x75, 0x00, 0x09, 0x03, 0x0b,
+ 0x15, 0x8a, 0x75, 0x00, 0x09, 0x02, 0x2f, 0x5f,
+ 0x75, 0x00, 0x09, 0x02, 0x2d, 0x43, 0x80, 0x75,
+ 0x00, 0x0d, 0x02, 0x2b, 0x92, 0x80, 0x71, 0x00,
+ 0x09, 0x02, 0x3d, 0x63, 0x82, 0xcf, 0x00, 0x09,
+ 0x03, 0x15, 0x60, 0x8e, 0x80, 0x30, 0x00, 0x00,
+ 0x02, 0x28, 0x47, 0x85, 0xb8, 0x00, 0x01, 0x04,
+ 0x11, 0x33, 0x8d, 0x8c, 0x80, 0x4a, 0x00, 0x01,
+ 0x02, 0x5d, 0x7a, 0x00, 0x00, 0x00, 0x02, 0x5d,
+ 0x7a, 0x84, 0x49, 0x00, 0x00, 0x04, 0x0b, 0x20,
0x2b, 0x3d, 0x00, 0x01, 0x20, 0x00, 0x04, 0x0b,
0x20, 0x2b, 0x3d, 0x00, 0x02, 0x20, 0x2b, 0x00,
0x01, 0x20, 0x01, 0x02, 0x0b, 0x20, 0x00, 0x02,
- 0x20, 0x7f, 0x00, 0x02, 0x0b, 0x20, 0x00, 0x02,
- 0x20, 0x7f, 0x00, 0x06, 0x20, 0x3d, 0x50, 0x72,
- 0x90, 0x92, 0x00, 0x01, 0x20, 0x01, 0x02, 0x20,
- 0x7f, 0x01, 0x01, 0x20, 0x00, 0x02, 0x20, 0x7f,
+ 0x20, 0x81, 0x00, 0x02, 0x0b, 0x20, 0x00, 0x02,
+ 0x20, 0x81, 0x00, 0x06, 0x20, 0x3d, 0x51, 0x74,
+ 0x92, 0x94, 0x00, 0x01, 0x20, 0x01, 0x02, 0x20,
+ 0x81, 0x01, 0x01, 0x20, 0x00, 0x02, 0x20, 0x81,
0x00, 0x02, 0x0b, 0x20, 0x06, 0x01, 0x20, 0x00,
- 0x02, 0x20, 0x61, 0x00, 0x02, 0x0b, 0x20, 0x01,
+ 0x02, 0x20, 0x63, 0x00, 0x02, 0x0b, 0x20, 0x01,
0x01, 0x20, 0x00, 0x02, 0x0b, 0x20, 0x03, 0x01,
- 0x20, 0x00, 0x08, 0x0b, 0x20, 0x2b, 0x3d, 0x61,
- 0x72, 0x92, 0x97, 0x00, 0x02, 0x20, 0x2b, 0x00,
+ 0x20, 0x00, 0x08, 0x0b, 0x20, 0x2b, 0x3d, 0x63,
+ 0x74, 0x94, 0x99, 0x00, 0x02, 0x20, 0x2b, 0x00,
0x03, 0x20, 0x2b, 0x3d, 0x01, 0x02, 0x0b, 0x20,
0x00, 0x01, 0x0b, 0x01, 0x02, 0x20, 0x2b, 0x00,
- 0x01, 0x61, 0x80, 0x44, 0x00, 0x01, 0x01, 0x2c,
- 0x35, 0x00, 0x00, 0x02, 0x1d, 0x89, 0x00, 0x00,
- 0x00, 0x01, 0x89, 0x81, 0xb3, 0x00, 0x00, 0x02,
- 0x46, 0x5c, 0x80, 0x3f, 0x00, 0x00, 0x03, 0x20,
- 0x2b, 0x46, 0x8c, 0xd1, 0x00, 0x00, 0x02, 0x1d,
+ 0x01, 0x63, 0x80, 0x44, 0x00, 0x01, 0x01, 0x2c,
+ 0x35, 0x00, 0x00, 0x02, 0x1d, 0x8b, 0x00, 0x00,
+ 0x00, 0x01, 0x8b, 0x81, 0xb3, 0x00, 0x00, 0x02,
+ 0x47, 0x5d, 0x80, 0x3f, 0x00, 0x00, 0x03, 0x20,
+ 0x2b, 0x47, 0x8c, 0xd1, 0x00, 0x00, 0x02, 0x1d,
0x29, 0x81, 0x3c, 0x00, 0x01, 0x06, 0x0d, 0x31,
- 0x30, 0x36, 0x3e, 0xa0, 0x00, 0x05, 0x0d, 0x31,
+ 0x30, 0x36, 0x3e, 0xa2, 0x00, 0x05, 0x0d, 0x31,
0x30, 0x36, 0x3e, 0x01, 0x00, 0x00, 0x01, 0x30,
0x00, 0x00, 0x09, 0x06, 0x0d, 0x31, 0x30, 0x36,
- 0x3e, 0xa0, 0x00, 0x00, 0x00, 0x05, 0x0d, 0x31,
+ 0x3e, 0xa2, 0x00, 0x00, 0x00, 0x05, 0x0d, 0x31,
0x30, 0x36, 0x3e, 0x07, 0x06, 0x0d, 0x31, 0x30,
- 0x36, 0x3e, 0xa0, 0x03, 0x05, 0x0d, 0x31, 0x30,
+ 0x36, 0x3e, 0xa2, 0x03, 0x05, 0x0d, 0x31, 0x30,
0x36, 0x3e, 0x09, 0x00, 0x03, 0x02, 0x0d, 0x30,
0x01, 0x00, 0x00, 0x05, 0x0d, 0x31, 0x30, 0x36,
0x3e, 0x04, 0x02, 0x36, 0x3e, 0x00, 0x00, 0x00,
@@ -3542,7 +3647,7 @@ static const uint8_t unicode_script_ext_table[828] = {
0x01, 0x03, 0x30, 0x36, 0x3e, 0x01, 0x01, 0x30,
0x58, 0x00, 0x03, 0x02, 0x36, 0x3e, 0x02, 0x00,
0x00, 0x02, 0x36, 0x3e, 0x59, 0x00, 0x00, 0x06,
- 0x0d, 0x31, 0x30, 0x36, 0x3e, 0xa0, 0x00, 0x02,
+ 0x0d, 0x31, 0x30, 0x36, 0x3e, 0xa2, 0x00, 0x02,
0x36, 0x3e, 0x80, 0x12, 0x00, 0x0f, 0x01, 0x30,
0x1f, 0x00, 0x23, 0x01, 0x30, 0x3b, 0x00, 0x27,
0x01, 0x30, 0x37, 0x00, 0x30, 0x01, 0x30, 0x0e,
@@ -3550,32 +3655,32 @@ static const uint8_t unicode_script_ext_table[828] = {
0x30, 0x57, 0x00, 0x18, 0x01, 0x30, 0x09, 0x00,
0x04, 0x01, 0x30, 0x5f, 0x00, 0x1e, 0x01, 0x30,
0xc0, 0x31, 0xef, 0x00, 0x00, 0x02, 0x1d, 0x29,
- 0x80, 0x0f, 0x00, 0x07, 0x02, 0x30, 0x46, 0x80,
+ 0x80, 0x0f, 0x00, 0x07, 0x02, 0x30, 0x47, 0x80,
0xa7, 0x00, 0x02, 0x0e, 0x20, 0x22, 0x2d, 0x2f,
- 0x42, 0x3d, 0x3c, 0x4f, 0x50, 0x5b, 0x61, 0x44,
- 0x8f, 0x97, 0x02, 0x0d, 0x20, 0x22, 0x2d, 0x2f,
- 0x42, 0x3d, 0x3c, 0x4f, 0x5b, 0x61, 0x44, 0x8f,
- 0x97, 0x03, 0x0b, 0x20, 0x22, 0x2d, 0x2f, 0x42,
- 0x3c, 0x4f, 0x5b, 0x44, 0x8f, 0x97, 0x80, 0x36,
+ 0x43, 0x3d, 0x3c, 0x50, 0x51, 0x5c, 0x63, 0x45,
+ 0x91, 0x99, 0x02, 0x0d, 0x20, 0x22, 0x2d, 0x2f,
+ 0x43, 0x3d, 0x3c, 0x50, 0x5c, 0x63, 0x45, 0x91,
+ 0x99, 0x03, 0x0b, 0x20, 0x22, 0x2d, 0x2f, 0x43,
+ 0x3c, 0x50, 0x5c, 0x45, 0x91, 0x99, 0x80, 0x36,
0x00, 0x00, 0x02, 0x0b, 0x20, 0x00, 0x00, 0x00,
- 0x02, 0x20, 0x90, 0x39, 0x00, 0x00, 0x03, 0x3f,
- 0x46, 0x5f, 0x80, 0x1f, 0x00, 0x00, 0x02, 0x10,
+ 0x02, 0x20, 0x92, 0x39, 0x00, 0x00, 0x03, 0x40,
+ 0x47, 0x60, 0x80, 0x1f, 0x00, 0x00, 0x02, 0x10,
0x3b, 0xc0, 0x12, 0xed, 0x00, 0x01, 0x02, 0x04,
- 0x64, 0x80, 0x31, 0x00, 0x00, 0x02, 0x04, 0x93,
- 0x09, 0x00, 0x00, 0x02, 0x04, 0x93, 0x46, 0x00,
+ 0x66, 0x80, 0x31, 0x00, 0x00, 0x02, 0x04, 0x95,
+ 0x09, 0x00, 0x00, 0x02, 0x04, 0x95, 0x46, 0x00,
0x01, 0x05, 0x0d, 0x31, 0x30, 0x36, 0x3e, 0x80,
0x99, 0x00, 0x04, 0x06, 0x0d, 0x31, 0x30, 0x36,
- 0x3e, 0xa0, 0x09, 0x00, 0x00, 0x02, 0x36, 0x3e,
+ 0x3e, 0xa2, 0x09, 0x00, 0x00, 0x02, 0x36, 0x3e,
0x2c, 0x00, 0x01, 0x02, 0x36, 0x3e, 0x80, 0xdf,
- 0x00, 0x01, 0x03, 0x1e, 0x1c, 0x4a, 0x00, 0x02,
- 0x1c, 0x4a, 0x03, 0x00, 0x2c, 0x03, 0x1c, 0x49,
- 0x4a, 0x02, 0x00, 0x08, 0x02, 0x1c, 0x4a, 0x81,
+ 0x00, 0x01, 0x03, 0x1e, 0x1c, 0x4b, 0x00, 0x02,
+ 0x1c, 0x4b, 0x03, 0x00, 0x2c, 0x03, 0x1c, 0x4a,
+ 0x4b, 0x02, 0x00, 0x08, 0x02, 0x1c, 0x4b, 0x81,
0x1f, 0x00, 0x1b, 0x02, 0x04, 0x1a, 0x87, 0x75,
- 0x00, 0x00, 0x02, 0x52, 0x71, 0x87, 0x8d, 0x00,
- 0x00, 0x02, 0x2b, 0x90, 0x00, 0x00, 0x00, 0x02,
- 0x2b, 0x90, 0x36, 0x00, 0x01, 0x02, 0x2b, 0x90,
- 0x8c, 0x12, 0x00, 0x01, 0x02, 0x2b, 0x90, 0x00,
- 0x00, 0x00, 0x02, 0x2b, 0x90, 0xc0, 0x5c, 0x4b,
+ 0x00, 0x00, 0x02, 0x53, 0x73, 0x87, 0x8d, 0x00,
+ 0x00, 0x02, 0x2b, 0x92, 0x00, 0x00, 0x00, 0x02,
+ 0x2b, 0x92, 0x36, 0x00, 0x01, 0x02, 0x2b, 0x92,
+ 0x8c, 0x12, 0x00, 0x01, 0x02, 0x2b, 0x92, 0x00,
+ 0x00, 0x00, 0x02, 0x2b, 0x92, 0xc0, 0x5c, 0x4b,
0x00, 0x03, 0x01, 0x23, 0x96, 0x3b, 0x00, 0x11,
0x01, 0x30, 0x9e, 0x5d, 0x00, 0x01, 0x01, 0x30,
0xce, 0xcd, 0x2d, 0x00,
@@ -3616,7 +3721,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[417] = {
+static const uint8_t unicode_prop_Other_Alphabetic_table[428] = {
0x43, 0x44, 0x80, 0x42, 0x69, 0x8d, 0x00, 0x01,
0x01, 0x00, 0xc7, 0x8a, 0xaf, 0x8c, 0x06, 0x8f,
0x80, 0xe4, 0x33, 0x19, 0x0b, 0x80, 0xa2, 0x80,
@@ -3628,59 +3733,61 @@ static const uint8_t unicode_prop_Other_Alphabetic_table[417] = {
0x0a, 0x80, 0x8a, 0x82, 0xb9, 0x38, 0x10, 0x81,
0x94, 0x81, 0x95, 0x13, 0x82, 0xb9, 0x31, 0x09,
0x81, 0x88, 0x81, 0x89, 0x81, 0x9d, 0x80, 0xba,
- 0x22, 0x10, 0x82, 0x89, 0x80, 0xa7, 0x83, 0xb9,
+ 0x22, 0x10, 0x82, 0x89, 0x80, 0xa7, 0x84, 0xb8,
0x30, 0x10, 0x17, 0x81, 0x8a, 0x81, 0x9c, 0x82,
- 0xb9, 0x30, 0x10, 0x17, 0x81, 0x8a, 0x81, 0x9b,
- 0x83, 0xb9, 0x30, 0x10, 0x82, 0x89, 0x80, 0x89,
- 0x81, 0x9c, 0x82, 0xca, 0x28, 0x00, 0x87, 0x91,
- 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, 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, 0xc9, 0x81, 0x8a,
- 0x82, 0xb0, 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, 0x41, 0x82, 0x81,
- 0x41, 0x52, 0x82, 0xb4, 0x8d, 0xac, 0x81, 0x8c,
- 0x80, 0xac, 0x88, 0x88, 0x80, 0xbc, 0x82, 0xa3,
- 0x8b, 0x91, 0x81, 0xb8, 0x82, 0xaf, 0x8c, 0x8d,
- 0x81, 0xdb, 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,
- 0x40, 0xf6, 0x28, 0x09, 0x0a, 0x00, 0x80, 0x40,
- 0x8d, 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, 0x50, 0x57, 0x00, 0xb6,
- 0x33, 0xdc, 0x81, 0x60, 0x4c, 0xab, 0x80, 0x60,
- 0x23, 0x60, 0x30, 0x90, 0x0e, 0x01, 0x04, 0x49,
- 0x1b, 0x80, 0x47, 0xe7, 0x99, 0x85, 0x99, 0x85,
- 0x99,
+ 0xb9, 0x30, 0x10, 0x17, 0x81, 0x8a, 0x81, 0x8e,
+ 0x80, 0x8b, 0x83, 0xb9, 0x30, 0x10, 0x82, 0x89,
+ 0x80, 0x89, 0x81, 0x9c, 0x82, 0xca, 0x28, 0x00,
+ 0x87, 0x91, 0x81, 0xbc, 0x01, 0x86, 0x91, 0x80,
+ 0xe2, 0x01, 0x28, 0x81, 0x8f, 0x80, 0x40, 0xa2,
+ 0x92, 0x88, 0x8a, 0x80, 0xa3, 0xed, 0x8b, 0x00,
+ 0x0b, 0x96, 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, 0xc9,
+ 0x81, 0x8a, 0x82, 0xb0, 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, 0x41,
+ 0x82, 0x81, 0x41, 0x52, 0x82, 0xb4, 0x8d, 0xac,
+ 0x81, 0x8a, 0x82, 0xac, 0x88, 0x88, 0x80, 0xbc,
+ 0x82, 0xa3, 0x8b, 0x91, 0x81, 0xb8, 0x82, 0xaf,
+ 0x8c, 0x8d, 0x81, 0xdb, 0x88, 0x08, 0x28, 0x08,
+ 0x40, 0x9c, 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, 0x40, 0xf6, 0x28, 0x09, 0x0a,
+ 0x00, 0x80, 0x40, 0x8d, 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, 0x88, 0x08,
+ 0x80, 0xaf, 0x32, 0x82, 0x60, 0x50, 0x0d, 0x00,
+ 0xb6, 0x33, 0xdc, 0x81, 0x60, 0x4c, 0xab, 0x80,
+ 0x60, 0x23, 0x60, 0x30, 0x90, 0x0e, 0x01, 0x04,
+ 0xe3, 0x80, 0x48, 0xb6, 0x80, 0x47, 0xe7, 0x99,
+ 0x85, 0x99, 0x85, 0x99,
};
-static const uint8_t unicode_prop_Other_Lowercase_table[59] = {
+static const uint8_t unicode_prop_Other_Lowercase_table[69] = {
0x40, 0xa9, 0x80, 0x8e, 0x80, 0x41, 0xf4, 0x88,
- 0x31, 0x9d, 0x84, 0xdf, 0x80, 0xb3, 0x80, 0x59,
- 0xb0, 0xbe, 0x8c, 0x80, 0xa1, 0xa4, 0x42, 0xb0,
- 0x80, 0x8c, 0x80, 0x8f, 0x8c, 0x40, 0xd2, 0x8f,
- 0x43, 0x4f, 0x99, 0x47, 0x91, 0x81, 0x60, 0x7a,
- 0x1d, 0x81, 0x40, 0xd1, 0x80, 0x40, 0x86, 0x81,
- 0x43, 0x61, 0x83, 0x60, 0x5c, 0x1f, 0x01, 0x10,
- 0xa9, 0x80, 0x88,
+ 0x31, 0x9d, 0x84, 0xdf, 0x80, 0xb3, 0x80, 0x4d,
+ 0x80, 0x80, 0x4c, 0x2e, 0xbe, 0x8c, 0x80, 0xa1,
+ 0xa4, 0x42, 0xb0, 0x80, 0x8c, 0x80, 0x8f, 0x8c,
+ 0x40, 0xd2, 0x8f, 0x43, 0x4f, 0x99, 0x47, 0x91,
+ 0x81, 0x60, 0x7a, 0x1d, 0x81, 0x40, 0xd1, 0x80,
+ 0x40, 0x80, 0x12, 0x81, 0x43, 0x61, 0x83, 0x88,
+ 0x80, 0x60, 0x5c, 0x15, 0x01, 0x10, 0xa9, 0x80,
+ 0x88, 0x60, 0xd8, 0x74, 0xbd,
};
static const uint8_t unicode_prop_Other_Uppercase_table[15] = {
@@ -3742,71 +3849,70 @@ static const uint8_t unicode_prop_Changes_When_Titlecased1_table[22] = {
0x8b, 0x80, 0x8e, 0x80, 0xae, 0x80,
};
-static const uint8_t unicode_prop_Changes_When_Casefolded1_table[33] = {
- 0x40, 0xde, 0x80, 0xcf, 0x80, 0x97, 0x80, 0x44,
- 0x3c, 0x80, 0x59, 0x11, 0x80, 0x40, 0xe4, 0x3f,
- 0x3f, 0x87, 0x89, 0x11, 0x05, 0x02, 0x11, 0x80,
- 0xa9, 0x11, 0x80, 0x60, 0xdb, 0x07, 0x86, 0x8b,
- 0x84,
+static const uint8_t unicode_prop_Changes_When_Casefolded1_table[29] = {
+ 0x41, 0xef, 0x80, 0x41, 0x9e, 0x80, 0x9e, 0x80,
+ 0x5a, 0xe4, 0x83, 0x40, 0xb5, 0x00, 0x00, 0x00,
+ 0x80, 0xde, 0x06, 0x06, 0x80, 0x8a, 0x09, 0x81,
+ 0x89, 0x10, 0x81, 0x8d, 0x80,
};
-static const uint8_t unicode_prop_Changes_When_NFKC_Casefolded1_table[448] = {
+static const uint8_t unicode_prop_Changes_When_NFKC_Casefolded1_table[447] = {
0x40, 0x9f, 0x06, 0x00, 0x01, 0x00, 0x01, 0x12,
- 0x10, 0x82, 0x9f, 0x80, 0xcf, 0x01, 0x80, 0x8b,
- 0x07, 0x80, 0xfb, 0x01, 0x01, 0x80, 0xa5, 0x80,
- 0x40, 0xbb, 0x88, 0x9e, 0x29, 0x84, 0xda, 0x08,
- 0x81, 0x89, 0x80, 0xa3, 0x04, 0x02, 0x04, 0x08,
- 0x80, 0xc9, 0x82, 0x9c, 0x80, 0x41, 0x93, 0x80,
- 0x40, 0x93, 0x80, 0xd7, 0x83, 0x42, 0xde, 0x87,
- 0xfb, 0x08, 0x80, 0xd2, 0x01, 0x80, 0xa1, 0x11,
- 0x80, 0x40, 0xfc, 0x81, 0x42, 0xd4, 0x80, 0xfe,
- 0x80, 0xa7, 0x81, 0xad, 0x80, 0xb5, 0x80, 0x88,
- 0x03, 0x03, 0x03, 0x80, 0x8b, 0x80, 0x88, 0x00,
- 0x26, 0x80, 0x90, 0x80, 0x88, 0x03, 0x03, 0x03,
- 0x80, 0x8b, 0x80, 0x41, 0x41, 0x80, 0xe1, 0x81,
- 0x46, 0x52, 0x81, 0xd4, 0x84, 0x45, 0x1b, 0x10,
- 0x8a, 0x80, 0x91, 0x80, 0x9b, 0x8c, 0x80, 0xa1,
- 0xa4, 0x40, 0xd9, 0x80, 0x40, 0xd5, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x3f, 0x3f, 0x87,
- 0x89, 0x11, 0x04, 0x00, 0x29, 0x04, 0x12, 0x80,
- 0x88, 0x12, 0x80, 0x88, 0x11, 0x11, 0x04, 0x08,
- 0x8f, 0x00, 0x20, 0x8b, 0x12, 0x2a, 0x08, 0x0b,
- 0x00, 0x07, 0x82, 0x8c, 0x06, 0x92, 0x81, 0x9a,
- 0x80, 0x8c, 0x8a, 0x80, 0xd6, 0x18, 0x10, 0x8a,
- 0x01, 0x0c, 0x0a, 0x00, 0x10, 0x11, 0x02, 0x06,
- 0x05, 0x1c, 0x85, 0x8f, 0x8f, 0x8f, 0x88, 0x80,
- 0x40, 0xa1, 0x08, 0x81, 0x40, 0xf7, 0x81, 0x41,
- 0x34, 0xd5, 0x99, 0x9a, 0x45, 0x20, 0x80, 0xe6,
- 0x82, 0xe4, 0x80, 0x41, 0x9e, 0x81, 0x40, 0xf0,
- 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, 0x41, 0x7f,
- 0x60, 0x72, 0x9b, 0x81, 0x40, 0xd1, 0x80, 0x40,
- 0x80, 0x12, 0x81, 0x43, 0x61, 0x83, 0x88, 0x80,
- 0x60, 0x4d, 0x95, 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, 0x47, 0x87, 0x20, 0xa9, 0x80, 0x88, 0x60,
- 0xb4, 0xe4, 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, 0x49, 0x9d, 0x89, 0x60, 0xfc,
- 0x05, 0x42, 0x1d, 0x6b, 0x05, 0xe1, 0x4f, 0xff,
+ 0x10, 0x82, 0xf3, 0x80, 0x8b, 0x80, 0x40, 0x84,
+ 0x01, 0x01, 0x80, 0xa2, 0x01, 0x80, 0x40, 0xbb,
+ 0x88, 0x9e, 0x29, 0x84, 0xda, 0x08, 0x81, 0x89,
+ 0x80, 0xa3, 0x04, 0x02, 0x04, 0x08, 0x07, 0x80,
+ 0x9e, 0x80, 0xa0, 0x82, 0x9c, 0x80, 0x42, 0x28,
+ 0x80, 0xd7, 0x83, 0x42, 0xde, 0x87, 0xfb, 0x08,
+ 0x80, 0xd2, 0x01, 0x80, 0xa1, 0x11, 0x80, 0x40,
+ 0xfc, 0x81, 0x42, 0xd4, 0x80, 0xfe, 0x80, 0xa7,
+ 0x81, 0xad, 0x80, 0xb5, 0x80, 0x88, 0x03, 0x03,
+ 0x03, 0x80, 0x8b, 0x80, 0x88, 0x00, 0x26, 0x80,
+ 0x90, 0x80, 0x88, 0x03, 0x03, 0x03, 0x80, 0x8b,
+ 0x80, 0x41, 0x41, 0x80, 0xe1, 0x81, 0x46, 0x52,
+ 0x81, 0xd4, 0x84, 0x45, 0x1b, 0x10, 0x8a, 0x80,
+ 0x91, 0x80, 0x9b, 0x8c, 0x80, 0xa1, 0xa4, 0x40,
+ 0xd5, 0x83, 0x40, 0xb5, 0x00, 0x00, 0x00, 0x80,
+ 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+ 0xb7, 0x05, 0x00, 0x13, 0x05, 0x11, 0x02, 0x0c,
+ 0x11, 0x00, 0x00, 0x0c, 0x15, 0x05, 0x08, 0x8f,
+ 0x00, 0x20, 0x8b, 0x12, 0x2a, 0x08, 0x0b, 0x00,
+ 0x07, 0x82, 0x8c, 0x06, 0x92, 0x81, 0x9a, 0x80,
+ 0x8c, 0x8a, 0x80, 0xd6, 0x18, 0x10, 0x8a, 0x01,
+ 0x0c, 0x0a, 0x00, 0x10, 0x11, 0x02, 0x06, 0x05,
+ 0x1c, 0x85, 0x8f, 0x8f, 0x8f, 0x88, 0x80, 0x40,
+ 0xa1, 0x08, 0x81, 0x40, 0xf7, 0x81, 0x41, 0x34,
+ 0xd5, 0x99, 0x9a, 0x45, 0x20, 0x80, 0xe6, 0x82,
+ 0xe4, 0x80, 0x41, 0x9e, 0x81, 0x40, 0xf0, 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, 0x41, 0x7f, 0x60,
+ 0x72, 0x9b, 0x81, 0x40, 0xd1, 0x80, 0x40, 0x80,
+ 0x12, 0x81, 0x43, 0x61, 0x83, 0x88, 0x80, 0x60,
+ 0x4d, 0x95, 0x41, 0x0d, 0x08, 0x00, 0x81, 0x89,
+ 0x00, 0x00, 0x09, 0x82, 0xc3, 0x81, 0xe9, 0xc2,
+ 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, 0x47, 0x87, 0x20,
+ 0xa9, 0x80, 0x88, 0x60, 0xb4, 0xe4, 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, 0x48, 0x2f,
+ 0xbd, 0x4d, 0x91, 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, 0x49, 0x9d, 0x89, 0x60, 0xfc, 0x05,
+ 0x42, 0x1d, 0x6b, 0x05, 0xe1, 0x4f, 0xff,
};
static const uint8_t unicode_prop_ASCII_Hex_Digit_table[5] = {
@@ -3834,7 +3940,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[391] = {
+static const uint8_t unicode_prop_Diacritic_table[399] = {
0xdd, 0x00, 0x80, 0xc6, 0x05, 0x03, 0x01, 0x81,
0x41, 0xf6, 0x40, 0x9e, 0x07, 0x25, 0x90, 0x0b,
0x80, 0x88, 0x81, 0x40, 0xfc, 0x84, 0x40, 0xd0,
@@ -3869,20 +3975,21 @@ static const uint8_t unicode_prop_Diacritic_table[391] = {
0x00, 0x8f, 0x41, 0x0d, 0x00, 0x80, 0xae, 0x80,
0xac, 0x81, 0xc2, 0x80, 0x42, 0xfb, 0x80, 0x44,
0x9e, 0x28, 0xa9, 0x80, 0x88, 0x43, 0x29, 0x81,
- 0x42, 0x3a, 0x85, 0x42, 0x1d, 0x8a, 0xb0, 0x83,
- 0x40, 0xbf, 0x80, 0xa8, 0x80, 0xc7, 0x81, 0xf7,
- 0x81, 0xbd, 0x80, 0xcb, 0x80, 0x88, 0x82, 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, 0x01, 0x0b,
- 0x80, 0x40, 0x9b, 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, 0xcf, 0x81, 0x60, 0x3f,
- 0xfd, 0x18, 0x30, 0x81, 0x5f, 0x00, 0xad, 0x81,
- 0x96, 0x42, 0x1f, 0x12, 0x2f, 0x39, 0x86, 0x9d,
- 0x83, 0x4f, 0x81, 0x86, 0x41, 0x76, 0x80, 0xbc,
+ 0x42, 0x3a, 0x85, 0x41, 0xd4, 0x82, 0xc5, 0x8a,
+ 0xb0, 0x83, 0x40, 0xbf, 0x80, 0xa8, 0x80, 0xc7,
+ 0x81, 0xf7, 0x81, 0xbd, 0x80, 0xcb, 0x80, 0x88,
+ 0x82, 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,
+ 0x01, 0x0b, 0x80, 0x40, 0x9b, 0x80, 0xd2, 0x80,
+ 0x91, 0x80, 0xd0, 0x80, 0x41, 0xa4, 0x80, 0x41,
+ 0x01, 0x00, 0x81, 0xd0, 0x80, 0x56, 0xae, 0x8e,
+ 0x60, 0x36, 0x99, 0x84, 0xba, 0x86, 0x44, 0x57,
+ 0x90, 0xcf, 0x81, 0x60, 0x3f, 0xfd, 0x18, 0x30,
+ 0x81, 0x5f, 0x00, 0xad, 0x81, 0x96, 0x42, 0x1f,
+ 0x12, 0x2f, 0x39, 0x86, 0x9d, 0x83, 0x4e, 0x81,
+ 0xbd, 0x40, 0xc1, 0x86, 0x41, 0x76, 0x80, 0xbc,
0x83, 0x45, 0xdf, 0x86, 0xec, 0x10, 0x82,
};
@@ -3914,16 +4021,16 @@ static const uint8_t unicode_prop_IDS_Trinary_Operator_table[4] = {
0x60, 0x2f, 0xf1, 0x81,
};
-static const uint8_t unicode_prop_Ideographic_table[66] = {
+static const uint8_t unicode_prop_Ideographic_table[69] = {
0x60, 0x30, 0x05, 0x81, 0x98, 0x88, 0x8d, 0x82,
0x43, 0xc4, 0x59, 0xbf, 0xbf, 0x60, 0x51, 0xff,
0x60, 0x58, 0xff, 0x41, 0x6d, 0x81, 0xe9, 0x60,
0x75, 0x09, 0x80, 0x9a, 0x57, 0xf7, 0x87, 0x44,
0xd5, 0xa9, 0x88, 0x60, 0x24, 0x66, 0x41, 0x8b,
0x60, 0x4d, 0x03, 0x60, 0xa6, 0xdf, 0x9f, 0x50,
- 0x38, 0x86, 0x40, 0xdd, 0x81, 0x56, 0x81, 0x8d,
+ 0x39, 0x85, 0x40, 0xdd, 0x81, 0x56, 0x81, 0x8d,
0x5d, 0x30, 0x4c, 0x1e, 0x42, 0x1d, 0x45, 0xe1,
- 0x53, 0x4a,
+ 0x53, 0x4a, 0x84, 0x50, 0x5f,
};
static const uint8_t unicode_prop_Join_Control_table[4] = {
@@ -3979,7 +4086,7 @@ static const uint8_t unicode_prop_Regional_Indicator_table[4] = {
0x61, 0xf1, 0xe5, 0x99,
};
-static const uint8_t unicode_prop_Sentence_Terminal_table[194] = {
+static const uint8_t unicode_prop_Sentence_Terminal_table[196] = {
0xa0, 0x80, 0x8b, 0x80, 0x8f, 0x80, 0x45, 0x48,
0x80, 0x40, 0x92, 0x82, 0x40, 0xb3, 0x80, 0xaa,
0x82, 0x40, 0xf5, 0x80, 0xbc, 0x00, 0x02, 0x81,
@@ -4001,13 +4108,13 @@ static const uint8_t unicode_prop_Sentence_Terminal_table[194] = {
0xeb, 0x80, 0x41, 0xa0, 0x81, 0x41, 0x74, 0x0c,
0x8e, 0xe8, 0x81, 0x40, 0xf8, 0x82, 0x42, 0x04,
0x00, 0x80, 0x40, 0xfa, 0x81, 0xd6, 0x81, 0x41,
- 0xa3, 0x81, 0x42, 0xb3, 0x81, 0x60, 0x4b, 0x74,
- 0x81, 0x40, 0x84, 0x80, 0xc0, 0x81, 0x8a, 0x80,
- 0x43, 0x52, 0x80, 0x60, 0x4e, 0x05, 0x80, 0x5d,
- 0xe7, 0x80,
+ 0xa3, 0x81, 0x42, 0xb3, 0x81, 0xc9, 0x81, 0x60,
+ 0x4b, 0x28, 0x81, 0x40, 0x84, 0x80, 0xc0, 0x81,
+ 0x8a, 0x80, 0x43, 0x52, 0x80, 0x60, 0x4e, 0x05,
+ 0x80, 0x5d, 0xe7, 0x80,
};
-static const uint8_t unicode_prop_Soft_Dotted_table[74] = {
+static const uint8_t unicode_prop_Soft_Dotted_table[79] = {
0xe8, 0x81, 0x40, 0xc3, 0x80, 0x41, 0x18, 0x80,
0x9d, 0x80, 0xb3, 0x80, 0x93, 0x80, 0x41, 0x3f,
0x80, 0xe1, 0x00, 0x80, 0x59, 0x08, 0x80, 0xb2,
@@ -4017,10 +4124,10 @@ static const uint8_t unicode_prop_Soft_Dotted_table[74] = {
0x81, 0xb1, 0x81, 0xb1, 0x81, 0xb1, 0x81, 0xb1,
0x81, 0xb1, 0x81, 0xb1, 0x81, 0xb1, 0x81, 0xb1,
0x81, 0xb1, 0x81, 0xb1, 0x81, 0xb1, 0x81, 0x48,
- 0x85, 0x80,
+ 0x85, 0x80, 0x41, 0x30, 0x81, 0x99, 0x80,
};
-static const uint8_t unicode_prop_Terminal_Punctuation_table[246] = {
+static const uint8_t unicode_prop_Terminal_Punctuation_table[248] = {
0xa0, 0x80, 0x89, 0x00, 0x80, 0x8a, 0x0a, 0x80,
0x43, 0x3d, 0x07, 0x80, 0x42, 0x00, 0x80, 0xb8,
0x80, 0xc7, 0x80, 0x8d, 0x00, 0x82, 0x40, 0xb3,
@@ -4048,19 +4155,19 @@ static const uint8_t unicode_prop_Terminal_Punctuation_table[246] = {
0x82, 0x8b, 0x81, 0x41, 0x65, 0x1a, 0x8e, 0xe8,
0x81, 0x40, 0xf8, 0x82, 0x42, 0x04, 0x00, 0x80,
0x40, 0xfa, 0x81, 0xd6, 0x0b, 0x81, 0x41, 0x9d,
- 0x82, 0xac, 0x80, 0x42, 0x84, 0x81, 0x45, 0x76,
- 0x84, 0x60, 0x45, 0xf8, 0x81, 0x40, 0x84, 0x80,
- 0xc0, 0x82, 0x89, 0x80, 0x43, 0x51, 0x81, 0x60,
- 0x4e, 0x05, 0x80, 0x5d, 0xe6, 0x83,
+ 0x82, 0xac, 0x80, 0x42, 0x84, 0x81, 0xc9, 0x81,
+ 0x45, 0x2a, 0x84, 0x60, 0x45, 0xf8, 0x81, 0x40,
+ 0x84, 0x80, 0xc0, 0x82, 0x89, 0x80, 0x43, 0x51,
+ 0x81, 0x60, 0x4e, 0x05, 0x80, 0x5d, 0xe6, 0x83,
};
-static const uint8_t unicode_prop_Unified_Ideograph_table[42] = {
+static const uint8_t unicode_prop_Unified_Ideograph_table[45] = {
0x60, 0x33, 0xff, 0x59, 0xbf, 0xbf, 0x60, 0x51,
0xff, 0x60, 0x5a, 0x0d, 0x08, 0x00, 0x81, 0x89,
0x00, 0x00, 0x09, 0x82, 0x61, 0x05, 0xd5, 0x60,
- 0xa6, 0xdf, 0x9f, 0x50, 0x38, 0x86, 0x40, 0xdd,
+ 0xa6, 0xdf, 0x9f, 0x50, 0x39, 0x85, 0x40, 0xdd,
0x81, 0x56, 0x81, 0x8d, 0x5d, 0x30, 0x54, 0x1e,
- 0x53, 0x4a,
+ 0x53, 0x4a, 0x84, 0x50, 0x5f,
};
static const uint8_t unicode_prop_Variation_Selector_table[13] = {
@@ -4125,11 +4232,11 @@ static const uint8_t unicode_prop_Emoji_table[239] = {
0xbe, 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, 0x0a, 0x84,
- 0x88, 0x10, 0x01, 0x10, 0x81, 0x89, 0x40, 0xe2,
+ 0x02, 0x05, 0xd5, 0xaf, 0xc5, 0x27, 0x0a, 0x83,
+ 0x89, 0x10, 0x01, 0x10, 0x81, 0x89, 0x40, 0xe2,
0x8b, 0x18, 0x41, 0x1a, 0xae, 0x80, 0x89, 0x80,
- 0x40, 0xb8, 0xef, 0x22, 0x22, 0x86, 0x88, 0x9c,
- 0x82, 0x8a, 0x25, 0x89, 0x89, 0x2f, 0x3e,
+ 0x40, 0xb8, 0xef, 0x8c, 0x82, 0x88, 0x86, 0xad,
+ 0x06, 0x87, 0x8d, 0x83, 0x88, 0x86, 0x88,
};
static const uint8_t unicode_prop_Emoji_Component_table[28] = {
@@ -4152,7 +4259,7 @@ static const uint8_t unicode_prop_Emoji_Modifier_Base_table[71] = {
0xd2, 0x80, 0x8f, 0x82, 0x88, 0x80, 0x8a, 0x80,
0x42, 0x3e, 0x01, 0x07, 0x3d, 0x80, 0x88, 0x89,
0x0a, 0xb7, 0x80, 0xbc, 0x08, 0x08, 0x80, 0x90,
- 0x10, 0x8c, 0x40, 0xe4, 0x82, 0xa9, 0x86,
+ 0x10, 0x8c, 0x40, 0xe4, 0x82, 0xa9, 0x88,
};
static const uint8_t unicode_prop_Emoji_Presentation_table[145] = {
@@ -4170,11 +4277,11 @@ static const uint8_t unicode_prop_Emoji_Presentation_table[145] = {
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, 0x0a, 0x22, 0x8a, 0x0e, 0x88,
+ 0xc5, 0x28, 0x12, 0x0a, 0x1b, 0x8a, 0x0e, 0x88,
0x40, 0xe2, 0x8b, 0x18, 0x41, 0x1a, 0xae, 0x80,
- 0x89, 0x80, 0x40, 0xb8, 0xef, 0x22, 0x22, 0x86,
- 0x88, 0x9c, 0x82, 0x8a, 0x25, 0x89, 0x89, 0x2f,
- 0x3e,
+ 0x89, 0x80, 0x40, 0xb8, 0xef, 0x8c, 0x82, 0x88,
+ 0x86, 0xad, 0x06, 0x87, 0x8d, 0x83, 0x88, 0x86,
+ 0x88,
};
static const uint8_t unicode_prop_Extended_Pictographic_table[156] = {
@@ -4447,3 +4554,4 @@ static const uint16_t unicode_prop_len_table[] = {
};
#endif /* CONFIG_ALL_UNICODE */
+/* 62 tables / 32261 bytes, 5 index / 345 bytes */
diff --git a/src/shared/quickjs/libunicode.c b/src/shared/quickjs/libunicode.c
index 112da72da..482c51944 100644
--- a/src/shared/quickjs/libunicode.c
+++ b/src/shared/quickjs/libunicode.c
@@ -43,11 +43,111 @@ enum {
RUN_TYPE_UF_D1_EXT,
RUN_TYPE_U_EXT,
RUN_TYPE_LF_EXT,
- RUN_TYPE_U_EXT2,
- RUN_TYPE_L_EXT2,
- RUN_TYPE_U_EXT3,
+ RUN_TYPE_UF_EXT2,
+ RUN_TYPE_LF_EXT2,
+ RUN_TYPE_UF_EXT3,
};
+static int lre_case_conv1(uint32_t c, int conv_type)
+{
+ uint32_t res[LRE_CC_RES_LEN_MAX];
+ lre_case_conv(res, c, conv_type);
+ return res[0];
+}
+
+/* case conversion using the table entry 'idx' with value 'v' */
+static int lre_case_conv_entry(uint32_t *res, uint32_t c, int conv_type, uint32_t idx, uint32_t v)
+{
+ uint32_t code, data, type, a, is_lower;
+ is_lower = (conv_type != 0);
+ type = (v >> (32 - 17 - 7 - 4)) & 0xf;
+ data = ((v & 0xf) << 8) | case_conv_table2[idx];
+ code = v >> (32 - 17);
+ switch(type) {
+ case RUN_TYPE_U:
+ case RUN_TYPE_L:
+ case RUN_TYPE_UF:
+ case RUN_TYPE_LF:
+ if (conv_type == (type & 1) ||
+ (type >= RUN_TYPE_UF && conv_type == 2)) {
+ c = c - code + (case_conv_table1[data] >> (32 - 17));
+ }
+ break;
+ case RUN_TYPE_UL:
+ a = c - code;
+ if ((a & 1) != (1 - is_lower))
+ break;
+ c = (a ^ 1) + code;
+ break;
+ case RUN_TYPE_LSU:
+ a = c - code;
+ if (a == 1) {
+ c += 2 * is_lower - 1;
+ } else if (a == (1 - is_lower) * 2) {
+ c += (2 * is_lower - 1) * 2;
+ }
+ break;
+ case RUN_TYPE_U2L_399_EXT2:
+ if (!is_lower) {
+ res[0] = c - code + case_conv_ext[data >> 6];
+ res[1] = 0x399;
+ return 2;
+ } else {
+ c = c - code + case_conv_ext[data & 0x3f];
+ }
+ break;
+ case RUN_TYPE_UF_D20:
+ if (conv_type == 1)
+ break;
+ c = data + (conv_type == 2) * 0x20;
+ break;
+ case RUN_TYPE_UF_D1_EXT:
+ if (conv_type == 1)
+ break;
+ c = case_conv_ext[data] + (conv_type == 2);
+ break;
+ case RUN_TYPE_U_EXT:
+ case RUN_TYPE_LF_EXT:
+ if (is_lower != (type - RUN_TYPE_U_EXT))
+ break;
+ c = case_conv_ext[data];
+ break;
+ case RUN_TYPE_LF_EXT2:
+ if (!is_lower)
+ break;
+ res[0] = c - code + case_conv_ext[data >> 6];
+ res[1] = case_conv_ext[data & 0x3f];
+ return 2;
+ case RUN_TYPE_UF_EXT2:
+ if (conv_type == 1)
+ break;
+ res[0] = c - code + case_conv_ext[data >> 6];
+ res[1] = case_conv_ext[data & 0x3f];
+ if (conv_type == 2) {
+ /* convert to lower */
+ res[0] = lre_case_conv1(res[0], 1);
+ res[1] = lre_case_conv1(res[1], 1);
+ }
+ return 2;
+ default:
+ case RUN_TYPE_UF_EXT3:
+ if (conv_type == 1)
+ break;
+ res[0] = case_conv_ext[data >> 8];
+ res[1] = case_conv_ext[(data >> 4) & 0xf];
+ res[2] = case_conv_ext[data & 0xf];
+ if (conv_type == 2) {
+ /* convert to lower */
+ res[0] = lre_case_conv1(res[0], 1);
+ res[1] = lre_case_conv1(res[1], 1);
+ res[2] = lre_case_conv1(res[2], 1);
+ }
+ return 3;
+ }
+ res[0] = c;
+ return 1;
+}
+
/* conv_type:
0 = to upper
1 = to lower
@@ -66,10 +166,9 @@ int lre_case_conv(uint32_t *res, uint32_t c, int conv_type)
}
}
} else {
- uint32_t v, code, data, type, len, a, is_lower;
+ uint32_t v, code, len;
int idx, idx_min, idx_max;
- is_lower = (conv_type != 0);
idx_min = 0;
idx_max = countof(case_conv_table1) - 1;
while (idx_min <= idx_max) {
@@ -82,74 +181,7 @@ int lre_case_conv(uint32_t *res, uint32_t c, int conv_type)
} else if (c >= code + len) {
idx_min = idx + 1;
} else {
- type = (v >> (32 - 17 - 7 - 4)) & 0xf;
- data = ((v & 0xf) << 8) | case_conv_table2[idx];
- switch(type) {
- case RUN_TYPE_U:
- case RUN_TYPE_L:
- case RUN_TYPE_UF:
- case RUN_TYPE_LF:
- if (conv_type == (type & 1) ||
- (type >= RUN_TYPE_UF && conv_type == 2)) {
- c = c - code + (case_conv_table1[data] >> (32 - 17));
- }
- break;
- case RUN_TYPE_UL:
- a = c - code;
- if ((a & 1) != (1 - is_lower))
- break;
- c = (a ^ 1) + code;
- break;
- case RUN_TYPE_LSU:
- a = c - code;
- if (a == 1) {
- c += 2 * is_lower - 1;
- } else if (a == (1 - is_lower) * 2) {
- c += (2 * is_lower - 1) * 2;
- }
- break;
- case RUN_TYPE_U2L_399_EXT2:
- if (!is_lower) {
- res[0] = c - code + case_conv_ext[data >> 6];
- res[1] = 0x399;
- return 2;
- } else {
- c = c - code + case_conv_ext[data & 0x3f];
- }
- break;
- case RUN_TYPE_UF_D20:
- if (conv_type == 1)
- break;
- c = data + (conv_type == 2) * 0x20;
- break;
- case RUN_TYPE_UF_D1_EXT:
- if (conv_type == 1)
- break;
- c = case_conv_ext[data] + (conv_type == 2);
- break;
- case RUN_TYPE_U_EXT:
- case RUN_TYPE_LF_EXT:
- if (is_lower != (type - RUN_TYPE_U_EXT))
- break;
- c = case_conv_ext[data];
- break;
- case RUN_TYPE_U_EXT2:
- case RUN_TYPE_L_EXT2:
- if (conv_type != (type - RUN_TYPE_U_EXT2))
- break;
- res[0] = c - code + case_conv_ext[data >> 6];
- res[1] = case_conv_ext[data & 0x3f];
- return 2;
- default:
- case RUN_TYPE_U_EXT3:
- if (conv_type != 0)
- break;
- res[0] = case_conv_ext[data >> 8];
- res[1] = case_conv_ext[(data >> 4) & 0xf];
- res[2] = case_conv_ext[data & 0xf];
- return 3;
- }
- break;
+ return lre_case_conv_entry(res, c, conv_type, idx, v);
}
}
}
@@ -157,13 +189,80 @@ int lre_case_conv(uint32_t *res, uint32_t c, int conv_type)
return 1;
}
+static int lre_case_folding_entry(uint32_t c, uint32_t idx, uint32_t v, BOOL is_unicode)
+{
+ uint32_t res[LRE_CC_RES_LEN_MAX];
+ int len;
+
+ if (is_unicode) {
+ len = lre_case_conv_entry(res, c, 2, idx, v);
+ if (len == 1) {
+ c = res[0];
+ } else {
+ /* handle the few specific multi-character cases (see
+ unicode_gen.c:dump_case_folding_special_cases()) */
+ if (c == 0xfb06) {
+ c = 0xfb05;
+ } else if (c == 0x01fd3) {
+ c = 0x390;
+ } else if (c == 0x01fe3) {
+ c = 0x3b0;
+ }
+ }
+ } else {
+ if (likely(c < 128)) {
+ if (c >= 'a' && c <= 'z')
+ c = c - 'a' + 'A';
+ } else {
+ /* legacy regexp: to upper case if single char >= 128 */
+ len = lre_case_conv_entry(res, c, FALSE, idx, v);
+ if (len == 1 && res[0] >= 128)
+ c = res[0];
+ }
+ }
+ return c;
+}
+
+/* JS regexp specific rules for case folding */
+int lre_canonicalize(uint32_t c, BOOL is_unicode)
+{
+ if (c < 128) {
+ /* fast case */
+ if (is_unicode) {
+ if (c >= 'A' && c <= 'Z') {
+ c = c - 'A' + 'a';
+ }
+ } else {
+ if (c >= 'a' && c <= 'z') {
+ c = c - 'a' + 'A';
+ }
+ }
+ } else {
+ uint32_t v, code, len;
+ int idx, idx_min, idx_max;
+
+ idx_min = 0;
+ idx_max = countof(case_conv_table1) - 1;
+ while (idx_min <= idx_max) {
+ idx = (unsigned)(idx_max + idx_min) / 2;
+ v = case_conv_table1[idx];
+ code = v >> (32 - 17);
+ len = (v >> (32 - 17 - 7)) & 0x7f;
+ if (c < code) {
+ idx_max = idx - 1;
+ } else if (c >= code + len) {
+ idx_min = idx + 1;
+ } else {
+ return lre_case_folding_entry(c, idx, v, is_unicode);
+ }
+ }
+ }
+ return c;
+}
+
static uint32_t get_le24(const uint8_t *ptr)
{
-#if defined(__x86__) || defined(__x86_64__)
- return *(uint16_t *)ptr | (ptr[2] << 16);
-#else
return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16);
-#endif
}
#define UNICODE_INDEX_BLOCK_LEN 32
@@ -214,6 +313,14 @@ static BOOL lre_is_in_table(uint32_t c, const uint8_t *table,
return FALSE; /* outside the table */
p = table + pos;
bit = 0;
+ /* Compressed run length encoding:
+ 00..3F: 2 packed lengths: 3-bit + 3-bit
+ 40..5F: 5-bits plus extra byte for length
+ 60..7F: 5-bits plus 2 extra bytes for length
+ 80..FF: 7-bit length
+ lengths must be incremented to get character count
+ Ranges alternate between false and true return value.
+ */
for(;;) {
b = *p++;
if (b < 64) {
@@ -271,7 +378,7 @@ BOOL lre_is_case_ignorable(uint32_t c)
/* character range */
-static maybe_unused void cr_dump(CharRange *cr)
+static __maybe_unused void cr_dump(CharRange *cr)
{
int i;
for(i = 0; i < cr->len; i++)
@@ -327,7 +434,7 @@ static void cr_compress(CharRange *cr)
{
int i, j, k, len;
uint32_t *pt;
-
+
pt = cr->points;
len = cr->len;
i = 0;
@@ -730,6 +837,13 @@ static int unicode_get_cc(uint32_t c)
if (pos < 0)
return 0;
p = unicode_cc_table + pos;
+ /* Compressed run length encoding:
+ - 2 high order bits are combining class type
+ - 0:0, 1:230, 2:extra byte linear progression, 3:extra byte
+ - 00..2F: range length (add 1)
+ - 30..37: 3-bit range-length + 1 extra byte
+ - 38..3F: 3-bit range-length + 2 extra byte
+ */
for(;;) {
b = *p++;
type = b >> 6;
@@ -1082,6 +1196,15 @@ static int unicode_general_category1(CharRange *cr, uint32_t gc_mask)
p = unicode_gc_table;
p_end = unicode_gc_table + countof(unicode_gc_table);
c = 0;
+ /* Compressed range encoding:
+ initial byte:
+ bits 0..4: category number (special case 31)
+ bits 5..7: range length (add 1)
+ special case bits 5..7 == 7: read an extra byte
+ - 00..7F: range length (add 7 + 1)
+ - 80..BF: 6-bits plus extra byte for range length (add 7 + 128)
+ - C0..FF: 6-bits plus 2 extra bytes for range length (add 7 + 128 + 16384)
+ */
while (p < p_end) {
b = *p++;
n = b >> 5;
@@ -1135,6 +1258,14 @@ static int unicode_prop1(CharRange *cr, int prop_idx)
p_end = p + unicode_prop_len_table[prop_idx];
c = 0;
bit = 0;
+ /* Compressed range encoding:
+ 00..3F: 2 packed lengths: 3-bit + 3-bit
+ 40..5F: 5-bits plus extra byte for length
+ 60..7F: 5-bits plus 2 extra bytes for length
+ 80..FF: 7-bit length
+ lengths must be incremented to get character count
+ Ranges alternate between false and true return value.
+ */
while (p < p_end) {
c0 = c;
b = *p++;
@@ -1179,11 +1310,11 @@ static int unicode_case1(CharRange *cr, int case_mask)
#define MR(x) (1 << RUN_TYPE_ ## x)
const uint32_t tab_run_mask[3] = {
MR(U) | MR(UF) | MR(UL) | MR(LSU) | MR(U2L_399_EXT2) | MR(UF_D20) |
- MR(UF_D1_EXT) | MR(U_EXT) | MR(U_EXT2) | MR(U_EXT3),
+ MR(UF_D1_EXT) | MR(U_EXT) | MR(UF_EXT2) | MR(UF_EXT3),
- MR(L) | MR(LF) | MR(UL) | MR(LSU) | MR(U2L_399_EXT2) | MR(LF_EXT) | MR(L_EXT2),
+ MR(L) | MR(LF) | MR(UL) | MR(LSU) | MR(U2L_399_EXT2) | MR(LF_EXT) | MR(LF_EXT2),
- MR(UF) | MR(LF) | MR(UL) | MR(LSU) | MR(U2L_399_EXT2) | MR(LF_EXT) | MR(UF_D20) | MR(UF_D1_EXT) | MR(LF_EXT),
+ MR(UF) | MR(LF) | MR(UL) | MR(LSU) | MR(U2L_399_EXT2) | MR(LF_EXT) | MR(LF_EXT2) | MR(UF_D20) | MR(UF_D1_EXT) | MR(LF_EXT) | MR(UF_EXT2) | MR(UF_EXT3),
};
#undef MR
uint32_t mask, v, code, type, len, i, idx;
@@ -1237,6 +1368,135 @@ static int unicode_case1(CharRange *cr, int case_mask)
return 0;
}
+static int point_cmp(const void *p1, const void *p2, void *arg)
+{
+ uint32_t v1 = *(uint32_t *)p1;
+ uint32_t v2 = *(uint32_t *)p2;
+ return (v1 > v2) - (v1 < v2);
+}
+
+static void cr_sort_and_remove_overlap(CharRange *cr)
+{
+ uint32_t start, end, start1, end1, i, j;
+
+ /* the resulting ranges are not necessarily sorted and may overlap */
+ rqsort(cr->points, cr->len / 2, sizeof(cr->points[0]) * 2, point_cmp, NULL);
+ j = 0;
+ for(i = 0; i < cr->len; ) {
+ start = cr->points[i];
+ end = cr->points[i + 1];
+ i += 2;
+ while (i < cr->len) {
+ start1 = cr->points[i];
+ end1 = cr->points[i + 1];
+ if (start1 > end) {
+ /* |------|
+ * |-------| */
+ break;
+ } else if (end1 <= end) {
+ /* |------|
+ * |--| */
+ i += 2;
+ } else {
+ /* |------|
+ * |-------| */
+ end = end1;
+ i += 2;
+ }
+ }
+ cr->points[j] = start;
+ cr->points[j + 1] = end;
+ j += 2;
+ }
+ cr->len = j;
+}
+
+/* canonicalize a character set using the JS regex case folding rules
+ (see lre_canonicalize()) */
+int cr_regexp_canonicalize(CharRange *cr, BOOL is_unicode)
+{
+ CharRange cr_inter, cr_mask, cr_result, cr_sub;
+ uint32_t v, code, len, i, idx, start, end, c, d_start, d_end, d;
+
+ cr_init(&cr_mask, cr->mem_opaque, cr->realloc_func);
+ cr_init(&cr_inter, cr->mem_opaque, cr->realloc_func);
+ cr_init(&cr_result, cr->mem_opaque, cr->realloc_func);
+ cr_init(&cr_sub, cr->mem_opaque, cr->realloc_func);
+
+ if (unicode_case1(&cr_mask, is_unicode ? CASE_F : CASE_U))
+ goto fail;
+ if (cr_op(&cr_inter, cr_mask.points, cr_mask.len, cr->points, cr->len, CR_OP_INTER))
+ goto fail;
+
+ if (cr_invert(&cr_mask))
+ goto fail;
+ if (cr_op(&cr_sub, cr_mask.points, cr_mask.len, cr->points, cr->len, CR_OP_INTER))
+ goto fail;
+
+ /* cr_inter = cr & cr_mask */
+ /* cr_sub = cr & ~cr_mask */
+
+ /* use the case conversion table to compute the result */
+ d_start = -1;
+ d_end = -1;
+ idx = 0;
+ v = case_conv_table1[idx];
+ code = v >> (32 - 17);
+ len = (v >> (32 - 17 - 7)) & 0x7f;
+ for(i = 0; i < cr_inter.len; i += 2) {
+ start = cr_inter.points[i];
+ end = cr_inter.points[i + 1];
+
+ for(c = start; c < end; c++) {
+ for(;;) {
+ if (c >= code && c < code + len)
+ break;
+ idx++;
+ assert(idx < countof(case_conv_table1));
+ v = case_conv_table1[idx];
+ code = v >> (32 - 17);
+ len = (v >> (32 - 17 - 7)) & 0x7f;
+ }
+ d = lre_case_folding_entry(c, idx, v, is_unicode);
+ /* try to merge with the current interval */
+ if (d_start == -1) {
+ d_start = d;
+ d_end = d + 1;
+ } else if (d_end == d) {
+ d_end++;
+ } else {
+ cr_add_interval(&cr_result, d_start, d_end);
+ d_start = d;
+ d_end = d + 1;
+ }
+ }
+ }
+ if (d_start != -1) {
+ if (cr_add_interval(&cr_result, d_start, d_end))
+ goto fail;
+ }
+
+ /* the resulting ranges are not necessarily sorted and may overlap */
+ cr_sort_and_remove_overlap(&cr_result);
+
+ /* or with the character not affected by the case folding */
+ cr->len = 0;
+ if (cr_op(cr, cr_result.points, cr_result.len, cr_sub.points, cr_sub.len, CR_OP_UNION))
+ goto fail;
+
+ cr_free(&cr_inter);
+ cr_free(&cr_mask);
+ cr_free(&cr_result);
+ cr_free(&cr_sub);
+ return 0;
+ fail:
+ cr_free(&cr_inter);
+ cr_free(&cr_mask);
+ cr_free(&cr_result);
+ cr_free(&cr_sub);
+ return -1;
+}
+
typedef enum {
POP_GC,
POP_PROP,
@@ -1556,3 +1816,97 @@ int unicode_prop(CharRange *cr, const char *prop_name)
}
#endif /* CONFIG_ALL_UNICODE */
+
+/*---- lre codepoint categorizing functions ----*/
+
+#define S UNICODE_C_SPACE
+#define D UNICODE_C_DIGIT
+#define X UNICODE_C_XDIGIT
+#define U UNICODE_C_UPPER
+#define L UNICODE_C_LOWER
+#define _ UNICODE_C_UNDER
+#define d UNICODE_C_DOLLAR
+
+uint8_t const lre_ctype_bits[256] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, S, S, S, S, S, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ S, 0, 0, 0, d, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ X|D, X|D, X|D, X|D, X|D, X|D, X|D, X|D,
+ X|D, X|D, 0, 0, 0, 0, 0, 0,
+
+ 0, X|U, X|U, X|U, X|U, X|U, X|U, U,
+ U, U, U, U, U, U, U, U,
+ U, U, U, U, U, U, U, U,
+ U, U, U, 0, 0, 0, 0, _,
+
+ 0, X|L, X|L, X|L, X|L, X|L, X|L, L,
+ L, L, L, L, L, L, L, L,
+ L, L, L, L, L, L, L, L,
+ L, L, L, 0, 0, 0, 0, 0,
+
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ S, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+#undef S
+#undef D
+#undef X
+#undef U
+#undef L
+#undef _
+#undef d
+
+/* code point ranges for Zs,Zl or Zp property */
+static const uint16_t char_range_s[] = {
+ 10,
+ 0x0009, 0x000D + 1,
+ 0x0020, 0x0020 + 1,
+ 0x00A0, 0x00A0 + 1,
+ 0x1680, 0x1680 + 1,
+ 0x2000, 0x200A + 1,
+ /* 2028;LINE SEPARATOR;Zl;0;WS;;;;;N;;;;; */
+ /* 2029;PARAGRAPH SEPARATOR;Zp;0;B;;;;;N;;;;; */
+ 0x2028, 0x2029 + 1,
+ 0x202F, 0x202F + 1,
+ 0x205F, 0x205F + 1,
+ 0x3000, 0x3000 + 1,
+ /* FEFF;ZERO WIDTH NO-BREAK SPACE;Cf;0;BN;;;;;N;BYTE ORDER MARK;;;; */
+ 0xFEFF, 0xFEFF + 1,
+};
+
+BOOL lre_is_space_non_ascii(uint32_t c)
+{
+ size_t i, n;
+
+ n = countof(char_range_s);
+ for(i = 5; i < n; i += 2) {
+ uint32_t low = char_range_s[i];
+ uint32_t high = char_range_s[i + 1];
+ if (c < low)
+ return FALSE;
+ if (c < high)
+ return TRUE;
+ }
+ return FALSE;
+}
diff --git a/src/shared/quickjs/libunicode.h b/src/shared/quickjs/libunicode.h
index cfa600a50..cc2f244c7 100644
--- a/src/shared/quickjs/libunicode.h
+++ b/src/shared/quickjs/libunicode.h
@@ -1,6 +1,6 @@
/*
* Unicode utilities
- *
+ *
* Copyright (c) 2017-2018 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -24,26 +24,13 @@
#ifndef LIBUNICODE_H
#define LIBUNICODE_H
-#include <inttypes.h>
-
-#define LRE_BOOL int /* for documentation purposes */
+#include <stdint.h>
/* define it to include all the unicode tables (40KB larger) */
#define CONFIG_ALL_UNICODE
#define LRE_CC_RES_LEN_MAX 3
-typedef enum {
- UNICODE_NFC,
- UNICODE_NFD,
- UNICODE_NFKC,
- UNICODE_NFKD,
-} UnicodeNormalizationEnum;
-
-int lre_case_conv(uint32_t *res, uint32_t c, int conv_type);
-LRE_BOOL lre_is_cased(uint32_t c);
-LRE_BOOL lre_is_case_ignorable(uint32_t c);
-
/* char ranges */
typedef struct {
@@ -101,10 +88,14 @@ int cr_op(CharRange *cr, const uint32_t *a_pt, int a_len,
int cr_invert(CharRange *cr);
-#ifdef CONFIG_ALL_UNICODE
+int cr_regexp_canonicalize(CharRange *cr, int is_unicode);
-LRE_BOOL lre_is_id_start(uint32_t c);
-LRE_BOOL lre_is_id_continue(uint32_t c);
+typedef enum {
+ UNICODE_NFC,
+ UNICODE_NFD,
+ UNICODE_NFKC,
+ UNICODE_NFKD,
+} UnicodeNormalizationEnum;
int unicode_normalize(uint32_t **pdst, const uint32_t *src, int src_len,
UnicodeNormalizationEnum n_type,
@@ -112,13 +103,80 @@ int unicode_normalize(uint32_t **pdst, const uint32_t *src, int src_len,
/* Unicode character range functions */
-int unicode_script(CharRange *cr,
- const char *script_name, LRE_BOOL is_ext);
+int unicode_script(CharRange *cr, const char *script_name, int is_ext);
int unicode_general_category(CharRange *cr, const char *gc_name);
int unicode_prop(CharRange *cr, const char *prop_name);
-#endif /* CONFIG_ALL_UNICODE */
+int lre_case_conv(uint32_t *res, uint32_t c, int conv_type);
+int lre_canonicalize(uint32_t c, int is_unicode);
+
+/* Code point type categories */
+enum {
+ UNICODE_C_SPACE = (1 << 0),
+ UNICODE_C_DIGIT = (1 << 1),
+ UNICODE_C_UPPER = (1 << 2),
+ UNICODE_C_LOWER = (1 << 3),
+ UNICODE_C_UNDER = (1 << 4),
+ UNICODE_C_DOLLAR = (1 << 5),
+ UNICODE_C_XDIGIT = (1 << 6),
+};
+extern uint8_t const lre_ctype_bits[256];
+
+/* zero or non-zero return value */
+int lre_is_cased(uint32_t c);
+int lre_is_case_ignorable(uint32_t c);
+int lre_is_id_start(uint32_t c);
+int lre_is_id_continue(uint32_t c);
+
+static inline int lre_is_space_byte(uint8_t c) {
+ return lre_ctype_bits[c] & UNICODE_C_SPACE;
+}
+
+static inline int lre_is_id_start_byte(uint8_t c) {
+ return lre_ctype_bits[c] & (UNICODE_C_UPPER | UNICODE_C_LOWER |
+ UNICODE_C_UNDER | UNICODE_C_DOLLAR);
+}
-#undef LRE_BOOL
+static inline int lre_is_id_continue_byte(uint8_t c) {
+ return lre_ctype_bits[c] & (UNICODE_C_UPPER | UNICODE_C_LOWER |
+ UNICODE_C_UNDER | UNICODE_C_DOLLAR |
+ UNICODE_C_DIGIT);
+}
+
+int lre_is_space_non_ascii(uint32_t c);
+
+static inline int lre_is_space(uint32_t c) {
+ if (c < 256)
+ return lre_is_space_byte(c);
+ else
+ return lre_is_space_non_ascii(c);
+}
+
+static inline int lre_js_is_ident_first(uint32_t c) {
+ if (c < 128) {
+ return lre_is_id_start_byte(c);
+ } else {
+#ifdef CONFIG_ALL_UNICODE
+ return lre_is_id_start(c);
+#else
+ return !lre_is_space_non_ascii(c);
+#endif
+ }
+}
+
+static inline int lre_js_is_ident_next(uint32_t c) {
+ if (c < 128) {
+ return lre_is_id_continue_byte(c);
+ } else {
+ /* ZWNJ and ZWJ are accepted in identifiers */
+ if (c >= 0x200C && c <= 0x200D)
+ return TRUE;
+#ifdef CONFIG_ALL_UNICODE
+ return lre_is_id_continue(c);
+#else
+ return !lre_is_space_non_ascii(c);
+#endif
+ }
+}
#endif /* LIBUNICODE_H */
diff --git a/src/shared/quickjs/list.h b/src/shared/quickjs/list.h
index e7f51a9d9..809831115 100644
--- a/src/shared/quickjs/list.h
+++ b/src/shared/quickjs/list.h
@@ -36,8 +36,7 @@ struct list_head {
#define LIST_HEAD_INIT(el) { &(el), &(el) }
/* return the pointer of type 'type *' containing 'el' as field 'member' */
-#define list_entry(el, type, member) \
- ((type *)((uint8_t *)(el) - offsetof(type, member)))
+#define list_entry(el, type, member) container_of(el, type, member)
static inline void init_list_head(struct list_head *head)
{
@@ -46,8 +45,8 @@ static inline void init_list_head(struct list_head *head)
}
/* insert 'el' between 'prev' and 'next' */
-static inline void list_add_impl(struct list_head *el,
- struct list_head *prev, struct list_head *next)
+static inline void __list_add(struct list_head *el,
+ struct list_head *prev, struct list_head *next)
{
prev->next = el;
el->prev = prev;
@@ -58,13 +57,13 @@ static inline void list_add_impl(struct list_head *el,
/* add 'el' at the head of the list 'head' (= after element head) */
static inline void list_add(struct list_head *el, struct list_head *head)
{
- list_add_impl(el, head, head->next);
+ __list_add(el, head, head->next);
}
/* add 'el' at the end of the list 'head' (= before element head) */
static inline void list_add_tail(struct list_head *el, struct list_head *head)
{
- list_add_impl(el, head->prev, head);
+ __list_add(el, head->prev, head);
}
static inline void list_del(struct list_head *el)
diff --git a/src/shared/quickjs/quickjs-atom.h b/src/shared/quickjs/quickjs-atom.h
index 4c2279452..f4d5838d4 100644
--- a/src/shared/quickjs/quickjs-atom.h
+++ b/src/shared/quickjs/quickjs-atom.h
@@ -1,6 +1,6 @@
/*
* QuickJS atom definitions
- *
+ *
* Copyright (c) 2017-2018 Fabrice Bellard
* Copyright (c) 2017-2018 Charlie Gordon
*
@@ -82,6 +82,7 @@ DEF(length, "length")
DEF(fileName, "fileName")
DEF(lineNumber, "lineNumber")
DEF(message, "message")
+DEF(cause, "cause")
DEF(errors, "errors")
DEF(stack, "stack")
DEF(name, "name")
@@ -166,22 +167,23 @@ DEF(revoke, "revoke")
DEF(async, "async")
DEF(exec, "exec")
DEF(groups, "groups")
+DEF(indices, "indices")
DEF(status, "status")
DEF(reason, "reason")
DEF(globalThis, "globalThis")
-#ifdef CONFIG_BIGNUM
DEF(bigint, "bigint")
+#ifdef CONFIG_BIGNUM
DEF(bigfloat, "bigfloat")
DEF(bigdecimal, "bigdecimal")
DEF(roundingMode, "roundingMode")
DEF(maximumSignificantDigits, "maximumSignificantDigits")
DEF(maximumFractionDigits, "maximumFractionDigits")
#endif
-#ifdef CONFIG_ATOMICS
+/* the following 3 atoms are only used with CONFIG_ATOMICS */
DEF(not_equal, "not-equal")
DEF(timed_out, "timed-out")
DEF(ok, "ok")
-#endif
+/* */
DEF(toJSON, "toJSON")
/* class names */
DEF(Object, "Object")
@@ -202,22 +204,20 @@ DEF(RegExp, "RegExp")
DEF(ArrayBuffer, "ArrayBuffer")
DEF(SharedArrayBuffer, "SharedArrayBuffer")
/* must keep same order as class IDs for typed arrays */
-DEF(Uint8ClampedArray, "Uint8ClampedArray")
+DEF(Uint8ClampedArray, "Uint8ClampedArray")
DEF(Int8Array, "Int8Array")
DEF(Uint8Array, "Uint8Array")
DEF(Int16Array, "Int16Array")
DEF(Uint16Array, "Uint16Array")
DEF(Int32Array, "Int32Array")
DEF(Uint32Array, "Uint32Array")
-#ifdef CONFIG_BIGNUM
DEF(BigInt64Array, "BigInt64Array")
DEF(BigUint64Array, "BigUint64Array")
-#endif
DEF(Float32Array, "Float32Array")
DEF(Float64Array, "Float64Array")
DEF(DataView, "DataView")
-#ifdef CONFIG_BIGNUM
DEF(BigInt, "BigInt")
+#ifdef CONFIG_BIGNUM
DEF(BigFloat, "BigFloat")
DEF(BigFloatEnv, "BigFloatEnv")
DEF(BigDecimal, "BigDecimal")
@@ -269,5 +269,5 @@ DEF(Symbol_asyncIterator, "Symbol.asyncIterator")
#ifdef CONFIG_BIGNUM
DEF(Symbol_operatorSet, "Symbol.operatorSet")
#endif
-
+
#endif /* DEF */
diff --git a/src/shared/quickjs/quickjs-opcode.h b/src/shared/quickjs/quickjs-opcode.h
index c731a14a9..1e1821259 100644
--- a/src/shared/quickjs/quickjs-opcode.h
+++ b/src/shared/quickjs/quickjs-opcode.h
@@ -1,6 +1,6 @@
/*
* QuickJS opcode definitions
- *
+ *
* Copyright (c) 2017-2018 Fabrice Bellard
* Copyright (c) 2017-2018 Charlie Gordon
*
@@ -165,14 +165,15 @@ DEF( set_loc, 3, 1, 1, loc) /* must come after put_loc */
DEF( get_arg, 3, 0, 1, arg)
DEF( put_arg, 3, 1, 0, arg) /* must come after get_arg */
DEF( set_arg, 3, 1, 1, arg) /* must come after put_arg */
-DEF( get_var_ref, 3, 0, 1, var_ref)
+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( 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)
-DEF(get_var_ref_check, 3, 0, 1, var_ref)
+DEF(get_loc_checkthis, 3, 0, 1, loc)
+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)
@@ -182,6 +183,7 @@ DEF( goto, 5, 0, 0, label) /* must come after if_true */
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( nip_catch, 1, 2, 1, none) /* catch ... a -> a */
DEF( to_object, 1, 1, 1, none)
//DEF( to_string, 1, 1, 1, none)
@@ -208,7 +210,6 @@ DEF( for_of_next, 2, 3, 5, u8)
DEF(iterator_check_object, 1, 1, 1, none)
DEF(iterator_get_value_done, 1, 1, 2, none)
DEF( iterator_close, 1, 3, 0, none)
-DEF(iterator_close_return, 1, 4, 4, none)
DEF( iterator_next, 1, 4, 4, none)
DEF( iterator_call, 2, 4, 5, u8)
DEF( initial_yield, 1, 0, 0, none)
@@ -256,12 +257,13 @@ DEF( and, 1, 2, 1, none)
DEF( xor, 1, 2, 1, none)
DEF( or, 1, 2, 1, none)
DEF(is_undefined_or_null, 1, 1, 1, none)
+DEF( private_in, 1, 2, 1, none)
#ifdef CONFIG_BIGNUM
DEF( mul_pow10, 1, 2, 1, none)
DEF( math_mod, 1, 2, 1, none)
#endif
/* must be the last non short and non temporary opcode */
-DEF( nop, 1, 0, 0, none)
+DEF( nop, 1, 0, 0, none)
/* temporary opcodes: never emitted in the final bytecode */
@@ -270,6 +272,8 @@ 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 */
+/* the following opcodes must be in the same order as the 'with_x' and
+ get_var_undef, get_var and put_var opcodes */
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 */
@@ -277,12 +281,15 @@ def(scope_delete_var, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase
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_var_checkthis, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2, only used to return 'this' in derived class constructors */
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(scope_put_private_field, 7, 2, 0, atom_u16) /* obj value ->, emitted in phase 1, removed in phase 2 */
+def(scope_in_private_field, 7, 1, 1, atom_u16) /* obj -> res emitted in phase 1, removed in phase 2 */
+def(get_field_opt_chain, 5, 1, 1, atom) /* emitted in phase 1, removed in phase 2 */
+def(get_array_el_opt_chain, 1, 2, 1, none) /* 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/src/shared/quickjs/quickjs.c b/src/shared/quickjs/quickjs.c
index 1e3b97d51..3bafe6948 100644
--- a/src/shared/quickjs/quickjs.c
+++ b/src/shared/quickjs/quickjs.c
@@ -58,9 +58,8 @@
#include "list.h"
#include "quickjs.h"
#include "libregexp.h"
-#ifdef CONFIG_BIGNUM
+#include "libunicode.h"
#include "libbf.h"
-#endif
#define OPTIMIZE 0
#define SHORT_OPCODES 1
@@ -102,6 +101,7 @@
8: dump stdlib functions
16: dump bytecode in hex
32: dump line number table
+ 64: dump compute_stack_size
*/
//#define DUMP_BYTECODE (1)
/* dump the occurence of the automatic GC */
@@ -176,15 +176,13 @@ enum {
JS_CLASS_UINT16_ARRAY, /* u.array (typed_array) */
JS_CLASS_INT32_ARRAY, /* u.array (typed_array) */
JS_CLASS_UINT32_ARRAY, /* u.array (typed_array) */
-#ifdef CONFIG_BIGNUM
JS_CLASS_BIG_INT64_ARRAY, /* u.array (typed_array) */
JS_CLASS_BIG_UINT64_ARRAY, /* u.array (typed_array) */
-#endif
JS_CLASS_FLOAT32_ARRAY, /* u.array (typed_array) */
JS_CLASS_FLOAT64_ARRAY, /* u.array (typed_array) */
JS_CLASS_DATAVIEW, /* u.typed_array */
-#ifdef CONFIG_BIGNUM
JS_CLASS_BIG_INT, /* u.object_data */
+#ifdef CONFIG_BIGNUM
JS_CLASS_BIG_FLOAT, /* u.object_data */
JS_CLASS_FLOAT_ENV, /* u.float_env */
JS_CLASS_BIG_DECIMAL, /* u.object_data */
@@ -232,14 +230,14 @@ typedef enum JSErrorEnum {
JS_NATIVE_ERROR_COUNT, /* number of different NativeError objects */
} JSErrorEnum;
-#define JS_MAX_LOCAL_VARS 65536
+#define JS_MAX_LOCAL_VARS 65535
#define JS_STACK_SIZE_MAX 65534
#define JS_STRING_LEN_MAX ((1 << 30) - 1)
#ifdef __GNUC__
-#define warn_unused __attribute__((warn_unused_result))
+#define __exception __attribute__((warn_unused_result))
#else
-#define warn_unused
+#define __exception
#endif
typedef struct JSShape JSShape;
@@ -254,7 +252,6 @@ typedef enum {
typedef enum OPCodeEnum OPCodeEnum;
-#ifdef CONFIG_BIGNUM
/* function pointers are used for numeric operations so that it is
possible to remove some numeric types */
typedef struct {
@@ -272,7 +269,6 @@ typedef struct {
int64_t exponent);
int (*mul_pow10)(JSContext *ctx, JSValue *sp);
} JSNumericOperations;
-#endif
struct JSRuntime {
JSMallocFunctions mf;
@@ -324,6 +320,8 @@ struct JSRuntime {
JSModuleNormalizeFunc *module_normalize_func;
JSModuleLoaderFunc *module_loader_func;
void *module_loader_opaque;
+ /* timestamp for internal use in module evaluation */
+ int64_t module_async_evaluation_next_timestamp;
BOOL can_block : 8; /* TRUE if Atomics.wait can block */
/* used to allocate, free and clone SharedArrayBuffers */
@@ -334,9 +332,9 @@ struct JSRuntime {
int shape_hash_size;
int shape_hash_count; /* number of hashed shapes */
JSShape **shape_hash;
-#ifdef CONFIG_BIGNUM
bf_context_t bf_ctx;
JSNumericOperations bigint_ops;
+#ifdef CONFIG_BIGNUM
JSNumericOperations bigfloat_ops;
JSNumericOperations bigdecimal_ops;
uint32_t operator_count;
@@ -357,17 +355,18 @@ struct JSClass {
#define JS_MODE_STRICT (1 << 0)
#define JS_MODE_STRIP (1 << 1)
#define JS_MODE_MATH (1 << 2)
+#define JS_MODE_ASYNC (1 << 3) /* async function */
typedef struct JSStackFrame {
struct JSStackFrame *prev_frame; /* NULL if first stack frame */
JSValue cur_func; /* current function, JS_UNDEFINED if the frame is detached */
JSValue *arg_buf; /* arguments */
JSValue *var_buf; /* variables */
- struct list_head var_ref_list; /* list of JSVarRef.link */
+ struct list_head var_ref_list; /* list of JSVarRef.var_ref_link */
const uint8_t *cur_pc; /* only used in bytecode functions : PC of the
instruction after the call */
int arg_count;
- int js_mode; /* 0 or JS_MODE_MATH for C functions */
+ int js_mode; /* for C functions, only JS_MODE_MATH may be set */
/* only used in generators. Current stack pointer value. NULL if
the function is running. */
JSValue *cur_sp;
@@ -398,13 +397,8 @@ typedef struct JSVarRef {
union {
JSGCObjectHeader header; /* must come first */
struct {
- int _gc_ref_count; /* corresponds to header.ref_count */
- uint8_t _gc_mark; /* corresponds to header.mark/gc_obj_type */
-
- /* 0 : the JSVarRef is on the stack. header.link is an element
- of JSStackFrame.var_ref_list.
- 1 : the JSVarRef is detached. header.link has the normal meanning
- */
+ int __gc_ref_count; /* corresponds to header.ref_count */
+ uint8_t __gc_mark; /* corresponds to header.mark/gc_obj_type */
uint8_t is_detached : 1;
uint8_t is_arg : 1;
uint16_t var_idx; /* index of the corresponding function variable on
@@ -413,16 +407,15 @@ typedef struct JSVarRef {
};
JSValue *pvalue; /* pointer to the value, either on the stack or
to 'value' */
- JSValue value; /* used when the variable is no longer on the stack */
+ union {
+ JSValue value; /* used when is_detached = TRUE */
+ struct {
+ struct list_head var_ref_link; /* JSStackFrame.var_ref_list list */
+ struct JSAsyncFunctionState *async_func; /* != NULL if async stack frame */
+ }; /* used when is_detached = FALSE */
+ };
} JSVarRef;
-#ifdef CONFIG_BIGNUM
-typedef struct JSFloatEnv {
- limb_t prec;
- bf_flags_t flags;
- unsigned int status;
-} JSFloatEnv;
-
/* the same structure is used for big integers and big floats. Big
integers are never infinite or NaNs */
typedef struct JSBigFloat {
@@ -430,6 +423,13 @@ typedef struct JSBigFloat {
bf_t num;
} JSBigFloat;
+#ifdef CONFIG_BIGNUM
+typedef struct JSFloatEnv {
+ limb_t prec;
+ bf_flags_t flags;
+ unsigned int status;
+} JSFloatEnv;
+
typedef struct JSBigDecimal {
JSRefCountHeader header; /* must come first, 32-bit */
bfdec_t num;
@@ -473,15 +473,14 @@ struct JSContext {
JSValue global_var_obj; /* contains the global let/const definitions */
uint64_t random_state;
-#ifdef CONFIG_BIGNUM
bf_context_t *bf_ctx; /* points to rt->bf_ctx, shared by all contexts */
+#ifdef CONFIG_BIGNUM
JSFloatEnv fp_env; /* global FP environment */
BOOL bignum_ext : 8; /* enable math mode */
BOOL allow_operator_overloading : 8;
#endif
/* when the counter reaches zero, JSRutime.interrupt_handler is called */
int interrupt_counter;
- BOOL is_error_property_enabled;
struct list_head loaded_modules; /* list of JSModuleDef.link */
@@ -598,6 +597,7 @@ typedef struct JSVarDef {
uint8_t is_const : 1;
uint8_t is_lexical : 1;
uint8_t is_captured : 1;
+ uint8_t is_static_private : 1; /* only used during private class field parsing */
uint8_t var_kind : 4; /* see JSVarKindEnum */
/* only used during compilation: function pool index for lexical
variables with var_kind =
@@ -638,7 +638,8 @@ typedef struct JSFunctionBytecode {
uint8_t has_debug : 1;
uint8_t backtrace_barrier : 1; /* stop backtrace on this function */
uint8_t read_only_bytecode : 1;
- /* XXX: 4 bits available */
+ uint8_t is_direct_or_indirect_eval : 1; /* used by JS_GetScriptOrModuleName() */
+ /* XXX: 10 bits available */
uint8_t *byte_code_buf; /* (self pointer) */
int byte_code_len;
JSAtom func_name;
@@ -678,9 +679,11 @@ typedef enum JSIteratorKindEnum {
typedef struct JSForInIterator {
JSValue obj;
- BOOL is_array;
- uint32_t array_length;
uint32_t idx;
+ uint32_t atom_count;
+ uint8_t in_prototype_chain;
+ uint8_t is_array;
+ JSPropertyEnum *tab_atom; /* is_array = FALSE */
} JSForInIterator;
typedef struct JSRegExp {
@@ -714,21 +717,16 @@ typedef struct JSTypedArray {
} JSTypedArray;
typedef struct JSAsyncFunctionState {
- JSValue this_val; /* 'this' generator argument */
+ JSGCObjectHeader header;
+ JSValue this_val; /* 'this' argument */
int argc; /* number of function arguments */
BOOL throw_flag; /* used to throw an exception in JS_CallInternal() */
+ BOOL is_completed; /* TRUE if the function has returned. The stack
+ frame is no longer valid */
+ JSValue resolving_funcs[2]; /* only used in JS async functions */
JSStackFrame frame;
} JSAsyncFunctionState;
-/* XXX: could use an object instead to avoid the
- JS_TAG_ASYNC_FUNCTION tag for the GC */
-typedef struct JSAsyncFunctionData {
- JSGCObjectHeader header; /* must come first */
- JSValue resolving_funcs[2];
- BOOL is_active; /* true if the async function state is valid */
- JSAsyncFunctionState func_state;
-} JSAsyncFunctionData;
-
typedef enum {
/* binary operators */
JS_OVOP_ADD,
@@ -810,6 +808,15 @@ typedef struct JSImportEntry {
int req_module_idx; /* in req_module_entries */
} JSImportEntry;
+typedef enum {
+ JS_MODULE_STATUS_UNLINKED,
+ JS_MODULE_STATUS_LINKING,
+ JS_MODULE_STATUS_LINKED,
+ JS_MODULE_STATUS_EVALUATING,
+ JS_MODULE_STATUS_EVALUATING_ASYNC,
+ JS_MODULE_STATUS_EVALUATED,
+} JSModuleStatus;
+
struct JSModuleDef {
JSRefCountHeader header; /* must come first, 32-bit */
JSAtom module_name;
@@ -834,11 +841,24 @@ struct JSModuleDef {
JSValue module_ns;
JSValue func_obj; /* only used for JS modules */
JSModuleInitFunc *init_func; /* only used for C modules */
+ BOOL has_tla : 8; /* true if func_obj contains await */
BOOL resolved : 8;
BOOL func_created : 8;
- BOOL instantiated : 8;
- BOOL evaluated : 8;
- BOOL eval_mark : 8; /* temporary use during js_evaluate_module() */
+ JSModuleStatus status : 8;
+ /* temp use during js_module_link() & js_module_evaluate() */
+ int dfs_index, dfs_ancestor_index;
+ JSModuleDef *stack_prev;
+ /* temp use during js_module_evaluate() */
+ JSModuleDef **async_parent_modules;
+ int async_parent_modules_count;
+ int async_parent_modules_size;
+ int pending_async_dependencies;
+ BOOL async_evaluation;
+ int64_t async_evaluation_timestamp;
+ JSModuleDef *cycle_root;
+ JSValue promise; /* corresponds to spec field: capability */
+ JSValue resolving_funcs[2]; /* corresponds to spec field: capability */
+
/* true if evaluation yielded an exception. It is saved in
eval_exception */
BOOL eval_has_exception : 8;
@@ -907,8 +927,8 @@ struct JSObject {
union {
JSGCObjectHeader header;
struct {
- int _gc_ref_count; /* corresponds to header.ref_count */
- uint8_t _gc_mark; /* corresponds to header.mark/gc_obj_type */
+ int __gc_ref_count; /* corresponds to header.ref_count */
+ uint8_t __gc_mark; /* corresponds to header.mark/gc_obj_type */
uint8_t extensible : 1;
uint8_t free_mark : 1; /* only used when freeing objects with cycles */
@@ -946,7 +966,7 @@ struct JSObject {
struct JSProxyData *proxy_data; /* JS_CLASS_PROXY */
struct JSPromiseData *promise_data; /* JS_CLASS_PROMISE */
struct JSPromiseFunctionData *promise_function_data; /* JS_CLASS_PROMISE_RESOLVE_FUNCTION, JS_CLASS_PROMISE_REJECT_FUNCTION */
- struct JSAsyncFunctionData *async_function_data; /* JS_CLASS_ASYNC_FUNCTION_RESOLVE, JS_CLASS_ASYNC_FUNCTION_REJECT */
+ struct JSAsyncFunctionState *async_function_data; /* JS_CLASS_ASYNC_FUNCTION_RESOLVE, JS_CLASS_ASYNC_FUNCTION_REJECT */
struct JSAsyncFromSyncIteratorData *async_from_sync_iterator_data; /* JS_CLASS_ASYNC_FROM_SYNC_ITERATOR */
struct JSAsyncGeneratorData *async_generator_data; /* JS_CLASS_ASYNC_GENERATOR */
struct { /* JS_CLASS_BYTECODE_FUNCTION: 12/24 bytes */
@@ -989,8 +1009,9 @@ struct JSObject {
} u;
/* byte sizes: 40/48/72 */
};
+
enum {
- JS_ATOM_NULL_ = JS_ATOM_NULL,
+ __JS_ATOM_NULL = JS_ATOM_NULL,
#define DEF(name, str) JS_ATOM_ ## name,
#include "quickjs-atom.h"
#undef DEF
@@ -1036,8 +1057,8 @@ enum OPCodeEnum {
};
static int JS_InitAtoms(JSRuntime *rt);
-static JSAtom JS_NewAtomInitImpl(JSRuntime *rt, const char *str, int len,
- int atom_type);
+static JSAtom __JS_NewAtomInit(JSRuntime *rt, const char *str, int len,
+ int atom_type);
static void JS_FreeAtomStruct(JSRuntime *rt, JSAtomStruct *p);
static void free_function_bytecode(JSRuntime *rt, JSFunctionBytecode *b);
static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj,
@@ -1057,34 +1078,29 @@ static JSValue JS_CallFree(JSContext *ctx, JSValue func_obj, JSValueConst this_o
int argc, JSValueConst *argv);
static JSValue JS_InvokeFree(JSContext *ctx, JSValue this_val, JSAtom atom,
int argc, JSValueConst *argv);
-static warn_unused int JS_ToArrayLengthFree(JSContext *ctx, uint32_t *plen,
+static __exception int JS_ToArrayLengthFree(JSContext *ctx, uint32_t *plen,
JSValue val, BOOL is_array_ctor);
static JSValue JS_EvalObject(JSContext *ctx, JSValueConst this_obj,
JSValueConst val, int flags, int scope_idx);
-static maybe_unused void JS_DumpAtoms(JSRuntime *rt);
-static maybe_unused void JS_DumpString(JSRuntime *rt,
- const JSString *p);
-static maybe_unused void JS_DumpObjectHeader(JSRuntime *rt);
-static maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p);
-static maybe_unused void JS_DumpGCObject(JSRuntime *rt, JSGCObjectHeader *p);
-static maybe_unused void JS_DumpValueShort(JSRuntime *rt,
- JSValueConst val);
-static maybe_unused void JS_DumpValue(JSContext *ctx, JSValueConst val);
-static maybe_unused void JS_PrintValue(JSContext *ctx,
+static __maybe_unused void JS_DumpAtoms(JSRuntime *rt);
+static __maybe_unused void JS_DumpString(JSRuntime *rt, const JSString *p);
+static __maybe_unused void JS_DumpObjectHeader(JSRuntime *rt);
+static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p);
+static __maybe_unused void JS_DumpGCObject(JSRuntime *rt, JSGCObjectHeader *p);
+static __maybe_unused void JS_DumpValueShort(JSRuntime *rt, JSValueConst val);
+static __maybe_unused void JS_DumpValue(JSContext *ctx, JSValueConst val);
+static __maybe_unused void JS_PrintValue(JSContext *ctx,
const char *str,
JSValueConst val);
-static maybe_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);
-static void js_array_mark(JSRuntime *rt, JSValueConst val,
- JS_MarkFunc *mark_func);
+static void js_array_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func);
static void js_object_data_finalizer(JSRuntime *rt, JSValue val);
-static void js_object_data_mark(JSRuntime *rt, JSValueConst val,
- JS_MarkFunc *mark_func);
+static void js_object_data_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func);
static void js_c_function_finalizer(JSRuntime *rt, JSValue val);
-static void js_c_function_mark(JSRuntime *rt, JSValueConst val,
- JS_MarkFunc *mark_func);
+static void js_c_function_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func);
static void js_bytecode_function_finalizer(JSRuntime *rt, JSValue val);
static void js_bytecode_function_mark(JSRuntime *rt, JSValueConst val,
JS_MarkFunc *mark_func);
@@ -1128,6 +1144,12 @@ static void js_operator_set_finalizer(JSRuntime *rt, JSValue val);
static void js_operator_set_mark(JSRuntime *rt, JSValueConst val,
JS_MarkFunc *mark_func);
#endif
+
+#define HINT_STRING 0
+#define HINT_NUMBER 1
+#define HINT_NONE 2
+#define HINT_FORCE_ORDINARY (1 << 4) // don't try Symbol.toPrimitive
+static JSValue JS_ToPrimitiveFree(JSContext *ctx, JSValue val, int hint);
static JSValue JS_ToStringFree(JSContext *ctx, JSValue val);
static int JS_ToBoolFree(JSContext *ctx, JSValue val);
static int JS_ToInt32Free(JSContext *ctx, int32_t *pres, JSValue val);
@@ -1149,13 +1171,25 @@ typedef enum JSStrictEqModeEnum {
static BOOL js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2,
JSStrictEqModeEnum eq_mode);
-static BOOL js_strict_eq(JSContext *ctx, JSValue op1, JSValue op2);
+static BOOL js_strict_eq(JSContext *ctx, JSValueConst op1, JSValueConst op2);
static BOOL js_same_value(JSContext *ctx, JSValueConst op1, JSValueConst op2);
static BOOL js_same_value_zero(JSContext *ctx, JSValueConst op1, JSValueConst op2);
static JSValue JS_ToObject(JSContext *ctx, JSValueConst val);
static JSValue JS_ToObjectFree(JSContext *ctx, JSValue val);
static JSProperty *add_property(JSContext *ctx,
JSObject *p, JSAtom prop, int prop_flags);
+static JSValue JS_NewBigInt(JSContext *ctx);
+static inline bf_t *JS_GetBigInt(JSValueConst val)
+{
+ JSBigFloat *p = JS_VALUE_GET_PTR(val);
+ return &p->num;
+}
+static JSValue JS_CompactBigInt1(JSContext *ctx, JSValue val,
+ BOOL convert_to_safe_integer);
+static JSValue JS_CompactBigInt(JSContext *ctx, JSValue val);
+static int JS_ToBigInt64Free(JSContext *ctx, int64_t *pres, JSValue val);
+static bf_t *JS_ToBigInt(JSContext *ctx, bf_t *buf, JSValueConst val);
+static void JS_FreeBigInt(JSContext *ctx, bf_t *a, bf_t *buf);
#ifdef CONFIG_BIGNUM
static void js_float_env_finalizer(JSRuntime *rt, JSValue val);
static JSValue JS_NewBigFloat(JSContext *ctx);
@@ -1170,18 +1204,6 @@ static inline bfdec_t *JS_GetBigDecimal(JSValueConst val)
JSBigDecimal *p = JS_VALUE_GET_PTR(val);
return &p->num;
}
-static JSValue JS_NewBigInt(JSContext *ctx);
-static inline bf_t *JS_GetBigInt(JSValueConst val)
-{
- JSBigFloat *p = JS_VALUE_GET_PTR(val);
- return &p->num;
-}
-static JSValue JS_CompactBigInt1(JSContext *ctx, JSValue val,
- BOOL convert_to_safe_integer);
-static JSValue JS_CompactBigInt(JSContext *ctx, JSValue val);
-static int JS_ToBigInt64Free(JSContext *ctx, int64_t *pres, JSValue val);
-static bf_t *JS_ToBigInt(JSContext *ctx, bf_t *buf, JSValueConst val);
-static void JS_FreeBigInt(JSContext *ctx, bf_t *a, bf_t *buf);
static bf_t *JS_ToBigFloat(JSContext *ctx, bf_t *buf, JSValueConst val);
static JSValue JS_ToBigDecimalFree(JSContext *ctx, JSValue val,
BOOL allow_null_or_undefined);
@@ -1191,9 +1213,10 @@ static JSValue JS_ThrowTypeErrorRevokedProxy(JSContext *ctx);
static JSValue js_proxy_getPrototypeOf(JSContext *ctx, JSValueConst obj);
static int js_proxy_setPrototypeOf(JSContext *ctx, JSValueConst obj,
JSValueConst proto_val, BOOL throw_flag);
+
+static int js_resolve_proxy(JSContext *ctx, JSValueConst *pval, int throw_exception);
static int js_proxy_isExtensible(JSContext *ctx, JSValueConst obj);
static int js_proxy_preventExtensions(JSContext *ctx, JSValueConst obj);
-static int js_proxy_isArray(JSContext *ctx, JSValueConst obj);
static int JS_CreateProperty(JSContext *ctx, JSObject *p,
JSAtom prop, JSValueConst val,
JSValueConst getter, JSValueConst setter,
@@ -1211,11 +1234,17 @@ static JSValue js_typed_array_constructor(JSContext *ctx,
JSValueConst this_val,
int argc, JSValueConst *argv,
int classid);
+static JSValue js_typed_array_constructor_ta(JSContext *ctx,
+ JSValueConst new_target,
+ JSValueConst src_obj,
+ int classid);
static BOOL typed_array_is_detached(JSContext *ctx, JSObject *p);
static uint32_t typed_array_get_length(JSContext *ctx, JSObject *p);
static JSValue JS_ThrowTypeErrorDetachedArrayBuffer(JSContext *ctx);
static JSVarRef *get_var_ref(JSContext *ctx, JSStackFrame *sf, int var_idx,
BOOL is_arg);
+static void __async_func_free(JSRuntime *rt, JSAsyncFunctionState *s);
+static void async_func_free(JSRuntime *rt, JSAsyncFunctionState *s);
static JSValue js_generator_function_call(JSContext *ctx, JSValueConst func_obj,
JSValueConst this_obj,
int argc, JSValueConst *argv,
@@ -1235,12 +1264,14 @@ static void free_var_ref(JSRuntime *rt, JSVarRef *var_ref);
static JSValue js_new_promise_capability(JSContext *ctx,
JSValue *resolving_funcs,
JSValueConst ctor);
-static warn_unused int perform_promise_then(JSContext *ctx,
+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 JSValue js_promise_then(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv);
static int js_string_compare(JSContext *ctx,
const JSString *p1, const JSString *p2);
static JSValue JS_ToNumber(JSContext *ctx, JSValueConst val);
@@ -1252,17 +1283,15 @@ static JSValue JS_ToNumberFree(JSContext *ctx, JSValue val);
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);
static void JS_AddIntrinsicBasicObjects(JSContext *ctx);
static void js_free_shape(JSRuntime *rt, JSShape *sh);
static void js_free_shape_null(JSRuntime *rt, JSShape *sh);
static int js_shape_prepare_update(JSContext *ctx, JSObject *p,
JSShapeProperty **pprs);
static int init_shape_hash(JSRuntime *rt);
-static warn_unused int js_get_length32(JSContext *ctx, uint32_t *pres,
+static __exception int js_get_length32(JSContext *ctx, uint32_t *pres,
JSValueConst obj);
-static warn_unused int js_get_length64(JSContext *ctx, int64_t *pres,
+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,
@@ -1281,13 +1310,13 @@ static JSAtom js_symbol_to_atom(JSContext *ctx, JSValue val);
static void add_gc_object(JSRuntime *rt, JSGCObjectHeader *h,
JSGCObjectTypeEnum type);
static void remove_gc_object(JSGCObjectHeader *h);
-static void js_async_function_free0(JSRuntime *rt, JSAsyncFunctionData *s);
static JSValue js_instantiate_prototype(JSContext *ctx, JSObject *p, JSAtom atom, void *opaque);
static JSValue js_module_ns_autoinit(JSContext *ctx, JSObject *p, JSAtom atom,
void *opaque);
static JSValue JS_InstantiateFunctionListItem2(JSContext *ctx, JSObject *p,
JSAtom atom, void *opaque);
-void JS_SetUncatchableError(JSContext *ctx, JSValueConst val, BOOL flag);
+static JSValue js_object_groupBy(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv, int is_map);
static const JSClassExoticMethods js_arguments_exotic_methods;
static const JSClassExoticMethods js_string_exotic_methods;
@@ -1349,14 +1378,12 @@ void *js_mallocz_rt(JSRuntime *rt, size_t size)
return memset(ptr, 0, size);
}
-#ifdef CONFIG_BIGNUM
/* called by libbf */
static void *js_bf_realloc(void *opaque, void *ptr, size_t size)
{
JSRuntime *rt = opaque;
return js_realloc_rt(rt, ptr, size);
}
-#endif /* CONFIG_BIGNUM */
/* Throw out of memory in case of error */
void *js_malloc(JSContext *ctx, size_t size)
@@ -1473,6 +1500,10 @@ static inline int is_digit(int c) {
return c >= '0' && c <= '9';
}
+static inline int string_get(const JSString *p, int idx) {
+ return p->is_wide_char ? p->u.str16[idx] : p->u.str8[idx];
+}
+
typedef struct JSClassShortDef {
JSAtom class_name;
JSClassFinalizer *finalizer;
@@ -1507,15 +1538,13 @@ static JSClassShortDef const js_std_class_def[] = {
{ JS_ATOM_Uint16Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_UINT16_ARRAY */
{ JS_ATOM_Int32Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_INT32_ARRAY */
{ JS_ATOM_Uint32Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_UINT32_ARRAY */
-#ifdef CONFIG_BIGNUM
{ JS_ATOM_BigInt64Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_BIG_INT64_ARRAY */
{ JS_ATOM_BigUint64Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_BIG_UINT64_ARRAY */
-#endif
{ JS_ATOM_Float32Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_FLOAT32_ARRAY */
{ JS_ATOM_Float64Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_FLOAT64_ARRAY */
{ JS_ATOM_DataView, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_DATAVIEW */
-#ifdef CONFIG_BIGNUM
{ JS_ATOM_BigInt, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_BIG_INT */
+#ifdef CONFIG_BIGNUM
{ JS_ATOM_BigFloat, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_BIG_FLOAT */
{ JS_ATOM_BigFloatEnv, js_float_env_finalizer, NULL }, /* JS_CLASS_FLOAT_ENV */
{ JS_ATOM_BigDecimal, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_BIG_DECIMAL */
@@ -1550,7 +1579,6 @@ static int init_class_range(JSRuntime *rt, JSClassShortDef const *tab,
return 0;
}
-#ifdef CONFIG_BIGNUM
static JSValue JS_ThrowUnsupportedOperation(JSContext *ctx)
{
return JS_ThrowTypeError(ctx, "unsupported operation");
@@ -1606,8 +1634,6 @@ static void set_dummy_numeric_ops(JSNumericOperations *ops)
ops->mul_pow10 = invalid_mul_pow10;
}
-#endif /* CONFIG_BIGNUM */
-
#if !defined(CONFIG_STACK_CHECK)
/* no stack limitation */
static inline uintptr_t js_get_stack_pointer(void)
@@ -1672,9 +1698,9 @@ JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque)
rt->malloc_state = ms;
rt->malloc_gc_threshold = 256 * 1024;
-#ifdef CONFIG_BIGNUM
bf_context_init(&rt->bf_ctx, js_bf_realloc, rt);
set_dummy_numeric_ops(&rt->bigint_ops);
+#ifdef CONFIG_BIGNUM
set_dummy_numeric_ops(&rt->bigfloat_ops);
set_dummy_numeric_ops(&rt->bigdecimal_ops);
#endif
@@ -1729,19 +1755,19 @@ void JS_SetRuntimeOpaque(JSRuntime *rt, void *opaque)
}
/* default memory allocation functions with memory limitation */
-static inline size_t js_def_malloc_usable_size(void *ptr)
+static size_t js_def_malloc_usable_size(const void *ptr)
{
#if defined(__APPLE__)
return malloc_size(ptr);
#elif defined(_WIN32)
- return _msize(ptr);
+ return _msize((void *)ptr);
#elif defined(EMSCRIPTEN)
return 0;
#elif defined(__linux__)
- return malloc_usable_size(ptr);
+ return malloc_usable_size((void *)ptr);
#else
/* change this to `return 0;` if compilation fails */
- return malloc_usable_size(ptr);
+ return malloc_usable_size((void *)ptr);
#endif
}
@@ -1805,18 +1831,7 @@ static const JSMallocFunctions def_malloc_funcs = {
js_def_malloc,
js_def_free,
js_def_realloc,
-#if defined(__APPLE__)
- malloc_size,
-#elif defined(_WIN32)
- (size_t (*)(const void *))_msize,
-#elif defined(EMSCRIPTEN)
- NULL,
-#elif defined(__linux__)
- (size_t (*)(const void *))malloc_usable_size,
-#else
- /* change this to `NULL,` if compilation fails */
- malloc_usable_size,
-#endif
+ js_def_malloc_usable_size,
};
JSRuntime *JS_NewRuntime(void)
@@ -2047,9 +2062,7 @@ void JS_FreeRuntime(JSRuntime *rt)
}
js_free_rt(rt, rt->class_array);
-#ifdef CONFIG_BIGNUM
bf_context_end(&rt->bf_ctx);
-#endif
#ifdef DUMP_LEAKS
/* only the atoms defined in JS_InitAtoms() should be left */
@@ -2187,8 +2200,8 @@ JSContext *JS_NewContextRaw(JSRuntime *rt)
}
ctx->rt = rt;
list_add_tail(&ctx->link, &rt->context_list);
-#ifdef CONFIG_BIGNUM
ctx->bf_ctx = &rt->bf_ctx;
+#ifdef CONFIG_BIGNUM
ctx->fp_env.prec = 113;
ctx->fp_env.flags = bf_set_exp_bits(15) | BF_RNDN | BF_FLAG_SUBNORMAL;
#endif
@@ -2221,9 +2234,7 @@ JSContext *JS_NewContext(JSRuntime *rt)
JS_AddIntrinsicMapSet(ctx);
JS_AddIntrinsicTypedArrays(ctx);
JS_AddIntrinsicPromise(ctx);
-#ifdef CONFIG_BIGNUM
JS_AddIntrinsicBigInt(ctx);
-#endif
return ctx;
}
@@ -2264,7 +2275,6 @@ JSValue JS_GetClassProto(JSContext *ctx, JSClassID class_id)
typedef enum JSFreeModuleEnum {
JS_FREE_MODULE_ALL,
JS_FREE_MODULE_NOT_RESOLVED,
- JS_FREE_MODULE_NOT_EVALUATED,
} JSFreeModuleEnum;
/* XXX: would be more efficient with separate module lists */
@@ -2274,8 +2284,7 @@ static void js_free_modules(JSContext *ctx, JSFreeModuleEnum flag)
list_for_each_safe(el, el1, &ctx->loaded_modules) {
JSModuleDef *m = list_entry(el, JSModuleDef, link);
if (flag == JS_FREE_MODULE_ALL ||
- (flag == JS_FREE_MODULE_NOT_RESOLVED && !m->resolved) ||
- (flag == JS_FREE_MODULE_NOT_EVALUATED && !m->evaluated)) {
+ (flag == JS_FREE_MODULE_NOT_RESOLVED && !m->resolved)) {
js_free_module_def(ctx, m);
}
}
@@ -2431,6 +2440,11 @@ static inline BOOL is_math_mode(JSContext *ctx)
JSStackFrame *sf = ctx->rt->current_stack_frame;
return (sf && (sf->js_mode & JS_MODE_MATH));
}
+#else
+static inline BOOL is_math_mode(JSContext *ctx)
+{
+ return FALSE;
+}
#endif
/* JSAtom support */
@@ -2442,7 +2456,7 @@ static inline BOOL is_math_mode(JSContext *ctx)
/* return the max count from the hash size */
#define JS_ATOM_COUNT_RESIZE(n) ((n) * 2)
-static inline BOOL JS_AtomIsConst(JSAtom v)
+static inline BOOL __JS_AtomIsConst(JSAtom v)
{
#if defined(DUMP_LEAKS) && DUMP_LEAKS > 1
return (int32_t)v <= 0;
@@ -2451,17 +2465,17 @@ static inline BOOL JS_AtomIsConst(JSAtom v)
#endif
}
-static inline BOOL JS_AtomIsTaggedInt(JSAtom v)
+static inline BOOL __JS_AtomIsTaggedInt(JSAtom v)
{
return (v & JS_ATOM_TAG_INT) != 0;
}
-static inline JSAtom JS_AtomFromUInt32(uint32_t v)
+static inline JSAtom __JS_AtomFromUInt32(uint32_t v)
{
return v | JS_ATOM_TAG_INT;
}
-static inline uint32_t JS_AtomToUInt32(JSAtom atom)
+static inline uint32_t __JS_AtomToUInt32(JSAtom atom)
{
return atom & ~JS_ATOM_TAG_INT;
}
@@ -2481,10 +2495,7 @@ static inline BOOL is_num_string(uint32_t *pval, const JSString *p)
len = p->len;
if (len == 0 || len > 10)
return FALSE;
- if (p->is_wide_char)
- c = p->u.str16[0];
- else
- c = p->u.str8[0];
+ c = string_get(p, 0);
if (is_num(c)) {
if (c == '0') {
if (len != 1)
@@ -2493,10 +2504,7 @@ static inline BOOL is_num_string(uint32_t *pval, const JSString *p)
} 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];
+ c = string_get(p, i);
if (!is_num(c))
return FALSE;
n64 = (uint64_t)n * 10 + (c - '0');
@@ -2541,10 +2549,24 @@ static uint32_t hash_string(const JSString *str, uint32_t h)
return h;
}
-static maybe_unused void JS_DumpString(JSRuntime *rt,
- const JSString *p)
+static __maybe_unused void JS_DumpChar(JSRuntime *rt, int c, int sep)
+{
+ if (c == sep || c == '\\') {
+ putchar('\\');
+ putchar(c);
+ } else if (c >= ' ' && c <= 126) {
+ putchar(c);
+ } else if (c == '\n') {
+ putchar('\\');
+ putchar('n');
+ } else {
+ printf("\\u%04x", c);
+ }
+}
+
+static __maybe_unused void JS_DumpString(JSRuntime *rt, const JSString *p)
{
- int i, c, sep;
+ int i, sep;
if (p == NULL) {
printf("<null>");
@@ -2554,26 +2576,12 @@ static maybe_unused void JS_DumpString(JSRuntime *rt,
sep = (p->header.ref_count == 1) ? '\"' : '\'';
putchar(sep);
for(i = 0; i < p->len; i++) {
- if (p->is_wide_char)
- c = p->u.str16[i];
- else
- c = p->u.str8[i];
- if (c == sep || c == '\\') {
- putchar('\\');
- putchar(c);
- } else if (c >= ' ' && c <= 126) {
- putchar(c);
- } else if (c == '\n') {
- putchar('\\');
- putchar('n');
- } else {
- printf("\\u%04x", c);
- }
+ JS_DumpChar(rt, string_get(p, i), sep);
}
putchar(sep);
}
-static maybe_unused void JS_DumpAtoms(JSRuntime *rt)
+static __maybe_unused void JS_DumpAtoms(JSRuntime *rt)
{
JSAtomStruct *p;
int h, i;
@@ -2660,7 +2668,7 @@ static int JS_InitAtoms(JSRuntime *rt)
else
atom_type = JS_ATOM_TYPE_STRING;
len = strlen(p);
- if (JS_NewAtomInitImpl(rt, p, len, atom_type) == JS_ATOM_NULL)
+ if (__JS_NewAtomInit(rt, p, len, atom_type) == JS_ATOM_NULL)
return -1;
p = p + len + 1;
}
@@ -2671,7 +2679,7 @@ static JSAtom JS_DupAtomRT(JSRuntime *rt, JSAtom v)
{
JSAtomStruct *p;
- if (!JS_AtomIsConst(v)) {
+ if (!__JS_AtomIsConst(v)) {
p = rt->atom_array[v];
p->header.ref_count++;
}
@@ -2683,7 +2691,7 @@ JSAtom JS_DupAtom(JSContext *ctx, JSAtom v)
JSRuntime *rt;
JSAtomStruct *p;
- if (!JS_AtomIsConst(v)) {
+ if (!__JS_AtomIsConst(v)) {
rt = ctx->rt;
p = rt->atom_array[v];
p->header.ref_count++;
@@ -2697,7 +2705,7 @@ static JSAtomKindEnum JS_AtomGetKind(JSContext *ctx, JSAtom v)
JSAtomStruct *p;
rt = ctx->rt;
- if (JS_AtomIsTaggedInt(v))
+ if (__JS_AtomIsTaggedInt(v))
return JS_ATOM_KIND_STRING;
p = rt->atom_array[v];
switch(p->atom_type) {
@@ -2743,7 +2751,7 @@ static JSAtom js_get_atom_index(JSRuntime *rt, JSAtomStruct *p)
/* string case (internal). Return JS_ATOM_NULL if error. 'str' is
freed. */
-static JSAtom JS_NewAtomImpl(JSRuntime *rt, JSString *str, int atom_type)
+static JSAtom __JS_NewAtom(JSRuntime *rt, JSString *str, int atom_type)
{
uint32_t h, h1, i;
JSAtomStruct *p;
@@ -2758,7 +2766,7 @@ static JSAtom JS_NewAtomImpl(JSRuntime *rt, JSString *str, int atom_type)
/* str is the atom, return its index */
i = js_get_atom_index(rt, str);
/* reduce string refcount and increase atom's unless constant */
- if (JS_AtomIsConst(i))
+ if (__JS_AtomIsConst(i))
str->header.ref_count--;
return i;
}
@@ -2774,7 +2782,7 @@ static JSAtom JS_NewAtomImpl(JSRuntime *rt, JSString *str, int atom_type)
p->atom_type == atom_type &&
p->len == len &&
js_string_memcmp(p, str, len) == 0) {
- if (!JS_AtomIsConst(i))
+ if (!__JS_AtomIsConst(i))
p->header.ref_count++;
goto done;
}
@@ -2899,8 +2907,8 @@ static JSAtom JS_NewAtomImpl(JSRuntime *rt, JSString *str, int atom_type)
}
/* only works with zero terminated 8 bit strings */
-static JSAtom JS_NewAtomInitImpl(JSRuntime *rt, const char *str, int len,
- int atom_type)
+static JSAtom __JS_NewAtomInit(JSRuntime *rt, const char *str, int len,
+ int atom_type)
{
JSString *p;
p = js_alloc_string_rt(rt, len, 0);
@@ -2908,10 +2916,11 @@ static JSAtom JS_NewAtomInitImpl(JSRuntime *rt, const char *str, int len,
return JS_ATOM_NULL;
memcpy(p->u.str8, str, len);
p->u.str8[len] = '\0';
- return JS_NewAtomImpl(rt, p, atom_type);
+ return __JS_NewAtom(rt, p, atom_type);
}
-static JSAtom JS_FindAtom(JSRuntime *rt, const char *str, size_t len,
+/* Warning: str must be ASCII only */
+static JSAtom __JS_FindAtom(JSRuntime *rt, const char *str, size_t len,
int atom_type)
{
uint32_t h, h1, i;
@@ -2928,7 +2937,7 @@ static JSAtom JS_FindAtom(JSRuntime *rt, const char *str, size_t len,
p->len == len &&
p->is_wide_char == 0 &&
memcmp(p->u.str8, str, len) == 0) {
- if (!JS_AtomIsConst(i))
+ if (!__JS_AtomIsConst(i))
p->header.ref_count++;
return i;
}
@@ -2980,7 +2989,7 @@ static void JS_FreeAtomStruct(JSRuntime *rt, JSAtomStruct *p)
assert(rt->atom_count >= 0);
}
-static void JS_FreeAtomImpl(JSRuntime *rt, uint32_t i)
+static void __JS_FreeAtom(JSRuntime *rt, uint32_t i)
{
JSAtomStruct *p;
@@ -2998,19 +3007,21 @@ static JSAtom JS_NewAtomStr(JSContext *ctx, JSString *p)
if (is_num_string(&n, p)) {
if (n <= JS_ATOM_MAX_INT) {
js_free_string(rt, p);
- return JS_AtomFromUInt32(n);
+ return __JS_AtomFromUInt32(n);
}
}
/* XXX: should generate an exception */
- return JS_NewAtomImpl(rt, p, JS_ATOM_TYPE_STRING);
+ return __JS_NewAtom(rt, p, JS_ATOM_TYPE_STRING);
}
+/* str is UTF-8 encoded */
JSAtom JS_NewAtomLen(JSContext *ctx, const char *str, size_t len)
{
JSValue val;
if (len == 0 || !is_digit(*str)) {
- JSAtom atom = JS_FindAtom(ctx->rt, str, len, JS_ATOM_TYPE_STRING);
+ // XXX: this will not work if UTF-8 encoded str contains non ASCII bytes
+ JSAtom atom = __JS_FindAtom(ctx->rt, str, len, JS_ATOM_TYPE_STRING);
if (atom)
return atom;
}
@@ -3028,7 +3039,7 @@ JSAtom JS_NewAtom(JSContext *ctx, const char *str)
JSAtom JS_NewAtomUInt32(JSContext *ctx, uint32_t n)
{
if (n <= JS_ATOM_MAX_INT) {
- return JS_AtomFromUInt32(n);
+ return __JS_AtomFromUInt32(n);
} else {
char buf[11];
JSValue val;
@@ -3036,7 +3047,7 @@ JSAtom JS_NewAtomUInt32(JSContext *ctx, uint32_t n)
val = JS_NewString(ctx, buf);
if (JS_IsException(val))
return JS_ATOM_NULL;
- return JS_NewAtomImpl(ctx->rt, JS_VALUE_GET_STRING(val),
+ return __JS_NewAtom(ctx->rt, JS_VALUE_GET_STRING(val),
JS_ATOM_TYPE_STRING);
}
}
@@ -3044,7 +3055,7 @@ JSAtom JS_NewAtomUInt32(JSContext *ctx, uint32_t n)
static JSAtom JS_NewAtomInt64(JSContext *ctx, int64_t n)
{
if ((uint64_t)n <= JS_ATOM_MAX_INT) {
- return JS_AtomFromUInt32((uint32_t)n);
+ return __JS_AtomFromUInt32((uint32_t)n);
} else {
char buf[24];
JSValue val;
@@ -3052,7 +3063,7 @@ static JSAtom JS_NewAtomInt64(JSContext *ctx, int64_t n)
val = JS_NewString(ctx, buf);
if (JS_IsException(val))
return JS_ATOM_NULL;
- return JS_NewAtomImpl(ctx->rt, JS_VALUE_GET_STRING(val),
+ return __JS_NewAtom(ctx->rt, JS_VALUE_GET_STRING(val),
JS_ATOM_TYPE_STRING);
}
}
@@ -3062,7 +3073,7 @@ static JSValue JS_NewSymbol(JSContext *ctx, JSString *p, int atom_type)
{
JSRuntime *rt = ctx->rt;
JSAtom atom;
- atom = JS_NewAtomImpl(rt, p, atom_type);
+ atom = __JS_NewAtom(rt, p, atom_type);
if (atom == JS_ATOM_NULL)
return JS_ThrowOutOfMemory(ctx);
return JS_MKPTR(JS_TAG_SYMBOL, rt->atom_array[atom]);
@@ -3075,7 +3086,7 @@ static JSValue JS_NewSymbolFromAtom(JSContext *ctx, JSAtom descr,
JSRuntime *rt = ctx->rt;
JSString *p;
- assert(!JS_AtomIsTaggedInt(descr));
+ assert(!__JS_AtomIsTaggedInt(descr));
assert(descr < rt->atom_size);
p = rt->atom_array[descr];
JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, p));
@@ -3088,8 +3099,8 @@ static JSValue JS_NewSymbolFromAtom(JSContext *ctx, JSAtom descr,
static const char *JS_AtomGetStrRT(JSRuntime *rt, char *buf, int buf_size,
JSAtom atom)
{
- if (JS_AtomIsTaggedInt(atom)) {
- snprintf(buf, buf_size, "%u", JS_AtomToUInt32(atom));
+ if (__JS_AtomIsTaggedInt(atom)) {
+ snprintf(buf, buf_size, "%u", __JS_AtomToUInt32(atom));
} else {
JSAtomStruct *p;
assert(atom < rt->atom_size);
@@ -3115,10 +3126,7 @@ static const char *JS_AtomGetStrRT(JSRuntime *rt, char *buf, int buf_size,
return (const char *)str->u.str8;
}
for(i = 0; i < str->len; i++) {
- if (str->is_wide_char)
- c = str->u.str16[i];
- else
- c = str->u.str8[i];
+ c = string_get(str, i);
if ((q - buf) >= buf_size - UTF8_CHAR_LEN_MAX)
break;
if (c < 128) {
@@ -3139,12 +3147,12 @@ static const char *JS_AtomGetStr(JSContext *ctx, char *buf, int buf_size, JSAtom
return JS_AtomGetStrRT(ctx->rt, buf, buf_size, atom);
}
-static JSValue JS_AtomToValueImpl(JSContext *ctx, JSAtom atom, BOOL force_string)
+static JSValue __JS_AtomToValue(JSContext *ctx, JSAtom atom, BOOL force_string)
{
char buf[ATOM_GET_STR_BUF_SIZE];
- if (JS_AtomIsTaggedInt(atom)) {
- snprintf(buf, sizeof(buf), "%u", JS_AtomToUInt32(atom));
+ if (__JS_AtomIsTaggedInt(atom)) {
+ snprintf(buf, sizeof(buf), "%u", __JS_AtomToUInt32(atom));
return JS_NewString(ctx, buf);
} else {
JSRuntime *rt = ctx->rt;
@@ -3168,20 +3176,20 @@ static JSValue JS_AtomToValueImpl(JSContext *ctx, JSAtom atom, BOOL force_string
JSValue JS_AtomToValue(JSContext *ctx, JSAtom atom)
{
- return JS_AtomToValueImpl(ctx, atom, FALSE);
+ return __JS_AtomToValue(ctx, atom, FALSE);
}
JSValue JS_AtomToString(JSContext *ctx, JSAtom atom)
{
- return JS_AtomToValueImpl(ctx, atom, TRUE);
+ return __JS_AtomToValue(ctx, atom, TRUE);
}
/* 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);
+ if (__JS_AtomIsTaggedInt(atom)) {
+ *pval = __JS_AtomToUInt32(atom);
return TRUE;
} else {
JSRuntime *rt = ctx->rt;
@@ -3212,8 +3220,8 @@ static JSValue JS_AtomIsNumericIndex1(JSContext *ctx, JSAtom atom)
int c, len, ret;
JSValue num, str;
- if (JS_AtomIsTaggedInt(atom))
- return JS_NewInt32(ctx, JS_AtomToUInt32(atom));
+ if (__JS_AtomIsTaggedInt(atom))
+ return JS_NewInt32(ctx, __JS_AtomToUInt32(atom));
assert(atom < rt->atom_size);
p1 = rt->atom_array[atom];
if (p1->atom_type != JS_ATOM_TYPE_STRING)
@@ -3255,7 +3263,7 @@ static JSValue JS_AtomIsNumericIndex1(JSContext *ctx, JSAtom atom)
/* -0 case is specific */
if (c == '0' && len == 2) {
minus_zero:
- return JS_NewFloat64Impl(ctx, -0.0);
+ return __JS_NewFloat64(ctx, -0.0);
}
}
if (!is_num(c)) {
@@ -3300,14 +3308,14 @@ static int JS_AtomIsNumericIndex(JSContext *ctx, JSAtom atom)
void JS_FreeAtom(JSContext *ctx, JSAtom v)
{
- if (!JS_AtomIsConst(v))
- JS_FreeAtomImpl(ctx->rt, v);
+ if (!__JS_AtomIsConst(v))
+ __JS_FreeAtom(ctx->rt, v);
}
void JS_FreeAtomRT(JSRuntime *rt, JSAtom v)
{
- if (!JS_AtomIsConst(v))
- JS_FreeAtomImpl(rt, v);
+ if (!__JS_AtomIsConst(v))
+ __JS_FreeAtom(rt, v);
}
/* return TRUE if 'v' is a symbol with a string description */
@@ -3317,7 +3325,7 @@ static BOOL JS_AtomSymbolHasDescription(JSContext *ctx, JSAtom v)
JSAtomStruct *p;
rt = ctx->rt;
- if (JS_AtomIsTaggedInt(v))
+ if (__JS_AtomIsTaggedInt(v))
return FALSE;
p = rt->atom_array[v];
return (((p->atom_type == JS_ATOM_TYPE_SYMBOL &&
@@ -3326,7 +3334,7 @@ static BOOL JS_AtomSymbolHasDescription(JSContext *ctx, JSAtom v)
!(p->len == 0 && p->is_wide_char != 0));
}
-static maybe_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;
@@ -3425,19 +3433,37 @@ static inline BOOL JS_IsEmptyString(JSValueConst v)
/* JSClass support */
+#ifdef CONFIG_ATOMICS
+static pthread_mutex_t js_class_id_mutex = PTHREAD_MUTEX_INITIALIZER;
+#endif
+
/* a new class ID is allocated if *pclass_id != 0 */
JSClassID JS_NewClassID(JSClassID *pclass_id)
{
JSClassID class_id;
- /* XXX: make it thread safe */
+#ifdef CONFIG_ATOMICS
+ pthread_mutex_lock(&js_class_id_mutex);
+#endif
class_id = *pclass_id;
if (class_id == 0) {
class_id = js_class_id_alloc++;
*pclass_id = class_id;
}
+#ifdef CONFIG_ATOMICS
+ pthread_mutex_unlock(&js_class_id_mutex);
+#endif
return class_id;
}
+JSClassID JS_GetClassID(JSValue v)
+{
+ JSObject *p;
+ if (JS_VALUE_GET_TAG(v) != JS_TAG_OBJECT)
+ return JS_INVALID_CLASS_ID;
+ p = JS_VALUE_GET_OBJ(v);
+ return p->class_id;
+}
+
BOOL JS_IsRegisteredClass(JSRuntime *rt, JSClassID class_id)
{
return (class_id < rt->class_count &&
@@ -3501,9 +3527,9 @@ int JS_NewClass(JSRuntime *rt, JSClassID class_id, const JSClassDef *class_def)
JSAtom name;
len = strlen(class_def->class_name);
- name = JS_FindAtom(rt, class_def->class_name, len, JS_ATOM_TYPE_STRING);
+ name = __JS_FindAtom(rt, class_def->class_name, len, JS_ATOM_TYPE_STRING);
if (name == JS_ATOM_NULL) {
- name = JS_NewAtomInitImpl(rt, class_def->class_name, len, JS_ATOM_TYPE_STRING);
+ name = __JS_NewAtomInit(rt, class_def->class_name, len, JS_ATOM_TYPE_STRING);
if (name == JS_ATOM_NULL)
return -1;
}
@@ -3732,28 +3758,23 @@ static int string_buffer_putc(StringBuffer *s, uint32_t c)
{
if (unlikely(c >= 0x10000)) {
/* surrogate pair */
- c -= 0x10000;
- if (string_buffer_putc16(s, (c >> 10) + 0xd800))
+ if (string_buffer_putc16(s, get_hi_surrogate(c)))
return -1;
- c = (c & 0x3ff) + 0xdc00;
+ c = get_lo_surrogate(c);
}
return string_buffer_putc16(s, c);
}
-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) {
+ if (is_hi_surrogate(c) && idx < p->len) {
c1 = p->u.str16[idx];
- if (c1 >= 0xdc00 && c1 < 0xe000) {
- c = (((c & 0x3ff) << 10) | (c1 & 0x3ff)) + 0x10000;
+ if (is_lo_surrogate(c1)) {
+ c = from_surrogate(c, c1);
idx++;
}
}
@@ -3951,9 +3972,8 @@ JSValue JS_NewStringLen(JSContext *ctx, const char *buf, size_t buf_len)
} else if (c <= 0x10FFFF) {
p = p_next;
/* surrogate pair */
- c -= 0x10000;
- string_buffer_putc16(b, (c >> 10) + 0xd800);
- c = (c & 0x3ff) + 0xdc00;
+ string_buffer_putc16(b, get_hi_surrogate(c));
+ c = get_lo_surrogate(c);
} else {
/* invalid char */
c = 0xfffd;
@@ -4091,13 +4111,12 @@ const char *JS_ToCStringLen2(JSContext *ctx, size_t *plen, JSValueConst val1, BO
if (c < 0x80) {
*q++ = c;
} else {
- if (c >= 0xd800 && c < 0xdc00) {
+ if (is_hi_surrogate(c)) {
if (pos < len && !cesu8) {
c1 = src[pos];
- if (c1 >= 0xdc00 && c1 < 0xe000) {
+ if (is_lo_surrogate(c1)) {
pos++;
- /* surrogate pair */
- c = (((c & 0x3ff) << 10) | (c1 & 0x3ff)) + 0x10000;
+ c = from_surrogate(c, c1);
} else {
/* Keep unmatched surrogate code points */
/* c = 0xfffd; */ /* error */
@@ -4130,7 +4149,7 @@ void JS_FreeCString(JSContext *ctx, const char *ptr)
if (!ptr)
return;
/* purposely removing constness */
- p = (JSString *)(void *)(ptr - offsetof(JSString, u));
+ p = container_of(ptr, JSString, u);
JS_FreeValue(ctx, JS_MKPTR(JS_TAG_STRING, p));
}
@@ -4230,7 +4249,43 @@ static JSValue JS_ConcatString1(JSContext *ctx,
return JS_MKPTR(JS_TAG_STRING, p);
}
-/* op1 and op2 are converted to strings. For convience, op1 or op2 =
+static BOOL JS_ConcatStringInPlace(JSContext *ctx, JSString *p1, JSValueConst op2) {
+ if (JS_VALUE_GET_TAG(op2) == JS_TAG_STRING) {
+ JSString *p2 = JS_VALUE_GET_STRING(op2);
+ size_t size1;
+
+ if (p2->len == 0)
+ return TRUE;
+ if (p1->header.ref_count != 1)
+ return FALSE;
+ size1 = js_malloc_usable_size(ctx, p1);
+ if (p1->is_wide_char) {
+ if (size1 >= sizeof(*p1) + ((p1->len + p2->len) << 1)) {
+ if (p2->is_wide_char) {
+ memcpy(p1->u.str16 + p1->len, p2->u.str16, p2->len << 1);
+ p1->len += p2->len;
+ return TRUE;
+ } else {
+ size_t i;
+ for (i = 0; i < p2->len; i++) {
+ p1->u.str16[p1->len++] = p2->u.str8[i];
+ }
+ return TRUE;
+ }
+ }
+ } else if (!p2->is_wide_char) {
+ if (size1 >= sizeof(*p1) + p1->len + p2->len + 1) {
+ memcpy(p1->u.str8 + p1->len, p2->u.str8, p2->len);
+ p1->len += p2->len;
+ p1->u.str8[p1->len] = '\0';
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+/* op1 and op2 are converted to strings. For convenience, op1 or op2 =
JS_EXCEPTION are accepted and return JS_EXCEPTION. */
static JSValue JS_ConcatString(JSContext *ctx, JSValue op1, JSValue op2)
{
@@ -4252,27 +4307,11 @@ static JSValue JS_ConcatString(JSContext *ctx, JSValue op1, JSValue op2)
}
}
p1 = JS_VALUE_GET_STRING(op1);
- p2 = JS_VALUE_GET_STRING(op2);
-
- /* XXX: could also check if p1 is empty */
- if (p2->len == 0) {
- goto ret_op1;
- }
- if (p1->header.ref_count == 1 && p1->is_wide_char == p2->is_wide_char
- && js_malloc_usable_size(ctx, p1) >= sizeof(*p1) + ((p1->len + p2->len) << p2->is_wide_char) + 1 - p1->is_wide_char) {
- /* Concatenate in place in available space at the end of p1 */
- if (p1->is_wide_char) {
- memcpy(p1->u.str16 + p1->len, p2->u.str16, p2->len << 1);
- p1->len += p2->len;
- } else {
- memcpy(p1->u.str8 + p1->len, p2->u.str8, p2->len);
- p1->len += p2->len;
- p1->u.str8[p1->len] = '\0';
- }
- ret_op1:
+ if (JS_ConcatStringInPlace(ctx, p1, op2)) {
JS_FreeValue(ctx, op2);
return op1;
}
+ p2 = JS_VALUE_GET_STRING(op2);
ret = JS_ConcatString1(ctx, p1, p2);
JS_FreeValue(ctx, op1);
JS_FreeValue(ctx, op2);
@@ -4509,6 +4548,7 @@ static no_inline int resize_properties(JSContext *ctx, JSShape **psh,
JSShapeProperty *pr;
void *sh_alloc;
intptr_t h;
+ JSShape *old_sh;
sh = *psh;
new_size = max_int(count, sh->prop_size * 3 / 2);
@@ -4524,19 +4564,21 @@ static no_inline int resize_properties(JSContext *ctx, JSShape **psh,
new_hash_size = sh->prop_hash_mask + 1;
while (new_hash_size < new_size)
new_hash_size = 2 * new_hash_size;
+ /* resize the property shapes. Using js_realloc() is not possible in
+ case the GC runs during the allocation */
+ old_sh = sh;
+ sh_alloc = js_malloc(ctx, get_shape_size(new_hash_size, new_size));
+ if (!sh_alloc)
+ return -1;
+ sh = get_shape_from_alloc(sh_alloc, new_hash_size);
+ list_del(&old_sh->header.link);
+ /* copy all the shape properties */
+ memcpy(sh, old_sh,
+ sizeof(JSShape) + sizeof(sh->prop[0]) * old_sh->prop_count);
+ list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list);
+
if (new_hash_size != (sh->prop_hash_mask + 1)) {
- JSShape *old_sh;
/* resize the hash table and the properties */
- old_sh = sh;
- sh_alloc = js_malloc(ctx, get_shape_size(new_hash_size, new_size));
- if (!sh_alloc)
- return -1;
- sh = get_shape_from_alloc(sh_alloc, new_hash_size);
- list_del(&old_sh->header.link);
- /* copy all the fields and the properties */
- memcpy(sh, old_sh,
- sizeof(JSShape) + sizeof(sh->prop[0]) * old_sh->prop_count);
- list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list);
new_hash_mask = new_hash_size - 1;
sh->prop_hash_mask = new_hash_mask;
memset(prop_hash_end(sh) - new_hash_size, 0,
@@ -4548,20 +4590,12 @@ static no_inline int resize_properties(JSContext *ctx, JSShape **psh,
prop_hash_end(sh)[-h - 1] = i + 1;
}
}
- js_free(ctx, get_alloc_from_shape(old_sh));
} else {
- /* only resize the properties */
- list_del(&sh->header.link);
- sh_alloc = js_realloc(ctx, get_alloc_from_shape(sh),
- get_shape_size(new_hash_size, new_size));
- if (unlikely(!sh_alloc)) {
- /* insert again in the GC list */
- list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list);
- return -1;
- }
- sh = get_shape_from_alloc(sh_alloc, new_hash_size);
- list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list);
+ /* just copy the previous hash table */
+ memcpy(prop_hash_end(sh) - new_hash_size, prop_hash_end(old_sh) - new_hash_size,
+ sizeof(prop_hash_end(sh)[0]) * new_hash_size);
}
+ js_free(ctx, get_alloc_from_shape(old_sh));
*psh = sh;
sh->prop_size = new_size;
return 0;
@@ -4670,7 +4704,7 @@ static int add_shape_property(JSContext *ctx, JSShape **psh,
pr = &prop[sh->prop_count++];
pr->atom = JS_DupAtom(ctx, atom);
pr->flags = prop_flags;
- sh->has_small_array_index |= JS_AtomIsTaggedInt(atom);
+ sh->has_small_array_index |= __JS_AtomIsTaggedInt(atom);
/* add in hash table */
hash_mask = sh->prop_hash_mask;
h = atom & hash_mask;
@@ -4731,7 +4765,7 @@ static JSShape *find_hashed_shape_prop(JSRuntime *rt, JSShape *sh,
return NULL;
}
-static maybe_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;
@@ -4747,7 +4781,7 @@ static maybe_unused void JS_DumpShape(JSRuntime *rt, int i, JSShape *sh)
printf("\n");
}
-static maybe_unused void JS_DumpShapes(JSRuntime *rt)
+static __maybe_unused void JS_DumpShapes(JSRuntime *rt)
{
int i;
JSShape *sh;
@@ -4838,10 +4872,8 @@ static JSValue JS_NewObjectFromShape(JSContext *ctx, JSShape *sh, JSClassID clas
case JS_CLASS_UINT16_ARRAY:
case JS_CLASS_INT32_ARRAY:
case JS_CLASS_UINT32_ARRAY:
-#ifdef CONFIG_BIGNUM
case JS_CLASS_BIG_INT64_ARRAY:
case JS_CLASS_BIG_UINT64_ARRAY:
-#endif
case JS_CLASS_FLOAT32_ARRAY:
case JS_CLASS_FLOAT64_ARRAY:
p->is_exotic = 1;
@@ -4858,8 +4890,8 @@ static JSValue JS_NewObjectFromShape(JSContext *ctx, JSShape *sh, JSClassID clas
case JS_CLASS_BOOLEAN:
case JS_CLASS_SYMBOL:
case JS_CLASS_DATE:
-#ifdef CONFIG_BIGNUM
case JS_CLASS_BIG_INT:
+#ifdef CONFIG_BIGNUM
case JS_CLASS_BIG_FLOAT:
case JS_CLASS_BIG_DECIMAL:
#endif
@@ -4921,8 +4953,8 @@ static JSValue JS_GetObjectData(JSContext *ctx, JSValueConst obj)
case JS_CLASS_BOOLEAN:
case JS_CLASS_SYMBOL:
case JS_CLASS_DATE:
-#ifdef CONFIG_BIGNUM
case JS_CLASS_BIG_INT:
+#ifdef CONFIG_BIGNUM
case JS_CLASS_BIG_FLOAT:
case JS_CLASS_BIG_DECIMAL:
#endif
@@ -4945,8 +4977,8 @@ static int JS_SetObjectData(JSContext *ctx, JSValueConst obj, JSValue val)
case JS_CLASS_BOOLEAN:
case JS_CLASS_SYMBOL:
case JS_CLASS_DATE:
-#ifdef CONFIG_BIGNUM
case JS_CLASS_BIG_INT:
+#ifdef CONFIG_BIGNUM
case JS_CLASS_BIG_FLOAT:
case JS_CLASS_BIG_DECIMAL:
#endif
@@ -5293,10 +5325,12 @@ static void free_var_ref(JSRuntime *rt, JSVarRef *var_ref)
if (--var_ref->header.ref_count == 0) {
if (var_ref->is_detached) {
JS_FreeValueRT(rt, var_ref->value);
- remove_gc_object(&var_ref->header);
} else {
- list_del(&var_ref->header.link); /* still on the stack */
+ list_del(&var_ref->var_ref_link); /* still on the stack */
+ if (var_ref->async_func)
+ async_func_free(rt, var_ref->async_func);
}
+ remove_gc_object(&var_ref->header);
js_free_rt(rt, var_ref);
}
}
@@ -5394,7 +5428,7 @@ static void js_bytecode_function_mark(JSRuntime *rt, JSValueConst val,
if (var_refs) {
for(i = 0; i < b->closure_var_count; i++) {
JSVarRef *var_ref = var_refs[i];
- if (var_ref && var_ref->is_detached) {
+ if (var_ref) {
mark_func(rt, &var_ref->header);
}
}
@@ -5436,7 +5470,15 @@ static void js_for_in_iterator_finalizer(JSRuntime *rt, JSValue val)
{
JSObject *p = JS_VALUE_GET_OBJ(val);
JSForInIterator *it = p->u.for_in_iterator;
+ int i;
+
JS_FreeValueRT(rt, it->obj);
+ if (!it->is_array) {
+ for(i = 0; i < it->atom_count; i++) {
+ JS_FreeAtomRT(rt, it->tab_atom[i].atom);
+ }
+ js_free_rt(rt, it->tab_atom);
+ }
js_free_rt(rt, it);
}
@@ -5504,6 +5546,9 @@ static void free_gc_object(JSRuntime *rt, JSGCObjectHeader *gp)
case JS_GC_OBJ_TYPE_FUNCTION_BYTECODE:
free_function_bytecode(rt, (JSFunctionBytecode *)gp);
break;
+ case JS_GC_OBJ_TYPE_ASYNC_FUNCTION:
+ __async_func_free(rt, (JSAsyncFunctionState *)gp);
+ break;
default:
abort();
}
@@ -5527,7 +5572,7 @@ static void free_zero_refcount(JSRuntime *rt)
}
/* called with the ref_count of 'v' reaches zero. */
-static void JS_FreeValueRTImpl(JSRuntime *rt, JSValue v)
+static void __JS_FreeValueRT(JSRuntime *rt, JSValue v)
{
uint32_t tag = JS_VALUE_GET_TAG(v);
@@ -5573,15 +5618,17 @@ static void JS_FreeValueRTImpl(JSRuntime *rt, JSValue v)
case JS_TAG_MODULE:
abort(); /* never freed here */
break;
-#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_INT:
+#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_FLOAT:
+#endif
{
JSBigFloat *bf = JS_VALUE_GET_PTR(v);
bf_delete(&bf->num);
js_free_rt(rt, bf);
}
break;
+#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_DECIMAL:
{
JSBigDecimal *bf = JS_VALUE_GET_PTR(v);
@@ -5602,9 +5649,9 @@ static void JS_FreeValueRTImpl(JSRuntime *rt, JSValue v)
}
}
-static void JS_FreeValueImpl(JSContext *ctx, JSValue v)
+static void __JS_FreeValue(JSContext *ctx, JSValue v)
{
- JS_FreeValueRTImpl(ctx->rt, v);
+ __JS_FreeValueRT(ctx->rt, v);
}
/* garbage collection */
@@ -5660,11 +5707,9 @@ static void mark_children(JSRuntime *rt, JSGCObjectHeader *gp,
if (pr->u.getset.setter)
mark_func(rt, &pr->u.getset.setter->header);
} else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) {
- if (pr->u.var_ref->is_detached) {
- /* Note: the tag does not matter
- provided it is a GC object */
- mark_func(rt, &pr->u.var_ref->header);
- }
+ /* Note: the tag does not matter
+ provided it is a GC object */
+ mark_func(rt, &pr->u.var_ref->header);
} else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {
js_autoinit_mark(rt, pr, mark_func);
}
@@ -5698,16 +5743,32 @@ static void mark_children(JSRuntime *rt, JSGCObjectHeader *gp,
case JS_GC_OBJ_TYPE_VAR_REF:
{
JSVarRef *var_ref = (JSVarRef *)gp;
- /* only detached variable referenced are taken into account */
- assert(var_ref->is_detached);
- JS_MarkValue(rt, *var_ref->pvalue, mark_func);
+ if (var_ref->is_detached) {
+ JS_MarkValue(rt, *var_ref->pvalue, mark_func);
+ } else if (var_ref->async_func) {
+ mark_func(rt, &var_ref->async_func->header);
+ }
}
break;
case JS_GC_OBJ_TYPE_ASYNC_FUNCTION:
{
- JSAsyncFunctionData *s = (JSAsyncFunctionData *)gp;
- if (s->is_active)
- async_func_mark(rt, &s->func_state, mark_func);
+ JSAsyncFunctionState *s = (JSAsyncFunctionState *)gp;
+ JSStackFrame *sf = &s->frame;
+ JSValue *sp;
+
+ if (!s->is_completed) {
+ JS_MarkValue(rt, sf->cur_func, mark_func);
+ JS_MarkValue(rt, s->this_val, mark_func);
+ /* sf->cur_sp = NULL if the function is running */
+ if (sf->cur_sp) {
+ /* if the function is running, cur_sp is not known so we
+ cannot mark the stack. Marking the variables is not needed
+ because a running function cannot be part of a removable
+ cycle */
+ for(sp = sf->arg_buf; sp < sf->cur_sp; sp++)
+ JS_MarkValue(rt, *sp, mark_func);
+ }
+ }
JS_MarkValue(rt, s->resolving_funcs[0], mark_func);
JS_MarkValue(rt, s->resolving_funcs[1], mark_func);
}
@@ -5815,12 +5876,13 @@ static void gc_free_cycles(JSRuntime *rt)
if (el == &rt->tmp_obj_list)
break;
p = list_entry(el, JSGCObjectHeader, link);
- /* Only need to free the GC object associated with JS
- values. The rest will be automatically removed because they
- must be referenced by them. */
+ /* Only need to free the GC object associated with JS values
+ or async functions. The rest will be automatically removed
+ because they must be referenced by them. */
switch(p->gc_obj_type) {
case JS_GC_OBJ_TYPE_JS_OBJECT:
case JS_GC_OBJ_TYPE_FUNCTION_BYTECODE:
+ case JS_GC_OBJ_TYPE_ASYNC_FUNCTION:
#ifdef DUMP_GC_FREE
if (!header_done) {
printf("Freeing cycles:\n");
@@ -5842,7 +5904,8 @@ static void gc_free_cycles(JSRuntime *rt)
list_for_each_safe(el, el1, &rt->gc_zero_ref_count_list) {
p = list_entry(el, JSGCObjectHeader, link);
assert(p->gc_obj_type == JS_GC_OBJ_TYPE_JS_OBJECT ||
- p->gc_obj_type == JS_GC_OBJ_TYPE_FUNCTION_BYTECODE);
+ p->gc_obj_type == JS_GC_OBJ_TYPE_FUNCTION_BYTECODE ||
+ p->gc_obj_type == JS_GC_OBJ_TYPE_ASYNC_FUNCTION);
js_free_rt(rt, p);
}
@@ -5944,13 +6007,13 @@ static void compute_value_size(JSValueConst val, JSMemoryUsage_helper *hp)
case JS_TAG_STRING:
compute_jsstring_size(JS_VALUE_GET_STRING(val), hp);
break;
-#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_INT:
+#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_FLOAT:
case JS_TAG_BIG_DECIMAL:
+#endif
/* should track JSBigFloat usage */
break;
-#endif
}
}
@@ -6074,8 +6137,8 @@ void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s)
case JS_CLASS_BOOLEAN: /* u.object_data */
case JS_CLASS_SYMBOL: /* u.object_data */
case JS_CLASS_DATE: /* u.object_data */
-#ifdef CONFIG_BIGNUM
case JS_CLASS_BIG_INT: /* u.object_data */
+#ifdef CONFIG_BIGNUM
case JS_CLASS_BIG_FLOAT: /* u.object_data */
case JS_CLASS_BIG_DECIMAL: /* u.object_data */
#endif
@@ -6167,10 +6230,8 @@ void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s)
case JS_CLASS_UINT16_ARRAY: /* u.typed_array / u.array */
case JS_CLASS_INT32_ARRAY: /* u.typed_array / u.array */
case JS_CLASS_UINT32_ARRAY: /* u.typed_array / u.array */
-#ifdef CONFIG_BIGNUM
case JS_CLASS_BIG_INT64_ARRAY: /* u.typed_array / u.array */
case JS_CLASS_BIG_UINT64_ARRAY: /* u.typed_array / u.array */
-#endif
case JS_CLASS_FLOAT32_ARRAY: /* u.typed_array / u.array */
case JS_CLASS_FLOAT64_ARRAY: /* u.typed_array / u.array */
case JS_CLASS_DATAVIEW: /* u.typed_array */
@@ -6251,7 +6312,7 @@ void JS_DumpMemoryUsage(FILE *fp, const JSMemoryUsage *s, JSRuntime *rt)
"BigNum "
#endif
CONFIG_VERSION " version, %d-bit, malloc limit: %"PRId64"\n\n",
- (int)sizeof(void *) * 8, (int64_t)(ssize_t)s->malloc_limit);
+ (int)sizeof(void *) * 8, s->malloc_limit);
#if 1
if (rt) {
static const struct {
@@ -6297,10 +6358,10 @@ void JS_DumpMemoryUsage(FILE *fp, const JSMemoryUsage *s, JSRuntime *rt)
if (obj_classes[0])
fprintf(fp, " %5d %2.0d %s\n", obj_classes[0], 0, "none");
for (class_id = 1; class_id < JS_CLASS_INIT_COUNT; class_id++) {
- if (obj_classes[class_id]) {
+ if (obj_classes[class_id] && class_id < rt->class_count) {
char buf[ATOM_GET_STR_BUF_SIZE];
fprintf(fp, " %5d %2.0d %s\n", obj_classes[class_id], class_id,
- JS_AtomGetStrRT(rt, buf, sizeof(buf), js_std_class_def[class_id - 1].class_name));
+ JS_AtomGetStrRT(rt, buf, sizeof(buf), rt->class_array[class_id].class_name));
}
}
if (obj_classes[JS_CLASS_INIT_COUNT])
@@ -6397,6 +6458,11 @@ JSValue JS_GetException(JSContext *ctx)
return val;
}
+JS_BOOL JS_HasException(JSContext *ctx)
+{
+ return !JS_IsNull(ctx->rt->current_exception);
+}
+
static void dbuf_put_leb128(DynBuf *s, uint32_t v)
{
uint32_t a;
@@ -6526,8 +6592,8 @@ static const char *get_func_name(JSContext *ctx, JSValueConst func)
/* if filename != NULL, an additional level is added with the filename
and line number information (used for parse error). */
void build_backtrace(JSContext *ctx, JSValueConst error_obj,
- const char *filename, int line_num,
- int backtrace_flags)
+ const char *filename, int line_num,
+ int backtrace_flags)
{
JSStackFrame *sf;
JSValue str;
@@ -6698,7 +6764,7 @@ static int FORMAT_ATTR(3, 4) JS_ThrowTypeErrorOrFalse(JSContext *ctx, int flags,
}
/* never use it directly */
-static JSValue FORMAT_ATTR(3, 4) JS_ThrowTypeErrorAtomImpl(JSContext *ctx, JSAtom atom, const char *fmt, ...)
+static JSValue FORMAT_ATTR(3, 4) __JS_ThrowTypeErrorAtom(JSContext *ctx, JSAtom atom, const char *fmt, ...)
{
char buf[ATOM_GET_STR_BUF_SIZE];
return JS_ThrowTypeError(ctx, fmt,
@@ -6706,7 +6772,7 @@ static JSValue FORMAT_ATTR(3, 4) JS_ThrowTypeErrorAtomImpl(JSContext *ctx, JSAto
}
/* never use it directly */
-static JSValue FORMAT_ATTR(3, 4) JS_ThrowSyntaxErrorAtomImpl(JSContext *ctx, JSAtom atom, const char *fmt, ...)
+static JSValue FORMAT_ATTR(3, 4) __JS_ThrowSyntaxErrorAtom(JSContext *ctx, JSAtom atom, const char *fmt, ...)
{
char buf[ATOM_GET_STR_BUF_SIZE];
return JS_ThrowSyntaxError(ctx, fmt,
@@ -6715,8 +6781,8 @@ static JSValue FORMAT_ATTR(3, 4) JS_ThrowSyntaxErrorAtomImpl(JSContext *ctx, JSA
/* %s is replaced by 'atom'. The macro is used so that gcc can check
the format string. */
-#define JS_ThrowTypeErrorAtom(ctx, fmt, atom) JS_ThrowTypeErrorAtomImpl(ctx, atom, fmt, "")
-#define JS_ThrowSyntaxErrorAtom(ctx, fmt, atom) JS_ThrowSyntaxErrorAtomImpl(ctx, atom, fmt, "")
+#define JS_ThrowTypeErrorAtom(ctx, fmt, atom) __JS_ThrowTypeErrorAtom(ctx, atom, fmt, "")
+#define JS_ThrowSyntaxErrorAtom(ctx, fmt, atom) __JS_ThrowSyntaxErrorAtom(ctx, atom, fmt, "")
static int JS_ThrowTypeErrorReadOnly(JSContext *ctx, int flags, JSAtom atom)
{
@@ -6826,7 +6892,7 @@ static JSValue JS_ThrowTypeErrorInvalidClass(JSContext *ctx, int class_id)
return JS_ThrowTypeErrorAtom(ctx, "%s object expected", name);
}
-static no_inline warn_unused int js_poll_interrupts_impl(JSContext *ctx)
+static no_inline __exception int __js_poll_interrupts(JSContext *ctx)
{
JSRuntime *rt = ctx->rt;
ctx->interrupt_counter = JS_INTERRUPT_COUNTER_INIT;
@@ -6841,10 +6907,10 @@ static no_inline warn_unused int js_poll_interrupts_impl(JSContext *ctx)
return 0;
}
-static inline warn_unused int js_poll_interrupts(JSContext *ctx)
+static inline __exception int js_poll_interrupts(JSContext *ctx)
{
if (unlikely(--ctx->interrupt_counter <= 0)) {
- return js_poll_interrupts_impl(ctx);
+ return __js_poll_interrupts(ctx);
} else {
return 0;
}
@@ -6931,10 +6997,10 @@ int JS_SetPrototype(JSContext *ctx, JSValueConst obj, JSValueConst proto_val)
static JSValueConst JS_GetPrototypePrimitive(JSContext *ctx, JSValueConst val)
{
switch(JS_VALUE_GET_NORM_TAG(val)) {
-#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_INT:
val = ctx->class_proto[JS_CLASS_BIG_INT];
break;
+#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_FLOAT:
val = ctx->class_proto[JS_CLASS_BIG_FLOAT];
break;
@@ -7148,9 +7214,9 @@ JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj,
case JS_TAG_STRING:
{
JSString *p1 = JS_VALUE_GET_STRING(obj);
- if (JS_AtomIsTaggedInt(prop)) {
+ if (__JS_AtomIsTaggedInt(prop)) {
uint32_t idx, ch;
- idx = JS_AtomToUInt32(prop);
+ idx = __JS_AtomToUInt32(prop);
if (idx < p1->len) {
if (p1->is_wide_char)
ch = p1->u.str16[idx];
@@ -7208,8 +7274,8 @@ JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj,
if (unlikely(p->is_exotic)) {
/* exotic behaviors */
if (p->fast_array) {
- if (JS_AtomIsTaggedInt(prop)) {
- uint32_t idx = JS_AtomToUInt32(prop);
+ if (__JS_AtomIsTaggedInt(prop)) {
+ uint32_t idx = __JS_AtomToUInt32(prop);
if (idx < p->u.array.count) {
/* we avoid duplicating the code */
return JS_GetPropertyUint32(ctx, JS_MKPTR(JS_TAG_OBJECT, p), idx);
@@ -7371,6 +7437,8 @@ static int JS_SetPrivateField(JSContext *ctx, JSValueConst obj,
return 0;
}
+/* add a private brand field to 'home_obj' if not already present and
+ if obj is != null add a private brand to it */
static int JS_AddBrand(JSContext *ctx, JSValueConst obj, JSValueConst home_obj)
{
JSObject *p, *p1;
@@ -7386,10 +7454,10 @@ static int JS_AddBrand(JSContext *ctx, JSValueConst obj, JSValueConst home_obj)
p = JS_VALUE_GET_OBJ(home_obj);
prs = find_own_property(&pr, p, JS_ATOM_Private_brand);
if (!prs) {
+ /* if the brand is not present, add it */
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);
@@ -7401,20 +7469,27 @@ static int JS_AddBrand(JSContext *ctx, JSValueConst obj, JSValueConst home_obj)
}
brand_atom = js_symbol_to_atom(ctx, brand);
- if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)) {
- JS_ThrowTypeErrorNotAnObject(ctx);
+ if (JS_IsObject(obj)) {
+ p1 = JS_VALUE_GET_OBJ(obj);
+ prs = find_own_property(&pr, p1, brand_atom);
+ if (unlikely(prs)) {
+ JS_FreeAtom(ctx, brand_atom);
+ JS_ThrowTypeError(ctx, "private method is already present");
+ return -1;
+ }
+ 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;
+ } else {
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;
}
+/* return a boolean telling if the brand of the home object of 'func'
+ is present on 'obj' or -1 in case of exception */
static int JS_CheckBrand(JSContext *ctx, JSValueConst obj, JSValueConst func)
{
JSObject *p, *p1, *home_obj;
@@ -7423,11 +7498,8 @@ static int JS_CheckBrand(JSContext *ctx, JSValueConst obj, JSValueConst func)
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;
- }
+ if (unlikely(JS_VALUE_GET_TAG(func) != JS_TAG_OBJECT))
+ goto not_obj;
p1 = JS_VALUE_GET_OBJ(func);
if (!js_class_has_bytecode(p1->class_id))
goto not_obj;
@@ -7445,15 +7517,14 @@ static int JS_CheckBrand(JSContext *ctx, JSValueConst obj, JSValueConst func)
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, brand));
- if (!prs) {
- JS_ThrowTypeError(ctx, "invalid brand on object");
+ if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)) {
+ not_obj:
+ JS_ThrowTypeErrorNotAnObject(ctx);
return -1;
}
- return 0;
+ p = JS_VALUE_GET_OBJ(obj);
+ prs = find_own_property(&pr, p, js_symbol_to_atom(ctx, brand));
+ return (prs != NULL);
}
static uint32_t js_string_obj_get_length(JSContext *ctx,
@@ -7503,7 +7574,7 @@ static void js_free_prop_enum(JSContext *ctx, JSPropertyEnum *tab, uint32_t len)
/* return < 0 in case if exception, 0 if OK. ptab and its atoms must
be freed by the user. */
-static int warn_unused JS_GetOwnPropertyNamesInternal(JSContext *ctx,
+static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx,
JSPropertyEnum **ptab,
uint32_t *plen,
JSObject *p, int flags)
@@ -7653,7 +7724,7 @@ static int warn_unused JS_GetOwnPropertyNamesInternal(JSContext *ctx,
len = js_string_obj_get_length(ctx, JS_MKPTR(JS_TAG_OBJECT, p));
add_array_keys:
for(i = 0; i < len; i++) {
- tab_atom[num_index].atom = JS_AtomFromUInt32(i);
+ tab_atom[num_index].atom = __JS_AtomFromUInt32(i);
if (tab_atom[num_index].atom == JS_ATOM_NULL) {
js_free_prop_enum(ctx, tab_atom, num_index);
return -1;
@@ -7761,9 +7832,9 @@ retry:
if (p->is_exotic) {
if (p->fast_array) {
/* specific case for fast arrays */
- if (JS_AtomIsTaggedInt(prop)) {
+ if (__JS_AtomIsTaggedInt(prop)) {
uint32_t idx;
- idx = JS_AtomToUInt32(prop);
+ idx = __JS_AtomToUInt32(prop);
if (idx < p->u.array.count) {
if (desc) {
desc->flags = JS_PROP_WRITABLE | JS_PROP_ENUMERABLE |
@@ -7883,7 +7954,7 @@ JSAtom JS_ValueToAtom(JSContext *ctx, JSValueConst val)
if (tag == JS_TAG_INT &&
(uint32_t)JS_VALUE_GET_INT(val) <= JS_ATOM_MAX_INT) {
/* fast path for integer values */
- atom = JS_AtomFromUInt32(JS_VALUE_GET_INT(val));
+ atom = __JS_AtomFromUInt32(JS_VALUE_GET_INT(val));
} else if (tag == JS_TAG_SYMBOL) {
JSAtomStruct *p = JS_VALUE_GET_PTR(val);
atom = JS_DupAtom(ctx, js_get_atom_index(ctx->rt, p));
@@ -7910,40 +7981,46 @@ static JSValue JS_GetPropertyValue(JSContext *ctx, JSValueConst this_obj,
if (likely(JS_VALUE_GET_TAG(this_obj) == JS_TAG_OBJECT &&
JS_VALUE_GET_TAG(prop) == JS_TAG_INT)) {
JSObject *p;
- uint32_t idx, len;
+ uint32_t idx;
/* fast path for array access */
p = JS_VALUE_GET_OBJ(this_obj);
idx = JS_VALUE_GET_INT(prop);
- len = p->u.array.count;
- if (unlikely(idx >= len))
- goto slow_path;
switch(p->class_id) {
case JS_CLASS_ARRAY:
case JS_CLASS_ARGUMENTS:
+ if (unlikely(idx >= p->u.array.count)) goto slow_path;
return JS_DupValue(ctx, p->u.array.u.values[idx]);
case JS_CLASS_INT8_ARRAY:
+ if (unlikely(idx >= p->u.array.count)) goto slow_path;
return JS_NewInt32(ctx, p->u.array.u.int8_ptr[idx]);
case JS_CLASS_UINT8C_ARRAY:
case JS_CLASS_UINT8_ARRAY:
+ if (unlikely(idx >= p->u.array.count)) goto slow_path;
return JS_NewInt32(ctx, p->u.array.u.uint8_ptr[idx]);
case JS_CLASS_INT16_ARRAY:
+ if (unlikely(idx >= p->u.array.count)) goto slow_path;
return JS_NewInt32(ctx, p->u.array.u.int16_ptr[idx]);
case JS_CLASS_UINT16_ARRAY:
+ if (unlikely(idx >= p->u.array.count)) goto slow_path;
return JS_NewInt32(ctx, p->u.array.u.uint16_ptr[idx]);
case JS_CLASS_INT32_ARRAY:
+ if (unlikely(idx >= p->u.array.count)) goto slow_path;
return JS_NewInt32(ctx, p->u.array.u.int32_ptr[idx]);
case JS_CLASS_UINT32_ARRAY:
+ if (unlikely(idx >= p->u.array.count)) goto slow_path;
return JS_NewUint32(ctx, p->u.array.u.uint32_ptr[idx]);
-#ifdef CONFIG_BIGNUM
case JS_CLASS_BIG_INT64_ARRAY:
+ if (unlikely(idx >= p->u.array.count)) goto slow_path;
return JS_NewBigInt64(ctx, p->u.array.u.int64_ptr[idx]);
case JS_CLASS_BIG_UINT64_ARRAY:
+ if (unlikely(idx >= p->u.array.count)) goto slow_path;
return JS_NewBigUint64(ctx, p->u.array.u.uint64_ptr[idx]);
-#endif
case JS_CLASS_FLOAT32_ARRAY:
- return JS_NewFloat64Impl(ctx, p->u.array.u.float_ptr[idx]);
+ if (unlikely(idx >= p->u.array.count)) goto slow_path;
+ return __JS_NewFloat64(ctx, p->u.array.u.float_ptr[idx]);
case JS_CLASS_FLOAT64_ARRAY:
- return JS_NewFloat64Impl(ctx, p->u.array.u.double_ptr[idx]);
+ if (unlikely(idx >= p->u.array.count)) goto slow_path;
+ return __JS_NewFloat64(ctx, p->u.array.u.double_ptr[idx]);
default:
goto slow_path;
}
@@ -7978,7 +8055,7 @@ static int JS_TryGetPropertyInt64(JSContext *ctx, JSValueConst obj, int64_t idx,
if (likely((uint64_t)idx <= JS_ATOM_MAX_INT)) {
/* fast path */
- present = JS_HasProperty(ctx, obj, JS_AtomFromUInt32(idx));
+ present = JS_HasProperty(ctx, obj, __JS_AtomFromUInt32(idx));
if (present > 0) {
val = JS_GetPropertyValue(ctx, obj, JS_NewInt32(ctx, idx));
if (unlikely(JS_IsException(val)))
@@ -8075,7 +8152,7 @@ static JSProperty *add_property(JSContext *ctx,
/* can be called on Array or Arguments objects. return < 0 if
memory alloc error. */
-static no_inline warn_unused int convert_fast_array_to_array(JSContext *ctx,
+static no_inline __exception int convert_fast_array_to_array(JSContext *ctx,
JSObject *p)
{
JSProperty *pr;
@@ -8097,8 +8174,8 @@ static no_inline warn_unused int convert_fast_array_to_array(JSContext *ctx,
tab = p->u.array.u.values;
for(i = 0; i < len; i++) {
/* add_property cannot fail here but
- JS_AtomFromUInt32(i) fails for i > INT32_MAX */
- pr = add_property(ctx, p, JS_AtomFromUInt32(i), JS_PROP_C_W_E);
+ __JS_AtomFromUInt32(i) fails for i > INT32_MAX */
+ pr = add_property(ctx, p, __JS_AtomFromUInt32(i), JS_PROP_C_W_E);
pr->u.value = *tab++;
}
js_free(ctx, p->u.array.u.values);
@@ -8203,7 +8280,7 @@ static int call_setter(JSContext *ctx, JSObject *setter,
func = JS_MKPTR(JS_TAG_OBJECT, setter);
/* Note: the field could be removed in the setter */
func = JS_DupValue(ctx, func);
- ret = JS_CallFree(ctx, func, this_obj, 1, &val);
+ ret = JS_CallFree(ctx, func, this_obj, 1, (JSValueConst *)&val);
JS_FreeValue(ctx, val);
if (JS_IsException(ret))
return -1;
@@ -8360,126 +8437,45 @@ static int add_fast_array_element(JSContext *ctx, JSObject *p,
return TRUE;
}
-static void js_free_desc(JSContext *ctx, JSPropertyDescriptor *desc)
+/* Allocate a new fast array. Its 'length' property is set to zero. It
+ maximum size is 2^31-1 elements. For convenience, 'len' is a 64 bit
+ integer. WARNING: the content of the array is not initialized. */
+static JSValue js_allocate_fast_array(JSContext *ctx, int64_t len)
{
- JS_FreeValue(ctx, desc->getter);
- JS_FreeValue(ctx, desc->setter);
- JS_FreeValue(ctx, desc->value);
-}
-
-/* generic (and slower) version of JS_SetProperty() for
- * Reflect.set(). 'obj' must be an object. */
-static int JS_SetPropertyGeneric(JSContext *ctx,
- JSValueConst obj, JSAtom prop,
- JSValue val, JSValueConst this_obj,
- int flags)
-{
- int ret;
- JSPropertyDescriptor desc;
- JSValue obj1;
+ JSValue arr;
JSObject *p;
- obj1 = JS_DupValue(ctx, obj);
- for(;;) {
- p = JS_VALUE_GET_OBJ(obj1);
- if (p->is_exotic) {
- const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic;
- if (em && em->set_property) {
- ret = em->set_property(ctx, obj1, prop,
- val, this_obj, flags);
- JS_FreeValue(ctx, obj1);
- JS_FreeValue(ctx, val);
- return ret;
- }
- }
-
- ret = JS_GetOwnPropertyInternal(ctx, &desc, p, prop);
- if (ret < 0) {
- JS_FreeValue(ctx, obj1);
- JS_FreeValue(ctx, val);
- return ret;
- }
- if (ret) {
- if (desc.flags & JS_PROP_GETSET) {
- JSObject *setter;
- if (JS_IsUndefined(desc.setter))
- setter = NULL;
- else
- setter = JS_VALUE_GET_OBJ(desc.setter);
- ret = call_setter(ctx, setter, this_obj, val, flags);
- JS_FreeValue(ctx, desc.getter);
- JS_FreeValue(ctx, desc.setter);
- JS_FreeValue(ctx, obj1);
- return ret;
- } else {
- JS_FreeValue(ctx, desc.value);
- if (!(desc.flags & JS_PROP_WRITABLE)) {
- JS_FreeValue(ctx, obj1);
- goto read_only_error;
- }
- }
- break;
- }
- /* Note: at this point 'obj1' cannot be a proxy. XXX: may have
- to check recursion */
- obj1 = JS_GetPrototypeFree(ctx, obj1);
- if (JS_IsNull(obj1))
- break;
- }
- JS_FreeValue(ctx, obj1);
-
- if (!JS_IsObject(this_obj)) {
- JS_FreeValue(ctx, val);
- return JS_ThrowTypeErrorOrFalse(ctx, flags, "receiver is not an object");
- }
-
- p = JS_VALUE_GET_OBJ(this_obj);
-
- /* modify the property in this_obj if it already exists */
- ret = JS_GetOwnPropertyInternal(ctx, &desc, p, prop);
- if (ret < 0) {
- JS_FreeValue(ctx, val);
- return ret;
- }
- if (ret) {
- if (desc.flags & JS_PROP_GETSET) {
- JS_FreeValue(ctx, desc.getter);
- JS_FreeValue(ctx, desc.setter);
- JS_FreeValue(ctx, val);
- return JS_ThrowTypeErrorOrFalse(ctx, flags, "setter is forbidden");
- } else {
- JS_FreeValue(ctx, desc.value);
- if (!(desc.flags & JS_PROP_WRITABLE) ||
- p->class_id == JS_CLASS_MODULE_NS) {
- read_only_error:
- JS_FreeValue(ctx, val);
- return JS_ThrowTypeErrorReadOnly(ctx, flags, prop);
- }
+ if (len > INT32_MAX)
+ return JS_ThrowRangeError(ctx, "invalid array length");
+ arr = JS_NewArray(ctx);
+ if (JS_IsException(arr))
+ return arr;
+ if (len > 0) {
+ p = JS_VALUE_GET_OBJ(arr);
+ if (expand_fast_array(ctx, p, len) < 0) {
+ JS_FreeValue(ctx, arr);
+ return JS_EXCEPTION;
}
- ret = JS_DefineProperty(ctx, this_obj, prop, val,
- JS_UNDEFINED, JS_UNDEFINED,
- JS_PROP_HAS_VALUE);
- JS_FreeValue(ctx, val);
- return ret;
+ p->u.array.count = len;
}
+ return arr;
+}
- ret = JS_CreateProperty(ctx, p, prop, val, JS_UNDEFINED, JS_UNDEFINED,
- flags |
- JS_PROP_HAS_VALUE |
- JS_PROP_HAS_ENUMERABLE |
- JS_PROP_HAS_WRITABLE |
- JS_PROP_HAS_CONFIGURABLE |
- JS_PROP_C_W_E);
- JS_FreeValue(ctx, val);
- return ret;
+static void js_free_desc(JSContext *ctx, JSPropertyDescriptor *desc)
+{
+ JS_FreeValue(ctx, desc->getter);
+ JS_FreeValue(ctx, desc->setter);
+ JS_FreeValue(ctx, desc->value);
}
/* return -1 in case of exception or TRUE or FALSE. Warning: 'val' is
freed by the function. 'flags' is a bitmask of JS_PROP_NO_ADD,
JS_PROP_THROW or JS_PROP_THROW_STRICT. If JS_PROP_NO_ADD is set,
- the new property is not added and an error is raised. */
-int JS_SetPropertyInternal(JSContext *ctx, JSValueConst this_obj,
- JSAtom prop, JSValue val, int flags)
+ the new property is not added and an error is raised. 'this_obj' is
+ the receiver. If obj != this_obj, then obj must be an object
+ (Reflect.set case). */
+int JS_SetPropertyInternal(JSContext *ctx, JSValueConst obj,
+ JSAtom prop, JSValue val, JSValueConst this_obj, int flags)
{
JSObject *p, *p1;
JSShapeProperty *prs;
@@ -8492,25 +8488,37 @@ int JS_SetPropertyInternal(JSContext *ctx, JSValueConst this_obj,
#endif
tag = JS_VALUE_GET_TAG(this_obj);
if (unlikely(tag != JS_TAG_OBJECT)) {
- switch(tag) {
- case JS_TAG_NULL:
- JS_FreeValue(ctx, val);
- JS_ThrowTypeErrorAtom(ctx, "cannot set property '%s' of null", prop);
- return -1;
- case JS_TAG_UNDEFINED:
- JS_FreeValue(ctx, val);
- JS_ThrowTypeErrorAtom(ctx, "cannot set property '%s' of undefined", prop);
- return -1;
- default:
- /* even on a primitive type we can have setters on the prototype */
+ if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) {
p = NULL;
- p1 = JS_VALUE_GET_OBJ(JS_GetPrototypePrimitive(ctx, this_obj));
+ p1 = JS_VALUE_GET_OBJ(obj);
goto prototype_lookup;
+ } else {
+ switch(tag) {
+ case JS_TAG_NULL:
+ JS_FreeValue(ctx, val);
+ JS_ThrowTypeErrorAtom(ctx, "cannot set property '%s' of null", prop);
+ return -1;
+ case JS_TAG_UNDEFINED:
+ JS_FreeValue(ctx, val);
+ JS_ThrowTypeErrorAtom(ctx, "cannot set property '%s' of undefined", prop);
+ return -1;
+ default:
+ /* even on a primitive type we can have setters on the prototype */
+ p = NULL;
+ p1 = JS_VALUE_GET_OBJ(JS_GetPrototypePrimitive(ctx, obj));
+ goto prototype_lookup;
+ }
}
+ } else {
+ p = JS_VALUE_GET_OBJ(this_obj);
+ p1 = JS_VALUE_GET_OBJ(obj);
+ if (unlikely(p != p1))
+ goto retry2;
}
- p = JS_VALUE_GET_OBJ(this_obj);
-retry:
- prs = find_own_property(&pr, p, prop);
+
+ /* fast path if obj == this_obj */
+ retry:
+ prs = find_own_property(&pr, p1, prop);
if (prs) {
if (likely((prs->flags & (JS_PROP_TMASK | JS_PROP_WRITABLE |
JS_PROP_LENGTH)) == JS_PROP_WRITABLE)) {
@@ -8543,12 +8551,11 @@ retry:
}
}
- p1 = p;
for(;;) {
if (p1->is_exotic) {
if (p1->fast_array) {
- if (JS_AtomIsTaggedInt(prop)) {
- uint32_t idx = JS_AtomToUInt32(prop);
+ if (__JS_AtomIsTaggedInt(prop)) {
+ uint32_t idx = __JS_AtomToUInt32(prop);
if (idx < p1->u.array.count) {
if (unlikely(p == p1))
return JS_SetPropertyValue(ctx, this_obj, JS_NewInt32(ctx, idx), val, flags);
@@ -8567,11 +8574,19 @@ retry:
return -1;
}
typed_array_oob:
- val = JS_ToNumberFree(ctx, val);
- JS_FreeValue(ctx, val);
- if (JS_IsException(val))
- return -1;
- return JS_ThrowTypeErrorOrFalse(ctx, flags, "out-of-bound numeric index");
+ /* must convert the argument even if out of bound access */
+ if (p1->class_id == JS_CLASS_BIG_INT64_ARRAY ||
+ p1->class_id == JS_CLASS_BIG_UINT64_ARRAY) {
+ int64_t v;
+ if (JS_ToBigInt64Free(ctx, &v, val))
+ return -1;
+ } else {
+ val = JS_ToNumberFree(ctx, val);
+ JS_FreeValue(ctx, val);
+ if (JS_IsException(val))
+ return -1;
+ }
+ return TRUE;
}
}
} else {
@@ -8643,9 +8658,7 @@ retry:
return -1;
goto retry2;
} else if (!(prs->flags & JS_PROP_WRITABLE)) {
- read_only_prop:
- JS_FreeValue(ctx, val);
- return JS_ThrowTypeErrorReadOnly(ctx, flags, prop);
+ goto read_only_prop;
}
}
}
@@ -8666,17 +8679,57 @@ retry:
return JS_ThrowTypeErrorOrFalse(ctx, flags, "object is not extensible");
}
- if (p->is_exotic) {
- if (p->class_id == JS_CLASS_ARRAY && p->fast_array &&
- JS_AtomIsTaggedInt(prop)) {
- uint32_t idx = JS_AtomToUInt32(prop);
- if (idx == p->u.array.count) {
- /* fast case */
- return add_fast_array_element(ctx, p, val, flags);
+ if (likely(p == JS_VALUE_GET_OBJ(obj))) {
+ if (p->is_exotic) {
+ if (p->class_id == JS_CLASS_ARRAY && p->fast_array &&
+ __JS_AtomIsTaggedInt(prop)) {
+ uint32_t idx = __JS_AtomToUInt32(prop);
+ if (idx == p->u.array.count) {
+ /* fast case */
+ return add_fast_array_element(ctx, p, val, flags);
+ } else {
+ goto generic_create_prop;
+ }
} else {
goto generic_create_prop;
}
} else {
+ pr = add_property(ctx, p, prop, JS_PROP_C_W_E);
+ if (unlikely(!pr)) {
+ JS_FreeValue(ctx, val);
+ return -1;
+ }
+ pr->u.value = val;
+ return TRUE;
+ }
+ } else {
+ /* generic case: modify the property in this_obj if it already exists */
+ ret = JS_GetOwnPropertyInternal(ctx, &desc, p, prop);
+ if (ret < 0) {
+ JS_FreeValue(ctx, val);
+ return ret;
+ }
+ if (ret) {
+ if (desc.flags & JS_PROP_GETSET) {
+ JS_FreeValue(ctx, desc.getter);
+ JS_FreeValue(ctx, desc.setter);
+ JS_FreeValue(ctx, val);
+ return JS_ThrowTypeErrorOrFalse(ctx, flags, "setter is forbidden");
+ } else {
+ JS_FreeValue(ctx, desc.value);
+ if (!(desc.flags & JS_PROP_WRITABLE) ||
+ p->class_id == JS_CLASS_MODULE_NS) {
+ read_only_prop:
+ JS_FreeValue(ctx, val);
+ return JS_ThrowTypeErrorReadOnly(ctx, flags, prop);
+ }
+ }
+ ret = JS_DefineProperty(ctx, this_obj, prop, val,
+ JS_UNDEFINED, JS_UNDEFINED,
+ JS_PROP_HAS_VALUE);
+ JS_FreeValue(ctx, val);
+ return ret;
+ } else {
generic_create_prop:
ret = JS_CreateProperty(ctx, p, prop, val, JS_UNDEFINED, JS_UNDEFINED,
flags |
@@ -8689,14 +8742,6 @@ retry:
return ret;
}
}
-
- pr = add_property(ctx, p, prop, JS_PROP_C_W_E);
- if (unlikely(!pr)) {
- JS_FreeValue(ctx, val);
- return -1;
- }
- pr->u.value = val;
- return TRUE;
}
/* flags can be JS_PROP_THROW or JS_PROP_THROW_STRICT */
@@ -8720,7 +8765,7 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj,
JSShape *sh1;
/* fast path to add an element to the array */
- if (idx != p->u.array.count ||
+ if (idx != (uint32_t)p->u.array.count ||
!p->fast_array || !p->extensible)
goto slow_path;
/* check if prototype chain has a numeric property */
@@ -8781,7 +8826,6 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj,
goto ta_out_of_bound;
p->u.array.u.uint32_ptr[idx] = v;
break;
-#ifdef CONFIG_BIGNUM
case JS_CLASS_BIG_INT64_ARRAY:
case JS_CLASS_BIG_UINT64_ARRAY:
/* XXX: need specific conversion function */
@@ -8794,7 +8838,6 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj,
p->u.array.u.uint64_ptr[idx] = v;
}
break;
-#endif
case JS_CLASS_FLOAT32_ARRAY:
if (JS_ToFloat64Free(ctx, &d, val))
return -1;
@@ -8807,7 +8850,7 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj,
return -1;
if (unlikely(idx >= (uint32_t)p->u.array.count)) {
ta_out_of_bound:
- return JS_ThrowTypeErrorOrFalse(ctx, flags, "out-of-bound numeric index");
+ return TRUE;
}
p->u.array.u.double_ptr[idx] = d;
break;
@@ -8825,7 +8868,7 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj,
JS_FreeValue(ctx, val);
return -1;
}
- ret = JS_SetPropertyInternal(ctx, this_obj, atom, val, flags);
+ ret = JS_SetPropertyInternal(ctx, this_obj, atom, val, this_obj, flags);
JS_FreeAtom(ctx, atom);
return ret;
}
@@ -8865,7 +8908,7 @@ int JS_SetPropertyStr(JSContext *ctx, JSValueConst this_obj,
JSAtom atom;
int ret;
atom = JS_NewAtom(ctx, prop);
- ret = JS_SetPropertyInternal(ctx, this_obj, atom, val, JS_PROP_THROW);
+ ret = JS_SetPropertyInternal(ctx, this_obj, atom, val, this_obj, JS_PROP_THROW);
JS_FreeAtom(ctx, atom);
return ret;
}
@@ -8895,8 +8938,8 @@ static int JS_CreateProperty(JSContext *ctx, JSObject *p,
uint32_t idx, len;
if (p->fast_array) {
- if (JS_AtomIsTaggedInt(prop)) {
- idx = JS_AtomToUInt32(prop);
+ if (__JS_AtomIsTaggedInt(prop)) {
+ idx = __JS_AtomToUInt32(prop);
if (idx == p->u.array.count) {
if (!p->extensible)
goto not_extensible;
@@ -9205,15 +9248,19 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
spaces. */
if (!js_same_value(ctx, val, *pr->u.var_ref->pvalue))
goto not_configurable;
+ } else {
+ /* update the reference */
+ set_value(ctx, pr->u.var_ref->pvalue,
+ JS_DupValue(ctx, val));
}
- /* update the reference */
- set_value(ctx, pr->u.var_ref->pvalue,
- JS_DupValue(ctx, val));
}
/* if writable is set to false, no longer a
reference (for mapped arguments) */
if ((flags & (JS_PROP_HAS_WRITABLE | JS_PROP_WRITABLE)) == JS_PROP_HAS_WRITABLE) {
JSValue val1;
+ if (p->class_id == JS_CLASS_MODULE_NS) {
+ return JS_ThrowTypeErrorOrFalse(ctx, flags, "module namespace properties have writable = false");
+ }
if (js_shape_prepare_update(ctx, p, &prs))
return -1;
val1 = JS_DupValue(ctx, *pr->u.var_ref->pvalue);
@@ -9272,8 +9319,8 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
uint32_t idx;
uint32_t prop_flags;
if (p->class_id == JS_CLASS_ARRAY) {
- if (JS_AtomIsTaggedInt(prop)) {
- idx = JS_AtomToUInt32(prop);
+ if (__JS_AtomIsTaggedInt(prop)) {
+ idx = __JS_AtomToUInt32(prop);
if (idx < p->u.array.count) {
prop_flags = get_prop_flags(flags, JS_PROP_C_W_E);
if (prop_flags != JS_PROP_C_W_E)
@@ -9296,7 +9343,7 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
JSValue num;
int ret;
- if (!JS_AtomIsTaggedInt(prop)) {
+ if (!__JS_AtomIsTaggedInt(prop)) {
/* slow path with to handle all numeric indexes */
num = JS_AtomIsNumericIndex1(ctx, prop);
if (JS_IsUndefined(num))
@@ -9317,12 +9364,12 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
if (ret) {
return JS_ThrowTypeErrorOrFalse(ctx, flags, "negative index in typed array");
}
- if (!JS_AtomIsTaggedInt(prop))
+ if (!__JS_AtomIsTaggedInt(prop))
goto typed_array_oob;
}
- idx = JS_AtomToUInt32(prop);
+ idx = __JS_AtomToUInt32(prop);
/* if the typed array is detached, p->u.array.count = 0 */
- if (idx >= typed_array_get_length(ctx, p)) {
+ if (idx >= p->u.array.count) {
typed_array_oob:
return JS_ThrowTypeErrorOrFalse(ctx, flags, "out-of-bound index in typed array");
}
@@ -9726,11 +9773,11 @@ static int JS_SetGlobalVar(JSContext *ctx, JSAtom prop, JSValue val,
struct LookupResult result = ctx->scopeLookup(ctx, prop);
if (result.useResult) {
JS_FreeValue(ctx, result.value);
- return JS_SetPropertyInternal(ctx, result.scope, prop, val, flags);
+ return JS_SetPropertyInternal(ctx, ctx->global_obj, prop, val, result.scope, flags);
}
}
- return JS_SetPropertyInternal(ctx, ctx->global_obj, prop, val, flags);
+ return JS_SetPropertyInternal(ctx, ctx->global_obj, prop, val, ctx->global_obj, flags);
}
/* return -1, FALSE or TRUE. return FALSE if not configurable or
@@ -9765,7 +9812,7 @@ int JS_DeletePropertyInt64(JSContext *ctx, JSValueConst obj, int64_t idx, int fl
if ((uint64_t)idx <= JS_ATOM_MAX_INT) {
/* fast path for fast arrays */
- return JS_DeleteProperty(ctx, obj, JS_AtomFromUInt32(idx), flags);
+ return JS_DeleteProperty(ctx, obj, __JS_AtomFromUInt32(idx), flags);
}
prop = JS_NewAtomInt64(ctx, idx);
if (prop == JS_ATOM_NULL)
@@ -9894,12 +9941,6 @@ void *JS_GetOpaque2(JSContext *ctx, JSValueConst obj, JSClassID class_id)
return p;
}
-#define HINT_STRING 0
-#define HINT_NUMBER 1
-#define HINT_NONE 2
-/* don't try Symbol.toPrimitive */
-#define HINT_FORCE_ORDINARY (1 << 4)
-
static JSValue JS_ToPrimitiveFree(JSContext *ctx, JSValue val, int hint)
{
int i;
@@ -9933,7 +9974,7 @@ static JSValue JS_ToPrimitiveFree(JSContext *ctx, JSValue val, int hint)
break;
}
arg = JS_AtomToString(ctx, atom);
- ret = JS_CallFree(ctx, method, val, 1, &arg);
+ ret = JS_CallFree(ctx, method, val, 1, (JSValueConst *)&arg);
JS_FreeValue(ctx, arg);
if (JS_IsException(ret))
goto exception;
@@ -10015,9 +10056,10 @@ static int JS_ToBoolFree(JSContext *ctx, JSValue val)
JS_FreeValue(ctx, val);
return ret;
}
-#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_INT:
+#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_FLOAT:
+#endif
{
JSBigFloat *p = JS_VALUE_GET_PTR(val);
BOOL ret;
@@ -10025,6 +10067,7 @@ static int JS_ToBoolFree(JSContext *ctx, JSValue val)
JS_FreeValue(ctx, val);
return ret;
}
+#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_DECIMAL:
{
JSBigDecimal *p = JS_VALUE_GET_PTR(val);
@@ -10094,12 +10137,13 @@ static inline int to_digit(int c)
}
/* XXX: remove */
-static double js_strtod(const char *p, int radix, BOOL is_float)
+static double js_strtod(const char *str, int radix, BOOL is_float)
{
double d;
int c;
if (!is_float || radix != 10) {
+ const char *p = str;
uint64_t n_max, n;
int int_exp, is_neg;
@@ -10126,6 +10170,8 @@ static double js_strtod(const char *p, int radix, BOOL is_float)
if (n <= n_max) {
n = n * radix + c;
} else {
+ if (radix == 10)
+ goto strtod_case;
int_exp++;
}
p++;
@@ -10137,7 +10183,8 @@ static double js_strtod(const char *p, int radix, BOOL is_float)
if (is_neg)
d = -d;
} else {
- d = safe_strtod(p, NULL);
+ strtod_case:
+ d = safe_strtod(str, NULL);
}
return d;
}
@@ -10155,15 +10202,16 @@ static double js_strtod(const char *p, int radix, BOOL is_float)
#define ATOD_TYPE_MASK (3 << 7)
#define ATOD_TYPE_FLOAT64 (0 << 7)
#define ATOD_TYPE_BIG_INT (1 << 7)
+#ifdef CONFIG_BIGNUM
#define ATOD_TYPE_BIG_FLOAT (2 << 7)
#define ATOD_TYPE_BIG_DECIMAL (3 << 7)
/* assume bigint mode: floats are parsed as integers if no decimal
point nor exponent */
#define ATOD_MODE_BIGINT (1 << 9)
+#endif
/* accept -0x1 */
#define ATOD_ACCEPT_PREFIX_AFTER_SIGN (1 << 10)
-#ifdef CONFIG_BIGNUM
static JSValue js_string_to_bigint(JSContext *ctx, const char *buf,
int radix, int flags, slimb_t *pexponent)
{
@@ -10179,10 +10227,15 @@ static JSValue js_string_to_bigint(JSContext *ctx, const char *buf,
JS_FreeValue(ctx, val);
return JS_ThrowOutOfMemory(ctx);
}
+#ifdef CONFIG_BIGNUM
val = JS_CompactBigInt1(ctx, val, (flags & ATOD_MODE_BIGINT) != 0);
+#else
+ val = JS_CompactBigInt1(ctx, val, FALSE);
+#endif
return val;
}
+#ifdef CONFIG_BIGNUM
static JSValue js_string_to_bigfloat(JSContext *ctx, const char *buf,
int radix, int flags, slimb_t *pexponent)
{
@@ -10228,7 +10281,6 @@ static JSValue js_string_to_bigdecimal(JSContext *ctx, const char *buf,
}
return val;
}
-
#endif
/* return an exception in case of memory error. Return JS_NAN if
@@ -10303,8 +10355,11 @@ static JSValue js_atof(JSContext *ctx, const char *str, const char **pp,
} else {
no_radix_prefix:
if (!(flags & ATOD_INT_ONLY) &&
- (atod_type == ATOD_TYPE_FLOAT64 ||
- atod_type == ATOD_TYPE_BIG_FLOAT) &&
+ (atod_type == ATOD_TYPE_FLOAT64
+#ifdef CONFIG_BIGNUM
+ || atod_type == ATOD_TYPE_BIG_FLOAT
+#endif
+ ) &&
strstart(p, "Infinity", &p)) {
#ifdef CONFIG_BIGNUM
if (atod_type == ATOD_TYPE_BIG_FLOAT) {
@@ -10350,8 +10405,11 @@ static JSValue js_atof(JSContext *ctx, const char *str, const char **pp,
((*p == 'p' || *p == 'P') && (radix == 2 || radix == 8 || radix == 16)))) {
const char *p1 = p + 1;
is_float = TRUE;
- if (*p1 == '+' || *p1 == '-')
+ if (*p1 == '+') {
+ p1++;
+ } else if (*p1 == '-') {
p1++;
+ }
if (is_digit((uint8_t)*p1)) {
p = p1 + 1;
while (is_digit((uint8_t)*p) || (*p == sep && is_digit((uint8_t)p[1])))
@@ -10381,36 +10439,40 @@ static JSValue js_atof(JSContext *ctx, const char *str, const char **pp,
}
buf[j] = '\0';
-#ifdef CONFIG_BIGNUM
if (flags & ATOD_ACCEPT_SUFFIX) {
if (*p == 'n') {
p++;
atod_type = ATOD_TYPE_BIG_INT;
- } else if (*p == 'l') {
+ } else
+#ifdef CONFIG_BIGNUM
+ if (*p == 'l') {
p++;
atod_type = ATOD_TYPE_BIG_FLOAT;
} else if (*p == 'm') {
p++;
atod_type = ATOD_TYPE_BIG_DECIMAL;
- } else {
- if (flags & ATOD_MODE_BIGINT) {
- if (!is_float)
- atod_type = ATOD_TYPE_BIG_INT;
- if (has_legacy_octal)
- goto fail;
- } else {
- if (is_float && radix != 10)
- goto fail;
- }
+ } else if (flags & ATOD_MODE_BIGINT) {
+ if (!is_float)
+ atod_type = ATOD_TYPE_BIG_INT;
+ if (has_legacy_octal)
+ goto fail;
+ } else
+#endif
+ {
+ if (is_float && radix != 10)
+ goto fail;
}
} else {
if (atod_type == ATOD_TYPE_FLOAT64) {
+#ifdef CONFIG_BIGNUM
if (flags & ATOD_MODE_BIGINT) {
if (!is_float)
atod_type = ATOD_TYPE_BIG_INT;
if (has_legacy_octal)
goto fail;
- } else {
+ } else
+#endif
+ {
if (is_float && radix != 10)
goto fail;
}
@@ -10431,6 +10493,7 @@ static JSValue js_atof(JSContext *ctx, const char *str, const char **pp,
goto fail;
val = ctx->rt->bigint_ops.from_string(ctx, buf, radix, flags, NULL);
break;
+#ifdef CONFIG_BIGNUM
case ATOD_TYPE_BIG_FLOAT:
if (has_legacy_octal)
goto fail;
@@ -10442,19 +10505,10 @@ static JSValue js_atof(JSContext *ctx, const char *str, const char **pp,
goto fail;
val = ctx->rt->bigdecimal_ops.from_string(ctx, buf, radix, flags, NULL);
break;
+#endif
default:
abort();
}
-#else
- {
- double d;
- (void)has_legacy_octal;
- if (is_float && radix != 10)
- goto fail;
- d = js_strtod(buf, radix, is_float);
- val = JS_NewFloat64(ctx, d);
- }
-#endif
done:
if (buf_allocated)
@@ -10492,18 +10546,18 @@ static JSValue JS_ToNumberHintFree(JSContext *ctx, JSValue val,
redo:
tag = JS_VALUE_GET_NORM_TAG(val);
switch(tag) {
-#ifdef CONFIG_BIGNUM
- case JS_TAG_BIG_DECIMAL:
+ case JS_TAG_BIG_INT:
if (flag != TON_FLAG_NUMERIC) {
JS_FreeValue(ctx, val);
- return JS_ThrowTypeError(ctx, "cannot convert bigdecimal to number");
+ return JS_ThrowTypeError(ctx, "cannot convert bigint to number");
}
ret = val;
break;
- case JS_TAG_BIG_INT:
+#ifdef CONFIG_BIGNUM
+ case JS_TAG_BIG_DECIMAL:
if (flag != TON_FLAG_NUMERIC) {
JS_FreeValue(ctx, val);
- return JS_ThrowTypeError(ctx, "cannot convert bigint to number");
+ return JS_ThrowTypeError(ctx, "cannot convert bigdecimal to number");
}
ret = val;
break;
@@ -10586,7 +10640,7 @@ static JSValue JS_ToNumeric(JSContext *ctx, JSValueConst val)
return JS_ToNumericFree(ctx, JS_DupValue(ctx, val));
}
-static warn_unused int JS_ToFloat64FreeImpl(JSContext *ctx, double *pres,
+static __exception int __JS_ToFloat64Free(JSContext *ctx, double *pres,
JSValue val)
{
double d;
@@ -10605,9 +10659,10 @@ static warn_unused int JS_ToFloat64FreeImpl(JSContext *ctx, double *pres,
case JS_TAG_FLOAT64:
d = JS_VALUE_GET_FLOAT64(val);
break;
-#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_INT:
+#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_FLOAT:
+#endif
{
JSBigFloat *p = JS_VALUE_GET_PTR(val);
/* XXX: there can be a double rounding issue with some
@@ -10617,7 +10672,6 @@ static warn_unused int JS_ToFloat64FreeImpl(JSContext *ctx, double *pres,
JS_FreeValue(ctx, val);
}
break;
-#endif
default:
abort();
}
@@ -10637,7 +10691,7 @@ static inline int JS_ToFloat64Free(JSContext *ctx, double *pres, JSValue val)
*pres = JS_VALUE_GET_FLOAT64(val);
return 0;
} else {
- return JS_ToFloat64FreeImpl(ctx, pres, val);
+ return __JS_ToFloat64Free(ctx, pres, val);
}
}
@@ -10652,7 +10706,7 @@ static JSValue JS_ToNumber(JSContext *ctx, JSValueConst val)
}
/* same as JS_ToNumber() but return 0 in case of NaN/Undefined */
-static maybe_unused JSValue JS_ToIntegerFree(JSContext *ctx, JSValue val)
+static __maybe_unused JSValue JS_ToIntegerFree(JSContext *ctx, JSValue val)
{
uint32_t tag;
JSValue ret;
@@ -10685,6 +10739,10 @@ static maybe_unused JSValue JS_ToIntegerFree(JSContext *ctx, JSValue val)
BOOL is_nan;
a = JS_ToBigFloat(ctx, &a_s, val);
+ if (!a) {
+ JS_FreeValue(ctx, val);
+ return JS_EXCEPTION;
+ }
if (!bf_is_finite(a)) {
is_nan = bf_is_nan(a);
if (is_nan)
@@ -10815,7 +10873,7 @@ static int JS_ToInt64SatFree(JSContext *ctx, int64_t *pres, JSValue val)
} else {
if (d < INT64_MIN)
*pres = INT64_MIN;
- else if (d > INT64_MAX)
+ else if (d >= 0x1p63) /* must use INT64_MAX + 1 because INT64_MAX cannot be exactly represented as a double */
*pres = INT64_MAX;
else
*pres = (int64_t)d;
@@ -11067,7 +11125,7 @@ static int JS_ToUint8ClampFree(JSContext *ctx, int32_t *pres, JSValue val)
return 0;
}
-static warn_unused int JS_ToArrayLengthFree(JSContext *ctx, uint32_t *plen,
+static __exception int JS_ToArrayLengthFree(JSContext *ctx, uint32_t *plen,
JSValue val, BOOL is_array_ctor)
{
uint32_t tag, len;
@@ -11085,9 +11143,10 @@ static warn_unused int JS_ToArrayLengthFree(JSContext *ctx, uint32_t *plen,
len = v;
}
break;
-#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_INT:
+#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_FLOAT:
+#endif
{
JSBigFloat *p = JS_VALUE_GET_PTR(val);
bf_t a;
@@ -11102,11 +11161,12 @@ static warn_unused int JS_ToArrayLengthFree(JSContext *ctx, uint32_t *plen,
goto fail;
}
break;
-#endif
default:
if (JS_TAG_IS_FLOAT64(tag)) {
double d;
d = JS_VALUE_GET_FLOAT64(val);
+ if (!(d >= 0 && d <= UINT32_MAX))
+ goto fail;
len = (uint32_t)d;
if (len != d)
goto fail;
@@ -11169,7 +11229,7 @@ int JS_ToIndex(JSContext *ctx, uint64_t *plen, JSValueConst val)
/* convert a value to a length between 0 and MAX_SAFE_INTEGER.
return -1 for exception */
-static warn_unused int JS_ToLengthFree(JSContext *ctx, int64_t *plen,
+static __exception int JS_ToLengthFree(JSContext *ctx, int64_t *plen,
JSValue val)
{
int res = JS_ToInt64Clamp(ctx, plen, val, 0, MAX_SAFE_INTEGER, 0);
@@ -11206,13 +11266,13 @@ static BOOL JS_NumberIsNegativeOrMinusZero(JSContext *ctx, JSValueConst val)
u.d = JS_VALUE_GET_FLOAT64(val);
return (u.u64 >> 63);
}
-#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_INT:
{
JSBigFloat *p = JS_VALUE_GET_PTR(val);
/* Note: integer zeros are not necessarily positive */
return p->num.sign && !bf_is_zero(&p->num);
}
+#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_FLOAT:
{
JSBigFloat *p = JS_VALUE_GET_PTR(val);
@@ -11231,8 +11291,6 @@ static BOOL JS_NumberIsNegativeOrMinusZero(JSContext *ctx, JSValueConst val)
}
}
-#ifdef CONFIG_BIGNUM
-
static JSValue js_bigint_to_string1(JSContext *ctx, JSValueConst val, int radix)
{
JSValue ret;
@@ -11262,6 +11320,8 @@ static JSValue js_bigint_to_string(JSContext *ctx, JSValueConst val)
return js_bigint_to_string1(ctx, val, 10);
}
+#ifdef CONFIG_BIGNUM
+
static JSValue js_ftoa(JSContext *ctx, JSValueConst val1, int radix,
limb_t prec, bf_flags_t flags)
{
@@ -11274,6 +11334,10 @@ static JSValue js_ftoa(JSContext *ctx, JSValueConst val1, int radix,
if (JS_IsException(val))
return val;
a = JS_ToBigFloat(ctx, &a_s, val);
+ if (!a) {
+ JS_FreeValue(ctx, val);
+ return JS_EXCEPTION;
+ }
saved_sign = a->sign;
if (a->expn == BF_EXP_ZERO)
a->sign = 0;
@@ -11330,6 +11394,8 @@ static JSValue js_bigdecimal_to_string1(JSContext *ctx, JSValueConst val,
int saved_sign;
a = JS_ToBigDecimal(ctx, val);
+ if (!a)
+ return JS_EXCEPTION;
saved_sign = a->sign;
if (a->expn == BF_EXP_ZERO)
a->sign = 0;
@@ -11351,6 +11417,8 @@ static JSValue js_bigdecimal_to_string(JSContext *ctx, JSValueConst val)
#endif /* CONFIG_BIGNUM */
/* 2 <= base <= 36 */
+static char const digits[36] = "0123456789abcdefghijklmnopqrstuvwxyz";
+
static char *i64toa(char *buf_end, int64_t n, unsigned int base)
{
char *q = buf_end;
@@ -11362,15 +11430,20 @@ static char *i64toa(char *buf_end, int64_t n, unsigned int base)
n = -n;
}
*--q = '\0';
- do {
- digit = (uint64_t)n % base;
- n = (uint64_t)n / base;
- if (digit < 10)
- digit += '0';
- else
- digit += 'a' - 10;
- *--q = digit;
- } while (n != 0);
+ if (base == 10) {
+ /* division by known base uses multiplication */
+ do {
+ digit = (uint64_t)n % 10;
+ n = (uint64_t)n / 10;
+ *--q = '0' + digit;
+ } while (n != 0);
+ } else {
+ do {
+ digit = (uint64_t)n % base;
+ n = (uint64_t)n / base;
+ *--q = digits[digit];
+ } while (n != 0);
+ }
if (is_neg)
*--q = '-';
return q;
@@ -11460,20 +11533,20 @@ static int js_ecvt(double d, int n_digits, int *decpt, int *sign, char *buf,
return n_digits;
}
-static int js_fcvt1(char *buf, int buf_size, double d, int n_digits,
+static int js_fcvt1(char (*buf)[JS_DTOA_BUF_SIZE], double d, int n_digits,
int rounding_mode)
{
int n;
if (rounding_mode != FE_TONEAREST)
fesetround(rounding_mode);
- n = snprintf(buf, buf_size, "%.*f", n_digits, d);
+ n = snprintf(*buf, sizeof(*buf), "%.*f", n_digits, d);
if (rounding_mode != FE_TONEAREST)
fesetround(FE_TONEAREST);
- assert(n < buf_size);
+ assert(n < sizeof(*buf));
return n;
}
-static void js_fcvt(char *buf, int buf_size, double d, int n_digits)
+static void js_fcvt(char (*buf)[JS_DTOA_BUF_SIZE], double d, int n_digits)
{
int rounding_mode;
rounding_mode = FE_TONEAREST;
@@ -11487,12 +11560,12 @@ static void js_fcvt(char *buf, int buf_size, double d, int n_digits)
zero (RNDNA), but in printf the "ties" case is not specified
(for example it is RNDN for glibc, RNDNA for Windows), so we
must round manually. */
- n1 = js_fcvt1(buf1, sizeof(buf1), d, n_digits + 1, FE_TONEAREST);
+ n1 = js_fcvt1(&buf1, d, n_digits + 1, FE_TONEAREST);
rounding_mode = FE_TONEAREST;
/* XXX: could use 2 digits to reduce the average running time */
if (buf1[n1 - 1] == '5') {
- n1 = js_fcvt1(buf1, sizeof(buf1), d, n_digits + 1, FE_DOWNWARD);
- n2 = js_fcvt1(buf2, sizeof(buf2), d, n_digits + 1, FE_UPWARD);
+ n1 = js_fcvt1(&buf1, d, n_digits + 1, FE_DOWNWARD);
+ n2 = js_fcvt1(&buf2, d, n_digits + 1, FE_UPWARD);
if (n1 == n2 && memcmp(buf1, buf2, n1) == 0) {
/* exact result: round away from zero */
if (buf1[0] == '-')
@@ -11503,7 +11576,7 @@ static void js_fcvt(char *buf, int buf_size, double d, int n_digits)
}
}
#endif /* CONFIG_PRINTF_RNDN */
- js_fcvt1(buf, buf_size, d, n_digits, rounding_mode);
+ js_fcvt1(buf, d, n_digits, rounding_mode);
}
/* radix != 10 is only supported with flags = JS_DTOA_VAR_FORMAT */
@@ -11519,33 +11592,35 @@ static void js_fcvt(char *buf, int buf_size, double d, int n_digits)
/* XXX: slow and maybe not fully correct. Use libbf when it is fast enough.
XXX: radix != 10 is only supported for small integers
*/
-static void js_dtoa1(char *buf, double d, int radix, int n_digits, int flags)
+static void js_dtoa1(char (*buf)[JS_DTOA_BUF_SIZE], double d,
+ int radix, int n_digits, int flags)
{
char *q;
if (!isfinite(d)) {
if (isnan(d)) {
- strcpy(buf, "NaN");
+ pstrcpy(*buf, sizeof(*buf), "NaN");
+ } else if (d < 0) {
+ pstrcpy(*buf, sizeof(*buf), "-Infinity");
} else {
- q = buf;
- if (d < 0)
- *q++ = '-';
- strcpy(q, "Infinity");
+ pstrcpy(*buf, sizeof(*buf), "Infinity");
}
} else if (flags == JS_DTOA_VAR_FORMAT) {
int64_t i64;
char buf1[70], *ptr;
+ if (d > (double)MAX_SAFE_INTEGER || d < (double)-MAX_SAFE_INTEGER)
+ goto generic_conv;
i64 = (int64_t)d;
- if (d != i64 || i64 > MAX_SAFE_INTEGER || i64 < -MAX_SAFE_INTEGER)
+ if (d != i64)
goto generic_conv;
/* fast path for integers */
ptr = i64toa(buf1 + sizeof(buf1), i64, radix);
- strcpy(buf, ptr);
+ pstrcpy(*buf, sizeof(*buf), ptr);
} else {
if (d == 0.0)
d = 0.0; /* convert -0 to 0 */
if (flags == JS_DTOA_FRAC_FORMAT) {
- js_fcvt(buf, JS_DTOA_BUF_SIZE, d, n_digits);
+ js_fcvt(buf, d, n_digits);
} else {
char buf1[JS_DTOA_BUF_SIZE];
int sign, decpt, k, n, i, p, n_max;
@@ -11560,7 +11635,7 @@ static void js_dtoa1(char *buf, double d, int radix, int n_digits, int flags)
/* the number has k digits (k >= 1) */
k = js_ecvt(d, n_digits, &decpt, &sign, buf1, is_fixed);
n = decpt; /* d=10^(n-k)*(buf1) i.e. d= < x.yyyy 10^(n-1) */
- q = buf;
+ q = *buf;
if (sign)
*q++ = '-';
if (flags & JS_DTOA_FORCE_EXP)
@@ -11602,7 +11677,7 @@ static void js_dtoa1(char *buf, double d, int radix, int n_digits, int flags)
p = n - 1;
if (p >= 0)
*q++ = '+';
- sprintf(q, "%d", p);
+ snprintf(q, *buf + sizeof(*buf) - q, "%d", p);
}
}
}
@@ -11612,10 +11687,84 @@ static JSValue js_dtoa(JSContext *ctx,
double d, int radix, int n_digits, int flags)
{
char buf[JS_DTOA_BUF_SIZE];
- js_dtoa1(buf, d, radix, n_digits, flags);
+ js_dtoa1(&buf, d, radix, n_digits, flags);
return JS_NewString(ctx, buf);
}
+static JSValue js_dtoa_radix(JSContext *ctx, double d, int radix)
+{
+ char buf[2200], *ptr, *ptr2;
+ /* d is finite */
+ int sign = d < 0;
+ int digit;
+ double frac, d0;
+ int64_t n0 = 0;
+ d = fabs(d);
+ d0 = trunc(d);
+ frac = d - d0;
+ ptr = buf + 1100;
+ *ptr = '\0';
+ if (d0 <= MAX_SAFE_INTEGER) {
+ int64_t n = n0 = (int64_t)d0;
+ while (n >= radix) {
+ digit = n % radix;
+ n = n / radix;
+ *--ptr = digits[digit];
+ }
+ *--ptr = digits[(int)n];
+ } else {
+ /* no decimals */
+ while (d0 >= radix) {
+ digit = fmod(d0, radix);
+ d0 = trunc(d0 / radix);
+ if (d0 >= MAX_SAFE_INTEGER)
+ digit = 0;
+ *--ptr = digits[digit];
+ }
+ *--ptr = digits[(int)d0];
+ goto done;
+ }
+ if (frac != 0) {
+ double log2_radix = log2(radix);
+ double prec = 1023 + 51; // handle subnormals
+ ptr2 = buf + 1100;
+ *ptr2++ = '.';
+ while (frac != 0 && n0 <= MAX_SAFE_INTEGER/2 && prec > 0) {
+ frac *= radix;
+ digit = trunc(frac);
+ frac -= digit;
+ *ptr2++ = digits[digit];
+ n0 = n0 * radix + digit;
+ prec -= log2_radix;
+ }
+ *ptr2 = '\0';
+ if (frac * radix >= radix / 2) {
+ char nine = digits[radix - 1];
+ // round to closest
+ while (ptr2[-1] == nine)
+ *--ptr2 = '\0';
+ if (ptr2[-1] == '.') {
+ *--ptr2 = '\0';
+ while (ptr2[-1] == nine)
+ *--ptr2 = '0';
+ }
+ if (ptr2 - 1 == ptr)
+ *--ptr = '1';
+ else
+ ptr2[-1] += 1;
+ } else {
+ while (ptr2[-1] == '0')
+ *--ptr2 = '\0';
+ if (ptr2[-1] == '.')
+ *--ptr2 = '\0';
+ }
+ }
+done:
+ ptr[-1] = '-';
+ ptr -= sign;
+ return JS_NewString(ctx, ptr);
+}
+
JSValue JS_ToStringInternal(JSContext *ctx, JSValueConst val, BOOL is_ToPropertyKey)
{
uint32_t tag;
@@ -11662,9 +11811,9 @@ JSValue JS_ToStringInternal(JSContext *ctx, JSValueConst val, BOOL is_ToProperty
case JS_TAG_FLOAT64:
return js_dtoa(ctx, JS_VALUE_GET_FLOAT64(val), 10, 0,
JS_DTOA_VAR_FORMAT);
-#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_INT:
return ctx->rt->bigint_ops.to_string(ctx, val);
+#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_FLOAT:
return ctx->rt->bigfloat_ops.to_string(ctx, val);
case JS_TAG_BIG_DECIMAL:
@@ -11756,7 +11905,7 @@ static JSValue JS_ToQuotedString(JSContext *ctx, JSValueConst val1)
goto fail;
break;
default:
- if (c < 32 || (c >= 0xd800 && c < 0xe000)) {
+ if (c < 32 || is_surrogate(c)) {
snprintf(buf, sizeof(buf), "\\u%04x", c);
if (string_buffer_puts8(b, buf))
goto fail;
@@ -11777,14 +11926,14 @@ static JSValue JS_ToQuotedString(JSContext *ctx, JSValueConst val1)
return JS_EXCEPTION;
}
-static maybe_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 maybe_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];
@@ -11825,10 +11974,8 @@ static maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p)
case JS_CLASS_UINT16_ARRAY:
case JS_CLASS_INT32_ARRAY:
case JS_CLASS_UINT32_ARRAY:
-#ifdef CONFIG_BIGNUM
case JS_CLASS_BIG_INT64_ARRAY:
case JS_CLASS_BIG_UINT64_ARRAY:
-#endif
case JS_CLASS_FLOAT32_ARRAY:
case JS_CLASS_FLOAT64_ARRAY:
{
@@ -11861,7 +12008,7 @@ static maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p)
printf("[autoinit %p %d %p]",
(void *)js_autoinit_get_realm(pr),
js_autoinit_get_id(pr),
- pr->u.init.opaque);
+ (void *)pr->u.init.opaque);
} else {
JS_DumpValueShort(rt, pr->u.value);
}
@@ -11890,7 +12037,7 @@ static maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p)
printf("\n");
}
-static maybe_unused void JS_DumpGCObject(JSRuntime *rt, JSGCObjectHeader *p)
+static __maybe_unused void JS_DumpGCObject(JSRuntime *rt, JSGCObjectHeader *p)
{
if (p->gc_obj_type == JS_GC_OBJ_TYPE_JS_OBJECT) {
JS_DumpObject(rt, (JSObject *)p);
@@ -11922,7 +12069,7 @@ static maybe_unused void JS_DumpGCObject(JSRuntime *rt, JSGCObjectHeader *p)
}
}
-static maybe_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);
@@ -11955,7 +12102,6 @@ static maybe_unused void JS_DumpValueShort(JSRuntime *rt,
case JS_TAG_FLOAT64:
printf("%.14g", JS_VALUE_GET_FLOAT64(val));
break;
-#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_INT:
{
JSBigFloat *p = JS_VALUE_GET_PTR(val);
@@ -11966,6 +12112,7 @@ static maybe_unused void JS_DumpValueShort(JSRuntime *rt,
bf_realloc(&rt->bf_ctx, str, 0);
}
break;
+#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_FLOAT:
{
JSBigFloat *p = JS_VALUE_GET_PTR(val);
@@ -12027,13 +12174,13 @@ static maybe_unused void JS_DumpValueShort(JSRuntime *rt,
}
}
-static maybe_unused void JS_DumpValue(JSContext *ctx,
+static __maybe_unused void JS_DumpValue(JSContext *ctx,
JSValueConst val)
{
JS_DumpValueShort(ctx->rt, val);
}
-static maybe_unused void JS_PrintValue(JSContext *ctx,
+static __maybe_unused void JS_PrintValue(JSContext *ctx,
const char *str,
JSValueConst val)
{
@@ -12043,15 +12190,14 @@ static maybe_unused void JS_PrintValue(JSContext *ctx,
}
/* return -1 if exception (proxy case) or TRUE/FALSE */
+// TODO: should take flags to make proxy resolution and exceptions optional
int JS_IsArray(JSContext *ctx, JSValueConst val)
{
- JSObject *p;
+ if (js_resolve_proxy(ctx, &val, TRUE))
+ return -1;
if (JS_VALUE_GET_TAG(val) == JS_TAG_OBJECT) {
- p = JS_VALUE_GET_OBJ(val);
- if (unlikely(p->class_id == JS_CLASS_PROXY))
- return js_proxy_isArray(ctx, val);
- else
- return p->class_id == JS_CLASS_ARRAY;
+ JSObject *p = JS_VALUE_GET_OBJ(val);
+ return p->class_id == JS_CLASS_ARRAY;
} else {
return FALSE;
}
@@ -12067,8 +12213,6 @@ static double js_pow(double a, double b)
}
}
-#ifdef CONFIG_BIGNUM
-
JSValue JS_NewBigInt64_1(JSContext *ctx, int64_t v)
{
JSValue val;
@@ -12113,70 +12257,6 @@ JSValue JS_NewBigUint64(JSContext *ctx, uint64_t v)
return val;
}
-/* if the returned bigfloat is allocated it is equal to
- 'buf'. Otherwise it is a pointer to the bigfloat in 'val'. Return
- NULL in case of error. */
-static bf_t *JS_ToBigFloat(JSContext *ctx, bf_t *buf, JSValueConst val)
-{
- uint32_t tag;
- bf_t *r;
- JSBigFloat *p;
-
- tag = JS_VALUE_GET_NORM_TAG(val);
- switch(tag) {
- case JS_TAG_INT:
- case JS_TAG_BOOL:
- case JS_TAG_NULL:
- r = buf;
- bf_init(ctx->bf_ctx, r);
- if (bf_set_si(r, JS_VALUE_GET_INT(val)))
- goto fail;
- break;
- case JS_TAG_FLOAT64:
- r = buf;
- bf_init(ctx->bf_ctx, r);
- if (bf_set_float64(r, JS_VALUE_GET_FLOAT64(val))) {
- fail:
- bf_delete(r);
- return NULL;
- }
- break;
- case JS_TAG_BIG_INT:
- case JS_TAG_BIG_FLOAT:
- p = JS_VALUE_GET_PTR(val);
- r = &p->num;
- break;
- case JS_TAG_UNDEFINED:
- default:
- r = buf;
- bf_init(ctx->bf_ctx, r);
- bf_set_nan(r);
- break;
- }
- return r;
-}
-
-/* return NULL if invalid type */
-static bfdec_t *JS_ToBigDecimal(JSContext *ctx, JSValueConst val)
-{
- uint32_t tag;
- JSBigDecimal *p;
- bfdec_t *r;
-
- tag = JS_VALUE_GET_NORM_TAG(val);
- switch(tag) {
- case JS_TAG_BIG_DECIMAL:
- p = JS_VALUE_GET_PTR(val);
- r = &p->num;
- break;
- default:
- JS_ThrowTypeError(ctx, "bigdecimal expected");
- r = NULL;
- break;
- }
- return r;
-}
-
/* return NaN if bad bigint literal */
static JSValue JS_StringToBigInt(JSContext *ctx, JSValue val)
{
@@ -12194,8 +12274,10 @@ static JSValue JS_StringToBigInt(JSContext *ctx, JSValue val)
val = JS_NewBigInt64(ctx, 0);
} else {
flags = ATOD_INT_ONLY | ATOD_ACCEPT_BIN_OCT | ATOD_TYPE_BIG_INT;
+#ifdef CONFIG_BIGNUM
if (is_math_mode(ctx))
flags |= ATOD_MODE_BIGINT;
+#endif
val = js_atof(ctx, p, &p, 0, flags);
p += skip_spaces(p);
if (!JS_IsException(val)) {
@@ -12256,6 +12338,7 @@ static bf_t *JS_ToBigIntFree(JSContext *ctx, bf_t *buf, JSValue val)
p = JS_VALUE_GET_PTR(val);
r = &p->num;
break;
+#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_FLOAT:
if (!is_math_mode(ctx))
goto fail;
@@ -12268,6 +12351,7 @@ static bf_t *JS_ToBigIntFree(JSContext *ctx, bf_t *buf, JSValue val)
bf_rint(r, BF_RNDZ);
JS_FreeValue(ctx, val);
break;
+#endif
case JS_TAG_STRING:
val = JS_StringToBigIntErr(ctx, val);
if (JS_IsException(val))
@@ -12328,7 +12412,7 @@ static void JS_FreeBigInt(JSContext *ctx, bf_t *a, bf_t *buf)
} else {
JSBigFloat *p = (JSBigFloat *)((uint8_t *)a -
offsetof(JSBigFloat, num));
- JS_FreeValue(ctx, JS_MKPTR(JS_TAG_BIG_FLOAT, p));
+ JS_FreeValue(ctx, JS_MKPTR(JS_TAG_BIG_INT, p));
}
}
@@ -12363,28 +12447,6 @@ static JSBigFloat *js_new_bf(JSContext *ctx)
return p;
}
-static JSValue JS_NewBigFloat(JSContext *ctx)
-{
- JSBigFloat *p;
- p = js_malloc(ctx, sizeof(*p));
- if (!p)
- return JS_EXCEPTION;
- p->header.ref_count = 1;
- bf_init(ctx->bf_ctx, &p->num);
- return JS_MKPTR(JS_TAG_BIG_FLOAT, p);
-}
-
-static JSValue JS_NewBigDecimal(JSContext *ctx)
-{
- JSBigDecimal *p;
- p = js_malloc(ctx, sizeof(*p));
- if (!p)
- return JS_EXCEPTION;
- p->header.ref_count = 1;
- bfdec_init(ctx->bf_ctx, &p->num);
- return JS_MKPTR(JS_TAG_BIG_DECIMAL, p);
-}
-
static JSValue JS_NewBigInt(JSContext *ctx)
{
JSBigFloat *p;
@@ -12426,6 +12488,110 @@ static JSValue JS_CompactBigInt(JSContext *ctx, JSValue val)
return JS_CompactBigInt1(ctx, val, is_math_mode(ctx));
}
+static JSValue throw_bf_exception(JSContext *ctx, int status)
+{
+ const char *str;
+ if (status & BF_ST_MEM_ERROR)
+ return JS_ThrowOutOfMemory(ctx);
+ if (status & BF_ST_DIVIDE_ZERO) {
+ str = "division by zero";
+ } else if (status & BF_ST_INVALID_OP) {
+ str = "invalid operation";
+ } else {
+ str = "integer overflow";
+ }
+ return JS_ThrowRangeError(ctx, "%s", str);
+}
+
+/* if the returned bigfloat is allocated it is equal to
+ 'buf'. Otherwise it is a pointer to the bigfloat in 'val'. Return
+ NULL in case of error. */
+static bf_t *JS_ToBigFloat(JSContext *ctx, bf_t *buf, JSValueConst val)
+{
+ uint32_t tag;
+ bf_t *r;
+ JSBigFloat *p;
+
+ tag = JS_VALUE_GET_NORM_TAG(val);
+ switch(tag) {
+ case JS_TAG_INT:
+ case JS_TAG_BOOL:
+ case JS_TAG_NULL:
+ r = buf;
+ bf_init(ctx->bf_ctx, r);
+ if (bf_set_si(r, JS_VALUE_GET_INT(val)))
+ goto fail;
+ break;
+ case JS_TAG_FLOAT64:
+ r = buf;
+ bf_init(ctx->bf_ctx, r);
+ if (bf_set_float64(r, JS_VALUE_GET_FLOAT64(val))) {
+ fail:
+ bf_delete(r);
+ return NULL;
+ }
+ break;
+ case JS_TAG_BIG_INT:
+#ifdef CONFIG_BIGNUM
+ case JS_TAG_BIG_FLOAT:
+#endif
+ p = JS_VALUE_GET_PTR(val);
+ r = &p->num;
+ break;
+ case JS_TAG_UNDEFINED:
+ default:
+ r = buf;
+ bf_init(ctx->bf_ctx, r);
+ bf_set_nan(r);
+ break;
+ }
+ return r;
+}
+
+#ifdef CONFIG_BIGNUM
+/* return NULL if invalid type */
+static bfdec_t *JS_ToBigDecimal(JSContext *ctx, JSValueConst val)
+{
+ uint32_t tag;
+ JSBigDecimal *p;
+ bfdec_t *r;
+
+ tag = JS_VALUE_GET_NORM_TAG(val);
+ switch(tag) {
+ case JS_TAG_BIG_DECIMAL:
+ p = JS_VALUE_GET_PTR(val);
+ r = &p->num;
+ break;
+ default:
+ JS_ThrowTypeError(ctx, "bigdecimal expected");
+ r = NULL;
+ break;
+ }
+ return r;
+}
+
+static JSValue JS_NewBigFloat(JSContext *ctx)
+{
+ JSBigFloat *p;
+ p = js_malloc(ctx, sizeof(*p));
+ if (!p)
+ return JS_EXCEPTION;
+ p->header.ref_count = 1;
+ bf_init(ctx->bf_ctx, &p->num);
+ return JS_MKPTR(JS_TAG_BIG_FLOAT, p);
+}
+
+static JSValue JS_NewBigDecimal(JSContext *ctx)
+{
+ JSBigDecimal *p;
+ p = js_malloc(ctx, sizeof(*p));
+ if (!p)
+ return JS_EXCEPTION;
+ p->header.ref_count = 1;
+ bfdec_init(ctx->bf_ctx, &p->num);
+ return JS_MKPTR(JS_TAG_BIG_DECIMAL, p);
+}
+
/* must be kept in sync with JSOverloadableOperatorEnum */
/* XXX: use atoms ? */
static const char js_overloadable_operator_names[JS_OVOP_COUNT][4] = {
@@ -12516,7 +12682,7 @@ static JSObject *find_binary_op(JSBinaryOperatorDef *def,
/* return -1 if exception, 0 if no operator overloading, 1 if
overloaded operator called */
-static WARN_UNUSED int js_call_binary_op_fallback(JSContext *ctx,
+static __exception int js_call_binary_op_fallback(JSContext *ctx,
JSValue *pret,
JSValueConst op1,
JSValueConst op2,
@@ -12645,7 +12811,7 @@ static WARN_UNUSED int js_call_binary_op_fallback(JSContext *ctx,
/* try to call the operation on the operatorSet field of 'obj'. Only
used for "/" and "**" on the BigInt prototype in math mode */
-static WARN_UNUSED int js_call_binary_op_simple(JSContext *ctx,
+static __exception int js_call_binary_op_simple(JSContext *ctx,
JSValue *pret,
JSValueConst obj,
JSValueConst op1,
@@ -12702,7 +12868,7 @@ static WARN_UNUSED int js_call_binary_op_simple(JSContext *ctx,
/* return -1 if exception, 0 if no operator overloading, 1 if
overloaded operator called */
-static WARN_UNUSED int js_call_unary_op_fallback(JSContext *ctx,
+static __exception int js_call_unary_op_fallback(JSContext *ctx,
JSValue *pret,
JSValueConst op1,
OPCodeEnum op)
@@ -12749,46 +12915,37 @@ static WARN_UNUSED int js_call_unary_op_fallback(JSContext *ctx,
return -1;
}
-static JSValue throw_bf_exception(JSContext *ctx, int status)
-{
- const char *str;
- if (status & BF_ST_MEM_ERROR)
- return JS_ThrowOutOfMemory(ctx);
- if (status & BF_ST_DIVIDE_ZERO) {
- str = "division by zero";
- } else if (status & BF_ST_INVALID_OP) {
- str = "invalid operation";
- } else {
- str = "integer overflow";
- }
- return JS_ThrowRangeError(ctx, "%s", str);
-}
-
-static int js_unary_arith_bigint(JSContext *ctx,
- JSValue *pres, OPCodeEnum op, JSValue op1)
+static int js_unary_arith_bigfloat(JSContext *ctx,
+ JSValue *pres, OPCodeEnum op, JSValue op1)
{
bf_t a_s, *r, *a;
int ret, v;
JSValue res;
if (op == OP_plus && !is_math_mode(ctx)) {
- JS_ThrowTypeError(ctx, "bigint argument with unary +");
+ JS_ThrowTypeError(ctx, "bigfloat argument with unary +");
JS_FreeValue(ctx, op1);
return -1;
}
- res = JS_NewBigInt(ctx);
+
+ res = JS_NewBigFloat(ctx);
if (JS_IsException(res)) {
JS_FreeValue(ctx, op1);
return -1;
}
- r = JS_GetBigInt(res);
- a = JS_ToBigInt(ctx, &a_s, op1);
+ r = JS_GetBigFloat(res);
+ a = JS_ToBigFloat(ctx, &a_s, op1);
+ if (!a) {
+ JS_FreeValue(ctx, res);
+ JS_FreeValue(ctx, op1);
+ return -1;
+ }
ret = 0;
switch(op) {
case OP_inc:
case OP_dec:
v = 2 * (op - OP_dec) - 1;
- ret = bf_add_si(r, a, v, BF_PREC_INF, BF_RNDZ);
+ ret = bf_add_si(r, a, v, ctx->fp_env.prec, ctx->fp_env.flags);
break;
case OP_plus:
ret = bf_set(r, a);
@@ -12797,66 +12954,65 @@ static int js_unary_arith_bigint(JSContext *ctx,
ret = bf_set(r, a);
bf_neg(r);
break;
- case OP_not:
- ret = bf_add_si(r, a, 1, BF_PREC_INF, BF_RNDZ);
- bf_neg(r);
- break;
default:
abort();
}
- JS_FreeBigInt(ctx, a, &a_s);
+ if (a == &a_s)
+ bf_delete(a);
JS_FreeValue(ctx, op1);
- if (unlikely(ret)) {
+ if (unlikely(ret & BF_ST_MEM_ERROR)) {
JS_FreeValue(ctx, res);
throw_bf_exception(ctx, ret);
return -1;
}
- res = JS_CompactBigInt(ctx, res);
*pres = res;
return 0;
}
-static int js_unary_arith_bigfloat(JSContext *ctx,
- JSValue *pres, OPCodeEnum op, JSValue op1)
+static int js_unary_arith_bigdecimal(JSContext *ctx,
+ JSValue *pres, OPCodeEnum op, JSValue op1)
{
- bf_t a_s, *r, *a;
+ bfdec_t *r, *a;
int ret, v;
JSValue res;
if (op == OP_plus && !is_math_mode(ctx)) {
- JS_ThrowTypeError(ctx, "bigfloat argument with unary +");
+ JS_ThrowTypeError(ctx, "bigdecimal argument with unary +");
JS_FreeValue(ctx, op1);
return -1;
}
- res = JS_NewBigFloat(ctx);
+ res = JS_NewBigDecimal(ctx);
if (JS_IsException(res)) {
JS_FreeValue(ctx, op1);
return -1;
}
- r = JS_GetBigFloat(res);
- a = JS_ToBigFloat(ctx, &a_s, op1);
+ r = JS_GetBigDecimal(res);
+ a = JS_ToBigDecimal(ctx, op1);
+ if (!a) {
+ JS_FreeValue(ctx, res);
+ JS_FreeValue(ctx, op1);
+ return -1;
+ }
ret = 0;
switch(op) {
case OP_inc:
case OP_dec:
v = 2 * (op - OP_dec) - 1;
- ret = bf_add_si(r, a, v, ctx->fp_env.prec, ctx->fp_env.flags);
+ ret = bfdec_add_si(r, a, v, BF_PREC_INF, BF_RNDZ);
break;
case OP_plus:
- ret = bf_set(r, a);
+ ret = bfdec_set(r, a);
break;
case OP_neg:
- ret = bf_set(r, a);
- bf_neg(r);
+ ret = bfdec_set(r, a);
+ bfdec_neg(r);
break;
default:
abort();
}
- if (a == &a_s)
- bf_delete(a);
JS_FreeValue(ctx, op1);
- if (unlikely(ret & BF_ST_MEM_ERROR)) {
+ if (unlikely(ret)) {
JS_FreeValue(ctx, res);
throw_bf_exception(ctx, ret);
return -1;
@@ -12865,67 +13021,81 @@ static int js_unary_arith_bigfloat(JSContext *ctx,
return 0;
}
-static int js_unary_arith_bigdecimal(JSContext *ctx,
- JSValue *pres, OPCodeEnum op, JSValue op1)
+#endif /* CONFIG_BIGNUM */
+
+static int js_unary_arith_bigint(JSContext *ctx,
+ JSValue *pres, OPCodeEnum op, JSValue op1)
{
- bfdec_t *r, *a;
+ bf_t a_s, *r, *a;
int ret, v;
JSValue res;
if (op == OP_plus && !is_math_mode(ctx)) {
- JS_ThrowTypeError(ctx, "bigdecimal argument with unary +");
+ JS_ThrowTypeError(ctx, "bigint argument with unary +");
JS_FreeValue(ctx, op1);
return -1;
}
-
- res = JS_NewBigDecimal(ctx);
+ res = JS_NewBigInt(ctx);
if (JS_IsException(res)) {
JS_FreeValue(ctx, op1);
return -1;
}
- r = JS_GetBigDecimal(res);
- a = JS_ToBigDecimal(ctx, op1);
+ r = JS_GetBigInt(res);
+ a = JS_ToBigInt(ctx, &a_s, op1);
+ if (!a) {
+ JS_FreeValue(ctx, res);
+ JS_FreeValue(ctx, op1);
+ return -1;
+ }
ret = 0;
switch(op) {
case OP_inc:
case OP_dec:
v = 2 * (op - OP_dec) - 1;
- ret = bfdec_add_si(r, a, v, BF_PREC_INF, BF_RNDZ);
+ ret = bf_add_si(r, a, v, BF_PREC_INF, BF_RNDZ);
break;
case OP_plus:
- ret = bfdec_set(r, a);
+ ret = bf_set(r, a);
break;
case OP_neg:
- ret = bfdec_set(r, a);
- bfdec_neg(r);
+ ret = bf_set(r, a);
+ bf_neg(r);
+ break;
+ case OP_not:
+ ret = bf_add_si(r, a, 1, BF_PREC_INF, BF_RNDZ);
+ bf_neg(r);
break;
default:
abort();
}
+ JS_FreeBigInt(ctx, a, &a_s);
JS_FreeValue(ctx, op1);
if (unlikely(ret)) {
JS_FreeValue(ctx, res);
throw_bf_exception(ctx, ret);
return -1;
}
+ res = JS_CompactBigInt(ctx, res);
*pres = res;
return 0;
}
-static no_inline WARN_UNUSED int js_unary_arith_slow(JSContext *ctx,
+static no_inline __exception int js_unary_arith_slow(JSContext *ctx,
JSValue *sp,
OPCodeEnum op)
{
- JSValue op1, val;
- int v, ret;
+ JSValue op1;
+ int v;
uint32_t tag;
op1 = sp[-1];
/* fast path for float64 */
if (JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(op1)))
goto handle_float64;
+#ifdef CONFIG_BIGNUM
if (JS_IsObject(op1)) {
- ret = js_call_unary_op_fallback(ctx, &val, op1, op);
+ JSValue val;
+ int ret = js_call_unary_op_fallback(ctx, &val, op1, op);
if (ret < 0)
return -1;
if (ret) {
@@ -12934,7 +13104,7 @@ static no_inline WARN_UNUSED int js_unary_arith_slow(JSContext *ctx,
return 0;
}
}
-
+#endif
op1 = JS_ToNumericFree(ctx, op1);
if (JS_IsException(op1))
goto exception;
@@ -12954,7 +13124,7 @@ static no_inline WARN_UNUSED int js_unary_arith_slow(JSContext *ctx,
break;
case OP_neg:
if (v64 == 0) {
- sp[-1] = __JS_NewFloat64(ctx, -0.0);
+ sp[-1] = JS_NewFloat64(ctx, -0.0);
return 0;
} else {
v64 = -v64;
@@ -12971,6 +13141,7 @@ static no_inline WARN_UNUSED int js_unary_arith_slow(JSContext *ctx,
if (ctx->rt->bigint_ops.unary_arith(ctx, sp - 1, op, op1))
goto exception;
break;
+#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_FLOAT:
if (ctx->rt->bigfloat_ops.unary_arith(ctx, sp - 1, op, op1))
goto exception;
@@ -12979,6 +13150,7 @@ static no_inline WARN_UNUSED int js_unary_arith_slow(JSContext *ctx,
if (ctx->rt->bigdecimal_ops.unary_arith(ctx, sp - 1, op, op1))
goto exception;
break;
+#endif
default:
handle_float64:
{
@@ -13000,7 +13172,7 @@ static no_inline WARN_UNUSED int js_unary_arith_slow(JSContext *ctx,
default:
abort();
}
- sp[-1] = __JS_NewFloat64(ctx, d);
+ sp[-1] = JS_NewFloat64(ctx, d);
}
break;
}
@@ -13010,7 +13182,7 @@ static no_inline WARN_UNUSED int js_unary_arith_slow(JSContext *ctx,
return -1;
}
-static WARN_UNUSED int js_post_inc_slow(JSContext *ctx,
+static __exception int js_post_inc_slow(JSContext *ctx,
JSValue *sp, OPCodeEnum op)
{
JSValue op1;
@@ -13029,12 +13201,13 @@ static WARN_UNUSED int js_post_inc_slow(JSContext *ctx,
static no_inline int js_not_slow(JSContext *ctx, JSValue *sp)
{
- JSValue op1, val;
- int ret;
+ JSValue op1;
op1 = sp[-1];
+#ifdef CONFIG_BIGNUM
if (JS_IsObject(op1)) {
- ret = js_call_unary_op_fallback(ctx, &val, op1, OP_not);
+ JSValue val;
+ int ret = js_call_unary_op_fallback(ctx, &val, op1, OP_not);
if (ret < 0)
return -1;
if (ret) {
@@ -13043,7 +13216,7 @@ static no_inline int js_not_slow(JSContext *ctx, JSValue *sp)
return 0;
}
}
-
+#endif
op1 = JS_ToNumericFree(ctx, op1);
if (JS_IsException(op1))
goto exception;
@@ -13062,67 +13235,6 @@ static no_inline int js_not_slow(JSContext *ctx, JSValue *sp)
return -1;
}
-static int js_binary_arith_bigfloat(JSContext *ctx, OPCodeEnum op,
- JSValue *pres, JSValue op1, JSValue op2)
-{
- bf_t a_s, b_s, *r, *a, *b;
- int ret;
- JSValue res;
-
- res = JS_NewBigFloat(ctx);
- if (JS_IsException(res)) {
- JS_FreeValue(ctx, op1);
- JS_FreeValue(ctx, op2);
- return -1;
- }
- r = JS_GetBigFloat(res);
- a = JS_ToBigFloat(ctx, &a_s, op1);
- b = JS_ToBigFloat(ctx, &b_s, op2);
- bf_init(ctx->bf_ctx, r);
- switch(op) {
- case OP_add:
- ret = bf_add(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags);
- break;
- case OP_sub:
- ret = bf_sub(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags);
- break;
- case OP_mul:
- ret = bf_mul(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags);
- break;
- case OP_div:
- ret = bf_div(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags);
- break;
- case OP_math_mod:
- /* Euclidian remainder */
- ret = bf_rem(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags,
- BF_DIVREM_EUCLIDIAN);
- break;
- case OP_mod:
- ret = bf_rem(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags,
- BF_RNDZ);
- break;
- case OP_pow:
- ret = bf_pow(r, a, b, ctx->fp_env.prec,
- ctx->fp_env.flags | BF_POW_JS_QUIRKS);
- break;
- default:
- abort();
- }
- if (a == &a_s)
- bf_delete(a);
- if (b == &b_s)
- bf_delete(b);
- JS_FreeValue(ctx, op1);
- JS_FreeValue(ctx, op2);
- if (unlikely(ret & BF_ST_MEM_ERROR)) {
- JS_FreeValue(ctx, res);
- throw_bf_exception(ctx, ret);
- return -1;
- }
- *pres = res;
- return 0;
-}
-
static int js_binary_arith_bigint(JSContext *ctx, OPCodeEnum op,
JSValue *pres, JSValue op1, JSValue op2)
{
@@ -13164,11 +13276,13 @@ static int js_binary_arith_bigint(JSContext *ctx, OPCodeEnum op,
goto math_mode_div_pow;
}
break;
+#ifdef CONFIG_BIGNUM
case OP_math_mod:
/* Euclidian remainder */
ret = bf_rem(r, a, b, BF_PREC_INF, BF_RNDZ,
BF_DIVREM_EUCLIDIAN) & BF_ST_INVALID_OP;
break;
+#endif
case OP_mod:
ret = bf_rem(r, a, b, BF_PREC_INF, BF_RNDZ,
BF_RNDZ) & BF_ST_INVALID_OP;
@@ -13179,6 +13293,7 @@ static int js_binary_arith_bigint(JSContext *ctx, OPCodeEnum op,
ret = BF_ST_INVALID_OP;
} else {
math_mode_div_pow:
+#ifdef CONFIG_BIGNUM
JS_FreeValue(ctx, res);
ret = js_call_binary_op_simple(ctx, &res, ctx->class_proto[JS_CLASS_BIG_INT], op1, op2, op);
if (ret != 0) {
@@ -13219,6 +13334,9 @@ static int js_binary_arith_bigint(JSContext *ctx, OPCodeEnum op,
}
*pres = res;
return 0;
+#else
+ abort();
+#endif
}
} else {
ret = bf_pow(r, a, b, BF_PREC_INF, BF_RNDZ | BF_POW_JS_QUIRKS);
@@ -13278,6 +13396,79 @@ static int js_binary_arith_bigint(JSContext *ctx, OPCodeEnum op,
return -1;
}
+#ifdef CONFIG_BIGNUM
+static int js_binary_arith_bigfloat(JSContext *ctx, OPCodeEnum op,
+ JSValue *pres, JSValue op1, JSValue op2)
+{
+ bf_t a_s, b_s, *r, *a, *b;
+ int ret;
+ JSValue res;
+
+ res = JS_NewBigFloat(ctx);
+ if (JS_IsException(res))
+ goto fail;
+ r = JS_GetBigFloat(res);
+ a = JS_ToBigFloat(ctx, &a_s, op1);
+ if (!a) {
+ JS_FreeValue(ctx, res);
+ goto fail;
+ }
+ b = JS_ToBigFloat(ctx, &b_s, op2);
+ if (!b) {
+ if (a == &a_s)
+ bf_delete(a);
+ JS_FreeValue(ctx, res);
+ goto fail;
+ }
+ bf_init(ctx->bf_ctx, r);
+ switch(op) {
+ case OP_add:
+ ret = bf_add(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags);
+ break;
+ case OP_sub:
+ ret = bf_sub(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags);
+ break;
+ case OP_mul:
+ ret = bf_mul(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags);
+ break;
+ case OP_div:
+ ret = bf_div(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags);
+ break;
+ case OP_math_mod:
+ /* Euclidian remainder */
+ ret = bf_rem(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags,
+ BF_DIVREM_EUCLIDIAN);
+ break;
+ case OP_mod:
+ ret = bf_rem(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags,
+ BF_RNDZ);
+ break;
+ case OP_pow:
+ ret = bf_pow(r, a, b, ctx->fp_env.prec,
+ ctx->fp_env.flags | BF_POW_JS_QUIRKS);
+ break;
+ default:
+ abort();
+ }
+ if (a == &a_s)
+ bf_delete(a);
+ if (b == &b_s)
+ bf_delete(b);
+ JS_FreeValue(ctx, op1);
+ JS_FreeValue(ctx, op2);
+ if (unlikely(ret & BF_ST_MEM_ERROR)) {
+ JS_FreeValue(ctx, res);
+ throw_bf_exception(ctx, ret);
+ return -1;
+ }
+ *pres = res;
+ return 0;
+ fail:
+ JS_FreeValue(ctx, op1);
+ JS_FreeValue(ctx, op2);
+ return -1;
+}
+
/* b must be a positive integer */
static int js_bfdec_pow(bfdec_t *r, const bfdec_t *a, const bfdec_t *b)
{
@@ -13364,13 +13555,13 @@ static int js_binary_arith_bigdecimal(JSContext *ctx, OPCodeEnum op,
JS_FreeValue(ctx, op2);
return -1;
}
+#endif /* CONFIG_BIGNUM */
-static no_inline WARN_UNUSED int js_binary_arith_slow(JSContext *ctx, JSValue *sp,
+static no_inline __exception int js_binary_arith_slow(JSContext *ctx, JSValue *sp,
OPCodeEnum op)
{
- JSValue op1, op2, res;
+ JSValue op1, op2;
uint32_t tag1, tag2;
- int ret;
double d1, d2;
op1 = sp[-2];
@@ -13384,12 +13575,14 @@ static no_inline WARN_UNUSED int js_binary_arith_slow(JSContext *ctx, JSValue *s
goto handle_float64;
}
+#ifdef CONFIG_BIGNUM
/* try to call an overloaded operator */
if ((tag1 == JS_TAG_OBJECT &&
(tag2 != JS_TAG_NULL && tag2 != JS_TAG_UNDEFINED)) ||
(tag2 == JS_TAG_OBJECT &&
(tag1 != JS_TAG_NULL && tag1 != JS_TAG_UNDEFINED))) {
- ret = js_call_binary_op_fallback(ctx, &res, op1, op2, op, TRUE, 0);
+ JSValue res;
+ int ret = js_call_binary_op_fallback(ctx, &res, op1, op2, op, TRUE, 0);
if (ret != 0) {
JS_FreeValue(ctx, op1);
JS_FreeValue(ctx, op2);
@@ -13401,6 +13594,7 @@ static no_inline WARN_UNUSED int js_binary_arith_slow(JSContext *ctx, JSValue *s
}
}
}
+#endif
op1 = JS_ToNumericFree(ctx, op1);
if (JS_IsException(op1)) {
@@ -13430,15 +13624,16 @@ static no_inline WARN_UNUSED int js_binary_arith_slow(JSContext *ctx, JSValue *s
(v < -MAX_SAFE_INTEGER || v > MAX_SAFE_INTEGER))
goto handle_bigint;
if (v == 0 && (v1 | v2) < 0) {
- sp[-2] = __JS_NewFloat64(ctx, -0.0);
+ sp[-2] = JS_NewFloat64(ctx, -0.0);
return 0;
}
break;
case OP_div:
if (is_math_mode(ctx))
goto handle_bigint;
- sp[-2] = __JS_NewFloat64(ctx, (double)v1 / (double)v2);
+ sp[-2] = JS_NewFloat64(ctx, (double)v1 / (double)v2);
return 0;
+#ifdef CONFIG_BIGNUM
case OP_math_mod:
if (unlikely(v2 == 0)) {
throw_bf_exception(ctx, BF_ST_DIVIDE_ZERO);
@@ -13452,6 +13647,7 @@ static no_inline WARN_UNUSED int js_binary_arith_slow(JSContext *ctx, JSValue *s
v += v2;
}
break;
+#endif
case OP_mod:
if (v1 < 0 || v2 <= 0) {
sp[-2] = JS_NewFloat64(ctx, fmod(v1, v2));
@@ -13472,13 +13668,17 @@ static no_inline WARN_UNUSED int js_binary_arith_slow(JSContext *ctx, JSValue *s
abort();
}
sp[-2] = JS_NewInt64(ctx, v);
- } else if (tag1 == JS_TAG_BIG_DECIMAL || tag2 == JS_TAG_BIG_DECIMAL) {
+ } else
+#ifdef CONFIG_BIGNUM
+ if (tag1 == JS_TAG_BIG_DECIMAL || tag2 == JS_TAG_BIG_DECIMAL) {
if (ctx->rt->bigdecimal_ops.binary_arith(ctx, op, sp - 2, op1, op2))
goto exception;
} else if (tag1 == JS_TAG_BIG_FLOAT || tag2 == JS_TAG_BIG_FLOAT) {
if (ctx->rt->bigfloat_ops.binary_arith(ctx, op, sp - 2, op1, op2))
goto exception;
- } else if (tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) {
+ } else
+#endif
+ if (tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) {
handle_bigint:
if (ctx->rt->bigint_ops.binary_arith(ctx, op, sp - 2, op1, op2))
goto exception;
@@ -13507,6 +13707,7 @@ static no_inline WARN_UNUSED int js_binary_arith_slow(JSContext *ctx, JSValue *s
case OP_mod:
dr = fmod(d1, d2);
break;
+#ifdef CONFIG_BIGNUM
case OP_math_mod:
d2 = fabs(d2);
dr = fmod(d1, d2);
@@ -13514,13 +13715,14 @@ static no_inline WARN_UNUSED int js_binary_arith_slow(JSContext *ctx, JSValue *s
if (dr < 0)
dr += d2;
break;
+#endif
case OP_pow:
dr = js_pow(d1, d2);
break;
default:
abort();
}
- sp[-2] = __JS_NewFloat64(ctx, dr);
+ sp[-2] = JS_NewFloat64(ctx, dr);
}
return 0;
exception:
@@ -13529,11 +13731,10 @@ static no_inline WARN_UNUSED int js_binary_arith_slow(JSContext *ctx, JSValue *s
return -1;
}
-static no_inline WARN_UNUSED int js_add_slow(JSContext *ctx, JSValue *sp)
+static no_inline __exception int js_add_slow(JSContext *ctx, JSValue *sp)
{
- JSValue op1, op2, res;
+ JSValue op1, op2;
uint32_t tag1, tag2;
- int ret;
op1 = sp[-2];
op2 = sp[-1];
@@ -13545,11 +13746,12 @@ static no_inline WARN_UNUSED int js_add_slow(JSContext *ctx, JSValue *sp)
double d1, d2;
d1 = JS_VALUE_GET_FLOAT64(op1);
d2 = JS_VALUE_GET_FLOAT64(op2);
- sp[-2] = __JS_NewFloat64(ctx, d1 + d2);
+ sp[-2] = JS_NewFloat64(ctx, d1 + d2);
return 0;
}
if (tag1 == JS_TAG_OBJECT || tag2 == JS_TAG_OBJECT) {
+#ifdef CONFIG_BIGNUM
/* try to call an overloaded operator */
if ((tag1 == JS_TAG_OBJECT &&
(tag2 != JS_TAG_NULL && tag2 != JS_TAG_UNDEFINED &&
@@ -13557,8 +13759,9 @@ static no_inline WARN_UNUSED int js_add_slow(JSContext *ctx, JSValue *sp)
(tag2 == JS_TAG_OBJECT &&
(tag1 != JS_TAG_NULL && tag1 != JS_TAG_UNDEFINED &&
tag1 != JS_TAG_STRING))) {
- ret = js_call_binary_op_fallback(ctx, &res, op1, op2, OP_add,
- FALSE, HINT_NONE);
+ JSValue res;
+ int ret = js_call_binary_op_fallback(ctx, &res, op1, op2, OP_add,
+ FALSE, HINT_NONE);
if (ret != 0) {
JS_FreeValue(ctx, op1);
JS_FreeValue(ctx, op2);
@@ -13570,7 +13773,7 @@ static no_inline WARN_UNUSED int js_add_slow(JSContext *ctx, JSValue *sp)
}
}
}
-
+#endif
op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NONE);
if (JS_IsException(op1)) {
JS_FreeValue(ctx, op2);
@@ -13613,13 +13816,17 @@ static no_inline WARN_UNUSED int js_add_slow(JSContext *ctx, JSValue *sp)
v2 = JS_VALUE_GET_INT(op2);
v = (int64_t)v1 + (int64_t)v2;
sp[-2] = JS_NewInt64(ctx, v);
- } else if (tag1 == JS_TAG_BIG_DECIMAL || tag2 == JS_TAG_BIG_DECIMAL) {
+ } else
+#ifdef CONFIG_BIGNUM
+ if (tag1 == JS_TAG_BIG_DECIMAL || tag2 == JS_TAG_BIG_DECIMAL) {
if (ctx->rt->bigdecimal_ops.binary_arith(ctx, OP_add, sp - 2, op1, op2))
goto exception;
} else if (tag1 == JS_TAG_BIG_FLOAT || tag2 == JS_TAG_BIG_FLOAT) {
if (ctx->rt->bigfloat_ops.binary_arith(ctx, OP_add, sp - 2, op1, op2))
goto exception;
- } else if (tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) {
+ } else
+#endif
+ if (tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) {
handle_bigint:
if (ctx->rt->bigint_ops.binary_arith(ctx, OP_add, sp - 2, op1, op2))
goto exception;
@@ -13634,7 +13841,7 @@ static no_inline WARN_UNUSED int js_add_slow(JSContext *ctx, JSValue *sp)
goto exception;
if (is_math_mode(ctx) && is_safe_integer(d1) && is_safe_integer(d2))
goto handle_bigint;
- sp[-2] = __JS_NewFloat64(ctx, d1 + d2);
+ sp[-2] = JS_NewFloat64(ctx, d1 + d2);
}
return 0;
exception:
@@ -13643,12 +13850,11 @@ static no_inline WARN_UNUSED int js_add_slow(JSContext *ctx, JSValue *sp)
return -1;
}
-static no_inline WARN_UNUSED int js_binary_logic_slow(JSContext *ctx,
+static no_inline __exception int js_binary_logic_slow(JSContext *ctx,
JSValue *sp,
OPCodeEnum op)
{
- JSValue op1, op2, res;
- int ret;
+ JSValue op1, op2;
uint32_t tag1, tag2;
uint32_t v1, v2, r;
@@ -13657,12 +13863,14 @@ static no_inline WARN_UNUSED int js_binary_logic_slow(JSContext *ctx,
tag1 = JS_VALUE_GET_NORM_TAG(op1);
tag2 = JS_VALUE_GET_NORM_TAG(op2);
+#ifdef CONFIG_BIGNUM
/* try to call an overloaded operator */
if ((tag1 == JS_TAG_OBJECT &&
(tag2 != JS_TAG_NULL && tag2 != JS_TAG_UNDEFINED)) ||
(tag2 == JS_TAG_OBJECT &&
(tag1 != JS_TAG_NULL && tag1 != JS_TAG_UNDEFINED))) {
- ret = js_call_binary_op_fallback(ctx, &res, op1, op2, op, TRUE, 0);
+ JSValue res;
+ int ret = js_call_binary_op_fallback(ctx, &res, op1, op2, op, TRUE, 0);
if (ret != 0) {
JS_FreeValue(ctx, op1);
JS_FreeValue(ctx, op2);
@@ -13674,6 +13882,7 @@ static no_inline WARN_UNUSED int js_binary_logic_slow(JSContext *ctx,
}
}
}
+#endif
op1 = JS_ToNumericFree(ctx, op1);
if (JS_IsException(op1)) {
@@ -13784,6 +13993,7 @@ static int js_compare_bigfloat(JSContext *ctx, OPCodeEnum op,
return res;
}
+#ifdef CONFIG_BIGNUM
static int js_compare_bigdecimal(JSContext *ctx, OPCodeEnum op,
JSValue op1, JSValue op2)
{
@@ -13803,8 +14013,8 @@ static int js_compare_bigdecimal(JSContext *ctx, OPCodeEnum op,
JS_FreeValue(ctx, op1);
return -1;
}
- a = JS_ToBigDecimal(ctx, op1);
- b = JS_ToBigDecimal(ctx, op2);
+ a = JS_ToBigDecimal(ctx, op1); /* cannot fail */
+ b = JS_ToBigDecimal(ctx, op2); /* cannot fail */
switch(op) {
case OP_lt:
@@ -13829,11 +14039,12 @@ static int js_compare_bigdecimal(JSContext *ctx, OPCodeEnum op,
JS_FreeValue(ctx, op2);
return res;
}
+#endif /* !CONFIG_BIGNUM */
static no_inline int js_relational_slow(JSContext *ctx, JSValue *sp,
OPCodeEnum op)
{
- JSValue op1, op2, ret;
+ JSValue op1, op2;
int res;
uint32_t tag1, tag2;
@@ -13841,11 +14052,13 @@ static no_inline int js_relational_slow(JSContext *ctx, JSValue *sp,
op2 = sp[-1];
tag1 = JS_VALUE_GET_NORM_TAG(op1);
tag2 = JS_VALUE_GET_NORM_TAG(op2);
+#ifdef CONFIG_BIGNUM
/* try to call an overloaded operator */
if ((tag1 == JS_TAG_OBJECT &&
(tag2 != JS_TAG_NULL && tag2 != JS_TAG_UNDEFINED)) ||
(tag2 == JS_TAG_OBJECT &&
(tag1 != JS_TAG_NULL && tag1 != JS_TAG_UNDEFINED))) {
+ JSValue ret;
res = js_call_binary_op_fallback(ctx, &ret, op1, op2, op,
FALSE, HINT_NUMBER);
if (res != 0) {
@@ -13859,6 +14072,7 @@ static no_inline int js_relational_slow(JSContext *ctx, JSValue *sp,
}
}
}
+#endif
op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NUMBER);
if (JS_IsException(op1)) {
JS_FreeValue(ctx, op2);
@@ -13933,6 +14147,7 @@ static no_inline int js_relational_slow(JSContext *ctx, JSValue *sp,
tag1 = JS_VALUE_GET_NORM_TAG(op1);
tag2 = JS_VALUE_GET_NORM_TAG(op2);
+#ifdef CONFIG_BIGNUM
if (tag1 == JS_TAG_BIG_DECIMAL || tag2 == JS_TAG_BIG_DECIMAL) {
res = ctx->rt->bigdecimal_ops.compare(ctx, op, op1, op2);
if (res < 0)
@@ -13941,7 +14156,9 @@ static no_inline int js_relational_slow(JSContext *ctx, JSValue *sp,
res = ctx->rt->bigfloat_ops.compare(ctx, op, op1, op2);
if (res < 0)
goto exception;
- } else if (tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) {
+ } else
+#endif
+ if (tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) {
res = ctx->rt->bigint_ops.compare(ctx, op, op1, op2);
if (res < 0)
goto exception;
@@ -13989,14 +14206,20 @@ static no_inline int js_relational_slow(JSContext *ctx, JSValue *sp,
static BOOL tag_is_number(uint32_t tag)
{
return (tag == JS_TAG_INT || tag == JS_TAG_BIG_INT ||
- tag == JS_TAG_FLOAT64 || tag == JS_TAG_BIG_FLOAT ||
- tag == JS_TAG_BIG_DECIMAL);
+ tag == JS_TAG_FLOAT64
+#ifdef CONFIG_BIGNUM
+ || tag == JS_TAG_BIG_FLOAT || tag == JS_TAG_BIG_DECIMAL
+#endif
+ );
}
-static no_inline WARN_UNUSED int js_eq_slow(JSContext *ctx, JSValue *sp,
+static no_inline __exception int js_eq_slow(JSContext *ctx, JSValue *sp,
BOOL is_neq)
{
- JSValue op1, op2, ret;
+ JSValue op1, op2;
+#ifdef CONFIG_BIGNUM
+ JSValue ret;
+#endif
int res;
uint32_t tag1, tag2;
@@ -14024,7 +14247,9 @@ static no_inline WARN_UNUSED int js_eq_slow(JSContext *ctx, JSValue *sp,
d2 = JS_VALUE_GET_INT(op2);
}
res = (d1 == d2);
- } else if (tag1 == JS_TAG_BIG_DECIMAL || tag2 == JS_TAG_BIG_DECIMAL) {
+ } else
+#ifdef CONFIG_BIGNUM
+ if (tag1 == JS_TAG_BIG_DECIMAL || tag2 == JS_TAG_BIG_DECIMAL) {
res = ctx->rt->bigdecimal_ops.compare(ctx, OP_eq, op1, op2);
if (res < 0)
goto exception;
@@ -14032,12 +14257,15 @@ static no_inline WARN_UNUSED int js_eq_slow(JSContext *ctx, JSValue *sp,
res = ctx->rt->bigfloat_ops.compare(ctx, OP_eq, op1, op2);
if (res < 0)
goto exception;
- } else {
+ } else
+#endif
+ {
res = ctx->rt->bigint_ops.compare(ctx, OP_eq, op1, op2);
if (res < 0)
goto exception;
}
} else if (tag1 == tag2) {
+#ifdef CONFIG_BIGNUM
if (tag1 == JS_TAG_OBJECT) {
/* try the fallback operator */
res = js_call_binary_op_fallback(ctx, &ret, op1, op2,
@@ -14054,6 +14282,7 @@ static no_inline WARN_UNUSED int js_eq_slow(JSContext *ctx, JSValue *sp,
}
}
}
+#endif
res = js_strict_eq2(ctx, op1, op2, JS_EQ_STRICT);
} else if ((tag1 == JS_TAG_NULL && tag2 == JS_TAG_UNDEFINED) ||
(tag2 == JS_TAG_NULL && tag1 == JS_TAG_UNDEFINED)) {
@@ -14090,7 +14319,7 @@ static no_inline WARN_UNUSED int js_eq_slow(JSContext *ctx, JSValue *sp,
goto exception;
}
}
- res = js_strict_eq(ctx, op1, op2);
+ res = js_strict_eq2(ctx, op1, op2, JS_EQ_STRICT);
} else if (tag1 == JS_TAG_BOOL) {
op1 = JS_NewInt32(ctx, JS_VALUE_GET_INT(op1));
goto redo;
@@ -14101,7 +14330,7 @@ static no_inline WARN_UNUSED int js_eq_slow(JSContext *ctx, JSValue *sp,
(tag_is_number(tag2) || tag2 == JS_TAG_STRING || tag2 == JS_TAG_SYMBOL)) ||
(tag2 == JS_TAG_OBJECT &&
(tag_is_number(tag1) || tag1 == JS_TAG_STRING || tag1 == JS_TAG_SYMBOL))) {
-
+#ifdef CONFIG_BIGNUM
/* try the fallback operator */
res = js_call_binary_op_fallback(ctx, &ret, op1, op2,
is_neq ? OP_neq : OP_eq,
@@ -14116,7 +14345,7 @@ static no_inline WARN_UNUSED int js_eq_slow(JSContext *ctx, JSValue *sp,
return 0;
}
}
-
+#endif
op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NONE);
if (JS_IsException(op1)) {
JS_FreeValue(ctx, op2);
@@ -14188,6 +14417,7 @@ static no_inline int js_shr_slow(JSContext *ctx, JSValue *sp)
return -1;
}
+#ifdef CONFIG_BIGNUM
static JSValue js_mul_pow10_to_float64(JSContext *ctx, const bf_t *a,
int64_t exponent)
{
@@ -14205,7 +14435,7 @@ static JSValue js_mul_pow10_to_float64(JSContext *ctx, const bf_t *a,
if (ret & BF_ST_MEM_ERROR)
return JS_ThrowOutOfMemory(ctx);
else
- return __JS_NewFloat64(ctx, d);
+ return JS_NewFloat64(ctx, d);
}
static no_inline int js_mul_pow10(JSContext *ctx, JSValue *sp)
@@ -14222,8 +14452,10 @@ static no_inline int js_mul_pow10(JSContext *ctx, JSValue *sp)
op1 = sp[-2];
op2 = sp[-1];
a = JS_ToBigFloat(ctx, &a_s, op1);
- if (!a)
+ if (!a) {
+ JS_FreeValue(ctx, res);
return -1;
+ }
if (JS_IsBigInt(ctx, op2)) {
ret = JS_ToBigInt64(ctx, &e, op2);
} else {
@@ -14244,395 +14476,7 @@ static no_inline int js_mul_pow10(JSContext *ctx, JSValue *sp)
sp[-2] = res;
return 0;
}
-
-#else /* !CONFIG_BIGNUM */
-
-static JSValue JS_ThrowUnsupportedBigint(JSContext *ctx)
-{
- return JS_ThrowTypeError(ctx, "bigint is not supported");
-}
-
-JSValue JS_NewBigInt64(JSContext *ctx, int64_t v)
-{
- return JS_ThrowUnsupportedBigint(ctx);
-}
-
-JSValue JS_NewBigUint64(JSContext *ctx, uint64_t v)
-{
- return JS_ThrowUnsupportedBigint(ctx);
-}
-
-int JS_ToBigInt64(JSContext *ctx, int64_t *pres, JSValueConst val)
-{
- JS_ThrowUnsupportedBigint(ctx);
- *pres = 0;
- return -1;
-}
-
-static no_inline warn_unused int js_unary_arith_slow(JSContext *ctx,
- JSValue *sp,
- OPCodeEnum op)
-{
- JSValue op1;
- double d;
-
- op1 = sp[-1];
- if (unlikely(JS_ToFloat64Free(ctx, &d, op1))) {
- sp[-1] = JS_UNDEFINED;
- return -1;
- }
- switch(op) {
- case OP_inc:
- d++;
- break;
- case OP_dec:
- d--;
- break;
- case OP_plus:
- break;
- case OP_neg:
- d = -d;
- break;
- default:
- abort();
- }
- sp[-1] = JS_NewFloat64(ctx, d);
- return 0;
-}
-
-/* specific case necessary for correct return value semantics */
-static warn_unused int js_post_inc_slow(JSContext *ctx,
- JSValue *sp, OPCodeEnum op)
-{
- JSValue op1;
- double d, r;
-
- op1 = sp[-1];
- if (unlikely(JS_ToFloat64Free(ctx, &d, op1))) {
- sp[-1] = JS_UNDEFINED;
- return -1;
- }
- r = d + 2 * (op - OP_post_dec) - 1;
- sp[0] = JS_NewFloat64(ctx, r);
- sp[-1] = JS_NewFloat64(ctx, d);
- return 0;
-}
-
-static no_inline warn_unused int js_binary_arith_slow(JSContext *ctx, JSValue *sp,
- OPCodeEnum op)
-{
- JSValue op1, op2;
- double d1, d2, r;
-
- op1 = sp[-2];
- op2 = sp[-1];
- if (unlikely(JS_ToFloat64Free(ctx, &d1, op1))) {
- JS_FreeValue(ctx, op2);
- goto exception;
- }
- if (unlikely(JS_ToFloat64Free(ctx, &d2, op2))) {
- goto exception;
- }
- switch(op) {
- case OP_sub:
- r = d1 - d2;
- break;
- case OP_mul:
- r = d1 * d2;
- break;
- case OP_div:
- r = d1 / d2;
- break;
- case OP_mod:
- r = fmod(d1, d2);
- break;
- case OP_pow:
- r = js_pow(d1, d2);
- break;
- default:
- abort();
- }
- sp[-2] = JS_NewFloat64(ctx, r);
- return 0;
- exception:
- sp[-2] = JS_UNDEFINED;
- sp[-1] = JS_UNDEFINED;
- return -1;
-}
-
-static no_inline warn_unused int js_add_slow(JSContext *ctx, JSValue *sp)
-{
- JSValue op1, op2;
- uint32_t tag1, tag2;
-
- op1 = sp[-2];
- op2 = sp[-1];
- tag1 = JS_VALUE_GET_TAG(op1);
- tag2 = JS_VALUE_GET_TAG(op2);
- if ((tag1 == JS_TAG_INT || JS_TAG_IS_FLOAT64(tag1)) &&
- (tag2 == JS_TAG_INT || JS_TAG_IS_FLOAT64(tag2))) {
- goto add_numbers;
- } else {
- op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NONE);
- if (JS_IsException(op1)) {
- JS_FreeValue(ctx, op2);
- goto exception;
- }
- op2 = JS_ToPrimitiveFree(ctx, op2, HINT_NONE);
- if (JS_IsException(op2)) {
- JS_FreeValue(ctx, op1);
- goto exception;
- }
- tag1 = JS_VALUE_GET_TAG(op1);
- tag2 = JS_VALUE_GET_TAG(op2);
- if (tag1 == JS_TAG_STRING || tag2 == JS_TAG_STRING) {
- sp[-2] = JS_ConcatString(ctx, op1, op2);
- if (JS_IsException(sp[-2]))
- goto exception;
- } else {
- double d1, d2;
- add_numbers:
- if (JS_ToFloat64Free(ctx, &d1, op1)) {
- JS_FreeValue(ctx, op2);
- goto exception;
- }
- if (JS_ToFloat64Free(ctx, &d2, op2))
- goto exception;
- sp[-2] = JS_NewFloat64(ctx, d1 + d2);
- }
- }
- return 0;
- exception:
- sp[-2] = JS_UNDEFINED;
- sp[-1] = JS_UNDEFINED;
- return -1;
-}
-
-static no_inline warn_unused int js_binary_logic_slow(JSContext *ctx,
- JSValue *sp,
- OPCodeEnum op)
-{
- JSValue op1, op2;
- uint32_t v1, v2, r;
-
- op1 = sp[-2];
- op2 = sp[-1];
- if (unlikely(JS_ToInt32Free(ctx, (int32_t *)&v1, op1))) {
- JS_FreeValue(ctx, op2);
- goto exception;
- }
- if (unlikely(JS_ToInt32Free(ctx, (int32_t *)&v2, op2)))
- goto exception;
- switch(op) {
- case OP_shl:
- r = v1 << (v2 & 0x1f);
- break;
- case OP_sar:
- r = (int)v1 >> (v2 & 0x1f);
- break;
- case OP_and:
- r = v1 & v2;
- break;
- case OP_or:
- r = v1 | v2;
- break;
- case OP_xor:
- r = v1 ^ v2;
- break;
- default:
- abort();
- }
- sp[-2] = JS_NewInt32(ctx, r);
- return 0;
- exception:
- sp[-2] = JS_UNDEFINED;
- sp[-1] = JS_UNDEFINED;
- return -1;
-}
-
-static no_inline int js_not_slow(JSContext *ctx, JSValue *sp)
-{
- int32_t v1;
-
- if (unlikely(JS_ToInt32Free(ctx, &v1, sp[-1]))) {
- sp[-1] = JS_UNDEFINED;
- return -1;
- }
- sp[-1] = JS_NewInt32(ctx, ~v1);
- return 0;
-}
-
-static no_inline int js_relational_slow(JSContext *ctx, JSValue *sp,
- OPCodeEnum op)
-{
- JSValue op1, op2;
- int res;
-
- op1 = sp[-2];
- op2 = sp[-1];
- op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NUMBER);
- if (JS_IsException(op1)) {
- JS_FreeValue(ctx, op2);
- goto exception;
- }
- op2 = JS_ToPrimitiveFree(ctx, op2, HINT_NUMBER);
- if (JS_IsException(op2)) {
- JS_FreeValue(ctx, op1);
- goto exception;
- }
- if (JS_VALUE_GET_TAG(op1) == JS_TAG_STRING &&
- JS_VALUE_GET_TAG(op2) == JS_TAG_STRING) {
- JSString *p1, *p2;
- p1 = JS_VALUE_GET_STRING(op1);
- p2 = JS_VALUE_GET_STRING(op2);
- res = js_string_compare(ctx, p1, p2);
- JS_FreeValue(ctx, op1);
- JS_FreeValue(ctx, op2);
- switch(op) {
- case OP_lt:
- res = (res < 0);
- break;
- case OP_lte:
- res = (res <= 0);
- break;
- case OP_gt:
- res = (res > 0);
- break;
- default:
- case OP_gte:
- res = (res >= 0);
- break;
- }
- } else {
- double d1, d2;
- if (JS_ToFloat64Free(ctx, &d1, op1)) {
- JS_FreeValue(ctx, op2);
- goto exception;
- }
- if (JS_ToFloat64Free(ctx, &d2, op2))
- goto exception;
- switch(op) {
- case OP_lt:
- res = (d1 < d2); /* if NaN return false */
- break;
- case OP_lte:
- res = (d1 <= d2); /* if NaN return false */
- break;
- case OP_gt:
- res = (d1 > d2); /* if NaN return false */
- break;
- default:
- case OP_gte:
- res = (d1 >= d2); /* if NaN return false */
- break;
- }
- }
- sp[-2] = JS_NewBool(ctx, res);
- return 0;
- exception:
- sp[-2] = JS_UNDEFINED;
- sp[-1] = JS_UNDEFINED;
- return -1;
-}
-
-static no_inline warn_unused int js_eq_slow(JSContext *ctx, JSValue *sp,
- BOOL is_neq)
-{
- JSValue op1, op2;
- int tag1, tag2;
- BOOL res;
-
- op1 = sp[-2];
- op2 = sp[-1];
- redo:
- tag1 = JS_VALUE_GET_NORM_TAG(op1);
- tag2 = JS_VALUE_GET_NORM_TAG(op2);
- if (tag1 == tag2 ||
- (tag1 == JS_TAG_INT && tag2 == JS_TAG_FLOAT64) ||
- (tag2 == JS_TAG_INT && tag1 == JS_TAG_FLOAT64)) {
- res = js_strict_eq(ctx, op1, op2);
- } else if ((tag1 == JS_TAG_NULL && tag2 == JS_TAG_UNDEFINED) ||
- (tag2 == JS_TAG_NULL && tag1 == JS_TAG_UNDEFINED)) {
- res = TRUE;
- } else if ((tag1 == JS_TAG_STRING && (tag2 == JS_TAG_INT ||
- tag2 == JS_TAG_FLOAT64)) ||
- (tag2 == JS_TAG_STRING && (tag1 == JS_TAG_INT ||
- tag1 == JS_TAG_FLOAT64))) {
- double d1;
- double d2;
- if (JS_ToFloat64Free(ctx, &d1, op1)) {
- JS_FreeValue(ctx, op2);
- goto exception;
- }
- if (JS_ToFloat64Free(ctx, &d2, op2))
- goto exception;
- res = (d1 == d2);
- } else if (tag1 == JS_TAG_BOOL) {
- op1 = JS_NewInt32(ctx, JS_VALUE_GET_INT(op1));
- goto redo;
- } else if (tag2 == JS_TAG_BOOL) {
- op2 = JS_NewInt32(ctx, JS_VALUE_GET_INT(op2));
- goto redo;
- } else if (tag1 == JS_TAG_OBJECT &&
- (tag2 == JS_TAG_INT || tag2 == JS_TAG_FLOAT64 || tag2 == JS_TAG_STRING || tag2 == JS_TAG_SYMBOL)) {
- op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NONE);
- if (JS_IsException(op1)) {
- JS_FreeValue(ctx, op2);
- goto exception;
- }
- goto redo;
- } else if (tag2 == JS_TAG_OBJECT &&
- (tag1 == JS_TAG_INT || tag1 == JS_TAG_FLOAT64 || tag1 == JS_TAG_STRING || tag1 == JS_TAG_SYMBOL)) {
- op2 = JS_ToPrimitiveFree(ctx, op2, HINT_NONE);
- if (JS_IsException(op2)) {
- JS_FreeValue(ctx, op1);
- goto exception;
- }
- goto redo;
- } else {
- /* IsHTMLDDA object is equivalent to undefined for '==' and '!=' */
- if ((JS_IsHTMLDDA(ctx, op1) &&
- (tag2 == JS_TAG_NULL || tag2 == JS_TAG_UNDEFINED)) ||
- (JS_IsHTMLDDA(ctx, op2) &&
- (tag1 == JS_TAG_NULL || tag1 == JS_TAG_UNDEFINED))) {
- res = TRUE;
- } else {
- res = FALSE;
- }
- JS_FreeValue(ctx, op1);
- JS_FreeValue(ctx, op2);
- }
- sp[-2] = JS_NewBool(ctx, res ^ is_neq);
- return 0;
- exception:
- sp[-2] = JS_UNDEFINED;
- sp[-1] = JS_UNDEFINED;
- return -1;
-}
-
-static no_inline int js_shr_slow(JSContext *ctx, JSValue *sp)
-{
- JSValue op1, op2;
- uint32_t v1, v2, r;
-
- op1 = sp[-2];
- op2 = sp[-1];
- if (unlikely(JS_ToUint32Free(ctx, &v1, op1))) {
- JS_FreeValue(ctx, op2);
- goto exception;
- }
- if (unlikely(JS_ToUint32Free(ctx, &v2, op2)))
- goto exception;
- r = v1 >> (v2 & 0x1f);
- sp[-2] = JS_NewUint32(ctx, r);
- return 0;
- exception:
- sp[-2] = JS_UNDEFINED;
- sp[-1] = JS_UNDEFINED;
- return -1;
-}
-
-#endif /* !CONFIG_BIGNUM */
+#endif
/* XXX: Should take JSValueConst arguments */
static BOOL js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2,
@@ -14726,7 +14570,6 @@ static BOOL js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2,
res = (d1 == d2); /* if NaN return false and +0 == -0 */
}
goto done_no_free;
-#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_INT:
{
bf_t a_s, *a, b_s, *b;
@@ -14734,8 +14577,8 @@ static BOOL js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2,
res = FALSE;
break;
}
- a = JS_ToBigFloat(ctx, &a_s, op1);
- b = JS_ToBigFloat(ctx, &b_s, op2);
+ a = JS_ToBigFloat(ctx, &a_s, op1); /* cannot fail */
+ b = JS_ToBigFloat(ctx, &b_s, op2); /* cannot fail */
res = bf_cmp_eq(a, b);
if (a == &a_s)
bf_delete(a);
@@ -14743,6 +14586,7 @@ static BOOL js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2,
bf_delete(b);
}
break;
+#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_FLOAT:
{
JSBigFloat *p1, *p2;
@@ -14793,9 +14637,16 @@ static BOOL js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2,
return res;
}
-static BOOL js_strict_eq(JSContext *ctx, JSValue op1, JSValue op2)
+static BOOL js_strict_eq(JSContext *ctx, JSValueConst op1, JSValueConst op2)
+{
+ return js_strict_eq2(ctx,
+ JS_DupValue(ctx, op1), JS_DupValue(ctx, op2),
+ JS_EQ_STRICT);
+}
+
+BOOL JS_StrictEq(JSContext *ctx, JSValueConst op1, JSValueConst op2)
{
- return js_strict_eq2(ctx, op1, op2, JS_EQ_STRICT);
+ return js_strict_eq(ctx, op1, op2);
}
static BOOL js_same_value(JSContext *ctx, JSValueConst op1, JSValueConst op2)
@@ -14805,6 +14656,11 @@ static BOOL js_same_value(JSContext *ctx, JSValueConst op1, JSValueConst op2)
JS_EQ_SAME_VALUE);
}
+BOOL JS_SameValue(JSContext *ctx, JSValueConst op1, JSValueConst op2)
+{
+ return js_same_value(ctx, op1, op2);
+}
+
static BOOL js_same_value_zero(JSContext *ctx, JSValueConst op1, JSValueConst op2)
{
return js_strict_eq2(ctx,
@@ -14812,16 +14668,21 @@ static BOOL js_same_value_zero(JSContext *ctx, JSValueConst op1, JSValueConst op
JS_EQ_SAME_VALUE_ZERO);
}
+BOOL JS_SameValueZero(JSContext *ctx, JSValueConst op1, JSValueConst op2)
+{
+ return js_same_value_zero(ctx, op1, op2);
+}
+
static no_inline int js_strict_eq_slow(JSContext *ctx, JSValue *sp,
BOOL is_neq)
{
BOOL res;
- res = js_strict_eq(ctx, sp[-2], sp[-1]);
+ res = js_strict_eq2(ctx, sp[-2], sp[-1], JS_EQ_STRICT);
sp[-2] = JS_NewBool(ctx, res ^ is_neq);
return 0;
}
-static warn_unused int js_operator_in(JSContext *ctx, JSValue *sp)
+static __exception int js_operator_in(JSContext *ctx, JSValue *sp)
{
JSValue op1, op2;
JSAtom atom;
@@ -14847,7 +14708,44 @@ static warn_unused int js_operator_in(JSContext *ctx, JSValue *sp)
return 0;
}
-static warn_unused int js_has_unscopable(JSContext *ctx, JSValueConst obj,
+static __exception int js_operator_private_in(JSContext *ctx, JSValue *sp)
+{
+ JSValue op1, op2;
+ int ret;
+
+ op1 = sp[-2]; /* object */
+ op2 = sp[-1]; /* field name or method function */
+
+ if (JS_VALUE_GET_TAG(op1) != JS_TAG_OBJECT) {
+ JS_ThrowTypeError(ctx, "invalid 'in' operand");
+ return -1;
+ }
+ if (JS_IsObject(op2)) {
+ /* method: use the brand */
+ ret = JS_CheckBrand(ctx, op1, op2);
+ if (ret < 0)
+ return -1;
+ } else {
+ JSAtom atom;
+ JSObject *p;
+ JSShapeProperty *prs;
+ JSProperty *pr;
+ /* field */
+ atom = JS_ValueToAtom(ctx, op2);
+ if (unlikely(atom == JS_ATOM_NULL))
+ return -1;
+ p = JS_VALUE_GET_OBJ(op1);
+ prs = find_own_property(&pr, p, atom);
+ JS_FreeAtom(ctx, atom);
+ ret = (prs != NULL);
+ }
+ JS_FreeValue(ctx, op1);
+ JS_FreeValue(ctx, op2);
+ sp[-2] = JS_NewBool(ctx, ret);
+ return 0;
+}
+
+static __exception int js_has_unscopable(JSContext *ctx, JSValueConst obj,
JSAtom atom)
{
JSValue arr, val;
@@ -14865,7 +14763,7 @@ static warn_unused int js_has_unscopable(JSContext *ctx, JSValueConst obj,
return ret;
}
-static warn_unused int js_operator_instanceof(JSContext *ctx, JSValue *sp)
+static __exception int js_operator_instanceof(JSContext *ctx, JSValue *sp)
{
JSValue op1, op2;
BOOL ret;
@@ -14881,17 +14779,17 @@ static warn_unused int js_operator_instanceof(JSContext *ctx, JSValue *sp)
return 0;
}
-static warn_unused int js_operator_typeof(JSContext *ctx, JSValueConst op1)
+static __exception int js_operator_typeof(JSContext *ctx, JSValueConst op1)
{
JSAtom atom;
uint32_t tag;
tag = JS_VALUE_GET_NORM_TAG(op1);
switch(tag) {
-#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_INT:
atom = JS_ATOM_bigint;
break;
+#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_FLOAT:
atom = JS_ATOM_bigfloat;
break;
@@ -14938,7 +14836,7 @@ static warn_unused int js_operator_typeof(JSContext *ctx, JSValueConst op1)
return atom;
}
-static warn_unused int js_operator_delete(JSContext *ctx, JSValue *sp)
+static __exception int js_operator_delete(JSContext *ctx, JSValue *sp)
{
JSValue op1, op2;
JSAtom atom;
@@ -15093,7 +14991,7 @@ static JSValue js_build_mapped_arguments(JSContext *ctx, int argc,
var_ref = get_var_ref(ctx, sf, i, TRUE);
if (!var_ref)
goto fail;
- pr = add_property(ctx, p, JS_AtomFromUInt32(i), JS_PROP_C_W_E | JS_PROP_VARREF);
+ pr = add_property(ctx, p, __JS_AtomFromUInt32(i), JS_PROP_C_W_E | JS_PROP_VARREF);
if (!pr) {
free_var_ref(ctx->rt, var_ref);
goto fail;
@@ -15145,10 +15043,10 @@ static JSValue js_build_rest(JSContext *ctx, int first, int argc, JSValueConst *
static JSValue build_for_in_iterator(JSContext *ctx, JSValue obj)
{
- JSObject *p;
+ JSObject *p, *p1;
JSPropertyEnum *tab_atom;
int i;
- JSValue enum_obj, obj1;
+ JSValue enum_obj;
JSForInIterator *it;
uint32_t tag, tab_atom_count;
@@ -15171,40 +15069,16 @@ static JSValue build_for_in_iterator(JSContext *ctx, JSValue obj)
it->is_array = FALSE;
it->obj = obj;
it->idx = 0;
- p = JS_VALUE_GET_OBJ(enum_obj);
- p->u.for_in_iterator = it;
+ it->tab_atom = NULL;
+ it->atom_count = 0;
+ it->in_prototype_chain = FALSE;
+ p1 = JS_VALUE_GET_OBJ(enum_obj);
+ p1->u.for_in_iterator = it;
if (tag == JS_TAG_NULL || tag == JS_TAG_UNDEFINED)
return enum_obj;
- /* fast path: assume no enumerable properties in the prototype chain */
- obj1 = JS_DupValue(ctx, obj);
- for(;;) {
- obj1 = JS_GetPrototypeFree(ctx, obj1);
- if (JS_IsNull(obj1))
- break;
- if (JS_IsException(obj1))
- goto fail;
- if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count,
- JS_VALUE_GET_OBJ(obj1),
- JS_GPN_STRING_MASK | JS_GPN_ENUM_ONLY)) {
- JS_FreeValue(ctx, obj1);
- goto fail;
- }
- js_free_prop_enum(ctx, tab_atom, tab_atom_count);
- if (tab_atom_count != 0) {
- JS_FreeValue(ctx, obj1);
- goto slow_path;
- }
- /* must check for timeout to avoid infinite loop */
- if (js_poll_interrupts(ctx)) {
- JS_FreeValue(ctx, obj1);
- goto fail;
- }
- }
-
p = JS_VALUE_GET_OBJ(obj);
-
if (p->fast_array) {
JSShape *sh;
JSShapeProperty *prs;
@@ -15216,70 +15090,101 @@ static JSValue build_for_in_iterator(JSContext *ctx, JSValue obj)
}
/* for fast arrays, we only store the number of elements */
it->is_array = TRUE;
- it->array_length = p->u.array.count;
+ it->atom_count = p->u.array.count;
} else {
normal_case:
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++) {
- JS_SetPropertyInternal(ctx, enum_obj, tab_atom[i].atom, JS_NULL, 0);
+ JS_GPN_STRING_MASK | JS_GPN_SET_ENUM)) {
+ JS_FreeValue(ctx, enum_obj);
+ return JS_EXCEPTION;
}
- js_free_prop_enum(ctx, tab_atom, tab_atom_count);
+ it->tab_atom = tab_atom;
+ it->atom_count = tab_atom_count;
}
return enum_obj;
+}
- slow_path:
- /* non enumerable properties hide the enumerables ones in the
- prototype chain */
- obj1 = JS_DupValue(ctx, obj);
+/* obj -> enum_obj */
+static __exception int js_for_in_start(JSContext *ctx, JSValue *sp)
+{
+ sp[-1] = build_for_in_iterator(ctx, sp[-1]);
+ if (JS_IsException(sp[-1]))
+ return -1;
+ return 0;
+}
+
+/* return -1 if exception, 0 if slow case, 1 if the enumeration is finished */
+static __exception int js_for_in_prepare_prototype_chain_enum(JSContext *ctx,
+ JSValueConst enum_obj)
+{
+ JSObject *p;
+ JSForInIterator *it;
+ JSPropertyEnum *tab_atom;
+ uint32_t tab_atom_count, i;
+ JSValue obj1;
+
+ p = JS_VALUE_GET_OBJ(enum_obj);
+ it = p->u.for_in_iterator;
+
+ /* check if there are enumerable properties in the prototype chain (fast path) */
+ obj1 = JS_DupValue(ctx, it->obj);
for(;;) {
+ obj1 = JS_GetPrototypeFree(ctx, obj1);
+ if (JS_IsNull(obj1))
+ break;
+ if (JS_IsException(obj1))
+ goto fail;
if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count,
JS_VALUE_GET_OBJ(obj1),
- JS_GPN_STRING_MASK | JS_GPN_SET_ENUM)) {
+ JS_GPN_STRING_MASK | JS_GPN_ENUM_ONLY)) {
JS_FreeValue(ctx, obj1);
goto fail;
}
- for(i = 0; i < tab_atom_count; i++) {
- JS_DefinePropertyValue(ctx, enum_obj, tab_atom[i].atom, JS_NULL,
- (tab_atom[i].is_enumerable ?
- JS_PROP_ENUMERABLE : 0));
- }
js_free_prop_enum(ctx, tab_atom, tab_atom_count);
- obj1 = JS_GetPrototypeFree(ctx, obj1);
- if (JS_IsNull(obj1))
- break;
- if (JS_IsException(obj1))
- goto fail;
+ if (tab_atom_count != 0) {
+ JS_FreeValue(ctx, obj1);
+ goto slow_path;
+ }
/* must check for timeout to avoid infinite loop */
if (js_poll_interrupts(ctx)) {
JS_FreeValue(ctx, obj1);
goto fail;
}
}
- return enum_obj;
+ JS_FreeValue(ctx, obj1);
+ return 1;
- fail:
- JS_FreeValue(ctx, enum_obj);
- return JS_EXCEPTION;
-}
+ slow_path:
+ /* add the visited properties, even if they are not enumerable */
+ if (it->is_array) {
+ if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count,
+ JS_VALUE_GET_OBJ(it->obj),
+ JS_GPN_STRING_MASK | JS_GPN_SET_ENUM)) {
+ goto fail;
+ }
+ it->is_array = FALSE;
+ it->tab_atom = tab_atom;
+ it->atom_count = tab_atom_count;
+ }
-/* obj -> enum_obj */
-static warn_unused int js_for_in_start(JSContext *ctx, JSValue *sp)
-{
- sp[-1] = build_for_in_iterator(ctx, sp[-1]);
- if (JS_IsException(sp[-1]))
- return -1;
+ for(i = 0; i < it->atom_count; i++) {
+ if (JS_DefinePropertyValue(ctx, enum_obj, it->tab_atom[i].atom, JS_NULL, JS_PROP_ENUMERABLE) < 0)
+ goto fail;
+ }
return 0;
+ fail:
+ return -1;
}
/* enum_obj -> enum_obj value done */
-static warn_unused int js_for_in_next(JSContext *ctx, JSValue *sp)
+static __exception int js_for_in_next(JSContext *ctx, JSValue *sp)
{
JSValueConst enum_obj;
JSObject *p;
JSAtom prop;
JSForInIterator *it;
+ JSPropertyEnum *tab_atom;
+ uint32_t tab_atom_count;
int ret;
enum_obj = sp[-1];
@@ -15292,28 +15197,68 @@ static warn_unused int js_for_in_next(JSContext *ctx, JSValue *sp)
it = p->u.for_in_iterator;
for(;;) {
- if (it->is_array) {
- if (it->idx >= it->array_length)
- goto done;
- prop = JS_AtomFromUInt32(it->idx);
- it->idx++;
+ if (it->idx >= it->atom_count) {
+ if (JS_IsNull(it->obj) || JS_IsUndefined(it->obj))
+ goto done; /* not an object */
+ /* no more property in the current object: look in the prototype */
+ if (!it->in_prototype_chain) {
+ ret = js_for_in_prepare_prototype_chain_enum(ctx, enum_obj);
+ if (ret < 0)
+ return -1;
+ if (ret)
+ goto done;
+ it->in_prototype_chain = TRUE;
+ }
+ it->obj = JS_GetPrototypeFree(ctx, it->obj);
+ if (JS_IsException(it->obj))
+ return -1;
+ if (JS_IsNull(it->obj))
+ goto done; /* no more prototype */
+
+ /* must check for timeout to avoid infinite loop */
+ if (js_poll_interrupts(ctx))
+ return -1;
+
+ if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count,
+ JS_VALUE_GET_OBJ(it->obj),
+ JS_GPN_STRING_MASK | JS_GPN_SET_ENUM)) {
+ return -1;
+ }
+ js_free_prop_enum(ctx, it->tab_atom, it->atom_count);
+ it->tab_atom = tab_atom;
+ it->atom_count = tab_atom_count;
+ it->idx = 0;
} else {
- JSShape *sh = p->shape;
- JSShapeProperty *prs;
- if (it->idx >= sh->prop_count)
- goto done;
- prs = get_shape_prop(sh) + it->idx;
- prop = prs->atom;
- it->idx++;
- if (prop == JS_ATOM_NULL || !(prs->flags & JS_PROP_ENUMERABLE))
- continue;
+ if (it->is_array) {
+ prop = __JS_AtomFromUInt32(it->idx);
+ it->idx++;
+ } else {
+ BOOL is_enumerable;
+ prop = it->tab_atom[it->idx].atom;
+ is_enumerable = it->tab_atom[it->idx].is_enumerable;
+ it->idx++;
+ if (it->in_prototype_chain) {
+ /* slow case: we are in the prototype chain */
+ ret = JS_GetOwnPropertyInternal(ctx, NULL, JS_VALUE_GET_OBJ(enum_obj), prop);
+ if (ret < 0)
+ return ret;
+ if (ret)
+ continue; /* already visited */
+ /* add to the visited property list */
+ if (JS_DefinePropertyValue(ctx, enum_obj, prop, JS_NULL,
+ JS_PROP_ENUMERABLE) < 0)
+ return -1;
+ }
+ if (!is_enumerable)
+ continue;
+ }
+ /* check if the property was deleted */
+ ret = JS_GetOwnPropertyInternal(ctx, NULL, JS_VALUE_GET_OBJ(it->obj), prop);
+ if (ret < 0)
+ return ret;
+ if (ret)
+ break;
}
- /* check if the property was deleted */
- ret = JS_HasProperty(ctx, it->obj, prop);
- if (ret < 0)
- return ret;
- if (ret)
- break;
}
/* return the property */
sp[0] = JS_AtomToValue(ctx, prop);
@@ -15488,7 +15433,7 @@ static int JS_IteratorClose(JSContext *ctx, JSValueConst enum_obj,
}
/* obj -> enum_rec (3 slots) */
-static warn_unused int js_for_of_start(JSContext *ctx, JSValue *sp,
+static __exception int js_for_of_start(JSContext *ctx, JSValue *sp,
BOOL is_async)
{
JSValue op1, obj, method;
@@ -15509,7 +15454,7 @@ static warn_unused int js_for_of_start(JSContext *ctx, JSValue *sp,
objs. If 'done' is true or in case of exception, 'enum_rec' is set
to undefined. If 'done' is true, 'value' is always set to
undefined. */
-static warn_unused int js_for_of_next(JSContext *ctx, JSValue *sp, int offset)
+static __exception int js_for_of_next(JSContext *ctx, JSValue *sp, int offset)
{
JSValue value = JS_UNDEFINED;
int done = 1;
@@ -15555,7 +15500,7 @@ static JSValue JS_IteratorGetCompleteValue(JSContext *ctx, JSValueConst obj,
return JS_EXCEPTION;
}
-static warn_unused int js_iterator_get_value_done(JSContext *ctx, JSValue *sp)
+static __exception int js_iterator_get_value_done(JSContext *ctx, JSValue *sp)
{
JSValue obj, value;
BOOL done;
@@ -15631,7 +15576,7 @@ static BOOL js_get_fast_array(JSContext *ctx, JSValueConst obj,
return FALSE;
}
-static warn_unused int js_append_enumerate(JSContext *ctx, JSValue *sp)
+static __exception int js_append_enumerate(JSContext *ctx, JSValue *sp)
{
JSValue iterator, enumobj, method, value;
int is_array_iterator;
@@ -15711,7 +15656,7 @@ exception:
return -1;
}
-static warn_unused int JS_CopyDataProperties(JSContext *ctx,
+static __exception int JS_CopyDataProperties(JSContext *ctx,
JSValueConst target,
JSValueConst source,
JSValueConst excluded,
@@ -15799,7 +15744,7 @@ static JSVarRef *get_var_ref(JSContext *ctx, JSStackFrame *sf,
struct list_head *el;
list_for_each(el, &sf->var_ref_list) {
- var_ref = list_entry(el, JSVarRef, header.link);
+ var_ref = list_entry(el, JSVarRef, var_ref_link);
if (var_ref->var_idx == var_idx && var_ref->is_arg == is_arg) {
var_ref->header.ref_count++;
return var_ref;
@@ -15810,15 +15755,29 @@ static JSVarRef *get_var_ref(JSContext *ctx, JSStackFrame *sf,
if (!var_ref)
return NULL;
var_ref->header.ref_count = 1;
+ add_gc_object(ctx->rt, &var_ref->header, JS_GC_OBJ_TYPE_VAR_REF);
var_ref->is_detached = FALSE;
var_ref->is_arg = is_arg;
var_ref->var_idx = var_idx;
- list_add_tail(&var_ref->header.link, &sf->var_ref_list);
+ list_add_tail(&var_ref->var_ref_link, &sf->var_ref_list);
+ if (sf->js_mode & JS_MODE_ASYNC) {
+ /* The stack frame is detached and may be destroyed at any
+ time so its reference count must be increased. Calling
+ close_var_refs() when destroying the stack frame is not
+ possible because it would change the graph between the GC
+ objects. Another solution could be to temporarily detach
+ the JSVarRef of async functions during the GC. It would
+ have the advantage of allowing the release of unused stack
+ frames in a cycle. */
+ var_ref->async_func = container_of(sf, JSAsyncFunctionState, frame);
+ var_ref->async_func->header.ref_count++;
+ } else {
+ var_ref->async_func = NULL;
+ }
if (is_arg)
var_ref->pvalue = &sf->arg_buf[var_idx];
else
var_ref->pvalue = &sf->var_buf[var_idx];
- var_ref->value = JS_UNDEFINED;
return var_ref;
}
@@ -16049,7 +16008,10 @@ static void close_var_refs(JSRuntime *rt, JSStackFrame *sf)
int var_idx;
list_for_each_safe(el, el1, &sf->var_ref_list) {
- var_ref = list_entry(el, JSVarRef, header.link);
+ var_ref = list_entry(el, JSVarRef, var_ref_link);
+ /* no need to unlink var_ref->var_ref_link as the list is never used afterwards */
+ if (var_ref->async_func)
+ async_func_free(rt, var_ref->async_func);
var_idx = var_ref->var_idx;
if (var_ref->is_arg)
var_ref->value = JS_DupValueRT(rt, sf->arg_buf[var_idx]);
@@ -16058,7 +16020,6 @@ static void close_var_refs(JSRuntime *rt, JSStackFrame *sf)
var_ref->pvalue = &var_ref->value;
/* the reference is no longer to a local variable */
var_ref->is_detached = TRUE;
- add_gc_object(rt, &var_ref->header, JS_GC_OBJ_TYPE_VAR_REF);
}
}
@@ -16069,14 +16030,15 @@ static void close_lexical_var(JSContext *ctx, JSStackFrame *sf, int idx, int is_
int var_idx = idx;
list_for_each_safe(el, el1, &sf->var_ref_list) {
- var_ref = list_entry(el, JSVarRef, header.link);
+ var_ref = list_entry(el, JSVarRef, var_ref_link);
if (var_idx == var_ref->var_idx && var_ref->is_arg == is_arg) {
+ list_del(&var_ref->var_ref_link);
+ if (var_ref->async_func)
+ async_func_free(ctx->rt, var_ref->async_func);
var_ref->value = JS_DupValue(ctx, sf->var_buf[var_idx]);
var_ref->pvalue = &var_ref->value;
- list_del(&var_ref->header.link);
/* the reference is no longer to a local variable */
var_ref->is_detached = TRUE;
- add_gc_object(ctx->rt, &var_ref->header, JS_GC_OBJ_TYPE_VAR_REF);
}
}
}
@@ -16133,7 +16095,7 @@ static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj,
arg_buf[i] = JS_UNDEFINED;
sf->arg_count = arg_count;
}
- sf->arg_buf = arg_buf;
+ sf->arg_buf = (JSValue*)arg_buf;
func = p->u.cfunc.c_function;
switch(cproto) {
@@ -16267,9 +16229,10 @@ typedef enum {
OP_SPECIAL_OBJECT_IMPORT_META,
} OPSpecialObjectEnum;
-#define FUNC_RET_AWAIT 0
-#define FUNC_RET_YIELD 1
-#define FUNC_RET_YIELD_STAR 2
+#define FUNC_RET_AWAIT 0
+#define FUNC_RET_YIELD 1
+#define FUNC_RET_YIELD_STAR 2
+#define FUNC_RET_INITIAL_YIELD 3
/* argv[] is modified if (flags & JS_CALL_FLAG_COPY_ARGV) = 0. */
static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
@@ -16303,7 +16266,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
#include "quickjs-opcode.h"
[ OP_COUNT ... 255 ] = &&case_default
};
-#define SWITCH(pc) goto *dispatch_table[opcode = *(pc)++];
+#define SWITCH(pc) goto *dispatch_table[opcode = *pc++];
#define CASE(op) case_ ## op
#define DEFAULT case_default
#define BREAK SWITCH(pc)
@@ -16346,7 +16309,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
return JS_ThrowTypeError(caller_ctx, "not a function");
}
return call_func(caller_ctx, func_obj, this_obj, argc,
- argv, flags);
+ (JSValueConst *)argv, flags);
}
b = p->u.func.function_bytecode;
@@ -16500,12 +16463,12 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
int arg = *pc++;
switch(arg) {
case OP_SPECIAL_OBJECT_ARGUMENTS:
- *sp++ = js_build_arguments(ctx, argc, argv);
+ *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, argv,
+ *sp++ = js_build_mapped_arguments(ctx, argc, (JSValueConst *)argv,
sf, min_int(argc, b->arg_count));
if (unlikely(JS_IsException(sp[-1])))
goto exception;
@@ -16545,7 +16508,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
{
int first = get_u16(pc);
pc += 2;
- *sp++ = js_build_rest(ctx, first, argc, argv);
+ *sp++ = js_build_rest(ctx, first, argc, (JSValueConst *)argv);
if (unlikely(JS_IsException(sp[-1])))
goto exception;
}
@@ -16778,7 +16741,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
goto exception;
call_argv = sp - call_argc;
for(i = 0; i < call_argc; i++) {
- ret = JS_DefinePropertyValue(ctx, ret_val, JS_AtomFromUInt32(i), call_argv[i],
+ ret = JS_DefinePropertyValue(ctx, ret_val, __JS_AtomFromUInt32(i), call_argv[i],
JS_PROP_C_W_E | JS_PROP_THROW);
call_argv[i] = JS_UNDEFINED;
if (ret < 0) {
@@ -16797,7 +16760,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
magic = get_u16(pc);
pc += 2;
- ret_val = js_function_apply(ctx, sp[-3], 2, &sp[-2], magic);
+ ret_val = js_function_apply(ctx, sp[-3], 2, (JSValueConst *)&sp[-2], magic);
if (unlikely(JS_IsException(ret_val)))
goto exception;
JS_FreeValue(ctx, sp[-3]);
@@ -16834,8 +16797,15 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
}
BREAK;
CASE(OP_check_brand):
- if (JS_CheckBrand(ctx, sp[-2], sp[-1]) < 0)
- goto exception;
+ {
+ int ret = JS_CheckBrand(ctx, sp[-2], sp[-1]);
+ if (ret < 0)
+ goto exception;
+ if (!ret) {
+ JS_ThrowTypeError(ctx, "invalid brand on object");
+ goto exception;
+ }
+ }
BREAK;
CASE(OP_add_brand):
if (JS_AddBrand(ctx, sp[-2], sp[-1]) < 0)
@@ -16930,7 +16900,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
JS_EVAL_TYPE_DIRECT, scope_idx);
} else {
ret_val = JS_Call(ctx, sp[-2], JS_UNDEFINED, len,
- tab);
+ (JSValueConst *)tab);
}
free_arg_list(ctx, tab, len);
if (unlikely(JS_IsException(ret_val)))
@@ -17257,6 +17227,19 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
sp++;
}
BREAK;
+ CASE(OP_get_loc_checkthis):
+ {
+ int idx;
+ idx = get_u16(pc);
+ pc += 2;
+ if (unlikely(JS_IsUninitialized(var_buf[idx]))) {
+ JS_ThrowReferenceErrorUninitialized2(caller_ctx, b, idx, FALSE);
+ goto exception;
+ }
+ sp[0] = JS_DupValue(ctx, var_buf[idx]);
+ sp++;
+ }
+ BREAK;
CASE(OP_put_loc_check):
{
int idx;
@@ -17380,6 +17363,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
op1 = sp[-1];
pc += 4;
+ /* quick and dirty test for JS_TAG_INT, JS_TAG_BOOL, JS_TAG_NULL and JS_TAG_UNDEFINED */
if ((uint32_t)JS_VALUE_GET_TAG(op1) <= JS_TAG_UNDEFINED) {
res = JS_VALUE_GET_INT(op1);
} else {
@@ -17526,26 +17510,21 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
}
sp--;
BREAK;
- CASE(OP_iterator_close_return):
+ CASE(OP_nip_catch):
{
JSValue ret_val;
- /* iter_obj next catch_offset ... ret_val ->
- ret_eval iter_obj next catch_offset */
+ /* catch_offset ... ret_val -> ret_eval */
ret_val = *--sp;
while (sp > stack_buf &&
JS_VALUE_GET_TAG(sp[-1]) != JS_TAG_CATCH_OFFSET) {
JS_FreeValue(ctx, *--sp);
}
- if (unlikely(sp < stack_buf + 3)) {
- JS_ThrowInternalError(ctx, "iterator_close_return");
+ if (unlikely(sp == stack_buf)) {
+ JS_ThrowInternalError(ctx, "nip_catch");
JS_FreeValue(ctx, ret_val);
goto exception;
}
- sp[0] = sp[-1];
- sp[-1] = sp[-2];
- sp[-2] = sp[-3];
- sp[-3] = ret_val;
- sp++;
+ sp[-1] = ret_val;
}
BREAK;
@@ -17554,7 +17533,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
{
JSValue ret;
ret = JS_Call(ctx, sp[-3], sp[-4],
- 1, (sp - 1));
+ 1, (JSValueConst *)(sp - 1));
if (JS_IsException(ret))
goto exception;
JS_FreeValue(ctx, sp[-1]);
@@ -17582,7 +17561,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
0, NULL);
} else {
ret = JS_CallFree(ctx, method, sp[-4],
- 1, (sp - 1));
+ 1, (JSValueConst *)(sp - 1));
}
if (JS_IsException(ret))
goto exception;
@@ -17646,7 +17625,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
atom = get_u32(pc);
pc += 4;
- ret = JS_SetPropertyInternal(ctx, sp[-2], atom, sp[-1],
+ ret = JS_SetPropertyInternal(ctx, sp[-2], atom, sp[-1], sp[-2],
JS_PROP_THROW_STRICT);
JS_FreeValue(ctx, sp[-2]);
sp -= 2;
@@ -17945,8 +17924,8 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
atom = JS_ValueToAtom(ctx, sp[-2]);
if (unlikely(atom == JS_ATOM_NULL))
goto exception;
- ret = JS_SetPropertyGeneric(ctx, sp[-3], atom, sp[-1], sp[-4],
- JS_PROP_THROW_STRICT);
+ ret = JS_SetPropertyInternal(ctx, sp[-3], atom, sp[-1], sp[-4],
+ JS_PROP_THROW_STRICT);
JS_FreeAtom(ctx, atom);
JS_FreeValue(ctx, sp[-4]);
JS_FreeValue(ctx, sp[-3]);
@@ -18005,9 +17984,14 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
sp[-2] = JS_NewInt32(ctx, r);
sp--;
} else if (JS_VALUE_IS_BOTH_FLOAT(op1, op2)) {
- sp[-2] = JS_NewFloat64Impl(ctx, JS_VALUE_GET_FLOAT64(op1) +
+ sp[-2] = __JS_NewFloat64(ctx, JS_VALUE_GET_FLOAT64(op1) +
JS_VALUE_GET_FLOAT64(op2));
sp--;
+ } else if (JS_IsString(op1) && JS_IsString(op2)) {
+ sp[-2] = JS_ConcatString(ctx, op1, op2);
+ sp--;
+ if (JS_IsException(sp[-1]))
+ goto exception;
} else {
add_slow:
if (js_add_slow(ctx, sp))
@@ -18018,38 +18002,45 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
BREAK;
CASE(OP_add_loc):
{
+ JSValue op2;
JSValue *pv;
int idx;
idx = *pc;
pc += 1;
+ op2 = sp[-1];
pv = &var_buf[idx];
- if (likely(JS_VALUE_IS_BOTH_INT(*pv, sp[-1]))) {
+ if (likely(JS_VALUE_IS_BOTH_INT(*pv, op2))) {
int64_t r;
- r = (int64_t)JS_VALUE_GET_INT(*pv) +
- JS_VALUE_GET_INT(sp[-1]);
+ r = (int64_t)JS_VALUE_GET_INT(*pv) + JS_VALUE_GET_INT(op2);
if (unlikely((int)r != r))
goto add_loc_slow;
*pv = JS_NewInt32(ctx, r);
sp--;
+ } else if (JS_VALUE_IS_BOTH_FLOAT(*pv, op2)) {
+ *pv = __JS_NewFloat64(ctx, JS_VALUE_GET_FLOAT64(*pv) +
+ JS_VALUE_GET_FLOAT64(op2));
+ sp--;
} else if (JS_VALUE_GET_TAG(*pv) == JS_TAG_STRING) {
- JSValue op1;
- op1 = sp[-1];
sp--;
- op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NONE);
- if (JS_IsException(op1))
- goto exception;
- op1 = JS_ConcatString(ctx, JS_DupValue(ctx, *pv), op1);
- if (JS_IsException(op1))
+ op2 = JS_ToPrimitiveFree(ctx, op2, HINT_NONE);
+ if (JS_IsException(op2))
goto exception;
- set_value(ctx, pv, op1);
+ if (JS_ConcatStringInPlace(ctx, JS_VALUE_GET_STRING(*pv), op2)) {
+ JS_FreeValue(ctx, op2);
+ } else {
+ op2 = JS_ConcatString(ctx, JS_DupValue(ctx, *pv), op2);
+ if (JS_IsException(op2))
+ goto exception;
+ set_value(ctx, pv, op2);
+ }
} else {
JSValue ops[2];
add_loc_slow:
/* In case of exception, js_add_slow frees ops[0]
and ops[1], so we must duplicate *pv */
ops[0] = JS_DupValue(ctx, *pv);
- ops[1] = sp[-1];
+ ops[1] = op2;
sp--;
if (js_add_slow(ctx, ops + 2))
goto exception;
@@ -18070,8 +18061,8 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
sp[-2] = JS_NewInt32(ctx, r);
sp--;
} else if (JS_VALUE_IS_BOTH_FLOAT(op1, op2)) {
- sp[-2] = JS_NewFloat64Impl(ctx, JS_VALUE_GET_FLOAT64(op1) -
- JS_VALUE_GET_FLOAT64(op2));
+ sp[-2] = __JS_NewFloat64(ctx, JS_VALUE_GET_FLOAT64(op1) -
+ JS_VALUE_GET_FLOAT64(op2));
sp--;
} else {
goto binary_arith_slow;
@@ -18113,7 +18104,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
#endif
d = JS_VALUE_GET_FLOAT64(op1) * JS_VALUE_GET_FLOAT64(op2);
mul_fp_res:
- sp[-2] = JS_NewFloat64Impl(ctx, d);
+ sp[-2] = __JS_NewFloat64(ctx, d);
sp--;
} else {
goto binary_arith_slow;
@@ -18205,7 +18196,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
} else if (JS_TAG_IS_FLOAT64(tag)) {
d = -JS_VALUE_GET_FLOAT64(op1);
neg_fp_res:
- sp[-1] = JS_NewFloat64Impl(ctx, d);
+ sp[-1] = __JS_NewFloat64(ctx, d);
} else {
if (js_unary_arith_slow(ctx, sp, opcode))
goto exception;
@@ -18495,6 +18486,11 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
goto exception;
sp--;
BREAK;
+ CASE(OP_private_in):
+ if (js_operator_private_in(ctx, sp))
+ goto exception;
+ sp--;
+ BREAK;
CASE(OP_instanceof):
if (js_operator_instanceof(ctx, sp))
goto exception;
@@ -18625,7 +18621,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
break;
case OP_with_put_var:
/* XXX: check if strict mode */
- ret = JS_SetPropertyInternal(ctx, obj, atom, sp[-2],
+ ret = JS_SetPropertyInternal(ctx, obj, atom, sp[-2], obj,
JS_PROP_THROW_STRICT);
JS_FreeValue(ctx, sp[-1]);
sp -= 2;
@@ -18681,9 +18677,11 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
ret_val = JS_NewInt32(ctx, FUNC_RET_YIELD_STAR);
goto done_generator;
CASE(OP_return_async):
- CASE(OP_initial_yield):
ret_val = JS_UNDEFINED;
goto done_generator;
+ CASE(OP_initial_yield):
+ ret_val = JS_NewInt32(ctx, FUNC_RET_INITIAL_YIELD);
+ goto done_generator;
CASE(OP_nop):
BREAK;
@@ -18802,14 +18800,14 @@ JSValue JS_Call(JSContext *ctx, JSValueConst func_obj, JSValueConst this_obj,
int argc, JSValueConst *argv)
{
return JS_CallInternal(ctx, func_obj, this_obj, JS_UNDEFINED,
- argc, argv, JS_CALL_FLAG_COPY_ARGV);
+ argc, (JSValue *)argv, JS_CALL_FLAG_COPY_ARGV);
}
static JSValue JS_CallFree(JSContext *ctx, JSValue func_obj, JSValueConst this_obj,
int argc, JSValueConst *argv)
{
JSValue res = JS_CallInternal(ctx, func_obj, this_obj, JS_UNDEFINED,
- argc, argv, JS_CALL_FLAG_COPY_ARGV);
+ argc, (JSValue *)argv, JS_CALL_FLAG_COPY_ARGV);
JS_FreeValue(ctx, func_obj);
return res;
}
@@ -18914,7 +18912,7 @@ static JSValue JS_CallConstructorInternal(JSContext *ctx,
return JS_ThrowTypeError(ctx, "not a function");
}
return call_func(ctx, func_obj, new_target, argc,
- argv, flags);
+ (JSValueConst *)argv, flags);
}
b = p->u.func.function_bytecode;
@@ -18943,7 +18941,7 @@ JSValue JS_CallConstructor2(JSContext *ctx, JSValueConst func_obj,
int argc, JSValueConst *argv)
{
return JS_CallConstructorInternal(ctx, func_obj, new_target,
- argc, argv,
+ argc, (JSValue *)argv,
JS_CALL_FLAG_COPY_ARGV);
}
@@ -18951,7 +18949,7 @@ JSValue JS_CallConstructor(JSContext *ctx, JSValueConst func_obj,
int argc, JSValueConst *argv)
{
return JS_CallConstructorInternal(ctx, func_obj, func_obj,
- argc, argv,
+ argc, (JSValue *)argv,
JS_CALL_FLAG_COPY_ARGV);
}
@@ -18974,26 +18972,35 @@ static JSValue JS_InvokeFree(JSContext *ctx, JSValue this_val, JSAtom atom,
}
/* JSAsyncFunctionState (used by generator and async functions) */
-static warn_unused int async_func_init(JSContext *ctx, JSAsyncFunctionState *s,
- JSValueConst func_obj, JSValueConst this_obj,
- int argc, JSValueConst *argv)
+static JSAsyncFunctionState *async_func_init(JSContext *ctx,
+ JSValueConst func_obj, JSValueConst this_obj,
+ int argc, JSValueConst *argv)
{
+ JSAsyncFunctionState *s;
JSObject *p;
JSFunctionBytecode *b;
JSStackFrame *sf;
int local_count, i, arg_buf_len, n;
+ s = js_mallocz(ctx, sizeof(*s));
+ if (!s)
+ return NULL;
+ s->header.ref_count = 1;
+ add_gc_object(ctx->rt, &s->header, JS_GC_OBJ_TYPE_ASYNC_FUNCTION);
+
sf = &s->frame;
init_list_head(&sf->var_ref_list);
p = JS_VALUE_GET_OBJ(func_obj);
b = p->u.func.function_bytecode;
- sf->js_mode = b->js_mode;
+ sf->js_mode = b->js_mode | JS_MODE_ASYNC;
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) * max_int(local_count, 1));
- if (!sf->arg_buf)
- return -1;
+ if (!sf->arg_buf) {
+ js_free(ctx, s);
+ return NULL;
+ }
sf->cur_func = JS_DupValue(ctx, func_obj);
s->this_val = JS_DupValue(ctx, this_obj);
s->argc = argc;
@@ -19005,38 +19012,17 @@ static warn_unused int async_func_init(JSContext *ctx, JSAsyncFunctionState *s,
n = arg_buf_len + b->var_count;
for(i = argc; i < n; i++)
sf->arg_buf[i] = JS_UNDEFINED;
- return 0;
-}
-
-static void async_func_mark(JSRuntime *rt, JSAsyncFunctionState *s,
- JS_MarkFunc *mark_func)
-{
- JSStackFrame *sf;
- JSValue *sp;
-
- sf = &s->frame;
- JS_MarkValue(rt, sf->cur_func, mark_func);
- JS_MarkValue(rt, s->this_val, mark_func);
- if (sf->cur_sp) {
- /* if the function is running, cur_sp is not known so we
- cannot mark the stack. Marking the variables is not needed
- because a running function cannot be part of a removable
- cycle */
- for(sp = sf->arg_buf; sp < sf->cur_sp; sp++)
- JS_MarkValue(rt, *sp, mark_func);
- }
+ s->resolving_funcs[0] = JS_UNDEFINED;
+ s->resolving_funcs[1] = JS_UNDEFINED;
+ s->is_completed = FALSE;
+ return s;
}
-static void async_func_free(JSRuntime *rt, JSAsyncFunctionState *s)
+static void async_func_free_frame(JSRuntime *rt, JSAsyncFunctionState *s)
{
- JSStackFrame *sf;
+ JSStackFrame *sf = &s->frame;
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);
@@ -19044,6 +19030,7 @@ static void async_func_free(JSRuntime *rt, JSAsyncFunctionState *s)
JS_FreeValueRT(rt, *sp);
}
js_free_rt(rt, sf->arg_buf);
+ sf->arg_buf = NULL;
}
JS_FreeValueRT(rt, sf->cur_func);
JS_FreeValueRT(rt, s->this_val);
@@ -19051,17 +19038,66 @@ static void async_func_free(JSRuntime *rt, JSAsyncFunctionState *s)
static JSValue async_func_resume(JSContext *ctx, JSAsyncFunctionState *s)
{
- JSValue func_obj;
+ JSRuntime *rt = ctx->rt;
+ JSStackFrame *sf = &s->frame;
+ JSValue func_obj, ret;
- if (js_check_stack_overflow(ctx->rt, 0))
- return JS_ThrowStackOverflow(ctx);
+ assert(!s->is_completed);
+ if (js_check_stack_overflow(ctx->rt, 0)) {
+ ret = JS_ThrowStackOverflow(ctx);
+ } else {
+ /* the tag does not matter provided it is not an object */
+ func_obj = JS_MKPTR(JS_TAG_INT, s);
+ ret = JS_CallInternal(ctx, func_obj, s->this_val, JS_UNDEFINED,
+ s->argc, sf->arg_buf, JS_CALL_FLAG_GENERATOR);
+ }
+ if (JS_IsException(ret) || JS_IsUndefined(ret)) {
+ if (JS_IsUndefined(ret)) {
+ ret = sf->cur_sp[-1];
+ sf->cur_sp[-1] = JS_UNDEFINED;
+ }
+ /* end of execution */
+ s->is_completed = TRUE;
+
+ /* close the closure variables. */
+ close_var_refs(rt, sf);
- /* the tag does not matter provided it is not an object */
- func_obj = JS_MKPTR(JS_TAG_INT, s);
- return JS_CallInternal(ctx, func_obj, s->this_val, JS_UNDEFINED,
- s->argc, s->frame.arg_buf, JS_CALL_FLAG_GENERATOR);
+ async_func_free_frame(rt, s);
+ }
+ return ret;
}
+static void __async_func_free(JSRuntime *rt, JSAsyncFunctionState *s)
+{
+ /* cannot close the closure variables here because it would
+ potentially modify the object graph */
+ if (!s->is_completed) {
+ async_func_free_frame(rt, s);
+ }
+
+ JS_FreeValueRT(rt, s->resolving_funcs[0]);
+ JS_FreeValueRT(rt, s->resolving_funcs[1]);
+
+ remove_gc_object(&s->header);
+ if (rt->gc_phase == JS_GC_PHASE_REMOVE_CYCLES && s->header.ref_count != 0) {
+ list_add_tail(&s->header.link, &rt->gc_zero_ref_count_list);
+ } else {
+ js_free_rt(rt, s);
+ }
+}
+
+static void async_func_free(JSRuntime *rt, JSAsyncFunctionState *s)
+{
+ if (--s->header.ref_count == 0) {
+ if (rt->gc_phase != JS_GC_PHASE_REMOVE_CYCLES) {
+ list_del(&s->header.link);
+ list_add(&s->header.link, &rt->gc_zero_ref_count_list);
+ if (rt->gc_phase == JS_GC_PHASE_NONE) {
+ free_zero_refcount(rt);
+ }
+ }
+ }
+}
/* Generators */
@@ -19075,14 +19111,17 @@ typedef enum JSGeneratorStateEnum {
typedef struct JSGeneratorData {
JSGeneratorStateEnum state;
- JSAsyncFunctionState func_state;
+ JSAsyncFunctionState *func_state;
} JSGeneratorData;
static void free_generator_stack_rt(JSRuntime *rt, JSGeneratorData *s)
{
if (s->state == JS_GENERATOR_STATE_COMPLETED)
return;
- async_func_free(rt, &s->func_state);
+ if (s->func_state) {
+ async_func_free(rt, s->func_state);
+ s->func_state = NULL;
+ }
s->state = JS_GENERATOR_STATE_COMPLETED;
}
@@ -19107,9 +19146,9 @@ static void js_generator_mark(JSRuntime *rt, JSValueConst val,
JSObject *p = JS_VALUE_GET_OBJ(val);
JSGeneratorData *s = p->u.generator_data;
- if (!s || s->state == JS_GENERATOR_STATE_COMPLETED)
+ if (!s || !s->func_state)
return;
- async_func_mark(rt, &s->func_state, mark_func);
+ mark_func(rt, &s->func_state->header);
}
/* XXX: use enum */
@@ -19128,10 +19167,10 @@ static JSValue js_generator_next(JSContext *ctx, JSValueConst this_val,
*pdone = TRUE;
if (!s)
return JS_ThrowTypeError(ctx, "not a generator");
- sf = &s->func_state.frame;
switch(s->state) {
default:
case JS_GENERATOR_STATE_SUSPENDED_START:
+ sf = &s->func_state->frame;
if (magic == GEN_MAGIC_NEXT) {
goto exec_no_arg;
} else {
@@ -19141,28 +19180,29 @@ static JSValue js_generator_next(JSContext *ctx, JSValueConst this_val,
break;
case JS_GENERATOR_STATE_SUSPENDED_YIELD_STAR:
case JS_GENERATOR_STATE_SUSPENDED_YIELD:
+ sf = &s->func_state->frame;
/* cur_sp[-1] was set to JS_UNDEFINED in the previous call */
ret = JS_DupValue(ctx, argv[0]);
if (magic == GEN_MAGIC_THROW &&
s->state == JS_GENERATOR_STATE_SUSPENDED_YIELD) {
JS_Throw(ctx, ret);
- s->func_state.throw_flag = TRUE;
+ s->func_state->throw_flag = TRUE;
} else {
sf->cur_sp[-1] = ret;
sf->cur_sp[0] = JS_NewInt32(ctx, magic);
sf->cur_sp++;
exec_no_arg:
- s->func_state.throw_flag = FALSE;
+ s->func_state->throw_flag = FALSE;
}
s->state = JS_GENERATOR_STATE_EXECUTING;
- func_ret = async_func_resume(ctx, &s->func_state);
+ func_ret = async_func_resume(ctx, s->func_state);
s->state = JS_GENERATOR_STATE_SUSPENDED_YIELD;
- if (JS_IsException(func_ret)) {
- /* finalize the execution in case of exception */
+ if (s->func_state->is_completed) {
+ /* finalize the execution in case of exception or normal return */
free_generator_stack(ctx, s);
return func_ret;
- }
- if (JS_VALUE_GET_TAG(func_ret) == JS_TAG_INT) {
+ } else {
+ assert(JS_VALUE_GET_TAG(func_ret) == JS_TAG_INT);
/* get the returned yield value at the top of the stack */
ret = sf->cur_sp[-1];
sf->cur_sp[-1] = JS_UNDEFINED;
@@ -19173,12 +19213,6 @@ static JSValue js_generator_next(JSContext *ctx, JSValueConst this_val,
} else {
*pdone = FALSE;
}
- } else {
- /* end of iterator */
- ret = sf->cur_sp[-1];
- sf->cur_sp[-1] = JS_UNDEFINED;
- JS_FreeValue(ctx, func_ret);
- free_generator_stack(ctx, s);
}
break;
case JS_GENERATOR_STATE_COMPLETED:
@@ -19216,13 +19250,14 @@ static JSValue js_generator_function_call(JSContext *ctx, JSValueConst func_obj,
if (!s)
return JS_EXCEPTION;
s->state = JS_GENERATOR_STATE_SUSPENDED_START;
- if (async_func_init(ctx, &s->func_state, func_obj, this_obj, argc, argv)) {
+ s->func_state = async_func_init(ctx, func_obj, this_obj, argc, argv);
+ if (!s->func_state) {
s->state = JS_GENERATOR_STATE_COMPLETED;
goto fail;
}
/* execute the function up to 'OP_initial_yield' */
- func_ret = async_func_resume(ctx, &s->func_state);
+ func_ret = async_func_resume(ctx, s->func_state);
if (JS_IsException(func_ret))
goto fail;
JS_FreeValue(ctx, func_ret);
@@ -19240,36 +19275,12 @@ static JSValue js_generator_function_call(JSContext *ctx, JSValueConst func_obj,
/* AsyncFunction */
-static void js_async_function_terminate(JSRuntime *rt, JSAsyncFunctionData *s)
-{
- if (s->is_active) {
- async_func_free(rt, &s->func_state);
- s->is_active = FALSE;
- }
-}
-
-static void js_async_function_free0(JSRuntime *rt, JSAsyncFunctionData *s)
-{
- js_async_function_terminate(rt, s);
- JS_FreeValueRT(rt, s->resolving_funcs[0]);
- JS_FreeValueRT(rt, s->resolving_funcs[1]);
- remove_gc_object(&s->header);
- js_free_rt(rt, s);
-}
-
-static void js_async_function_free(JSRuntime *rt, JSAsyncFunctionData *s)
-{
- if (--s->header.ref_count == 0) {
- js_async_function_free0(rt, s);
- }
-}
-
static void js_async_function_resolve_finalizer(JSRuntime *rt, JSValue val)
{
JSObject *p = JS_VALUE_GET_OBJ(val);
- JSAsyncFunctionData *s = p->u.async_function_data;
+ JSAsyncFunctionState *s = p->u.async_function_data;
if (s) {
- js_async_function_free(rt, s);
+ async_func_free(rt, s);
}
}
@@ -19277,14 +19288,14 @@ static void js_async_function_resolve_mark(JSRuntime *rt, JSValueConst val,
JS_MarkFunc *mark_func)
{
JSObject *p = JS_VALUE_GET_OBJ(val);
- JSAsyncFunctionData *s = p->u.async_function_data;
+ JSAsyncFunctionState *s = p->u.async_function_data;
if (s) {
mark_func(rt, &s->header);
}
}
static int js_async_function_resolve_create(JSContext *ctx,
- JSAsyncFunctionData *s,
+ JSAsyncFunctionState *s,
JSValue *resolving_funcs)
{
int i;
@@ -19306,60 +19317,58 @@ static int js_async_function_resolve_create(JSContext *ctx,
return 0;
}
-static void js_async_function_resume(JSContext *ctx, JSAsyncFunctionData *s)
+static void js_async_function_resume(JSContext *ctx, JSAsyncFunctionState *s)
{
JSValue func_ret, ret2;
- func_ret = async_func_resume(ctx, &s->func_state);
- if (JS_IsException(func_ret)) {
- JSValue error;
- fail:
- error = JS_GetException(ctx);
- ret2 = JS_Call(ctx, s->resolving_funcs[1], JS_UNDEFINED,
- 1, &error);
- JS_FreeValue(ctx, error);
- js_async_function_terminate(ctx->rt, s);
- JS_FreeValue(ctx, ret2); /* XXX: what to do if exception ? */
- } else {
- JSValue value;
- value = s->func_state.frame.cur_sp[-1];
- s->func_state.frame.cur_sp[-1] = JS_UNDEFINED;
- if (JS_IsUndefined(func_ret)) {
- /* function returned */
- ret2 = JS_Call(ctx, s->resolving_funcs[0], JS_UNDEFINED,
- 1, &value);
+ func_ret = async_func_resume(ctx, s);
+ if (s->is_completed) {
+ if (JS_IsException(func_ret)) {
+ JSValue error;
+ fail:
+ error = JS_GetException(ctx);
+ ret2 = JS_Call(ctx, s->resolving_funcs[1], JS_UNDEFINED,
+ 1, (JSValueConst *)&error);
+ JS_FreeValue(ctx, error);
JS_FreeValue(ctx, ret2); /* XXX: what to do if exception ? */
- JS_FreeValue(ctx, value);
- js_async_function_terminate(ctx->rt, s);
} else {
- JSValue promise, resolving_funcs[2], resolving_funcs1[2];
- int i, res;
+ /* normal return */
+ ret2 = JS_Call(ctx, s->resolving_funcs[0], JS_UNDEFINED,
+ 1, (JSValueConst *)&func_ret);
+ JS_FreeValue(ctx, func_ret);
+ JS_FreeValue(ctx, ret2); /* XXX: what to do if exception ? */
+ }
+ } else {
+ JSValue value, promise, resolving_funcs[2], resolving_funcs1[2];
+ int i, res;
- /* await */
- JS_FreeValue(ctx, func_ret); /* not used */
- promise = js_promise_resolve(ctx, ctx->promise_ctor,
- 1, &value, 0);
- JS_FreeValue(ctx, value);
- if (JS_IsException(promise))
- goto fail;
- if (js_async_function_resolve_create(ctx, s, resolving_funcs)) {
- JS_FreeValue(ctx, promise);
- goto fail;
- }
+ value = s->frame.cur_sp[-1];
+ s->frame.cur_sp[-1] = JS_UNDEFINED;
- /* Note: no need to create 'thrownawayCapability' as in
- the spec */
- for(i = 0; i < 2; i++)
- resolving_funcs1[i] = JS_UNDEFINED;
- res = perform_promise_then(ctx, promise,
- (JSValueConst *)resolving_funcs,
- (JSValueConst *)resolving_funcs1);
+ /* await */
+ JS_FreeValue(ctx, func_ret); /* not used */
+ promise = js_promise_resolve(ctx, ctx->promise_ctor,
+ 1, (JSValueConst *)&value, 0);
+ JS_FreeValue(ctx, value);
+ if (JS_IsException(promise))
+ goto fail;
+ if (js_async_function_resolve_create(ctx, s, resolving_funcs)) {
JS_FreeValue(ctx, promise);
- for(i = 0; i < 2; i++)
- JS_FreeValue(ctx, resolving_funcs[i]);
- if (res)
- goto fail;
+ goto fail;
}
+
+ /* Note: no need to create 'thrownawayCapability' as in
+ the spec */
+ for(i = 0; i < 2; i++)
+ resolving_funcs1[i] = JS_UNDEFINED;
+ res = perform_promise_then(ctx, promise,
+ (JSValueConst *)resolving_funcs,
+ (JSValueConst *)resolving_funcs1);
+ JS_FreeValue(ctx, promise);
+ for(i = 0; i < 2; i++)
+ JS_FreeValue(ctx, resolving_funcs[i]);
+ if (res)
+ goto fail;
}
}
@@ -19370,7 +19379,7 @@ static JSValue js_async_function_resolve_call(JSContext *ctx,
int flags)
{
JSObject *p = JS_VALUE_GET_OBJ(func_obj);
- JSAsyncFunctionData *s = p->u.async_function_data;
+ JSAsyncFunctionState *s = p->u.async_function_data;
BOOL is_reject = p->class_id - JS_CLASS_ASYNC_FUNCTION_RESOLVE;
JSValueConst arg;
@@ -19378,12 +19387,12 @@ static JSValue js_async_function_resolve_call(JSContext *ctx,
arg = argv[0];
else
arg = JS_UNDEFINED;
- s->func_state.throw_flag = is_reject;
+ s->throw_flag = is_reject;
if (is_reject) {
JS_Throw(ctx, JS_DupValue(ctx, arg));
} else {
/* return value of await */
- s->func_state.frame.cur_sp[-1] = JS_DupValue(ctx, arg);
+ s->frame.cur_sp[-1] = JS_DupValue(ctx, arg);
}
js_async_function_resume(ctx, s);
return JS_UNDEFINED;
@@ -19394,32 +19403,21 @@ static JSValue js_async_function_call(JSContext *ctx, JSValueConst func_obj,
int argc, JSValueConst *argv, int flags)
{
JSValue promise;
- JSAsyncFunctionData *s;
+ JSAsyncFunctionState *s;
- s = js_mallocz(ctx, sizeof(*s));
+ s = async_func_init(ctx, func_obj, this_obj, argc, argv);
if (!s)
return JS_EXCEPTION;
- s->header.ref_count = 1;
- add_gc_object(ctx->rt, &s->header, JS_GC_OBJ_TYPE_ASYNC_FUNCTION);
- s->is_active = FALSE;
- s->resolving_funcs[0] = JS_UNDEFINED;
- s->resolving_funcs[1] = JS_UNDEFINED;
promise = JS_NewPromiseCapability(ctx, s->resolving_funcs);
- if (JS_IsException(promise))
- goto fail;
-
- if (async_func_init(ctx, &s->func_state, func_obj, this_obj, argc, argv)) {
- fail:
- JS_FreeValue(ctx, promise);
- js_async_function_free(ctx->rt, s);
+ if (JS_IsException(promise)) {
+ async_func_free(ctx->rt, s);
return JS_EXCEPTION;
}
- s->is_active = TRUE;
js_async_function_resume(ctx, s);
- js_async_function_free(ctx->rt, s);
+ async_func_free(ctx->rt, s);
return promise;
}
@@ -19448,7 +19446,8 @@ typedef struct JSAsyncGeneratorRequest {
typedef struct JSAsyncGeneratorData {
JSObject *generator; /* back pointer to the object (const) */
JSAsyncGeneratorStateEnum state;
- JSAsyncFunctionState func_state;
+ /* func_state is NULL is state AWAITING_RETURN and COMPLETED */
+ JSAsyncFunctionState *func_state;
struct list_head queue; /* list of JSAsyncGeneratorRequest.link */
} JSAsyncGeneratorData;
@@ -19466,10 +19465,8 @@ static void js_async_generator_free(JSRuntime *rt,
JS_FreeValueRT(rt, req->resolving_funcs[1]);
js_free_rt(rt, req);
}
- if (s->state != JS_ASYNC_GENERATOR_STATE_COMPLETED &&
- s->state != JS_ASYNC_GENERATOR_STATE_AWAITING_RETURN) {
- async_func_free(rt, &s->func_state);
- }
+ if (s->func_state)
+ async_func_free(rt, s->func_state);
js_free_rt(rt, s);
}
@@ -19496,9 +19493,8 @@ static void js_async_generator_mark(JSRuntime *rt, JSValueConst val,
JS_MarkValue(rt, req->resolving_funcs[0], mark_func);
JS_MarkValue(rt, req->resolving_funcs[1], mark_func);
}
- if (s->state != JS_ASYNC_GENERATOR_STATE_COMPLETED &&
- s->state != JS_ASYNC_GENERATOR_STATE_AWAITING_RETURN) {
- async_func_mark(rt, &s->func_state, mark_func);
+ if (s->func_state) {
+ mark_func(rt, &s->func_state->header);
}
}
}
@@ -19608,7 +19604,8 @@ 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_free(ctx->rt, &s->func_state);
+ async_func_free(ctx->rt, s->func_state);
+ s->func_state = NULL;
}
}
@@ -19619,10 +19616,19 @@ static int js_async_generator_completed_return(JSContext *ctx,
JSValue promise, resolving_funcs[2], resolving_funcs1[2];
int res;
- promise = js_promise_resolve(ctx, ctx->promise_ctor,
- 1, &value, 0);
- if (JS_IsException(promise))
- return -1;
+ // Can fail looking up JS_ATOM_constructor when is_reject==0.
+ promise = js_promise_resolve(ctx, ctx->promise_ctor, 1, &value,
+ /*is_reject*/0);
+ // A poisoned .constructor property is observable and the resulting
+ // exception should be delivered to the catch handler.
+ if (JS_IsException(promise)) {
+ JSValue err = JS_GetException(ctx);
+ promise = js_promise_resolve(ctx, ctx->promise_ctor, 1, (JSValueConst *)&err,
+ /*is_reject*/1);
+ JS_FreeValue(ctx, err);
+ if (JS_IsException(promise))
+ return -1;
+ }
if (js_async_generator_resolve_function_create(ctx,
JS_MKPTR(JS_TAG_OBJECT, s->generator),
resolving_funcs1,
@@ -19670,7 +19676,6 @@ static void js_async_generator_resume_next(JSContext *ctx,
} else if (next->completion_type == GEN_MAGIC_RETURN) {
s->state = JS_ASYNC_GENERATOR_STATE_AWAITING_RETURN;
js_async_generator_completed_return(ctx, s, next->result);
- goto done;
} else {
js_async_generator_reject(ctx, s, next->result);
}
@@ -19681,30 +19686,38 @@ static void js_async_generator_resume_next(JSContext *ctx,
if (next->completion_type == GEN_MAGIC_THROW &&
s->state == JS_ASYNC_GENERATOR_STATE_SUSPENDED_YIELD) {
JS_Throw(ctx, value);
- s->func_state.throw_flag = TRUE;
+ s->func_state->throw_flag = TRUE;
} else {
/* 'yield' returns a value. 'yield *' also returns a value
in case the 'throw' method is called */
- s->func_state.frame.cur_sp[-1] = value;
- s->func_state.frame.cur_sp[0] =
+ s->func_state->frame.cur_sp[-1] = value;
+ s->func_state->frame.cur_sp[0] =
JS_NewInt32(ctx, next->completion_type);
- s->func_state.frame.cur_sp++;
+ s->func_state->frame.cur_sp++;
exec_no_arg:
- s->func_state.throw_flag = FALSE;
+ s->func_state->throw_flag = FALSE;
}
s->state = JS_ASYNC_GENERATOR_STATE_EXECUTING;
resume_exec:
- func_ret = async_func_resume(ctx, &s->func_state);
- if (JS_IsException(func_ret)) {
- value = JS_GetException(ctx);
- js_async_generator_complete(ctx, s);
- js_async_generator_reject(ctx, s, value);
- JS_FreeValue(ctx, value);
- } else if (JS_VALUE_GET_TAG(func_ret) == JS_TAG_INT) {
- int func_ret_code;
- value = s->func_state.frame.cur_sp[-1];
- s->func_state.frame.cur_sp[-1] = JS_UNDEFINED;
+ func_ret = async_func_resume(ctx, s->func_state);
+ if (s->func_state->is_completed) {
+ if (JS_IsException(func_ret)) {
+ value = JS_GetException(ctx);
+ js_async_generator_complete(ctx, s);
+ js_async_generator_reject(ctx, s, value);
+ JS_FreeValue(ctx, value);
+ } else {
+ /* end of function */
+ js_async_generator_complete(ctx, s);
+ js_async_generator_resolve(ctx, s, func_ret, TRUE);
+ JS_FreeValue(ctx, func_ret);
+ }
+ } else {
+ int func_ret_code, ret;
+ assert(JS_VALUE_GET_TAG(func_ret) == JS_TAG_INT);
func_ret_code = JS_VALUE_GET_INT(func_ret);
+ value = s->func_state->frame.cur_sp[-1];
+ s->func_state->frame.cur_sp[-1] = JS_UNDEFINED;
switch(func_ret_code) {
case FUNC_RET_YIELD:
case FUNC_RET_YIELD_STAR:
@@ -19716,20 +19729,17 @@ static void js_async_generator_resume_next(JSContext *ctx,
JS_FreeValue(ctx, value);
break;
case FUNC_RET_AWAIT:
- js_async_generator_await(ctx, s, value);
+ ret = js_async_generator_await(ctx, s, value);
JS_FreeValue(ctx, value);
+ if (ret < 0) {
+ /* exception: throw it */
+ s->func_state->throw_flag = TRUE;
+ goto resume_exec;
+ }
goto done;
default:
abort();
}
- } else {
- assert(JS_IsUndefined(func_ret));
- /* end of function */
- value = s->func_state.frame.cur_sp[-1];
- s->func_state.frame.cur_sp[-1] = JS_UNDEFINED;
- js_async_generator_complete(ctx, s);
- js_async_generator_resolve(ctx, s, value, TRUE);
- JS_FreeValue(ctx, value);
}
break;
default:
@@ -19763,12 +19773,12 @@ static JSValue js_async_generator_resolve_function(JSContext *ctx,
} else {
/* restart function execution after await() */
assert(s->state == JS_ASYNC_GENERATOR_STATE_EXECUTING);
- s->func_state.throw_flag = is_reject;
+ s->func_state->throw_flag = is_reject;
if (is_reject) {
JS_Throw(ctx, JS_DupValue(ctx, arg));
} else {
/* return value of await */
- s->func_state.frame.cur_sp[-1] = JS_DupValue(ctx, arg);
+ s->func_state->frame.cur_sp[-1] = JS_DupValue(ctx, arg);
}
js_async_generator_resume_next(ctx, s);
}
@@ -19792,7 +19802,7 @@ static JSValue js_async_generator_next(JSContext *ctx, JSValueConst this_val,
JS_ThrowTypeError(ctx, "not an AsyncGenerator object");
err = JS_GetException(ctx);
res2 = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED,
- 1, &err);
+ 1, (JSValueConst *)&err);
JS_FreeValue(ctx, err);
JS_FreeValue(ctx, res2);
JS_FreeValue(ctx, resolving_funcs[0]);
@@ -19832,14 +19842,12 @@ static JSValue js_async_generator_function_call(JSContext *ctx, JSValueConst fun
return JS_EXCEPTION;
s->state = JS_ASYNC_GENERATOR_STATE_SUSPENDED_START;
init_list_head(&s->queue);
- if (async_func_init(ctx, &s->func_state, func_obj, this_obj, argc, argv)) {
- s->state = JS_ASYNC_GENERATOR_STATE_COMPLETED;
+ s->func_state = async_func_init(ctx, func_obj, this_obj, argc, argv);
+ if (!s->func_state)
goto fail;
- }
-
/* execute the function up to 'OP_initial_yield' (no yield nor
await are possible) */
- func_ret = async_func_resume(ctx, &s->func_state);
+ func_ret = async_func_resume(ctx, s->func_state);
if (JS_IsException(func_ret))
goto fail;
JS_FreeValue(ctx, func_ret);
@@ -20025,6 +20033,7 @@ typedef enum JSParseFunctionEnum {
JS_PARSE_FUNC_GETTER,
JS_PARSE_FUNC_SETTER,
JS_PARSE_FUNC_METHOD,
+ JS_PARSE_FUNC_CLASS_STATIC_INIT,
JS_PARSE_FUNC_CLASS_CONSTRUCTOR,
JS_PARSE_FUNC_DERIVED_CLASS_CONSTRUCTOR,
} JSParseFunctionEnum;
@@ -20144,6 +20153,7 @@ typedef struct JSFunctionDef {
int source_len;
JSModuleDef *module; /* != NULL when parsing a module */
+ BOOL has_await; /* TRUE if await is used (used in module eval) */
} JSFunctionDef;
typedef struct JSToken {
@@ -20227,16 +20237,14 @@ static const JSOpCode opcode_info[OP_COUNT + (OP_TEMP_END - OP_TEMP_START)] = {
#define short_opcode_info(op) opcode_info[op]
#endif
-static warn_unused int next_token(JSParseState *s);
+static __exception int next_token(JSParseState *s);
static void free_token(JSParseState *s, JSToken *token)
{
switch(token->val) {
-#ifdef CONFIG_BIGNUM
case TOK_NUMBER:
JS_FreeValue(s->ctx, token->u.num.val);
break;
-#endif
case TOK_STRING:
case TOK_TEMPLATE:
JS_FreeValue(s->ctx, token->u.str.str);
@@ -20258,7 +20266,7 @@ static void free_token(JSParseState *s, JSToken *token)
}
}
-static void maybe_unused dump_token(JSParseState *s,
+static void __maybe_unused dump_token(JSParseState *s,
const JSToken *token)
{
switch(token->val) {
@@ -20365,7 +20373,7 @@ static int js_parse_error_reserved_identifier(JSParseState *s)
s->token.u.ident.atom));
}
-static warn_unused int js_parse_template_part(JSParseState *s, const uint8_t *p)
+static __exception int js_parse_template_part(JSParseState *s, const uint8_t *p)
{
uint32_t c;
StringBuffer b_s, *b = &b_s;
@@ -20426,7 +20434,7 @@ static warn_unused int js_parse_template_part(JSParseState *s, const uint8_t *p)
return -1;
}
-static warn_unused int js_parse_string(JSParseState *s, int sep,
+static __exception int js_parse_string(JSParseState *s, int sep,
BOOL do_throw, const uint8_t *p,
JSToken *token, const uint8_t **pp)
{
@@ -20571,7 +20579,7 @@ static inline BOOL token_is_pseudo_keyword(JSParseState *s, JSAtom atom) {
!s->token.u.ident.has_escape;
}
-static warn_unused int js_parse_regexp(JSParseState *s)
+static __exception int js_parse_regexp(JSParseState *s)
{
const uint8_t *p;
BOOL in_class;
@@ -20669,7 +20677,7 @@ static warn_unused int js_parse_regexp(JSParseState *s)
return -1;
}
-static warn_unused int ident_realloc(JSContext *ctx, char **pbuf, size_t *psize,
+static __exception int ident_realloc(JSContext *ctx, char **pbuf, size_t *psize,
const char *static_buf)
{
char *buf, *new_buf;
@@ -20696,6 +20704,48 @@ static warn_unused int ident_realloc(JSContext *ctx, char **pbuf, size_t *psize,
return 0;
}
+/* convert a TOK_IDENT to a keyword when needed */
+static void update_token_ident(JSParseState *s)
+{
+ if (s->token.u.ident.atom <= JS_ATOM_LAST_KEYWORD ||
+ (s->token.u.ident.atom <= JS_ATOM_LAST_STRICT_KEYWORD &&
+ (s->cur_func->js_mode & JS_MODE_STRICT)) ||
+ (s->token.u.ident.atom == JS_ATOM_yield &&
+ ((s->cur_func->func_kind & JS_FUNC_GENERATOR) ||
+ (s->cur_func->func_type == JS_PARSE_FUNC_ARROW &&
+ !s->cur_func->in_function_body && s->cur_func->parent &&
+ (s->cur_func->parent->func_kind & JS_FUNC_GENERATOR)))) ||
+ (s->token.u.ident.atom == JS_ATOM_await &&
+ (s->is_module ||
+ (s->cur_func->func_kind & JS_FUNC_ASYNC) ||
+ s->cur_func->func_type == JS_PARSE_FUNC_CLASS_STATIC_INIT ||
+ (s->cur_func->func_type == JS_PARSE_FUNC_ARROW &&
+ !s->cur_func->in_function_body && s->cur_func->parent &&
+ ((s->cur_func->parent->func_kind & JS_FUNC_ASYNC) ||
+ s->cur_func->parent->func_type == JS_PARSE_FUNC_CLASS_STATIC_INIT))))) {
+ if (s->token.u.ident.has_escape) {
+ s->token.u.ident.is_reserved = TRUE;
+ s->token.val = TOK_IDENT;
+ } else {
+ /* The keywords atoms are pre allocated */
+ s->token.val = s->token.u.ident.atom - 1 + TOK_FIRST_KEYWORD;
+ }
+ }
+}
+
+/* if the current token is an identifier or keyword, reparse it
+ according to the current function type */
+static void reparse_ident_token(JSParseState *s)
+{
+ if (s->token.val == TOK_IDENT ||
+ (s->token.val >= TOK_FIRST_KEYWORD &&
+ s->token.val <= TOK_LAST_KEYWORD)) {
+ s->token.val = TOK_IDENT;
+ s->token.u.ident.is_reserved = FALSE;
+ update_token_ident(s);
+ }
+}
+
/* 'c' is the first character. Return JS_ATOM_NULL in case of error */
static JSAtom parse_ident(JSParseState *s, const uint8_t **pp,
BOOL *pident_has_escape, int c, BOOL is_private)
@@ -20745,7 +20795,7 @@ static JSAtom parse_ident(JSParseState *s, const uint8_t **pp,
}
-static warn_unused int next_token(JSParseState *s)
+static __exception int next_token(JSParseState *s)
{
const uint8_t *p;
int c;
@@ -20902,30 +20952,8 @@ static warn_unused int next_token(JSParseState *s)
s->token.u.ident.atom = atom;
s->token.u.ident.has_escape = ident_has_escape;
s->token.u.ident.is_reserved = FALSE;
- if (s->token.u.ident.atom <= JS_ATOM_LAST_KEYWORD ||
- (s->token.u.ident.atom <= JS_ATOM_LAST_STRICT_KEYWORD &&
- (s->cur_func->js_mode & JS_MODE_STRICT)) ||
- (s->token.u.ident.atom == JS_ATOM_yield &&
- ((s->cur_func->func_kind & JS_FUNC_GENERATOR) ||
- (s->cur_func->func_type == JS_PARSE_FUNC_ARROW &&
- !s->cur_func->in_function_body && s->cur_func->parent &&
- (s->cur_func->parent->func_kind & JS_FUNC_GENERATOR)))) ||
- (s->token.u.ident.atom == JS_ATOM_await &&
- (s->is_module ||
- (((s->cur_func->func_kind & JS_FUNC_ASYNC) ||
- (s->cur_func->func_type == JS_PARSE_FUNC_ARROW &&
- !s->cur_func->in_function_body && s->cur_func->parent &&
- (s->cur_func->parent->func_kind & JS_FUNC_ASYNC))))))) {
- if (ident_has_escape) {
- s->token.u.ident.is_reserved = TRUE;
- s->token.val = TOK_IDENT;
- } else {
- /* The keywords atoms are pre allocated */
- s->token.val = s->token.u.ident.atom - 1 + TOK_FIRST_KEYWORD;
- }
- } else {
- s->token.val = TOK_IDENT;
- }
+ s->token.val = TOK_IDENT;
+ update_token_ident(s);
break;
case '#':
/* private name */
@@ -20982,8 +21010,8 @@ static warn_unused int next_token(JSParseState *s)
int flags, radix;
flags = ATOD_ACCEPT_BIN_OCT | ATOD_ACCEPT_LEGACY_OCTAL |
ATOD_ACCEPT_UNDERSCORES;
-#ifdef CONFIG_BIGNUM
flags |= ATOD_ACCEPT_SUFFIX;
+#ifdef CONFIG_BIGNUM
if (s->cur_func->js_mode & JS_MODE_MATH) {
flags |= ATOD_MODE_BIGINT;
if (s->cur_func->js_mode & JS_MODE_MATH)
@@ -21274,8 +21302,7 @@ static JSAtom json_parse_ident(JSParseState *s, const uint8_t **pp, int c)
for(;;) {
buf[ident_pos++] = c;
c = *p;
- if (c >= 128 ||
- !((lre_id_continue_table_ascii[c >> 5] >> (c & 31)) & 1))
+ if (c >= 128 || !lre_is_id_continue_byte(c))
break;
p++;
if (unlikely(ident_pos >= ident_size - UTF8_CHAR_LEN_MAX)) {
@@ -21293,7 +21320,7 @@ static JSAtom json_parse_ident(JSParseState *s, const uint8_t **pp, int c)
return atom;
}
-static warn_unused int json_next_token(JSParseState *s)
+static __exception int json_next_token(JSParseState *s)
{
const uint8_t *p;
int c;
@@ -21487,9 +21514,29 @@ static warn_unused int json_next_token(JSParseState *s)
return -1;
}
-/* 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 match_identifier(const uint8_t *p, const char *s) {
+ uint32_t c;
+ while (*s) {
+ if ((uint8_t)*s++ != *p++)
+ return 0;
+ }
+ c = *p;
+ if (c >= 128)
+ c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p);
+ return !lre_js_is_ident_next(c);
+}
+
+/* simple_next_token() is used to check for the next token in simple cases.
+ It is only used for ':' and '=>', 'let' or 'function' look-ahead.
+ (*pp) is only set if TOK_IMPORT is returned for JS_DetectModule()
+ Whitespace and comments are skipped correctly.
+ Then the next token is analyzed, only for specific words.
+ Return values:
+ - '\n' if !no_line_terminator
+ - TOK_ARROW, TOK_IN, TOK_IMPORT, TOK_OF, TOK_EXPORT, TOK_FUNCTION
+ - TOK_IDENT is returned for other identifiers and keywords
+ - otherwise the next character or unicode codepoint is returned.
+ */
static int simple_next_token(const uint8_t **pp, BOOL no_line_terminator)
{
const uint8_t *p;
@@ -21533,33 +21580,42 @@ static int simple_next_token(const uint8_t **pp, BOOL no_line_terminator)
if (*p == '>')
return TOK_ARROW;
break;
+ case 'i':
+ if (match_identifier(p, "n"))
+ return TOK_IN;
+ if (match_identifier(p, "mport")) {
+ *pp = p + 5;
+ return TOK_IMPORT;
+ }
+ return TOK_IDENT;
+ case 'o':
+ if (match_identifier(p, "f"))
+ return TOK_OF;
+ return TOK_IDENT;
+ case 'e':
+ if (match_identifier(p, "xport"))
+ return TOK_EXPORT;
+ return TOK_IDENT;
+ case 'f':
+ if (match_identifier(p, "unction"))
+ return TOK_FUNCTION;
+ return TOK_IDENT;
+ case '\\':
+ if (*p == 'u') {
+ if (lre_js_is_ident_first(lre_parse_escape(&p, TRUE)))
+ return TOK_IDENT;
+ }
+ break;
default:
- if (lre_js_is_ident_first(c)) {
- 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 == 'e' &&
- p[0] == 'x' && p[1] == 'p' && p[2] == 'o' &&
- p[3] == 'r' && p[4] == 't' &&
- !lre_js_is_ident_next(p[5])) {
- *pp = p + 5;
- return TOK_EXPORT;
- } 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])) {
- return TOK_FUNCTION;
- }
- return TOK_IDENT;
+ if (c >= 128) {
+ c = unicode_from_utf8(p - 1, UTF8_CHAR_LEN_MAX, &p);
+ if (no_line_terminator && (c == CP_PS || c == CP_LS))
+ return '\n';
}
+ if (lre_is_space(c))
+ continue;
+ if (lre_js_is_ident_first(c))
+ return TOK_IDENT;
break;
}
return c;
@@ -21572,6 +21628,31 @@ static int peek_token(JSParseState *s, BOOL no_line_terminator)
return simple_next_token(&p, no_line_terminator);
}
+static void skip_shebang(const uint8_t **pp, const uint8_t *buf_end)
+{
+ const uint8_t *p = *pp;
+ int c;
+
+ if (p[0] == '#' && p[1] == '!') {
+ p += 2;
+ while (p < 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 if (c == -1) {
+ p++; /* skip invalid UTF-8 */
+ }
+ } else {
+ p++;
+ }
+ }
+ *pp = p;
+ }
+}
+
/* return true if 'input' contains the source of a module
(heuristic). 'input' must be a zero terminated.
@@ -21582,6 +21663,8 @@ BOOL JS_DetectModule(const char *input, size_t input_len)
{
const uint8_t *p = (const uint8_t *)input;
int tok;
+
+ skip_shebang(&p, p + input_len);
switch(simple_next_token(&p, FALSE)) {
case TOK_IMPORT:
tok = simple_next_token(&p, FALSE);
@@ -21694,6 +21777,14 @@ static int new_label(JSParseState *s)
return new_label_fd(s->cur_func, -1);
}
+/* don't update the last opcode and don't emit line number info */
+static void emit_label_raw(JSParseState *s, int label)
+{
+ emit_u8(s, OP_label);
+ emit_u32(s, label);
+ s->cur_func->label_slots[label].pos = s->cur_func->byte_code.size;
+}
+
/* return the label ID offset */
static int emit_label(JSParseState *s, int label)
{
@@ -21733,7 +21824,7 @@ static int cpool_add(JSParseState *s, JSValue val)
return fd->cpool_count - 1;
}
-static warn_unused int emit_push_const(JSParseState *s, JSValueConst val,
+static __exception int emit_push_const(JSParseState *s, JSValueConst val,
BOOL as_atom)
{
int idx;
@@ -21743,7 +21834,7 @@ static warn_unused int emit_push_const(JSParseState *s, JSValueConst val,
/* warning: JS_NewAtomStr frees the string value */
JS_DupValue(s->ctx, val);
atom = JS_NewAtomStr(s->ctx, JS_VALUE_GET_STRING(val));
- if (atom != JS_ATOM_NULL && !JS_AtomIsTaggedInt(atom)) {
+ if (atom != JS_ATOM_NULL && !__JS_AtomIsTaggedInt(atom)) {
emit_op(s, OP_push_atom_value);
emit_u32(s, atom);
return 0;
@@ -22192,7 +22283,7 @@ static int define_var(JSParseState *s, JSFunctionDef *fd, JSAtom name,
/* add a private field variable in the current scope */
static int add_private_class_field(JSParseState *s, JSFunctionDef *fd,
- JSAtom name, JSVarKindEnum var_kind)
+ JSAtom name, JSVarKindEnum var_kind, BOOL is_static)
{
JSContext *ctx = s->ctx;
JSVarDef *vd;
@@ -22204,17 +22295,18 @@ static int add_private_class_field(JSParseState *s, JSFunctionDef *fd,
vd = &fd->vars[idx];
vd->is_lexical = 1;
vd->is_const = 1;
+ vd->is_static_private = is_static;
return idx;
}
-static warn_unused int js_parse_expr(JSParseState *s);
-static warn_unused int js_parse_function_decl(JSParseState *s,
+static __exception int js_parse_expr(JSParseState *s);
+static __exception int js_parse_function_decl(JSParseState *s,
JSParseFunctionEnum func_type,
JSFunctionKindEnum func_kind,
JSAtom func_name, const uint8_t *ptr,
int start_line);
static JSFunctionDef *js_parse_function_class_fields_init(JSParseState *s);
-static warn_unused int js_parse_function_decl2(JSParseState *s,
+static __exception int js_parse_function_decl2(JSParseState *s,
JSParseFunctionEnum func_type,
JSFunctionKindEnum func_kind,
JSAtom func_name,
@@ -22222,9 +22314,9 @@ static warn_unused int js_parse_function_decl2(JSParseState *s,
int function_line_num,
JSParseExportEnum export_flag,
JSFunctionDef **pfd);
-static warn_unused int js_parse_assign_expr2(JSParseState *s, int parse_flags);
-static warn_unused int js_parse_assign_expr(JSParseState *s);
-static warn_unused int js_parse_unary(JSParseState *s, int parse_flags);
+static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags);
+static __exception int js_parse_assign_expr(JSParseState *s);
+static __exception int js_parse_unary(JSParseState *s, int parse_flags);
static void push_break_entry(JSFunctionDef *fd, BlockEnv *be,
JSAtom label_name,
int label_break, int label_cont,
@@ -22251,7 +22343,7 @@ static int seal_template_obj(JSContext *ctx, JSValueConst obj)
return 0;
}
-static warn_unused int js_parse_template(JSParseState *s, int call, int *argc)
+static __exception int js_parse_template(JSParseState *s, int call, int *argc)
{
JSContext *ctx = s->ctx;
JSValue raw_array, template_object;
@@ -22382,7 +22474,7 @@ static BOOL token_is_ident(int tok)
}
/* if the property is an expression, name = JS_ATOM_NULL */
-static int warn_unused js_parse_property_name(JSParseState *s,
+static int __exception js_parse_property_name(JSParseState *s,
JSAtom *pname,
BOOL allow_method, BOOL allow_var,
BOOL allow_private)
@@ -22401,7 +22493,8 @@ static int warn_unused 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 == '(') {
+ s->token.val == '}' || s->token.val == '(' ||
+ s->token.val == '=') {
is_non_reserved_ident = TRUE;
goto ident_found;
}
@@ -22417,7 +22510,8 @@ static int warn_unused 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 == '(') {
+ s->token.val == '}' || s->token.val == '(' ||
+ s->token.val == '=') {
is_non_reserved_ident = TRUE;
goto ident_found;
}
@@ -22524,7 +22618,7 @@ static int js_parse_get_pos(JSParseState *s, JSParsePos *sp)
return 0;
}
-static warn_unused int js_parse_seek_token(JSParseState *s, const JSParsePos *sp)
+static __exception int js_parse_seek_token(JSParseState *s, const JSParsePos *sp)
{
s->token.line_num = sp->last_line_num;
s->line_num = sp->line_num;
@@ -22730,7 +22824,7 @@ static void set_object_name_computed(JSParseState *s)
}
}
-static warn_unused int js_parse_object_literal(JSParseState *s)
+static __exception int js_parse_object_literal(JSParseState *s)
{
JSAtom name = JS_ATOM_NULL;
const uint8_t *start_ptr;
@@ -22848,22 +22942,20 @@ static warn_unused int js_parse_object_literal(JSParseState *s)
#define PF_IN_ACCEPTED (1 << 0)
/* allow function calls parsing in js_parse_postfix_expr() */
#define PF_POSTFIX_CALL (1 << 1)
-/* allow arrow functions parsing in js_parse_postfix_expr() */
-#define PF_ARROW_FUNC (1 << 2)
/* allow the exponentiation operator in js_parse_unary() */
-#define PF_POW_ALLOWED (1 << 3)
+#define PF_POW_ALLOWED (1 << 2)
/* forbid the exponentiation operator in js_parse_unary() */
-#define PF_POW_FORBIDDEN (1 << 4)
+#define PF_POW_FORBIDDEN (1 << 3)
-static warn_unused int js_parse_postfix_expr(JSParseState *s, int parse_flags);
+static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags);
-static warn_unused int js_parse_left_hand_side_expr(JSParseState *s)
+static __exception int js_parse_left_hand_side_expr(JSParseState *s)
{
return js_parse_postfix_expr(s, PF_POSTFIX_CALL);
}
/* XXX: could generate specific bytecode */
-static warn_unused int js_parse_class_default_ctor(JSParseState *s,
+static __exception int js_parse_class_default_ctor(JSParseState *s,
BOOL has_super,
JSFunctionDef **pfd)
{
@@ -22950,11 +23042,12 @@ static JSAtom get_private_setter_name(JSContext *ctx, JSAtom name)
typedef struct {
JSFunctionDef *fields_init_fd;
int computed_fields_count;
- BOOL has_brand;
+ BOOL need_brand;
int brand_push_pos;
+ BOOL is_static;
} ClassFieldsDef;
-static warn_unused int emit_class_init_start(JSParseState *s,
+static __exception int emit_class_init_start(JSParseState *s,
ClassFieldsDef *cf)
{
int label_add_brand;
@@ -22965,41 +23058,27 @@ static warn_unused int emit_class_init_start(JSParseState *s,
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);
+ if (!cf->is_static) {
+ /* add the brand to the newly created instance */
+ /* 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_home_object);
- emit_u16(s, 0);
-
- emit_op(s, OP_add_brand);
-
- emit_label(s, label_add_brand);
+ emit_op(s, OP_scope_get_var);
+ emit_atom(s, JS_ATOM_this);
+ emit_u16(s, 0);
- s->cur_func = s->cur_func->parent;
- return 0;
-}
+ emit_op(s, OP_scope_get_var);
+ emit_atom(s, JS_ATOM_home_object);
+ emit_u16(s, 0);
-static warn_unused 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;
+ emit_op(s, OP_add_brand);
- cf->has_brand = TRUE;
+ emit_label(s, label_add_brand);
}
+ s->cur_func = s->cur_func->parent;
return 0;
}
@@ -23019,7 +23098,7 @@ static void emit_class_init_end(JSParseState *s, ClassFieldsDef *cf)
}
-static warn_unused int js_parse_class(JSParseState *s, BOOL is_class_expr,
+static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr,
JSParseExportEnum export_flag)
{
JSContext *ctx = s->ctx;
@@ -23106,7 +23185,8 @@ static warn_unused int js_parse_class(JSParseState *s, BOOL is_class_expr,
ClassFieldsDef *cf = &class_fields[i];
cf->fields_init_fd = NULL;
cf->computed_fields_count = 0;
- cf->has_brand = FALSE;
+ cf->need_brand = FALSE;
+ cf->is_static = i;
}
ctor_fd = NULL;
@@ -23116,11 +23196,51 @@ static warn_unused int js_parse_class(JSParseState *s, BOOL is_class_expr,
goto fail;
continue;
}
- is_static = (s->token.val == TOK_STATIC);
+ is_static = FALSE;
+ if (s->token.val == TOK_STATIC) {
+ int next = peek_token(s, TRUE);
+ if (!(next == ';' || next == '}' || next == '(' || next == '='))
+ is_static = TRUE;
+ }
prop_type = -1;
if (is_static) {
if (next_token(s))
goto fail;
+ if (s->token.val == '{') {
+ ClassFieldsDef *cf = &class_fields[is_static];
+ JSFunctionDef *init;
+ if (!cf->fields_init_fd) {
+ if (emit_class_init_start(s, cf))
+ goto fail;
+ }
+ s->cur_func = cf->fields_init_fd;
+ /* XXX: could try to avoid creating a new function and
+ reuse 'fields_init_fd' with a specific 'var'
+ scope */
+ // stack is now: <empty>
+ if (js_parse_function_decl2(s, JS_PARSE_FUNC_CLASS_STATIC_INIT,
+ JS_FUNC_NORMAL, JS_ATOM_NULL,
+ s->token.ptr, s->token.line_num,
+ JS_PARSE_EXPORT_NONE, &init) < 0) {
+ goto fail;
+ }
+ // stack is now: fclosure
+ push_scope(s);
+ emit_op(s, OP_scope_get_var);
+ emit_atom(s, JS_ATOM_this);
+ emit_u16(s, 0);
+ // stack is now: fclosure this
+ emit_op(s, OP_swap);
+ // stack is now: this fclosure
+ emit_op(s, OP_call_method);
+ emit_u16(s, 0);
+ // stack is now: returnvalue
+ emit_op(s, OP_drop);
+ // stack is now: <empty>
+ pop_scope(s);
+ s->cur_func = s->cur_func->parent;
+ continue;
+ }
/* allow "static" field name */
if (s->token.val == ';' || s->token.val == '=') {
is_static = FALSE;
@@ -23151,24 +23271,26 @@ static warn_unused int js_parse_class(JSParseState *s, BOOL is_class_expr,
JSFunctionDef *method_fd;
if (is_private) {
- int idx, var_kind;
+ int idx, var_kind, is_static1;
idx = find_private_class_field(ctx, fd, name, fd->scope_level);
if (idx >= 0) {
var_kind = fd->vars[idx].var_kind;
+ is_static1 = fd->vars[idx].is_static_private;
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)) {
+ var_kind == (JS_VAR_PRIVATE_GETTER + is_set) ||
+ (var_kind == (JS_VAR_PRIVATE_GETTER + 1 - is_set) &&
+ is_static != is_static1)) {
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)
+ JS_VAR_PRIVATE_GETTER + is_set, is_static) < 0)
goto fail;
}
- if (add_brand(s, &class_fields[is_static]) < 0)
- goto fail;
+ class_fields[is_static].need_brand = TRUE;
}
if (js_parse_function_decl2(s, JS_PARSE_FUNC_GETTER + is_set,
@@ -23190,7 +23312,7 @@ static warn_unused int js_parse_class(JSParseState *s, BOOL is_class_expr,
goto fail;
emit_atom(s, setter_name);
ret = add_private_class_field(s, fd, setter_name,
- JS_VAR_PRIVATE_SETTER);
+ JS_VAR_PRIVATE_SETTER, is_static);
JS_FreeAtom(ctx, setter_name);
if (ret < 0)
goto fail;
@@ -23225,7 +23347,7 @@ static warn_unused int js_parse_class(JSParseState *s, BOOL is_class_expr,
goto private_field_already_defined;
}
if (add_private_class_field(s, fd, name,
- JS_VAR_PRIVATE_FIELD) < 0)
+ JS_VAR_PRIVATE_FIELD, is_static) < 0)
goto fail;
emit_op(s, OP_private_symbol);
emit_atom(s, name);
@@ -23315,8 +23437,7 @@ static warn_unused int js_parse_class(JSParseState *s, BOOL is_class_expr,
func_type = JS_PARSE_FUNC_CLASS_CONSTRUCTOR;
}
if (is_private) {
- if (add_brand(s, &class_fields[is_static]) < 0)
- goto fail;
+ class_fields[is_static].need_brand = TRUE;
}
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;
@@ -23332,7 +23453,7 @@ static warn_unused int js_parse_class(JSParseState *s, BOOL is_class_expr,
goto fail;
}
if (add_private_class_field(s, fd, name,
- JS_VAR_PRIVATE_METHOD) < 0)
+ JS_VAR_PRIVATE_METHOD, is_static) < 0)
goto fail;
emit_op(s, OP_set_home_object);
emit_op(s, OP_set_name);
@@ -23382,12 +23503,29 @@ static warn_unused 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;
+ if (cf->need_brand) {
+ /* add a private brand to the prototype */
+ emit_op(s, OP_dup);
+ emit_op(s, OP_null);
+ emit_op(s, OP_swap);
+ emit_op(s, OP_add_brand);
+
+ /* define the brand field in 'this' of the initializer */
+ if (!cf->fields_init_fd) {
+ if (emit_class_init_start(s, cf))
+ goto fail;
+ }
+ /* patch the start of the function to enable the
+ OP_add_brand_instance code */
+ cf->fields_init_fd->byte_code.buf[cf->brand_push_pos] = OP_push_true;
+ }
+
+ /* store the function to initialize the fields to that it can be
+ referenced by the constructor */
var_idx = define_var(s, fd, JS_ATOM_class_fields_init,
JS_VAR_DEF_CONST);
if (var_idx < 0)
@@ -23405,14 +23543,11 @@ static warn_unused int js_parse_class(JSParseState *s, BOOL is_class_expr,
/* 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];
+ if (class_fields[1].need_brand) {
+ /* add a private brand to the class */
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);
+ emit_op(s, OP_dup);
+ emit_op(s, OP_add_brand);
}
if (class_name != JS_ATOM_NULL) {
@@ -23424,6 +23559,17 @@ static warn_unused int js_parse_class(JSParseState *s, BOOL is_class_expr,
emit_atom(s, class_name);
emit_u16(s, fd->scope_level);
}
+
+ /* 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);
+ }
+
pop_scope(s);
pop_scope(s);
@@ -23464,7 +23610,7 @@ static warn_unused int js_parse_class(JSParseState *s, BOOL is_class_expr,
return -1;
}
-static warn_unused int js_parse_array_literal(JSParseState *s)
+static __exception int js_parse_array_literal(JSParseState *s)
{
uint32_t idx;
BOOL need_length;
@@ -23500,7 +23646,7 @@ static warn_unused int js_parse_array_literal(JSParseState *s)
if (js_parse_assign_expr(s))
return -1;
emit_op(s, OP_define_field);
- emit_u32(s, JS_AtomFromUInt32(idx));
+ emit_u32(s, __JS_AtomFromUInt32(idx));
need_length = FALSE;
}
idx++;
@@ -23610,7 +23756,7 @@ static BOOL has_with_scope(JSFunctionDef *s, int scope_level)
return FALSE;
}
-static warn_unused int get_lvalue(JSParseState *s, int *popcode, int *pscope,
+static __exception int get_lvalue(JSParseState *s, int *popcode, int *pscope,
JSAtom *pname, int *plabel, int *pdepth, BOOL keep,
int tok)
{
@@ -23850,7 +23996,7 @@ static void put_lvalue(JSParseState *s, int opcode, int scope,
}
}
-static warn_unused int js_parse_expr_paren(JSParseState *s)
+static __exception int js_parse_expr_paren(JSParseState *s)
{
if (js_parse_expect(s, '('))
return -1;
@@ -23868,7 +24014,7 @@ static int js_unsupported_keyword(JSParseState *s, JSAtom atom)
JS_AtomGetStr(s->ctx, buf, sizeof(buf), atom));
}
-static warn_unused int js_define_var(JSParseState *s, JSAtom name, int tok)
+static __exception int js_define_var(JSParseState *s, JSAtom name, int tok)
{
JSFunctionDef *fd = s->cur_func;
JSVarDefEnum var_def_type;
@@ -24416,8 +24562,8 @@ static void optional_chain_test(JSParseState *s, int *poptional_chaining_label,
emit_label(s, label_next);
}
-/* allowed parse_flags: PF_POSTFIX_CALL, PF_ARROW_FUNC */
-static warn_unused int js_parse_postfix_expr(JSParseState *s, int parse_flags)
+/* allowed parse_flags: PF_POSTFIX_CALL */
+static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags)
{
FuncCallType call_type;
int optional_chaining_label;
@@ -24519,16 +24665,8 @@ static warn_unused int js_parse_postfix_expr(JSParseState *s, int parse_flags)
}
break;
case '(':
- if ((parse_flags & PF_ARROW_FUNC) &&
- js_parse_skip_parens_token(s, NULL, TRUE) == TOK_ARROW) {
- if (js_parse_function_decl(s, JS_PARSE_FUNC_ARROW,
- JS_FUNC_NORMAL, JS_ATOM_NULL,
- s->token.ptr, s->token.line_num))
- return -1;
- } else {
- if (js_parse_expr_paren(s))
- return -1;
- }
+ if (js_parse_expr_paren(s))
+ return -1;
break;
case TOK_FUNCTION:
if (js_parse_function_decl(s, JS_PARSE_FUNC_EXPR,
@@ -24568,14 +24706,8 @@ static warn_unused int js_parse_postfix_expr(JSParseState *s, int parse_flags)
if (s->token.u.ident.is_reserved) {
return js_parse_error_reserved_identifier(s);
}
- if ((parse_flags & PF_ARROW_FUNC) &&
- peek_token(s, TRUE) == TOK_ARROW) {
- if (js_parse_function_decl(s, JS_PARSE_FUNC_ARROW,
- JS_FUNC_NORMAL, JS_ATOM_NULL,
- s->token.ptr, s->token.line_num))
- return -1;
- } else if (token_is_pseudo_keyword(s, JS_ATOM_async) &&
- peek_token(s, TRUE) != '\n') {
+ if (token_is_pseudo_keyword(s, JS_ATOM_async) &&
+ peek_token(s, TRUE) != '\n') {
const uint8_t *source_ptr;
int source_line_num;
@@ -24588,15 +24720,6 @@ static warn_unused int js_parse_postfix_expr(JSParseState *s, int parse_flags)
JS_FUNC_ASYNC, JS_ATOM_NULL,
source_ptr, source_line_num))
return -1;
- } else if ((parse_flags & PF_ARROW_FUNC) &&
- ((s->token.val == '(' &&
- js_parse_skip_parens_token(s, NULL, TRUE) == TOK_ARROW) ||
- (s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved &&
- peek_token(s, TRUE) == TOK_ARROW))) {
- if (js_parse_function_decl(s, JS_PARSE_FUNC_ARROW,
- JS_FUNC_ASYNC, JS_ATOM_NULL,
- source_ptr, source_line_num))
- return -1;
} else {
name = JS_DupAtom(s->ctx, JS_ATOM_async);
goto do_get_var;
@@ -24608,8 +24731,10 @@ static warn_unused int js_parse_postfix_expr(JSParseState *s, int parse_flags)
return -1;
}
name = JS_DupAtom(s->ctx, s->token.u.ident.atom);
- if (next_token(s)) /* update line number before emitting code */
+ if (next_token(s)) { /* update line number before emitting code */
+ JS_FreeAtom(s->ctx, name);
return -1;
+ }
do_get_var:
emit_op(s, OP_scope_get_var);
emit_u32(s, name);
@@ -24756,6 +24881,25 @@ static warn_unused int js_parse_postfix_expr(JSParseState *s, int parse_flags)
fd->byte_code.buf[fd->last_opcode_pos] = OP_get_field2;
drop_count = 2;
break;
+ case OP_get_field_opt_chain:
+ {
+ int opt_chain_label, next_label;
+ opt_chain_label = get_u32(fd->byte_code.buf +
+ fd->last_opcode_pos + 1 + 4 + 1);
+ /* keep the object on the stack */
+ fd->byte_code.buf[fd->last_opcode_pos] = OP_get_field2;
+ fd->byte_code.size = fd->last_opcode_pos + 1 + 4;
+ next_label = emit_goto(s, OP_goto, -1);
+ emit_label(s, opt_chain_label);
+ /* need an additional undefined value for the
+ case where the optional field does not
+ exists */
+ emit_op(s, OP_undefined);
+ emit_label(s, next_label);
+ drop_count = 2;
+ opcode = OP_get_field;
+ }
+ 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;
@@ -24766,6 +24910,25 @@ static warn_unused int js_parse_postfix_expr(JSParseState *s, int parse_flags)
fd->byte_code.buf[fd->last_opcode_pos] = OP_get_array_el2;
drop_count = 2;
break;
+ case OP_get_array_el_opt_chain:
+ {
+ int opt_chain_label, next_label;
+ opt_chain_label = get_u32(fd->byte_code.buf +
+ fd->last_opcode_pos + 1 + 1);
+ /* keep the object on the stack */
+ fd->byte_code.buf[fd->last_opcode_pos] = OP_get_array_el2;
+ fd->byte_code.size = fd->last_opcode_pos + 1;
+ next_label = emit_goto(s, OP_goto, -1);
+ emit_label(s, opt_chain_label);
+ /* need an additional undefined value for the
+ case where the optional field does not
+ exists */
+ emit_op(s, OP_undefined);
+ emit_label(s, next_label);
+ drop_count = 2;
+ opcode = OP_get_array_el;
+ }
+ break;
case OP_scope_get_var:
{
JSAtom name;
@@ -25048,43 +25211,89 @@ static warn_unused int js_parse_postfix_expr(JSParseState *s, int parse_flags)
break;
}
}
- if (optional_chaining_label >= 0)
- emit_label(s, optional_chaining_label);
+ if (optional_chaining_label >= 0) {
+ JSFunctionDef *fd = s->cur_func;
+ int opcode;
+ emit_label_raw(s, optional_chaining_label);
+ /* modify the last opcode so that it is an indicator of an
+ optional chain */
+ opcode = get_prev_opcode(fd);
+ if (opcode == OP_get_field || opcode == OP_get_array_el) {
+ if (opcode == OP_get_field)
+ opcode = OP_get_field_opt_chain;
+ else
+ opcode = OP_get_array_el_opt_chain;
+ fd->byte_code.buf[fd->last_opcode_pos] = opcode;
+ } else {
+ fd->last_opcode_pos = -1;
+ }
+ }
return 0;
}
-static warn_unused int js_parse_delete(JSParseState *s)
+static __exception int js_parse_delete(JSParseState *s)
{
JSFunctionDef *fd = s->cur_func;
JSAtom name;
+ int opcode;
if (next_token(s))
return -1;
if (js_parse_unary(s, PF_POW_FORBIDDEN))
return -1;
- switch (get_prev_opcode(fd)) {
+ switch(opcode = get_prev_opcode(fd)) {
case OP_get_field:
+ case OP_get_field_opt_chain:
{
JSValue val;
- int ret;
-
+ int ret, opt_chain_label, next_label;
+ if (opcode == OP_get_field_opt_chain) {
+ opt_chain_label = get_u32(fd->byte_code.buf +
+ fd->last_opcode_pos + 1 + 4 + 1);
+ } else {
+ opt_chain_label = -1;
+ }
name = get_u32(fd->byte_code.buf + fd->last_opcode_pos + 1);
fd->byte_code.size = fd->last_opcode_pos;
- fd->last_opcode_pos = -1;
val = JS_AtomToValue(s->ctx, name);
ret = emit_push_const(s, val, 1);
JS_FreeValue(s->ctx, val);
JS_FreeAtom(s->ctx, name);
if (ret)
return ret;
+ emit_op(s, OP_delete);
+ if (opt_chain_label >= 0) {
+ next_label = emit_goto(s, OP_goto, -1);
+ emit_label(s, opt_chain_label);
+ /* if the optional chain is not taken, return 'true' */
+ emit_op(s, OP_drop);
+ emit_op(s, OP_push_true);
+ emit_label(s, next_label);
+ }
+ fd->last_opcode_pos = -1;
}
- goto do_delete;
+ break;
case OP_get_array_el:
fd->byte_code.size = fd->last_opcode_pos;
fd->last_opcode_pos = -1;
- do_delete:
emit_op(s, OP_delete);
break;
+ case OP_get_array_el_opt_chain:
+ {
+ int opt_chain_label, next_label;
+ opt_chain_label = get_u32(fd->byte_code.buf +
+ fd->last_opcode_pos + 1 + 1);
+ fd->byte_code.size = fd->last_opcode_pos;
+ emit_op(s, OP_delete);
+ next_label = emit_goto(s, OP_goto, -1);
+ emit_label(s, opt_chain_label);
+ /* if the optional chain is not taken, return 'true' */
+ emit_op(s, OP_drop);
+ emit_op(s, OP_push_true);
+ emit_label(s, next_label);
+ fd->last_opcode_pos = -1;
+ }
+ break;
case OP_scope_get_var:
/* 'delete this': this is not a reference */
name = get_u32(fd->byte_code.buf + fd->last_opcode_pos + 1);
@@ -25099,6 +25308,8 @@ static warn_unused int js_parse_delete(JSParseState *s)
case OP_scope_get_private_field:
return js_parse_error(s, "cannot delete a private class field");
case OP_get_super_value:
+ fd->byte_code.size = fd->last_opcode_pos;
+ fd->last_opcode_pos = -1;
emit_op(s, OP_throw_error);
emit_atom(s, JS_ATOM_NULL);
emit_u8(s, JS_THROW_ERROR_DELETE_SUPER);
@@ -25112,8 +25323,8 @@ static warn_unused int js_parse_delete(JSParseState *s)
return 0;
}
-/* allowed parse_flags: PF_ARROW_FUNC, PF_POW_ALLOWED, PF_POW_FORBIDDEN */
-static warn_unused int js_parse_unary(JSParseState *s, int parse_flags)
+/* allowed parse_flags: PF_POW_ALLOWED, PF_POW_FORBIDDEN */
+static __exception int js_parse_unary(JSParseState *s, int parse_flags)
{
int op;
@@ -25198,12 +25409,12 @@ static warn_unused int js_parse_unary(JSParseState *s, int parse_flags)
return -1;
if (js_parse_unary(s, PF_POW_FORBIDDEN))
return -1;
+ s->cur_func->has_await = TRUE;
emit_op(s, OP_await);
parse_flags = 0;
break;
default:
- if (js_parse_postfix_expr(s, (parse_flags & PF_ARROW_FUNC) |
- PF_POSTFIX_CALL))
+ if (js_parse_postfix_expr(s, PF_POSTFIX_CALL))
return -1;
if (!s->got_lf &&
(s->token.val == TOK_DEC || s->token.val == TOK_INC)) {
@@ -25260,18 +25471,40 @@ static warn_unused int js_parse_unary(JSParseState *s, int parse_flags)
return 0;
}
-/* allowed parse_flags: PF_ARROW_FUNC, PF_IN_ACCEPTED */
-static warn_unused int js_parse_expr_binary(JSParseState *s, int level,
+/* allowed parse_flags: PF_IN_ACCEPTED */
+static __exception int js_parse_expr_binary(JSParseState *s, int level,
int parse_flags)
{
int op, opcode;
if (level == 0) {
- return js_parse_unary(s, (parse_flags & PF_ARROW_FUNC) |
- PF_POW_ALLOWED);
+ return js_parse_unary(s, PF_POW_ALLOWED);
+ } else if (s->token.val == TOK_PRIVATE_NAME &&
+ (parse_flags & PF_IN_ACCEPTED) && level == 4 &&
+ peek_token(s, FALSE) == TOK_IN) {
+ JSAtom atom;
+
+ atom = JS_DupAtom(s->ctx, s->token.u.ident.atom);
+ if (next_token(s))
+ goto fail_private_in;
+ if (s->token.val != TOK_IN)
+ goto fail_private_in;
+ if (next_token(s))
+ goto fail_private_in;
+ if (js_parse_expr_binary(s, level - 1, parse_flags)) {
+ fail_private_in:
+ JS_FreeAtom(s->ctx, atom);
+ return -1;
+ }
+ emit_op(s, OP_scope_in_private_field);
+ emit_atom(s, atom);
+ emit_u16(s, s->cur_func->scope_level);
+ JS_FreeAtom(s->ctx, atom);
+ return 0;
+ } else {
+ if (js_parse_expr_binary(s, level - 1, parse_flags))
+ return -1;
}
- if (js_parse_expr_binary(s, level - 1, parse_flags))
- return -1;
for(;;) {
op = s->token.val;
switch(level) {
@@ -25400,15 +25633,15 @@ static warn_unused int js_parse_expr_binary(JSParseState *s, int level,
}
if (next_token(s))
return -1;
- if (js_parse_expr_binary(s, level - 1, parse_flags & ~PF_ARROW_FUNC))
+ if (js_parse_expr_binary(s, level - 1, parse_flags))
return -1;
emit_op(s, opcode);
}
return 0;
}
-/* allowed parse_flags: PF_ARROW_FUNC, PF_IN_ACCEPTED */
-static warn_unused int js_parse_logical_and_or(JSParseState *s, int op,
+/* allowed parse_flags: PF_IN_ACCEPTED */
+static __exception int js_parse_logical_and_or(JSParseState *s, int op,
int parse_flags)
{
int label1;
@@ -25431,11 +25664,11 @@ static warn_unused int js_parse_logical_and_or(JSParseState *s, int op,
emit_op(s, OP_drop);
if (op == TOK_LAND) {
- if (js_parse_expr_binary(s, 8, parse_flags & ~PF_ARROW_FUNC))
+ if (js_parse_expr_binary(s, 8, parse_flags))
return -1;
} else {
if (js_parse_logical_and_or(s, TOK_LAND,
- parse_flags & ~PF_ARROW_FUNC))
+ parse_flags))
return -1;
}
if (s->token.val != op) {
@@ -25450,7 +25683,7 @@ static warn_unused int js_parse_logical_and_or(JSParseState *s, int op,
return 0;
}
-static warn_unused int js_parse_coalesce_expr(JSParseState *s, int parse_flags)
+static __exception int js_parse_coalesce_expr(JSParseState *s, int parse_flags)
{
int label1;
@@ -25467,7 +25700,7 @@ static warn_unused int js_parse_coalesce_expr(JSParseState *s, int parse_flags)
emit_goto(s, OP_if_false, label1);
emit_op(s, OP_drop);
- if (js_parse_expr_binary(s, 8, parse_flags & ~PF_ARROW_FUNC))
+ if (js_parse_expr_binary(s, 8, parse_flags))
return -1;
if (s->token.val != TOK_DOUBLE_QUESTION_MARK)
break;
@@ -25477,8 +25710,8 @@ static warn_unused int js_parse_coalesce_expr(JSParseState *s, int parse_flags)
return 0;
}
-/* allowed parse_flags: PF_ARROW_FUNC, PF_IN_ACCEPTED */
-static warn_unused int js_parse_cond_expr(JSParseState *s, int parse_flags)
+/* allowed parse_flags: PF_IN_ACCEPTED */
+static __exception int js_parse_cond_expr(JSParseState *s, int parse_flags)
{
int label1, label2;
@@ -25509,7 +25742,7 @@ static warn_unused int js_parse_cond_expr(JSParseState *s, int parse_flags)
static void emit_return(JSParseState *s, BOOL hasval);
/* allowed parse_flags: PF_IN_ACCEPTED */
-static warn_unused int js_parse_assign_expr2(JSParseState *s, int parse_flags)
+static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags)
{
int opcode, op, scope;
JSAtom name0 = JS_ATOM_NULL;
@@ -25571,7 +25804,6 @@ static warn_unused int js_parse_assign_expr2(JSParseState *s, int parse_flags)
/* OP_async_yield_star takes the value as parameter */
emit_op(s, OP_get_field);
emit_atom(s, JS_ATOM_value);
- emit_op(s, OP_await);
emit_op(s, OP_async_yield_star);
} else {
/* OP_yield_star takes (value, done) as parameter */
@@ -25653,12 +25885,50 @@ static warn_unused int js_parse_assign_expr2(JSParseState *s, int parse_flags)
emit_label(s, label_next);
}
return 0;
+ } else if (s->token.val == '(' &&
+ js_parse_skip_parens_token(s, NULL, TRUE) == TOK_ARROW) {
+ return js_parse_function_decl(s, JS_PARSE_FUNC_ARROW,
+ JS_FUNC_NORMAL, JS_ATOM_NULL,
+ s->token.ptr, s->token.line_num);
+ } else if (token_is_pseudo_keyword(s, JS_ATOM_async)) {
+ const uint8_t *source_ptr;
+ int source_line_num, tok;
+ JSParsePos pos;
+
+ /* fast test */
+ tok = peek_token(s, TRUE);
+ if (tok == TOK_FUNCTION || tok == '\n')
+ goto next;
+
+ source_ptr = s->token.ptr;
+ source_line_num = s->token.line_num;
+ js_parse_get_pos(s, &pos);
+ if (next_token(s))
+ return -1;
+ if ((s->token.val == '(' &&
+ js_parse_skip_parens_token(s, NULL, TRUE) == TOK_ARROW) ||
+ (s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved &&
+ peek_token(s, TRUE) == TOK_ARROW)) {
+ return js_parse_function_decl(s, JS_PARSE_FUNC_ARROW,
+ JS_FUNC_ASYNC, JS_ATOM_NULL,
+ source_ptr, source_line_num);
+ } else {
+ /* undo the token parsing */
+ if (js_parse_seek_token(s, &pos))
+ return -1;
+ }
+ } else if (s->token.val == TOK_IDENT &&
+ peek_token(s, TRUE) == TOK_ARROW) {
+ return js_parse_function_decl(s, JS_PARSE_FUNC_ARROW,
+ JS_FUNC_NORMAL, JS_ATOM_NULL,
+ s->token.ptr, s->token.line_num);
}
+ next:
if (s->token.val == TOK_IDENT) {
/* name0 is used to check for OP_set_name pattern, not duplicated */
name0 = s->token.u.ident.atom;
}
- if (js_parse_cond_expr(s, parse_flags | PF_ARROW_FUNC))
+ if (js_parse_cond_expr(s, parse_flags))
return -1;
op = s->token.val;
@@ -25755,13 +26025,13 @@ static warn_unused int js_parse_assign_expr2(JSParseState *s, int parse_flags)
return 0;
}
-static warn_unused int js_parse_assign_expr(JSParseState *s)
+static __exception int js_parse_assign_expr(JSParseState *s)
{
return js_parse_assign_expr2(s, PF_IN_ACCEPTED);
}
/* allowed parse_flags: PF_IN_ACCEPTED */
-static warn_unused int js_parse_expr2(JSParseState *s, int parse_flags)
+static __exception int js_parse_expr2(JSParseState *s, int parse_flags)
{
BOOL comma = FALSE;
for(;;) {
@@ -25785,7 +26055,7 @@ static warn_unused int js_parse_expr2(JSParseState *s, int parse_flags)
return 0;
}
-static warn_unused int js_parse_expr(JSParseState *s)
+static __exception int js_parse_expr(JSParseState *s)
{
return js_parse_expr2(s, PF_IN_ACCEPTED);
}
@@ -25813,7 +26083,7 @@ static void pop_break_entry(JSFunctionDef *fd)
fd->top_break = be->prev;
}
-static warn_unused int emit_break(JSParseState *s, JSAtom name, int is_cont)
+static __exception int emit_break(JSParseState *s, JSAtom name, int is_cont)
{
BlockEnv *top;
int i, scope_level;
@@ -25865,61 +26135,61 @@ static warn_unused int emit_break(JSParseState *s, JSAtom name, int is_cont)
static void emit_return(JSParseState *s, BOOL hasval)
{
BlockEnv *top;
- int drop_count;
- drop_count = 0;
+ if (s->cur_func->func_kind != JS_FUNC_NORMAL) {
+ if (!hasval) {
+ /* no value: direct return in case of async generator */
+ emit_op(s, OP_undefined);
+ hasval = TRUE;
+ } else if (s->cur_func->func_kind == JS_FUNC_ASYNC_GENERATOR) {
+ /* the await must be done before handling the "finally" in
+ case it raises an exception */
+ emit_op(s, OP_await);
+ }
+ }
+
top = s->cur_func->top_break;
while (top != NULL) {
- /* XXX: emit the appropriate OP_leave_scope opcodes? Probably not
- required as all local variables will be closed upon returning
- from JS_CallInternal, but not in the same order. */
- if (top->has_iterator) {
- /* with 'yield', the exact number of OP_drop to emit is
- unknown, so we use a specific operation to look for
- the catch offset */
+ if (top->has_iterator || top->label_finally != -1) {
if (!hasval) {
emit_op(s, OP_undefined);
hasval = TRUE;
}
- emit_op(s, OP_iterator_close_return);
- if (s->cur_func->func_kind == JS_FUNC_ASYNC_GENERATOR) {
- int label_next, label_next2;
-
- emit_op(s, OP_drop); /* catch offset */
- emit_op(s, OP_drop); /* next */
- emit_op(s, OP_get_field2);
- emit_atom(s, JS_ATOM_return);
- /* stack: iter_obj return_func */
- emit_op(s, OP_dup);
- emit_op(s, OP_is_undefined_or_null);
- label_next = emit_goto(s, OP_if_true, -1);
- emit_op(s, OP_call_method);
- emit_u16(s, 0);
- emit_op(s, OP_iterator_check_object);
- emit_op(s, OP_await);
- label_next2 = emit_goto(s, OP_goto, -1);
- emit_label(s, label_next);
- emit_op(s, OP_drop);
- emit_label(s, label_next2);
- emit_op(s, OP_drop);
+ /* Remove the stack elements up to and including the catch
+ offset. When 'yield' is used in an expression we have
+ no easy way to count them, so we use this specific
+ instruction instead. */
+ emit_op(s, OP_nip_catch);
+ /* stack: iter_obj next ret_val */
+ if (top->has_iterator) {
+ if (s->cur_func->func_kind == JS_FUNC_ASYNC_GENERATOR) {
+ int label_next, label_next2;
+ emit_op(s, OP_nip); /* next */
+ emit_op(s, OP_swap);
+ emit_op(s, OP_get_field2);
+ emit_atom(s, JS_ATOM_return);
+ /* stack: iter_obj return_func */
+ emit_op(s, OP_dup);
+ emit_op(s, OP_is_undefined_or_null);
+ label_next = emit_goto(s, OP_if_true, -1);
+ emit_op(s, OP_call_method);
+ emit_u16(s, 0);
+ emit_op(s, OP_iterator_check_object);
+ emit_op(s, OP_await);
+ label_next2 = emit_goto(s, OP_goto, -1);
+ emit_label(s, label_next);
+ emit_op(s, OP_drop);
+ emit_label(s, label_next2);
+ emit_op(s, OP_drop);
+ } else {
+ emit_op(s, OP_rot3r);
+ emit_op(s, OP_undefined); /* dummy catch offset */
+ emit_op(s, OP_iterator_close);
+ }
} else {
- emit_op(s, OP_iterator_close);
- }
- drop_count = -3;
- }
- drop_count += top->drop_count;
- if (top->label_finally != -1) {
- while(drop_count) {
- /* must keep the stack top if hasval */
- emit_op(s, hasval ? OP_nip : OP_drop);
- drop_count--;
+ /* execute the "finally" block */
+ emit_goto(s, OP_gosub, top->label_finally);
}
- if (!hasval) {
- /* must push return value to keep same stack size */
- emit_op(s, OP_undefined);
- hasval = TRUE;
- }
- emit_goto(s, OP_gosub, top->label_finally);
}
top = top->prev;
}
@@ -25936,20 +26206,15 @@ static void emit_return(JSParseState *s, BOOL hasval)
label_return = -1;
}
- /* XXX: if this is not initialized, should throw the
- ReferenceError in the caller realm */
- emit_op(s, OP_scope_get_var);
+ /* The error should be raised in the caller context, so we use
+ a specific opcode */
+ emit_op(s, OP_scope_get_var_checkthis);
emit_atom(s, JS_ATOM_this);
emit_u16(s, 0);
emit_label(s, label_return);
emit_op(s, OP_return);
} else if (s->cur_func->func_kind != JS_FUNC_NORMAL) {
- 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);
@@ -25962,15 +26227,15 @@ static void emit_return(JSParseState *s, BOOL hasval)
#define DECL_MASK_OTHER (1 << 2) /* all other declarations */
#define DECL_MASK_ALL (DECL_MASK_FUNC | DECL_MASK_FUNC_WITH_LABEL | DECL_MASK_OTHER)
-static warn_unused int js_parse_statement_or_decl(JSParseState *s,
+static __exception int js_parse_statement_or_decl(JSParseState *s,
int decl_mask);
-static warn_unused int js_parse_statement(JSParseState *s)
+static __exception int js_parse_statement(JSParseState *s)
{
return js_parse_statement_or_decl(s, 0);
}
-static warn_unused int js_parse_block(JSParseState *s)
+static __exception int js_parse_block(JSParseState *s)
{
if (js_parse_expect(s, '{'))
return -1;
@@ -25990,7 +26255,7 @@ static warn_unused int js_parse_block(JSParseState *s)
}
/* allowed parse_flags: PF_IN_ACCEPTED */
-static warn_unused int js_parse_var(JSParseState *s, int parse_flags, int tok,
+static __exception int js_parse_var(JSParseState *s, int parse_flags, int tok,
BOOL export_flag)
{
JSContext *ctx = s->ctx;
@@ -26096,7 +26361,6 @@ static int is_let(JSParseState *s, int decl_mask)
int res = FALSE;
if (token_is_pseudo_keyword(s, JS_ATOM_let)) {
-#if 1
JSParsePos pos;
js_parse_get_pos(s, &pos);
for (;;) {
@@ -26129,19 +26393,13 @@ static int is_let(JSParseState *s, int decl_mask)
if (js_parse_seek_token(s, &pos)) {
res = -1;
}
-#else
- int tok = peek_token(s, TRUE);
- if (tok == '{' || tok == TOK_IDENT || peek_token(s, FALSE) == '[') {
- res = TRUE;
- }
-#endif
}
return res;
}
/* XXX: handle IteratorClose when exiting the loop before the
enumeration is done */
-static warn_unused int js_parse_for_in_of(JSParseState *s, int label_name,
+static __exception int js_parse_for_in_of(JSParseState *s, int label_name,
BOOL is_async)
{
JSContext *ctx = s->ctx;
@@ -26216,6 +26474,9 @@ static warn_unused int js_parse_for_in_of(JSParseState *s, int label_name,
emit_atom(s, var_name);
emit_u16(s, fd->scope_level);
}
+ } else if (!is_async && token_is_pseudo_keyword(s, JS_ATOM_async) &&
+ peek_token(s, FALSE) == TOK_OF) {
+ return js_parse_error(s, "'for of' expression cannot start with 'async'");
} else {
int skip_bits;
if ((s->token.val == '[' || s->token.val == '{')
@@ -26372,7 +26633,7 @@ static void set_eval_ret_undefined(JSParseState *s)
}
}
-static warn_unused int js_parse_statement_or_decl(JSParseState *s,
+static __exception int js_parse_statement_or_decl(JSParseState *s,
int decl_mask)
{
JSContext *ctx = s->ctx;
@@ -26432,6 +26693,10 @@ static warn_unused int js_parse_statement_or_decl(JSParseState *s,
js_parse_error(s, "return not in a function");
goto fail;
}
+ if (s->cur_func->func_type == JS_PARSE_FUNC_CLASS_STATIC_INIT) {
+ js_parse_error(s, "return in a static initializer block");
+ goto fail;
+ }
if (next_token(s))
goto fail;
if (s->token.val != ';' && s->token.val != '}' && !s->got_lf) {
@@ -26600,6 +26865,7 @@ static warn_unused int js_parse_statement_or_decl(JSParseState *s,
is_async = TRUE;
if (next_token(s))
goto fail;
+ s->cur_func->has_await = TRUE;
}
if (js_parse_expect(s, '('))
goto fail;
@@ -27130,6 +27396,9 @@ static JSModuleDef *js_new_module_def(JSContext *ctx, JSAtom name)
m->func_obj = JS_UNDEFINED;
m->eval_exception = JS_UNDEFINED;
m->meta_obj = JS_UNDEFINED;
+ m->promise = JS_UNDEFINED;
+ m->resolving_funcs[0] = JS_UNDEFINED;
+ m->resolving_funcs[1] = JS_UNDEFINED;
list_add_tail(&m->link, &ctx->loaded_modules);
return m;
}
@@ -27151,6 +27420,9 @@ static void js_mark_module_def(JSRuntime *rt, JSModuleDef *m,
JS_MarkValue(rt, m->func_obj, mark_func);
JS_MarkValue(rt, m->eval_exception, mark_func);
JS_MarkValue(rt, m->meta_obj, mark_func);
+ JS_MarkValue(rt, m->promise, mark_func);
+ JS_MarkValue(rt, m->resolving_funcs[0], mark_func);
+ JS_MarkValue(rt, m->resolving_funcs[1], mark_func);
}
static void js_free_module_def(JSContext *ctx, JSModuleDef *m)
@@ -27181,11 +27453,15 @@ static void js_free_module_def(JSContext *ctx, JSModuleDef *m)
JS_FreeAtom(ctx, mi->import_name);
}
js_free(ctx, m->import_entries);
+ js_free(ctx, m->async_parent_modules);
JS_FreeValue(ctx, m->module_ns);
JS_FreeValue(ctx, m->func_obj);
JS_FreeValue(ctx, m->eval_exception);
JS_FreeValue(ctx, m->meta_obj);
+ JS_FreeValue(ctx, m->promise);
+ JS_FreeValue(ctx, m->resolving_funcs[0]);
+ JS_FreeValue(ctx, m->resolving_funcs[1]);
list_del(&m->link);
js_free(ctx, m);
}
@@ -27346,6 +27622,7 @@ static char *js_default_module_normalize_name(JSContext *ctx,
{
char *filename, *p;
const char *r;
+ int cap;
int len;
if (name[0] != '.') {
@@ -27359,7 +27636,8 @@ static char *js_default_module_normalize_name(JSContext *ctx,
else
len = 0;
- filename = js_malloc(ctx, len + strlen(name) + 1 + 1);
+ cap = len + strlen(name) + 1 + 1;
+ filename = js_malloc(ctx, cap);
if (!filename)
return NULL;
memcpy(filename, base_name, len);
@@ -27391,8 +27669,8 @@ static char *js_default_module_normalize_name(JSContext *ctx,
}
}
if (filename[0] != '\0')
- strcat(filename, "/");
- strcat(filename, r);
+ pstrcat(filename, cap, "/");
+ pstrcat(filename, cap, r);
// printf("normalize: %s %s -> %s\n", base_name, name, filename);
return filename;
}
@@ -27692,7 +27970,7 @@ static int find_exported_name(GetExportNamesState *s, JSAtom name)
return -1;
}
-static warn_unused int get_exported_names(JSContext *ctx,
+static __exception int get_exported_names(JSContext *ctx,
GetExportNamesState *s,
JSModuleDef *m, BOOL from_star)
{
@@ -27774,13 +28052,11 @@ 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 JSValue js_module_ns_autoinit(JSContext *ctx, JSObject *p, JSAtom atom,
void *opaque)
{
JSModuleDef *m = opaque;
- return js_get_module_ns(ctx, m);
+ return JS_GetModuleNamespace(ctx, m);
}
static JSValue js_build_module_ns(JSContext *ctx, JSModuleDef *m)
@@ -27885,7 +28161,7 @@ static JSValue js_build_module_ns(JSContext *ctx, JSModuleDef *m)
return JS_EXCEPTION;
}
-static JSValue js_get_module_ns(JSContext *ctx, JSModuleDef *m)
+JSValue JS_GetModuleNamespace(JSContext *ctx, JSModuleDef *m)
{
if (JS_IsUndefined(m->module_ns)) {
JSValue val;
@@ -28040,7 +28316,8 @@ static int js_create_module_function(JSContext *ctx, JSModuleDef *m)
/* Prepare a module to be executed by resolving all the imported
variables. */
-static int js_link_module(JSContext *ctx, JSModuleDef *m)
+static int js_inner_module_linking(JSContext *ctx, JSModuleDef *m,
+ JSModuleDef **pstack_top, int index)
{
int i;
JSImportEntry *mi;
@@ -28050,21 +28327,47 @@ static int js_link_module(JSContext *ctx, JSModuleDef *m)
BOOL is_c_module;
JSValue ret_val;
- if (m->instantiated)
- return 0;
- m->instantiated = TRUE;
+ if (js_check_stack_overflow(ctx->rt, 0)) {
+ JS_ThrowStackOverflow(ctx);
+ return -1;
+ }
#ifdef DUMP_MODULE_RESOLVE
{
char buf1[ATOM_GET_STR_BUF_SIZE];
- printf("start instantiating module '%s':\n", JS_AtomGetStr(ctx, buf1, sizeof(buf1), m->module_name));
+ printf("js_inner_module_linking '%s':\n", JS_AtomGetStr(ctx, buf1, sizeof(buf1), m->module_name));
}
#endif
+ if (m->status == JS_MODULE_STATUS_LINKING ||
+ m->status == JS_MODULE_STATUS_LINKED ||
+ m->status == JS_MODULE_STATUS_EVALUATING_ASYNC ||
+ m->status == JS_MODULE_STATUS_EVALUATED)
+ return index;
+
+ assert(m->status == JS_MODULE_STATUS_UNLINKED);
+ m->status = JS_MODULE_STATUS_LINKING;
+ m->dfs_index = index;
+ m->dfs_ancestor_index = index;
+ index++;
+ /* push 'm' on stack */
+ m->stack_prev = *pstack_top;
+ *pstack_top = m;
+
for(i = 0; i < m->req_module_entries_count; i++) {
JSReqModuleEntry *rme = &m->req_module_entries[i];
- if (js_link_module(ctx, rme->module) < 0)
+ m1 = rme->module;
+ index = js_inner_module_linking(ctx, m1, pstack_top, index);
+ if (index < 0)
goto fail;
+ assert(m1->status == JS_MODULE_STATUS_LINKING ||
+ m1->status == JS_MODULE_STATUS_LINKED ||
+ m1->status == JS_MODULE_STATUS_EVALUATING_ASYNC ||
+ m1->status == JS_MODULE_STATUS_EVALUATED);
+ if (m1->status == JS_MODULE_STATUS_LINKING) {
+ m->dfs_ancestor_index = min_int(m->dfs_ancestor_index,
+ m1->dfs_ancestor_index);
+ }
}
#ifdef DUMP_MODULE_RESOLVE
@@ -28119,7 +28422,7 @@ static int js_link_module(JSContext *ctx, JSModuleDef *m)
if (mi->import_name == JS_ATOM__star_) {
JSValue val;
/* name space import */
- val = js_get_module_ns(ctx, m1);
+ val = JS_GetModuleNamespace(ctx, m1);
if (JS_IsException(val))
goto fail;
set_value(ctx, &var_refs[mi->var_idx]->value, val);
@@ -28143,7 +28446,7 @@ static int js_link_module(JSContext *ctx, JSModuleDef *m)
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);
+ val = JS_GetModuleNamespace(ctx, m2);
if (JS_IsException(val))
goto fail;
var_ref = js_create_module_var(ctx, TRUE);
@@ -28190,14 +28493,59 @@ static int js_link_module(JSContext *ctx, JSModuleDef *m)
JS_FreeValue(ctx, ret_val);
}
+ assert(m->dfs_ancestor_index <= m->dfs_index);
+ if (m->dfs_index == m->dfs_ancestor_index) {
+ for(;;) {
+ /* pop m1 from stack */
+ m1 = *pstack_top;
+ *pstack_top = m1->stack_prev;
+ m1->status = JS_MODULE_STATUS_LINKED;
+ if (m1 == m)
+ break;
+ }
+ }
+
#ifdef DUMP_MODULE_RESOLVE
- printf("done instantiate\n");
+ printf("js_inner_module_linking done\n");
#endif
- return 0;
+ return index;
fail:
return -1;
}
+/* Prepare a module to be executed by resolving all the imported
+ variables. */
+static int js_link_module(JSContext *ctx, JSModuleDef *m)
+{
+ JSModuleDef *stack_top, *m1;
+
+#ifdef DUMP_MODULE_RESOLVE
+ {
+ char buf1[ATOM_GET_STR_BUF_SIZE];
+ printf("js_link_module '%s':\n", JS_AtomGetStr(ctx, buf1, sizeof(buf1), m->module_name));
+ }
+#endif
+ assert(m->status == JS_MODULE_STATUS_UNLINKED ||
+ m->status == JS_MODULE_STATUS_LINKED ||
+ m->status == JS_MODULE_STATUS_EVALUATING_ASYNC ||
+ m->status == JS_MODULE_STATUS_EVALUATED);
+ stack_top = NULL;
+ if (js_inner_module_linking(ctx, m, &stack_top, 0) < 0) {
+ while (stack_top != NULL) {
+ m1 = stack_top;
+ assert(m1->status == JS_MODULE_STATUS_LINKING);
+ m1->status = JS_MODULE_STATUS_UNLINKED;
+ stack_top = m1->stack_prev;
+ }
+ return -1;
+ }
+ assert(stack_top == NULL);
+ assert(m->status == JS_MODULE_STATUS_LINKED ||
+ m->status == JS_MODULE_STATUS_EVALUATING_ASYNC ||
+ m->status == JS_MODULE_STATUS_EVALUATED);
+ return 0;
+}
+
/* return JS_ATOM_NULL if the name cannot be found. Only works with
not striped bytecode functions. */
JSAtom JS_GetScriptOrModuleName(JSContext *ctx, int n_stack_levels)
@@ -28206,8 +28554,8 @@ JSAtom JS_GetScriptOrModuleName(JSContext *ctx, int n_stack_levels)
JSFunctionBytecode *b;
JSObject *p;
/* 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 */
+ function from the debug info. May need to add a ScriptOrModule
+ info in JSFunctionBytecode. */
sf = ctx->rt->current_stack_frame;
if (!sf)
return JS_ATOM_NULL;
@@ -28216,15 +28564,23 @@ JSAtom JS_GetScriptOrModuleName(JSContext *ctx, int n_stack_levels)
if (!sf)
return JS_ATOM_NULL;
}
- if (JS_VALUE_GET_TAG(sf->cur_func) != JS_TAG_OBJECT)
- return JS_ATOM_NULL;
- p = JS_VALUE_GET_OBJ(sf->cur_func);
- if (!js_class_has_bytecode(p->class_id))
- return JS_ATOM_NULL;
- b = p->u.func.function_bytecode;
- if (!b->has_debug)
- return JS_ATOM_NULL;
- return JS_DupAtom(ctx, b->debug.filename);
+ for(;;) {
+ if (JS_VALUE_GET_TAG(sf->cur_func) != JS_TAG_OBJECT)
+ return JS_ATOM_NULL;
+ p = JS_VALUE_GET_OBJ(sf->cur_func);
+ if (!js_class_has_bytecode(p->class_id))
+ return JS_ATOM_NULL;
+ b = p->u.func.function_bytecode;
+ if (!b->is_direct_or_indirect_eval) {
+ if (!b->has_debug)
+ return JS_ATOM_NULL;
+ return JS_DupAtom(ctx, b->debug.filename);
+ } else {
+ sf = sf->prev_frame;
+ if (!sf)
+ return JS_ATOM_NULL;
+ }
+ }
}
JSAtom JS_GetModuleName(JSContext *ctx, JSModuleDef *m)
@@ -28267,29 +28623,110 @@ static JSValue js_import_meta(JSContext *ctx)
return JS_GetImportMeta(ctx, m);
}
-/* used by os.Worker() and import() */
-JSModuleDef *JS_RunModule(JSContext *ctx, const char *basename,
- const char *filename)
+static JSValue JS_NewModuleValue(JSContext *ctx, JSModuleDef *m)
+{
+ return JS_DupValue(ctx, JS_MKPTR(JS_TAG_MODULE, m));
+}
+
+static JSValue js_load_module_rejected(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv, int magic, JSValue *func_data)
{
+ JSValueConst *resolving_funcs = (JSValueConst *)func_data;
+ JSValueConst error;
+ JSValue ret;
+
+ /* XXX: check if the test is necessary */
+ if (argc >= 1)
+ error = argv[0];
+ else
+ error = JS_UNDEFINED;
+ ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED,
+ 1, &error);
+ JS_FreeValue(ctx, ret);
+ return JS_UNDEFINED;
+}
+
+static JSValue js_load_module_fulfilled(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv, int magic, JSValue *func_data)
+{
+ JSValueConst *resolving_funcs = (JSValueConst *)func_data;
+ JSModuleDef *m = JS_VALUE_GET_PTR(func_data[2]);
+ JSValue ret, ns;
+
+ /* return the module namespace */
+ ns = JS_GetModuleNamespace(ctx, m);
+ if (JS_IsException(ns)) {
+ JSValue err = JS_GetException(ctx);
+ js_load_module_rejected(ctx, JS_UNDEFINED, 1, (JSValueConst *)&err, 0, func_data);
+ return JS_UNDEFINED;
+ }
+ ret = JS_Call(ctx, resolving_funcs[0], JS_UNDEFINED,
+ 1, (JSValueConst *)&ns);
+ JS_FreeValue(ctx, ret);
+ JS_FreeValue(ctx, ns);
+ return JS_UNDEFINED;
+}
+
+static void JS_LoadModuleInternal(JSContext *ctx, const char *basename,
+ const char *filename,
+ JSValueConst *resolving_funcs)
+{
+ JSValue evaluate_promise;
JSModuleDef *m;
- JSValue ret, func_obj;
+ JSValue ret, err, func_obj, evaluate_resolving_funcs[2];
+ JSValueConst func_data[3];
m = js_host_resolve_imported_module(ctx, basename, filename);
if (!m)
- return NULL;
+ goto fail;
if (js_resolve_module(ctx, m) < 0) {
js_free_modules(ctx, JS_FREE_MODULE_NOT_RESOLVED);
- return NULL;
+ goto fail;
}
/* Evaluate the module code */
- func_obj = JS_DupValue(ctx, JS_MKPTR(JS_TAG_MODULE, m));
- ret = JS_EvalFunction(ctx, func_obj);
- if (JS_IsException(ret))
- return NULL;
+ func_obj = JS_NewModuleValue(ctx, m);
+ evaluate_promise = JS_EvalFunction(ctx, func_obj);
+ if (JS_IsException(evaluate_promise)) {
+ fail:
+ 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);
+ return;
+ }
+
+ func_obj = JS_NewModuleValue(ctx, m);
+ func_data[0] = resolving_funcs[0];
+ func_data[1] = resolving_funcs[1];
+ func_data[2] = func_obj;
+ evaluate_resolving_funcs[0] = JS_NewCFunctionData(ctx, js_load_module_fulfilled, 0, 0, 3, func_data);
+ evaluate_resolving_funcs[1] = JS_NewCFunctionData(ctx, js_load_module_rejected, 0, 0, 3, func_data);
+ JS_FreeValue(ctx, func_obj);
+ ret = js_promise_then(ctx, evaluate_promise, 2, (JSValueConst *)evaluate_resolving_funcs);
JS_FreeValue(ctx, ret);
- return m;
+ JS_FreeValue(ctx, evaluate_resolving_funcs[0]);
+ JS_FreeValue(ctx, evaluate_resolving_funcs[1]);
+ JS_FreeValue(ctx, evaluate_promise);
+}
+
+/* Return a promise or an exception in case of memory error. Used by
+ os.Worker() */
+JSValue JS_LoadModule(JSContext *ctx, const char *basename,
+ const char *filename)
+{
+ JSValue promise, resolving_funcs[2];
+
+ promise = JS_NewPromiseCapability(ctx, resolving_funcs);
+ if (JS_IsException(promise))
+ return JS_EXCEPTION;
+ JS_LoadModuleInternal(ctx, basename, filename,
+ (JSValueConst *)resolving_funcs);
+ JS_FreeValue(ctx, resolving_funcs[0]);
+ JS_FreeValue(ctx, resolving_funcs[1]);
+ return promise;
}
static JSValue js_dynamic_import_job(JSContext *ctx,
@@ -28298,9 +28735,8 @@ static JSValue js_dynamic_import_job(JSContext *ctx,
JSValueConst *resolving_funcs = argv;
JSValueConst basename_val = argv[2];
JSValueConst specifier = argv[3];
- JSModuleDef *m;
const char *basename = NULL, *filename;
- JSValue ret, err, ns;
+ JSValue ret, err;
if (!JS_IsString(basename_val)) {
JS_ThrowTypeError(ctx, "no function filename for import()");
@@ -28314,27 +28750,15 @@ static JSValue js_dynamic_import_job(JSContext *ctx,
if (!filename)
goto exception;
- m = JS_RunModule(ctx, basename, filename);
+ JS_LoadModuleInternal(ctx, basename, filename,
+ resolving_funcs);
JS_FreeCString(ctx, filename);
- if (!m)
- goto exception;
-
- /* return the module namespace */
- ns = js_get_module_ns(ctx, m);
- if (JS_IsException(ns))
- goto exception;
-
- ret = JS_Call(ctx, resolving_funcs[0], JS_UNDEFINED,
- 1, &ns);
- JS_FreeValue(ctx, ret); /* XXX: what to do if exception ? */
- JS_FreeValue(ctx, ns);
JS_FreeCString(ctx, basename);
return JS_UNDEFINED;
exception:
-
err = JS_GetException(ctx);
ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED,
- 1, &err);
+ 1, (JSValueConst *)&err);
JS_FreeValue(ctx, ret); /* XXX: what to do if exception ? */
JS_FreeValue(ctx, err);
JS_FreeCString(ctx, basename);
@@ -28367,6 +28791,8 @@ static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier)
args[2] = basename_val;
args[3] = specifier;
+ /* cannot run JS_LoadModuleInternal synchronously because it would
+ cause an unexpected recursion in js_evaluate_module() */
JS_EnqueueJob(ctx, js_dynamic_import_job, 4, args);
JS_FreeValue(ctx, basename_val);
@@ -28375,63 +28801,400 @@ static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier)
return promise;
}
-/* Run the <eval> function of the module and of all its requested
- modules. */
-static JSValue js_evaluate_module(JSContext *ctx, JSModuleDef *m)
+static void js_set_module_evaluated(JSContext *ctx, JSModuleDef *m)
+{
+ m->status = JS_MODULE_STATUS_EVALUATED;
+ if (!JS_IsUndefined(m->promise)) {
+ JSValue value, ret_val;
+ assert(m->cycle_root == m);
+ value = JS_UNDEFINED;
+ ret_val = JS_Call(ctx, m->resolving_funcs[0], JS_UNDEFINED,
+ 1, (JSValueConst *)&value);
+ JS_FreeValue(ctx, ret_val);
+ }
+}
+
+typedef struct {
+ JSModuleDef **tab;
+ int count;
+ int size;
+} ExecModuleList;
+
+/* XXX: slow. Could use a linked list instead of ExecModuleList */
+static BOOL find_in_exec_module_list(ExecModuleList *exec_list, JSModuleDef *m)
+{
+ int i;
+ for(i = 0; i < exec_list->count; i++) {
+ if (exec_list->tab[i] == m)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static int gather_available_ancestors(JSContext *ctx, JSModuleDef *module,
+ ExecModuleList *exec_list)
+{
+ int i;
+
+ if (js_check_stack_overflow(ctx->rt, 0)) {
+ JS_ThrowStackOverflow(ctx);
+ return -1;
+ }
+ for(i = 0; i < module->async_parent_modules_count; i++) {
+ JSModuleDef *m = module->async_parent_modules[i];
+ if (!find_in_exec_module_list(exec_list, m) &&
+ !m->cycle_root->eval_has_exception) {
+ assert(m->status == JS_MODULE_STATUS_EVALUATING_ASYNC);
+ assert(!m->eval_has_exception);
+ assert(m->async_evaluation);
+ assert(m->pending_async_dependencies > 0);
+ m->pending_async_dependencies--;
+ if (m->pending_async_dependencies == 0) {
+ if (js_resize_array(ctx, (void **)&exec_list->tab, sizeof(exec_list->tab[0]), &exec_list->size, exec_list->count + 1)) {
+ return -1;
+ }
+ exec_list->tab[exec_list->count++] = m;
+ if (!m->has_tla) {
+ if (gather_available_ancestors(ctx, m, exec_list))
+ return -1;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+static int exec_module_list_cmp(const void *p1, const void *p2, void *opaque)
+{
+ JSModuleDef *m1 = *(JSModuleDef **)p1;
+ JSModuleDef *m2 = *(JSModuleDef **)p2;
+ return (m1->async_evaluation_timestamp > m2->async_evaluation_timestamp) -
+ (m1->async_evaluation_timestamp < m2->async_evaluation_timestamp);
+}
+
+static int js_execute_async_module(JSContext *ctx, JSModuleDef *m);
+static int js_execute_sync_module(JSContext *ctx, JSModuleDef *m,
+ JSValue *pvalue);
+
+static JSValue js_async_module_execution_rejected(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv, int magic, JSValue *func_data)
+{
+ JSModuleDef *module = JS_VALUE_GET_PTR(func_data[0]);
+ JSValueConst error = argv[0];
+ int i;
+
+ if (js_check_stack_overflow(ctx->rt, 0))
+ return JS_ThrowStackOverflow(ctx);
+
+ if (module->status == JS_MODULE_STATUS_EVALUATED) {
+ assert(module->eval_has_exception);
+ return JS_UNDEFINED;
+ }
+
+ assert(module->status == JS_MODULE_STATUS_EVALUATING_ASYNC);
+ assert(!module->eval_has_exception);
+ assert(module->async_evaluation);
+
+ module->eval_has_exception = TRUE;
+ module->eval_exception = JS_DupValue(ctx, error);
+ module->status = JS_MODULE_STATUS_EVALUATED;
+
+ for(i = 0; i < module->async_parent_modules_count; i++) {
+ JSModuleDef *m = module->async_parent_modules[i];
+ JSValue m_obj = JS_NewModuleValue(ctx, m);
+ js_async_module_execution_rejected(ctx, JS_UNDEFINED, 1, &error, 0,
+ &m_obj);
+ JS_FreeValue(ctx, m_obj);
+ }
+
+ if (!JS_IsUndefined(module->promise)) {
+ JSValue ret_val;
+ assert(module->cycle_root == module);
+ ret_val = JS_Call(ctx, module->resolving_funcs[1], JS_UNDEFINED,
+ 1, &error);
+ JS_FreeValue(ctx, ret_val);
+ }
+ return JS_UNDEFINED;
+}
+
+static JSValue js_async_module_execution_fulfilled(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv, int magic, JSValue *func_data)
+{
+ JSModuleDef *module = JS_VALUE_GET_PTR(func_data[0]);
+ ExecModuleList exec_list_s, *exec_list = &exec_list_s;
+ int i;
+
+ if (module->status == JS_MODULE_STATUS_EVALUATED) {
+ assert(module->eval_has_exception);
+ return JS_UNDEFINED;
+ }
+ assert(module->status == JS_MODULE_STATUS_EVALUATING_ASYNC);
+ assert(!module->eval_has_exception);
+ assert(module->async_evaluation);
+ module->async_evaluation = FALSE;
+ js_set_module_evaluated(ctx, module);
+
+ exec_list->tab = NULL;
+ exec_list->count = 0;
+ exec_list->size = 0;
+
+ if (gather_available_ancestors(ctx, module, exec_list) < 0) {
+ js_free(ctx, exec_list->tab);
+ return JS_EXCEPTION;
+ }
+
+ /* sort by increasing async_evaluation timestamp */
+ rqsort(exec_list->tab, exec_list->count, sizeof(exec_list->tab[0]),
+ exec_module_list_cmp, NULL);
+
+ for(i = 0; i < exec_list->count; i++) {
+ JSModuleDef *m = exec_list->tab[i];
+ if (m->status == JS_MODULE_STATUS_EVALUATED) {
+ assert(m->eval_has_exception);
+ } else if (m->has_tla) {
+ js_execute_async_module(ctx, m);
+ } else {
+ JSValue error;
+ if (js_execute_sync_module(ctx, m, &error) < 0) {
+ JSValue m_obj = JS_NewModuleValue(ctx, m);
+ js_async_module_execution_rejected(ctx, JS_UNDEFINED,
+ 1, (JSValueConst *)&error, 0,
+ &m_obj);
+ JS_FreeValue(ctx, m_obj);
+ JS_FreeValue(ctx, error);
+ } else {
+ js_set_module_evaluated(ctx, m);
+ }
+ }
+ }
+ js_free(ctx, exec_list->tab);
+ return JS_UNDEFINED;
+}
+
+static int js_execute_async_module(JSContext *ctx, JSModuleDef *m)
+{
+ JSValue promise, m_obj;
+ JSValue resolve_funcs[2], ret_val;
+ promise = js_async_function_call(ctx, m->func_obj, JS_UNDEFINED, 0, NULL, 0);
+ if (JS_IsException(promise))
+ return -1;
+ m_obj = JS_NewModuleValue(ctx, m);
+ resolve_funcs[0] = JS_NewCFunctionData(ctx, js_async_module_execution_fulfilled, 0, 0, 1, (JSValueConst *)&m_obj);
+ resolve_funcs[1] = JS_NewCFunctionData(ctx, js_async_module_execution_rejected, 0, 0, 1, (JSValueConst *)&m_obj);
+ ret_val = js_promise_then(ctx, promise, 2, (JSValueConst *)resolve_funcs);
+ JS_FreeValue(ctx, ret_val);
+ JS_FreeValue(ctx, m_obj);
+ JS_FreeValue(ctx, resolve_funcs[0]);
+ JS_FreeValue(ctx, resolve_funcs[1]);
+ JS_FreeValue(ctx, promise);
+ return 0;
+}
+
+/* return < 0 in case of exception. *pvalue contains the exception. */
+static int js_execute_sync_module(JSContext *ctx, JSModuleDef *m,
+ JSValue *pvalue)
+{
+ if (m->init_func) {
+ /* C module init : no asynchronous execution */
+ if (m->init_func(ctx, m) < 0)
+ goto fail;
+ } else {
+ JSValue promise;
+ JSPromiseStateEnum state;
+
+ promise = js_async_function_call(ctx, m->func_obj, JS_UNDEFINED, 0, NULL, 0);
+ if (JS_IsException(promise))
+ goto fail;
+ state = JS_PromiseState(ctx, promise);
+ if (state == JS_PROMISE_FULFILLED) {
+ JS_FreeValue(ctx, promise);
+ } else if (state == JS_PROMISE_REJECTED) {
+ *pvalue = JS_PromiseResult(ctx, promise);
+ JS_FreeValue(ctx, promise);
+ return -1;
+ } else {
+ JS_FreeValue(ctx, promise);
+ JS_ThrowTypeError(ctx, "promise is pending");
+ fail:
+ *pvalue = JS_GetException(ctx);
+ return -1;
+ }
+ }
+ *pvalue = JS_UNDEFINED;
+ return 0;
+}
+
+/* spec: InnerModuleEvaluation. Return (index, JS_UNDEFINED) or (-1,
+ exception) */
+static int js_inner_module_evaluation(JSContext *ctx, JSModuleDef *m,
+ int index, JSModuleDef **pstack_top,
+ JSValue *pvalue)
{
JSModuleDef *m1;
int i;
- JSValue ret_val;
- if (m->eval_mark)
- return JS_UNDEFINED; /* avoid cycles */
+ if (js_check_stack_overflow(ctx->rt, 0)) {
+ JS_ThrowStackOverflow(ctx);
+ *pvalue = JS_GetException(ctx);
+ return -1;
+ }
+
+#ifdef DUMP_MODULE_RESOLVE
+ {
+ char buf1[ATOM_GET_STR_BUF_SIZE];
+ printf("js_inner_module_evaluation '%s':\n", JS_AtomGetStr(ctx, buf1, sizeof(buf1), m->module_name));
+ }
+#endif
- if (m->evaluated) {
- /* if the module was already evaluated, rethrow the exception
- it raised */
+ if (m->status == JS_MODULE_STATUS_EVALUATING_ASYNC ||
+ m->status == JS_MODULE_STATUS_EVALUATED) {
if (m->eval_has_exception) {
- return JS_Throw(ctx, JS_DupValue(ctx, m->eval_exception));
+ *pvalue = JS_DupValue(ctx, m->eval_exception);
+ return -1;
} else {
- return JS_UNDEFINED;
+ *pvalue = JS_UNDEFINED;
+ return index;
}
}
+ if (m->status == JS_MODULE_STATUS_EVALUATING) {
+ *pvalue = JS_UNDEFINED;
+ return index;
+ }
+ assert(m->status == JS_MODULE_STATUS_LINKED);
- m->eval_mark = TRUE;
+ m->status = JS_MODULE_STATUS_EVALUATING;
+ m->dfs_index = index;
+ m->dfs_ancestor_index = index;
+ m->pending_async_dependencies = 0;
+ index++;
+ /* push 'm' on stack */
+ m->stack_prev = *pstack_top;
+ *pstack_top = m;
for(i = 0; i < m->req_module_entries_count; i++) {
JSReqModuleEntry *rme = &m->req_module_entries[i];
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;
+ index = js_inner_module_evaluation(ctx, m1, index, pstack_top, pvalue);
+ if (index < 0)
+ return -1;
+ assert(m1->status == JS_MODULE_STATUS_EVALUATING ||
+ m1->status == JS_MODULE_STATUS_EVALUATING_ASYNC ||
+ m1->status == JS_MODULE_STATUS_EVALUATED);
+ if (m1->status == JS_MODULE_STATUS_EVALUATING) {
+ m->dfs_ancestor_index = min_int(m->dfs_ancestor_index,
+ m1->dfs_ancestor_index);
+ } else {
+ m1 = m1->cycle_root;
+ assert(m1->status == JS_MODULE_STATUS_EVALUATING_ASYNC ||
+ m1->status == JS_MODULE_STATUS_EVALUATED);
+ if (m1->eval_has_exception) {
+ *pvalue = JS_DupValue(ctx, m1->eval_exception);
+ return -1;
}
- JS_FreeValue(ctx, ret_val);
+ }
+ if (m1->async_evaluation) {
+ m->pending_async_dependencies++;
+ if (js_resize_array(ctx, (void **)&m1->async_parent_modules, sizeof(m1->async_parent_modules[0]), &m1->async_parent_modules_size, m1->async_parent_modules_count + 1)) {
+ *pvalue = JS_GetException(ctx);
+ return -1;
+ }
+ m1->async_parent_modules[m1->async_parent_modules_count++] = m;
}
}
- if (m->init_func) {
- /* C module init */
- if (m->init_func(ctx, m) < 0)
- ret_val = JS_EXCEPTION;
- else
- ret_val = JS_UNDEFINED;
+ if (m->pending_async_dependencies > 0) {
+ assert(!m->async_evaluation);
+ m->async_evaluation = TRUE;
+ m->async_evaluation_timestamp =
+ ctx->rt->module_async_evaluation_next_timestamp++;
+ } else if (m->has_tla) {
+ assert(!m->async_evaluation);
+ m->async_evaluation = TRUE;
+ m->async_evaluation_timestamp =
+ ctx->rt->module_async_evaluation_next_timestamp++;
+ js_execute_async_module(ctx, m);
} else {
- ret_val = JS_CallFree(ctx, m->func_obj, JS_UNDEFINED, 0, NULL);
- m->func_obj = JS_UNDEFINED;
+ if (js_execute_sync_module(ctx, m, pvalue) < 0)
+ return -1;
}
- if (JS_IsException(ret_val)) {
- /* save the thrown exception value */
- m->eval_has_exception = TRUE;
- m->eval_exception = JS_DupValue(ctx, ctx->rt->current_exception);
+
+ assert(m->dfs_ancestor_index <= m->dfs_index);
+ if (m->dfs_index == m->dfs_ancestor_index) {
+ for(;;) {
+ /* pop m1 from stack */
+ m1 = *pstack_top;
+ *pstack_top = m1->stack_prev;
+ if (!m1->async_evaluation) {
+ m1->status = JS_MODULE_STATUS_EVALUATED;
+ } else {
+ m1->status = JS_MODULE_STATUS_EVALUATING_ASYNC;
+ }
+ /* spec bug: cycle_root must be assigned before the test */
+ m1->cycle_root = m;
+ if (m1 == m)
+ break;
+ }
}
- m->eval_mark = FALSE;
- m->evaluated = TRUE;
- return ret_val;
+ *pvalue = JS_UNDEFINED;
+ return index;
}
-static warn_unused JSAtom js_parse_from_clause(JSParseState *s)
+/* Run the <eval> function of the module and of all its requested
+ modules. Return a promise or an exception. */
+static JSValue js_evaluate_module(JSContext *ctx, JSModuleDef *m)
+{
+ JSModuleDef *m1, *stack_top;
+ JSValue ret_val, result;
+
+ assert(m->status == JS_MODULE_STATUS_LINKED ||
+ m->status == JS_MODULE_STATUS_EVALUATING_ASYNC ||
+ m->status == JS_MODULE_STATUS_EVALUATED);
+ if (m->status == JS_MODULE_STATUS_EVALUATING_ASYNC ||
+ m->status == JS_MODULE_STATUS_EVALUATED) {
+ m = m->cycle_root;
+ }
+ /* a promise may be created only on the cycle_root of a cycle */
+ if (!JS_IsUndefined(m->promise))
+ return JS_DupValue(ctx, m->promise);
+ m->promise = JS_NewPromiseCapability(ctx, m->resolving_funcs);
+ if (JS_IsException(m->promise))
+ return JS_EXCEPTION;
+
+ stack_top = NULL;
+ if (js_inner_module_evaluation(ctx, m, 0, &stack_top, &result) < 0) {
+ while (stack_top != NULL) {
+ m1 = stack_top;
+ assert(m1->status == JS_MODULE_STATUS_EVALUATING);
+ m1->status = JS_MODULE_STATUS_EVALUATED;
+ m1->eval_has_exception = TRUE;
+ m1->eval_exception = JS_DupValue(ctx, result);
+ m1->cycle_root = m; /* spec bug: should be present */
+ stack_top = m1->stack_prev;
+ }
+ JS_FreeValue(ctx, result);
+ assert(m->status == JS_MODULE_STATUS_EVALUATED);
+ assert(m->eval_has_exception);
+ ret_val = JS_Call(ctx, m->resolving_funcs[1], JS_UNDEFINED,
+ 1, (JSValueConst *)&m->eval_exception);
+ JS_FreeValue(ctx, ret_val);
+ } else {
+ assert(m->status == JS_MODULE_STATUS_EVALUATING_ASYNC ||
+ m->status == JS_MODULE_STATUS_EVALUATED);
+ assert(!m->eval_has_exception);
+ if (!m->async_evaluation) {
+ JSValue value;
+ assert(m->status == JS_MODULE_STATUS_EVALUATED);
+ value = JS_UNDEFINED;
+ ret_val = JS_Call(ctx, m->resolving_funcs[0], JS_UNDEFINED,
+ 1, (JSValueConst *)&value);
+ JS_FreeValue(ctx, ret_val);
+ }
+ assert(stack_top == NULL);
+ }
+ return JS_DupValue(ctx, m->promise);
+}
+
+static __exception JSAtom js_parse_from_clause(JSParseState *s)
{
JSAtom module_name;
if (!token_is_pseudo_keyword(s, JS_ATOM_from)) {
@@ -28454,7 +29217,7 @@ static warn_unused JSAtom js_parse_from_clause(JSParseState *s)
return module_name;
}
-static warn_unused int js_parse_export(JSParseState *s)
+static __exception int js_parse_export(JSParseState *s)
{
JSContext *ctx = s->ctx;
JSModuleDef *m = s->cur_func->module;
@@ -28657,7 +29420,7 @@ static int add_import(JSParseState *s, JSModuleDef *m,
return 0;
}
-static warn_unused int js_parse_import(JSParseState *s)
+static __exception int js_parse_import(JSParseState *s)
{
JSContext *ctx = s->ctx;
JSModuleDef *m = s->cur_func->module;
@@ -28772,7 +29535,7 @@ static warn_unused int js_parse_import(JSParseState *s)
return js_parse_expect_semi(s);
}
-static warn_unused int js_parse_source_element(JSParseState *s)
+static __exception int js_parse_source_element(JSParseState *s)
{
JSFunctionDef *fd = s->cur_func;
int tok;
@@ -29696,7 +30459,8 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s,
}
var_idx = idx;
break;
- } else if (vd->var_name == JS_ATOM__with_ && !is_pseudo_var) {
+ } else
+ if (vd->var_name == JS_ATOM__with_ && !is_pseudo_var) {
dbuf_putc(bc, OP_get_loc);
dbuf_put_u16(bc, idx);
var_object_test(ctx, s, var_name, op, bc, &label_done, 1);
@@ -29781,6 +30545,7 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s,
case OP_scope_get_ref:
dbuf_putc(bc, OP_undefined);
/* fall thru */
+ case OP_scope_get_var_checkthis:
case OP_scope_get_var_undef:
case OP_scope_get_var:
case OP_scope_put_var:
@@ -29806,7 +30571,12 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s,
}
} else {
if (s->vars[var_idx].is_lexical) {
- dbuf_putc(bc, OP_get_loc_check);
+ if (op == OP_scope_get_var_checkthis) {
+ /* only used for 'this' return in derived class constructors */
+ dbuf_putc(bc, OP_get_loc_checkthis);
+ } else {
+ dbuf_putc(bc, OP_get_loc_check);
+ }
} else {
dbuf_putc(bc, OP_get_loc);
}
@@ -30263,12 +31033,17 @@ static int resolve_scope_private_field(JSContext *ctx, JSFunctionDef *s,
/* obj func value */
dbuf_putc(bc, OP_call_method);
dbuf_put_u16(bc, 1);
+ dbuf_putc(bc, OP_drop);
}
break;
default:
abort();
}
break;
+ case OP_scope_in_private_field:
+ get_loc_or_ref(bc, is_ref, idx);
+ dbuf_putc(bc, OP_private_in);
+ break;
default:
abort();
}
@@ -30387,12 +31162,13 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s)
is_arg_scope = (scope_idx == ARG_SCOPE_END);
if (!is_arg_scope) {
/* add unscoped variables */
+ /* XXX: propagate is_const and var_kind too ? */
for(i = 0; i < fd->arg_count; i++) {
vd = &fd->args[i];
if (vd->var_name != JS_ATOM_NULL) {
get_closure_var(ctx, s, fd,
- TRUE, i, vd->var_name, FALSE, FALSE,
- JS_VAR_NORMAL);
+ TRUE, i, vd->var_name, FALSE,
+ vd->is_lexical, JS_VAR_NORMAL);
}
}
for(i = 0; i < fd->var_count; i++) {
@@ -30402,8 +31178,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,
- JS_VAR_NORMAL);
+ FALSE, i, vd->var_name, FALSE,
+ vd->is_lexical, JS_VAR_NORMAL);
}
}
} else {
@@ -30412,8 +31188,8 @@ static void add_eval_variables(JSContext *ctx, JSFunctionDef *s)
/* do not close top level last result */
if (vd->scope_level == 0 && is_var_in_arg_scope(vd)) {
get_closure_var(ctx, s, fd,
- FALSE, i, vd->var_name, FALSE, FALSE,
- JS_VAR_NORMAL);
+ FALSE, i, vd->var_name, FALSE,
+ vd->is_lexical, JS_VAR_NORMAL);
}
}
}
@@ -30446,7 +31222,7 @@ static void set_closure_from_var(JSContext *ctx, JSClosureVar *cv,
/* for direct eval compilation: add references to the variables of the
calling function */
-static warn_unused int add_closure_variables(JSContext *ctx, JSFunctionDef *s,
+static __exception int add_closure_variables(JSContext *ctx, JSFunctionDef *s,
JSFunctionBytecode *b, int scope_idx)
{
int i, count;
@@ -30866,7 +31642,7 @@ static int get_label_pos(JSFunctionDef *s, int label)
/* convert global variable accesses to local variables or closure
variables when necessary */
-static warn_unused int resolve_variables(JSContext *ctx, JSFunctionDef *s)
+static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s)
{
int pos, pos_next, bc_len, op, len, i, idx, line_num;
uint8_t *bc_buf;
@@ -30945,6 +31721,7 @@ static warn_unused int resolve_variables(JSContext *ctx, JSFunctionDef *s)
dbuf_putc(&bc_out, op);
dbuf_put_u16(&bc_out, s->scopes[scope].first + 1);
break;
+ case OP_scope_get_var_checkthis:
case OP_scope_get_var_undef:
case OP_scope_get_var:
case OP_scope_put_var:
@@ -30974,6 +31751,7 @@ static warn_unused int resolve_variables(JSContext *ctx, JSFunctionDef *s)
case OP_scope_get_private_field:
case OP_scope_get_private_field2:
case OP_scope_put_private_field:
+ case OP_scope_in_private_field:
{
int ret;
var_name = get_u32(bc_buf + pos + 1);
@@ -31186,6 +31964,17 @@ static warn_unused int resolve_variables(JSContext *ctx, JSFunctionDef *s)
/* only used during parsing */
break;
+ case OP_get_field_opt_chain: /* equivalent to OP_get_field */
+ {
+ JSAtom name = get_u32(bc_buf + pos + 1);
+ dbuf_putc(&bc_out, OP_get_field);
+ dbuf_put_u32(&bc_out, name);
+ }
+ break;
+ case OP_get_array_el_opt_chain: /* equivalent to OP_get_array_el */
+ dbuf_putc(&bc_out, OP_get_array_el);
+ break;
+
default:
no_change:
dbuf_put(&bc_out, bc_buf + pos, len);
@@ -31430,7 +32219,7 @@ static void put_short_code(DynBuf *bc_out, int op, int idx)
}
/* peephole optimizations and resolve goto/labels */
-static warn_unused int resolve_labels(JSContext *ctx, JSFunctionDef *s)
+static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s)
{
int pos, pos_next, bc_len, op, op1, len, i, line_num;
const uint8_t *bc_buf;
@@ -32239,7 +33028,8 @@ static warn_unused int resolve_labels(JSContext *ctx, JSFunctionDef *s)
bc_out.buf[pos - 1] = jp->op = OP_if_false8 + (op - OP_if_false);
}
goto shrink;
- } else if (diff == (int16_t)diff && op == OP_goto) {
+ } else
+ if (diff == (int16_t)diff && op == OP_goto) {
//put_u16(bc_out.buf + pos, diff);
jp->size = 2;
delta = 2;
@@ -32316,14 +33106,15 @@ typedef struct StackSizeState {
int bc_len;
int stack_len_max;
uint16_t *stack_level_tab;
+ int32_t *catch_pos_tab;
int *pc_stack;
int pc_stack_len;
int pc_stack_size;
} StackSizeState;
/* 'op' is only used for error indication */
-static warn_unused int ss_check(JSContext *ctx, StackSizeState *s,
- int pos, int op, int stack_len)
+static __exception int ss_check(JSContext *ctx, StackSizeState *s,
+ int pos, int op, int stack_len, int catch_pos)
{
if ((unsigned)pos >= s->bc_len) {
JS_ThrowInternalError(ctx, "bytecode buffer overflow (op=%d, pc=%d)", op, pos);
@@ -32339,9 +33130,13 @@ static warn_unused int ss_check(JSContext *ctx, StackSizeState *s,
if (s->stack_level_tab[pos] != 0xffff) {
/* already explored: check that the stack size is consistent */
if (s->stack_level_tab[pos] != stack_len) {
- JS_ThrowInternalError(ctx, "unconsistent stack size: %d %d (pc=%d)",
+ JS_ThrowInternalError(ctx, "inconsistent stack size: %d %d (pc=%d)",
s->stack_level_tab[pos], stack_len, pos);
return -1;
+ } else if (s->catch_pos_tab[pos] != catch_pos) {
+ JS_ThrowInternalError(ctx, "inconsistent catch position: %d %d (pc=%d)",
+ s->catch_pos_tab[pos], catch_pos, pos);
+ return -1;
} else {
return 0;
}
@@ -32349,6 +33144,7 @@ static warn_unused int ss_check(JSContext *ctx, StackSizeState *s,
/* mark as explored and store the stack size */
s->stack_level_tab[pos] = stack_len;
+ s->catch_pos_tab[pos] = catch_pos;
/* queue the new PC to explore */
if (js_resize_array(ctx, (void **)&s->pc_stack, sizeof(s->pc_stack[0]),
@@ -32358,12 +33154,12 @@ static warn_unused int ss_check(JSContext *ctx, StackSizeState *s,
return 0;
}
-static warn_unused int compute_stack_size(JSContext *ctx,
+static __exception int compute_stack_size(JSContext *ctx,
JSFunctionDef *fd,
int *pstack_size)
{
StackSizeState s_s, *s = &s_s;
- int i, diff, n_pop, pos_next, stack_len, pos, op;
+ int i, diff, n_pop, pos_next, stack_len, pos, op, catch_pos, catch_level;
const JSOpCode *oi;
const uint8_t *bc_buf;
@@ -32376,24 +33172,33 @@ static warn_unused int compute_stack_size(JSContext *ctx,
return -1;
for(i = 0; i < s->bc_len; i++)
s->stack_level_tab[i] = 0xffff;
- s->stack_len_max = 0;
s->pc_stack = NULL;
+ s->catch_pos_tab = js_malloc(ctx, sizeof(s->catch_pos_tab[0]) *
+ s->bc_len);
+ if (!s->catch_pos_tab)
+ goto fail;
+
+ s->stack_len_max = 0;
s->pc_stack_len = 0;
s->pc_stack_size = 0;
/* breadth-first graph exploration */
- if (ss_check(ctx, s, 0, OP_invalid, 0))
+ if (ss_check(ctx, s, 0, OP_invalid, 0, -1))
goto fail;
while (s->pc_stack_len > 0) {
pos = s->pc_stack[--s->pc_stack_len];
stack_len = s->stack_level_tab[pos];
+ catch_pos = s->catch_pos_tab[pos];
op = bc_buf[pos];
if (op == 0 || op >= OP_COUNT) {
JS_ThrowInternalError(ctx, "invalid opcode (op=%d, pc=%d)", op, pos);
goto fail;
}
oi = &short_opcode_info(op);
+#if defined(DUMP_BYTECODE) && (DUMP_BYTECODE & 64)
+ printf("%5d: %10s %5d %5d\n", pos, oi->name, stack_len, catch_pos);
+#endif
pos_next = pos + oi->size;
if (pos_next > s->bc_len) {
JS_ThrowInternalError(ctx, "bytecode buffer overflow (op=%d, pc=%d)", op, pos);
@@ -32449,55 +33254,104 @@ static warn_unused int compute_stack_size(JSContext *ctx,
case OP_if_true8:
case OP_if_false8:
diff = (int8_t)bc_buf[pos + 1];
- if (ss_check(ctx, s, pos + 1 + diff, op, stack_len))
+ if (ss_check(ctx, s, pos + 1 + diff, op, stack_len, catch_pos))
goto fail;
break;
#endif
case OP_if_true:
case OP_if_false:
- case OP_catch:
diff = get_u32(bc_buf + pos + 1);
- if (ss_check(ctx, s, pos + 1 + diff, op, stack_len))
+ if (ss_check(ctx, s, pos + 1 + diff, op, stack_len, catch_pos))
goto fail;
break;
case OP_gosub:
diff = get_u32(bc_buf + pos + 1);
- if (ss_check(ctx, s, pos + 1 + diff, op, stack_len + 1))
+ if (ss_check(ctx, s, pos + 1 + diff, op, stack_len + 1, catch_pos))
goto fail;
break;
case OP_with_get_var:
case OP_with_delete_var:
diff = get_u32(bc_buf + pos + 5);
- if (ss_check(ctx, s, pos + 5 + diff, op, stack_len + 1))
+ if (ss_check(ctx, s, pos + 5 + diff, op, stack_len + 1, catch_pos))
goto fail;
break;
case OP_with_make_ref:
case OP_with_get_ref:
case OP_with_get_ref_undef:
diff = get_u32(bc_buf + pos + 5);
- if (ss_check(ctx, s, pos + 5 + diff, op, stack_len + 2))
+ if (ss_check(ctx, s, pos + 5 + diff, op, stack_len + 2, catch_pos))
goto fail;
break;
case OP_with_put_var:
diff = get_u32(bc_buf + pos + 5);
- if (ss_check(ctx, s, pos + 5 + diff, op, stack_len - 1))
+ if (ss_check(ctx, s, pos + 5 + diff, op, stack_len - 1, catch_pos))
goto fail;
break;
-
+ case OP_catch:
+ diff = get_u32(bc_buf + pos + 1);
+ if (ss_check(ctx, s, pos + 1 + diff, op, stack_len, catch_pos))
+ goto fail;
+ catch_pos = pos;
+ break;
+ case OP_for_of_start:
+ case OP_for_await_of_start:
+ catch_pos = pos;
+ break;
+ /* we assume the catch offset entry is only removed with
+ some op codes */
+ case OP_drop:
+ catch_level = stack_len;
+ goto check_catch;
+ case OP_nip:
+ catch_level = stack_len - 1;
+ goto check_catch;
+ case OP_nip1:
+ catch_level = stack_len - 1;
+ goto check_catch;
+ case OP_iterator_close:
+ catch_level = stack_len + 2;
+ check_catch:
+ /* Note: for for_of_start/for_await_of_start we consider
+ the catch offset is on the first stack entry instead of
+ the thirst */
+ if (catch_pos >= 0) {
+ int level;
+ level = s->stack_level_tab[catch_pos];
+ if (bc_buf[catch_pos] != OP_catch)
+ level++; /* for_of_start, for_wait_of_start */
+ /* catch_level = stack_level before op_catch is executed ? */
+ if (catch_level == level) {
+ catch_pos = s->catch_pos_tab[catch_pos];
+ }
+ }
+ break;
+ case OP_nip_catch:
+ if (catch_pos < 0) {
+ JS_ThrowInternalError(ctx, "nip_catch: no catch op (pc=%d)", pos);
+ goto fail;
+ }
+ stack_len = s->stack_level_tab[catch_pos];
+ if (bc_buf[catch_pos] != OP_catch)
+ stack_len++; /* for_of_start, for_wait_of_start */
+ stack_len++; /* no stack overflow is possible by construction */
+ catch_pos = s->catch_pos_tab[catch_pos];
+ break;
default:
break;
}
- if (ss_check(ctx, s, pos_next, op, stack_len))
+ if (ss_check(ctx, s, pos_next, op, stack_len, catch_pos))
goto fail;
done_insn: ;
}
- js_free(ctx, s->stack_level_tab);
js_free(ctx, s->pc_stack);
+ js_free(ctx, s->catch_pos_tab);
+ js_free(ctx, s->stack_level_tab);
*pstack_size = s->stack_len_max;
return 0;
fail:
- js_free(ctx, s->stack_level_tab);
js_free(ctx, s->pc_stack);
+ js_free(ctx, s->catch_pos_tab);
+ js_free(ctx, s->stack_level_tab);
*pstack_size = 0;
return -1;
}
@@ -32679,10 +33533,8 @@ static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd)
}
} else {
b->vardefs = (void *)((uint8_t*)b + vardefs_offset);
- if (fd->arg_count)
- memcpy(b->vardefs, fd->args, fd->arg_count * sizeof(fd->args[0]));
- if (fd->var_count)
- memcpy(b->vardefs + fd->arg_count, fd->vars, fd->var_count * sizeof(fd->vars[0]));
+ memcpy_no_ub(b->vardefs, fd->args, fd->arg_count * sizeof(fd->args[0]));
+ memcpy_no_ub(b->vardefs + fd->arg_count, fd->vars, fd->var_count * sizeof(fd->vars[0]));
}
b->var_count = fd->var_count;
b->arg_count = fd->arg_count;
@@ -32744,6 +33596,8 @@ static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd)
b->super_allowed = fd->super_allowed;
b->arguments_allowed = fd->arguments_allowed;
b->backtrace_barrier = fd->backtrace_barrier;
+ b->is_direct_or_indirect_eval = (fd->eval_type == JS_EVAL_TYPE_DIRECT ||
+ fd->eval_type == JS_EVAL_TYPE_INDIRECT);
b->realm = JS_DupContext(ctx);
add_gc_object(ctx->rt, &b->header, JS_GC_OBJ_TYPE_FUNCTION_BYTECODE);
@@ -32809,7 +33663,7 @@ static void free_function_bytecode(JSRuntime *rt, JSFunctionBytecode *b)
}
}
-static warn_unused int js_parse_directives(JSParseState *s)
+static __exception int js_parse_directives(JSParseState *s)
{
char str[20];
JSParsePos pos;
@@ -32983,7 +33837,7 @@ static JSFunctionDef *js_parse_function_class_fields_init(JSParseState *s)
/* 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 warn_unused int js_parse_function_decl2(JSParseState *s,
+static __exception int js_parse_function_decl2(JSParseState *s,
JSParseFunctionEnum func_type,
JSFunctionKindEnum func_kind,
JSAtom func_name,
@@ -33026,8 +33880,9 @@ static warn_unused int js_parse_function_decl2(JSParseState *s,
func_type == JS_PARSE_FUNC_EXPR &&
(func_kind & JS_FUNC_GENERATOR)) ||
(s->token.u.ident.atom == JS_ATOM_await &&
- func_type == JS_PARSE_FUNC_EXPR &&
- (func_kind & JS_FUNC_ASYNC))) {
+ ((func_type == JS_PARSE_FUNC_EXPR &&
+ (func_kind & JS_FUNC_ASYNC)) ||
+ func_type == JS_PARSE_FUNC_CLASS_STATIC_INIT))) {
return js_parse_error_reserved_identifier(s);
}
}
@@ -33121,7 +33976,8 @@ static warn_unused int js_parse_function_decl2(JSParseState *s,
func_type == JS_PARSE_FUNC_SETTER ||
func_type == JS_PARSE_FUNC_CLASS_CONSTRUCTOR ||
func_type == JS_PARSE_FUNC_DERIVED_CLASS_CONSTRUCTOR);
- fd->has_arguments_binding = (func_type != JS_PARSE_FUNC_ARROW);
+ fd->has_arguments_binding = (func_type != JS_PARSE_FUNC_ARROW &&
+ func_type != JS_PARSE_FUNC_CLASS_STATIC_INIT);
fd->has_this_binding = fd->has_arguments_binding;
fd->is_derived_class_constructor = (func_type == JS_PARSE_FUNC_DERIVED_CLASS_CONSTRUCTOR);
if (func_type == JS_PARSE_FUNC_ARROW) {
@@ -33129,6 +33985,11 @@ static warn_unused int js_parse_function_decl2(JSParseState *s,
fd->super_call_allowed = fd->parent->super_call_allowed;
fd->super_allowed = fd->parent->super_allowed;
fd->arguments_allowed = fd->parent->arguments_allowed;
+ } else if (func_type == JS_PARSE_FUNC_CLASS_STATIC_INIT) {
+ fd->new_target_allowed = TRUE; // although new.target === undefined
+ fd->super_call_allowed = FALSE;
+ fd->super_allowed = TRUE;
+ fd->arguments_allowed = FALSE;
} else {
fd->new_target_allowed = TRUE;
fd->super_call_allowed = fd->is_derived_class_constructor;
@@ -33166,7 +34027,7 @@ static warn_unused int js_parse_function_decl2(JSParseState *s,
if (add_arg(ctx, fd, name) < 0)
goto fail;
fd->defined_arg_count = 1;
- } else {
+ } else if (func_type != JS_PARSE_FUNC_CLASS_STATIC_INIT) {
if (s->token.val == '(') {
int skip_bits;
/* if there is an '=' inside the parameter list, we
@@ -33227,6 +34088,8 @@ static warn_unused int js_parse_function_decl2(JSParseState *s,
goto fail;
}
if (fd->has_parameter_expressions) {
+ if (js_parse_check_duplicate_parameter(s, name))
+ goto fail;
if (define_var(s, fd, name, JS_VAR_DEF_LET) < 0)
goto fail;
}
@@ -33387,8 +34250,10 @@ static warn_unused int js_parse_function_decl2(JSParseState *s,
}
}
- if (js_parse_expect(s, '{'))
- goto fail;
+ if (func_type != JS_PARSE_FUNC_CLASS_STATIC_INIT) {
+ if (js_parse_expect(s, '{'))
+ goto fail;
+ }
if (js_parse_directives(s))
goto fail;
@@ -33418,9 +34283,15 @@ static warn_unused int js_parse_function_decl2(JSParseState *s,
if (js_is_live_code(s)) {
emit_return(s, FALSE);
}
-done:
+ done:
s->cur_func = fd->parent;
+ /* Reparse identifiers after the function is terminated so that
+ the token is parsed in the englobing function. It could be done
+ by just using next_token() here for normal functions, but it is
+ necessary for arrow functions with an expression body. */
+ reparse_ident_token(s);
+
/* create the function object */
{
int idx;
@@ -33531,7 +34402,7 @@ done:
return -1;
}
-static warn_unused int js_parse_function_decl(JSParseState *s,
+static __exception int js_parse_function_decl(JSParseState *s,
JSParseFunctionEnum func_type,
JSFunctionKindEnum func_kind,
JSAtom func_name,
@@ -33543,7 +34414,7 @@ static warn_unused int js_parse_function_decl(JSParseState *s,
NULL);
}
-static warn_unused int js_parse_program(JSParseState *s)
+static __exception int js_parse_program(JSParseState *s)
{
JSFunctionDef *fd = s->cur_func;
int idx;
@@ -33572,12 +34443,24 @@ static warn_unused int js_parse_program(JSParseState *s)
if (!s->is_module) {
/* return the value of the hidden variable eval_ret_idx */
- emit_op(s, OP_get_loc);
- emit_u16(s, fd->eval_ret_idx);
+ if (fd->func_kind == JS_FUNC_ASYNC) {
+ /* wrap the return value in an object so that promises can
+ be safely returned */
+ emit_op(s, OP_object);
+ emit_op(s, OP_dup);
- emit_op(s, OP_return);
+ emit_op(s, OP_get_loc);
+ emit_u16(s, fd->eval_ret_idx);
+
+ emit_op(s, OP_put_field);
+ emit_atom(s, JS_ATOM_value);
+ } else {
+ emit_op(s, OP_get_loc);
+ emit_u16(s, fd->eval_ret_idx);
+ }
+ emit_return(s, TRUE);
} else {
- emit_op(s, OP_return_undef);
+ emit_return(s, FALSE);
}
return 0;
@@ -33620,7 +34503,6 @@ static JSValue JS_EvalFunctionInternal(JSContext *ctx, JSValue fun_obj,
ret_val = js_evaluate_module(ctx, m);
if (JS_IsException(ret_val)) {
fail:
- js_free_modules(ctx, JS_FREE_MODULE_NOT_EVALUATED);
return JS_EXCEPTION;
}
} else {
@@ -33635,33 +34517,8 @@ JSValue JS_EvalFunction(JSContext *ctx, JSValue fun_obj)
return JS_EvalFunctionInternal(ctx, fun_obj, ctx->global_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 if (c == -1) {
- p++; /* skip invalid UTF-8 */
- }
- } else {
- p++;
- }
- }
- s->buf_ptr = p;
- }
-}
-
/* 'input' must be zero terminated i.e. input[input_len] = '\0'. */
-static JSValue JS_EvalInternalImpl(JSContext *ctx, JSValueConst this_obj,
+static JSValue __JS_EvalInternal(JSContext *ctx, JSValueConst this_obj,
const char *input, size_t input_len,
const char *filename, int line, int flags, int scope_idx)
{
@@ -33675,7 +34532,7 @@ static JSValue JS_EvalInternalImpl(JSContext *ctx, JSValueConst this_obj,
JSModuleDef *m;
js_parse_init(ctx, s, input, input_len, filename, line);
- skip_shebang(s);
+ skip_shebang(&s->buf_ptr, s->buf_end);
eval_type = flags & JS_EVAL_TYPE_MASK;
m = NULL;
@@ -33733,6 +34590,10 @@ static JSValue JS_EvalInternalImpl(JSContext *ctx, JSValueConst this_obj,
goto fail;
}
fd->module = m;
+ if (m != NULL || (flags & JS_EVAL_FLAG_ASYNC)) {
+ fd->in_function_body = TRUE;
+ fd->func_kind = JS_FUNC_ASYNC;
+ }
s->is_module = (m != NULL);
s->allow_html_comments = !s->is_module;
@@ -33747,6 +34608,9 @@ static JSValue JS_EvalInternalImpl(JSContext *ctx, JSValueConst this_obj,
goto fail1;
}
+ if (m != NULL)
+ m->has_tla = fd->has_await;
+
/* create the function object and all the enclosed functions */
fun_obj = js_create_function(ctx, fd);
if (JS_IsException(fun_obj))
@@ -33756,7 +34620,7 @@ static JSValue JS_EvalInternalImpl(JSContext *ctx, JSValueConst this_obj,
m->func_obj = fun_obj;
if (js_resolve_module(ctx, m) < 0)
goto fail1;
- fun_obj = JS_DupValue(ctx, JS_MKPTR(JS_TAG_MODULE, m));
+ fun_obj = JS_NewModuleValue(ctx, m);
}
if (flags & JS_EVAL_FLAG_COMPILE_ONLY) {
ret_val = fun_obj;
@@ -33952,8 +34816,6 @@ typedef enum BCTagEnum {
BC_TAG_OBJECT,
BC_TAG_ARRAY,
BC_TAG_BIG_INT,
- BC_TAG_BIG_FLOAT,
- BC_TAG_BIG_DECIMAL,
BC_TAG_TEMPLATE_OBJECT,
BC_TAG_FUNCTION_BYTECODE,
BC_TAG_MODULE,
@@ -33963,24 +34825,21 @@ typedef enum BCTagEnum {
BC_TAG_DATE,
BC_TAG_OBJECT_VALUE,
BC_TAG_OBJECT_REFERENCE,
+#ifdef CONFIG_BIGNUM
+ BC_TAG_BIG_FLOAT,
+ BC_TAG_BIG_DECIMAL,
+#endif
} BCTagEnum;
#ifdef CONFIG_BIGNUM
-#define BC_BASE_VERSION 2
+#define BC_VERSION 0x43
#else
-#define BC_BASE_VERSION 1
-#endif
-#define BC_BE_VERSION 0x40
-#ifdef WORDS_BIGENDIAN
-#define BC_VERSION (BC_BASE_VERSION | BC_BE_VERSION)
-#else
-#define BC_VERSION BC_BASE_VERSION
+#define BC_VERSION 3
#endif
typedef struct BCWriterState {
JSContext *ctx;
DynBuf dbuf;
- BOOL byte_swap : 8;
BOOL allow_bytecode : 8;
BOOL allow_sab : 8;
BOOL allow_reference : 8;
@@ -34010,8 +34869,6 @@ static const char * const bc_tag_str[] = {
"object",
"array",
"bigint",
- "bigfloat",
- "bigdecimal",
"template",
"function",
"module",
@@ -34021,9 +34878,22 @@ static const char * const bc_tag_str[] = {
"Date",
"ObjectValue",
"ObjectReference",
+#ifdef CONFIG_BIGNUM
+ "bigfloat",
+ "bigdecimal",
+#endif
};
#endif
+static inline BOOL is_be(void)
+{
+ union {
+ uint16_t a;
+ uint8_t b;
+ } u = {0x100};
+ return u.b;
+}
+
static void bc_put_u8(BCWriterState *s, uint8_t v)
{
dbuf_putc(&s->dbuf, v);
@@ -34031,21 +34901,21 @@ static void bc_put_u8(BCWriterState *s, uint8_t v)
static void bc_put_u16(BCWriterState *s, uint16_t v)
{
- if (s->byte_swap)
+ if (is_be())
v = bswap16(v);
dbuf_put_u16(&s->dbuf, v);
}
-static maybe_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)
+ if (is_be())
v = bswap32(v);
dbuf_put_u32(&s->dbuf, v);
}
static void bc_put_u64(BCWriterState *s, uint64_t v)
{
- if (s->byte_swap)
+ if (is_be())
v = bswap64(v);
dbuf_put(&s->dbuf, (uint8_t *)&v, sizeof(v));
}
@@ -34070,7 +34940,7 @@ static int bc_atom_to_idx(BCWriterState *s, uint32_t *pres, JSAtom atom)
{
uint32_t v;
- if (atom < s->first_atom || JS_AtomIsTaggedInt(atom)) {
+ if (atom < s->first_atom || __JS_AtomIsTaggedInt(atom)) {
*pres = atom;
return 0;
}
@@ -34110,8 +34980,8 @@ static int bc_put_atom(BCWriterState *s, JSAtom atom)
{
uint32_t v;
- if (JS_AtomIsTaggedInt(atom)) {
- v = (JS_AtomToUInt32(atom) << 1) | 1;
+ if (__JS_AtomIsTaggedInt(atom)) {
+ v = (__JS_AtomToUInt32(atom) << 1) | 1;
} else {
if (bc_atom_to_idx(s, &v, atom))
return -1;
@@ -34215,7 +35085,7 @@ static int JS_WriteFunctionBytecode(BCWriterState *s,
pos += len;
}
- if (s->byte_swap)
+ if (is_be())
bc_byte_swap(bc_buf, bc_len);
dbuf_put(&s->dbuf, bc_buf, bc_len);
@@ -34230,7 +35100,7 @@ static int JS_WriteFunctionBytecode(BCWriterState *s,
static void JS_WriteString(BCWriterState *s, JSString *p)
{
int i;
- bc_put_leb128(s, (p->len << 1) | p->is_wide_char);
+ bc_put_leb128(s, ((uint32_t)p->len << 1) | p->is_wide_char);
if (p->is_wide_char) {
for(i = 0; i < p->len; i++)
bc_put_u16(s, p->u.str16[i]);
@@ -34239,7 +35109,6 @@ static void JS_WriteString(BCWriterState *s, JSString *p)
}
}
-#ifdef CONFIG_BIGNUM
static int JS_WriteBigNum(BCWriterState *s, JSValueConst obj)
{
uint32_t tag, tag1;
@@ -34254,12 +35123,14 @@ static int JS_WriteBigNum(BCWriterState *s, JSValueConst obj)
case JS_TAG_BIG_INT:
tag1 = BC_TAG_BIG_INT;
break;
+#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_FLOAT:
tag1 = BC_TAG_BIG_FLOAT;
break;
case JS_TAG_BIG_DECIMAL:
tag1 = BC_TAG_BIG_DECIMAL;
break;
+#endif
default:
abort();
}
@@ -34276,7 +35147,7 @@ static int JS_WriteBigNum(BCWriterState *s, JSValueConst obj)
e = a->expn + 3;
else
e = a->expn;
- e = (e << 1) | a->sign;
+ e = (e * 2) | a->sign;
if (e < INT32_MIN || e > INT32_MAX) {
JS_ThrowInternalError(s->ctx, "bignum exponent is too large");
return -1;
@@ -34305,20 +35176,14 @@ static int JS_WriteBigNum(BCWriterState *s, JSValueConst obj)
bc_put_leb128(s, len);
/* always saved in byte based little endian representation */
for(j = 0; j < n1; j++) {
- dbuf_putc(&s->dbuf, v >> (j * 8));
+ bc_put_u8(s, v >> (j * 8));
}
for(; i < a->len; i++) {
limb_t v = a->tab[i];
#if LIMB_BITS == 32
-#ifdef WORDS_BIGENDIAN
- v = bswap32(v);
-#endif
- dbuf_put_u32(&s->dbuf, v);
+ bc_put_u32(s, v);
#else
-#ifdef WORDS_BIGENDIAN
- v = bswap64(v);
-#endif
- dbuf_put_u64(&s->dbuf, v);
+ bc_put_u64(s, v);
#endif
}
} else {
@@ -34361,20 +35226,19 @@ static int JS_WriteBigNum(BCWriterState *s, JSValueConst obj)
v8 = d;
bpos = 1;
} else {
- dbuf_putc(&s->dbuf, v8 | (d << 4));
+ bc_put_u8(s, v8 | (d << 4));
bpos = 0;
}
}
}
/* flush the last digit */
if (bpos) {
- dbuf_putc(&s->dbuf, v8);
+ bc_put_u8(s, v8);
}
}
}
return 0;
}
-#endif /* CONFIG_BIGNUM */
static int JS_WriteObjectRec(BCWriterState *s, JSValueConst obj);
@@ -34397,6 +35261,7 @@ static int JS_WriteFunctionTag(BCWriterState *s, JSValueConst obj)
bc_set_flags(&flags, &idx, b->arguments_allowed, 1);
bc_set_flags(&flags, &idx, b->has_debug, 1);
bc_set_flags(&flags, &idx, b->backtrace_barrier, 1);
+ bc_set_flags(&flags, &idx, b->is_direct_or_indirect_eval, 1);
assert(idx <= 16);
bc_put_u16(s, flags);
bc_put_u8(s, b->js_mode);
@@ -34503,6 +35368,8 @@ static int JS_WriteModule(BCWriterState *s, JSValueConst obj)
bc_put_leb128(s, mi->req_module_idx);
}
+ bc_put_u8(s, m->has_tla);
+
if (JS_WriteObjectRec(s, m->func_obj))
goto fail;
return 0;
@@ -34731,8 +35598,8 @@ static int JS_WriteObjectRec(BCWriterState *s, JSValueConst obj)
case JS_CLASS_NUMBER:
case JS_CLASS_STRING:
case JS_CLASS_BOOLEAN:
-#ifdef CONFIG_BIGNUM
case JS_CLASS_BIG_INT:
+#ifdef CONFIG_BIGNUM
case JS_CLASS_BIG_FLOAT:
case JS_CLASS_BIG_DECIMAL:
#endif
@@ -34754,14 +35621,14 @@ static int JS_WriteObjectRec(BCWriterState *s, JSValueConst obj)
goto fail;
}
break;
-#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_INT:
+#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_FLOAT:
case JS_TAG_BIG_DECIMAL:
+#endif
if (JS_WriteBigNum(s, obj))
goto fail;
break;
-#endif
default:
invalid_tag:
JS_ThrowInternalError(s->ctx, "unsupported tag (%d)", tag);
@@ -34779,15 +35646,10 @@ static int JS_WriteObjectAtoms(BCWriterState *s)
JSRuntime *rt = s->ctx->rt;
DynBuf dbuf1;
int i, atoms_size;
- uint8_t version;
dbuf1 = s->dbuf;
js_dbuf_init(s->ctx, &s->dbuf);
-
- version = BC_VERSION;
- if (s->byte_swap)
- version ^= BC_BE_VERSION;
- bc_put_u8(s, version);
+ bc_put_u8(s, BC_VERSION);
bc_put_leb128(s, s->idx_to_atom_count);
for(i = 0; i < s->idx_to_atom_count; i++) {
@@ -34820,8 +35682,6 @@ uint8_t *JS_WriteObject2(JSContext *ctx, size_t *psize, JSValueConst obj,
memset(s, 0, sizeof(*s));
s->ctx = ctx;
- /* XXX: byte swapped output is untested */
- s->byte_swap = ((flags & JS_WRITE_OBJ_BSWAP) != 0);
s->allow_bytecode = ((flags & JS_WRITE_OBJ_BYTECODE) != 0);
s->allow_sab = ((flags & JS_WRITE_OBJ_SAB) != 0);
s->allow_reference = ((flags & JS_WRITE_OBJ_REFERENCE) != 0);
@@ -34942,33 +35802,45 @@ static int bc_get_u8(BCReaderState *s, uint8_t *pval)
static int bc_get_u16(BCReaderState *s, uint16_t *pval)
{
+ uint16_t v;
if (unlikely(s->buf_end - s->ptr < 2)) {
*pval = 0; /* avoid warning */
return bc_read_error_end(s);
}
- *pval = get_u16(s->ptr);
+ v = get_u16(s->ptr);
+ if (is_be())
+ v = bswap16(v);
+ *pval = v;
s->ptr += 2;
return 0;
}
-static maybe_unused int bc_get_u32(BCReaderState *s, uint32_t *pval)
+static __maybe_unused int bc_get_u32(BCReaderState *s, uint32_t *pval)
{
+ uint32_t v;
if (unlikely(s->buf_end - s->ptr < 4)) {
*pval = 0; /* avoid warning */
return bc_read_error_end(s);
}
- *pval = get_u32(s->ptr);
+ v = get_u32(s->ptr);
+ if (is_be())
+ v = bswap32(v);
+ *pval = v;
s->ptr += 4;
return 0;
}
static int bc_get_u64(BCReaderState *s, uint64_t *pval)
{
+ uint64_t v;
if (unlikely(s->buf_end - s->ptr < 8)) {
*pval = 0; /* avoid warning */
return bc_read_error_end(s);
}
- *pval = get_u64(s->ptr);
+ v = get_u64(s->ptr);
+ if (is_be())
+ v = bswap64(v);
+ *pval = v;
s->ptr += 8;
return 0;
}
@@ -35025,7 +35897,7 @@ static int bc_idx_to_atom(BCReaderState *s, JSAtom *patom, uint32_t idx)
{
JSAtom atom;
- if (JS_AtomIsTaggedInt(idx)) {
+ if (__JS_AtomIsTaggedInt(idx)) {
atom = idx;
} else if (idx < s->first_atom) {
atom = JS_DupAtom(s->ctx, idx);
@@ -35049,7 +35921,7 @@ static int bc_get_atom(BCReaderState *s, JSAtom *patom)
if (bc_get_leb128(s, &v))
return -1;
if (v & 1) {
- *patom = JS_AtomFromUInt32(v >> 1);
+ *patom = __JS_AtomFromUInt32(v >> 1);
return 0;
} else {
return bc_idx_to_atom(s, patom, v >> 1);
@@ -35080,7 +35952,13 @@ static JSString *JS_ReadString(BCReaderState *s)
}
memcpy(p->u.str8, s->ptr, size);
s->ptr += size;
- if (!is_wide_char) {
+ if (is_wide_char) {
+ if (is_be()) {
+ uint32_t i;
+ for (i = 0; i < len; i++)
+ p->u.str16[i] = bswap16(p->u.str16[i]);
+ }
+ } else {
p->u.str8[size] = '\0'; /* add the trailing zero for 8 bit strings */
}
#ifdef DUMP_READ_OBJECT
@@ -35119,6 +35997,9 @@ static int JS_ReadFunctionBytecode(BCReaderState *s, JSFunctionBytecode *b,
}
b->byte_code_buf = bc_buf;
+ if (is_be())
+ bc_byte_swap(bc_buf, bc_len);
+
pos = 0;
while (pos < bc_len) {
op = bc_buf[pos];
@@ -35153,18 +36034,16 @@ static int JS_ReadFunctionBytecode(BCReaderState *s, JSFunctionBytecode *b,
return 0;
}
-#ifdef CONFIG_BIGNUM
static JSValue JS_ReadBigNum(BCReaderState *s, int tag)
{
JSValue obj = JS_UNDEFINED;
uint8_t v8;
int32_t e;
uint32_t len;
- limb_t l, i, n, j;
+ limb_t l, i, n;
JSBigFloat *p;
limb_t v;
bf_t *a;
- int bpos, d;
p = js_new_bf(s->ctx);
if (!p)
@@ -35173,12 +36052,14 @@ static JSValue JS_ReadBigNum(BCReaderState *s, int tag)
case BC_TAG_BIG_INT:
obj = JS_MKPTR(JS_TAG_BIG_INT, p);
break;
+#ifdef CONFIG_BIGNUM
case BC_TAG_BIG_FLOAT:
obj = JS_MKPTR(JS_TAG_BIG_FLOAT, p);
break;
case BC_TAG_BIG_DECIMAL:
obj = JS_MKPTR(JS_TAG_BIG_DECIMAL, p);
break;
+#endif
default:
abort();
}
@@ -35212,45 +36093,23 @@ static JSValue JS_ReadBigNum(BCReaderState *s, int tag)
JS_ThrowInternalError(s->ctx, "invalid bignum length");
goto fail;
}
- if (tag != BC_TAG_BIG_DECIMAL)
- l = (len + sizeof(limb_t) - 1) / sizeof(limb_t);
- else
+#ifdef CONFIG_BIGNUM
+ if (tag == BC_TAG_BIG_DECIMAL) {
l = (len + LIMB_DIGITS - 1) / LIMB_DIGITS;
+ } else
+#endif
+ {
+ l = (len + sizeof(limb_t) - 1) / sizeof(limb_t);
+ }
if (bf_resize(a, l)) {
JS_ThrowOutOfMemory(s->ctx);
goto fail;
}
- if (tag != BC_TAG_BIG_DECIMAL) {
- n = len & (sizeof(limb_t) - 1);
- if (n != 0) {
- v = 0;
- for(i = 0; i < n; i++) {
- if (bc_get_u8(s, &v8))
- goto fail;
- v |= (limb_t)v8 << ((sizeof(limb_t) - n + i) * 8);
- }
- a->tab[0] = v;
- i = 1;
- } else {
- i = 0;
- }
- for(; i < l; i++) {
-#if LIMB_BITS == 32
- if (bc_get_u32(s, &v))
- goto fail;
-#ifdef WORDS_BIGENDIAN
- v = bswap32(v);
-#endif
-#else
- if (bc_get_u64(s, &v))
- goto fail;
-#ifdef WORDS_BIGENDIAN
- v = bswap64(v);
-#endif
-#endif
- a->tab[i] = v;
- }
- } else {
+#ifdef CONFIG_BIGNUM
+ if (tag == BC_TAG_BIG_DECIMAL) {
+ limb_t j;
+ int bpos, d;
+
bpos = 0;
for(i = 0; i < l; i++) {
if (i == 0 && (n = len % LIMB_DIGITS) != 0) {
@@ -35277,6 +36136,32 @@ static JSValue JS_ReadBigNum(BCReaderState *s, int tag)
}
a->tab[i] = v;
}
+ } else
+#endif /* CONFIG_BIGNUM */
+ {
+ n = len & (sizeof(limb_t) - 1);
+ if (n != 0) {
+ v = 0;
+ for(i = 0; i < n; i++) {
+ if (bc_get_u8(s, &v8))
+ goto fail;
+ v |= (limb_t)v8 << ((sizeof(limb_t) - n + i) * 8);
+ }
+ a->tab[0] = v;
+ i = 1;
+ } else {
+ i = 0;
+ }
+ for(; i < l; i++) {
+#if LIMB_BITS == 32
+ if (bc_get_u32(s, &v))
+ goto fail;
+#else
+ if (bc_get_u64(s, &v))
+ goto fail;
+#endif
+ a->tab[i] = v;
+ }
}
}
bc_read_trace(s, "}\n");
@@ -35285,7 +36170,6 @@ static JSValue JS_ReadBigNum(BCReaderState *s, int tag)
JS_FreeValue(s->ctx, obj);
return JS_EXCEPTION;
}
-#endif /* CONFIG_BIGNUM */
static JSValue JS_ReadObjectRec(BCReaderState *s);
@@ -35335,6 +36219,7 @@ static JSValue JS_ReadFunctionTag(BCReaderState *s)
bc.arguments_allowed = bc_get_flags(v16, &idx, 1);
bc.has_debug = bc_get_flags(v16, &idx, 1);
bc.backtrace_barrier = bc_get_flags(v16, &idx, 1);
+ bc.is_direct_or_indirect_eval = bc_get_flags(v16, &idx, 1);
bc.read_only_bytecode = s->is_rom_data;
if (bc_get_u8(s, &v8))
goto fail;
@@ -35513,7 +36398,7 @@ static JSValue JS_ReadModule(BCReaderState *s)
m = js_new_module_def(ctx, module_name);
if (!m)
goto fail;
- obj = JS_DupValue(ctx, JS_MKPTR(JS_TAG_MODULE, m));
+ obj = JS_NewModuleValue(ctx, m);
if (bc_get_leb128_int(s, &m->req_module_entries_count))
goto fail;
if (m->req_module_entries_count != 0) {
@@ -35586,6 +36471,10 @@ static JSValue JS_ReadModule(BCReaderState *s)
}
}
+ if (bc_get_u8(s, &v8))
+ goto fail;
+ m->has_tla = (v8 != 0);
+
m->func_obj = JS_ReadObjectRec(s);
if (JS_IsException(m->func_obj))
goto fail;
@@ -35864,7 +36753,7 @@ static JSValue JS_ReadObjectRec(BCReaderState *s)
if (bc_get_u64(s, &u.u64))
return JS_EXCEPTION;
bc_read_trace(s, "%g\n", u.d);
- obj = JS_NewFloat64Impl(ctx, u.d);
+ obj = __JS_NewFloat64(ctx, u.d);
}
break;
case BC_TAG_STRING:
@@ -35910,13 +36799,13 @@ static JSValue JS_ReadObjectRec(BCReaderState *s)
case BC_TAG_OBJECT_VALUE:
obj = JS_ReadObjectValue(s);
break;
-#ifdef CONFIG_BIGNUM
case BC_TAG_BIG_INT:
+#ifdef CONFIG_BIGNUM
case BC_TAG_BIG_FLOAT:
case BC_TAG_BIG_DECIMAL:
+#endif
obj = JS_ReadBigNum(s, tag);
break;
-#endif
case BC_TAG_OBJECT_REFERENCE:
{
uint32_t val;
@@ -35950,7 +36839,6 @@ static int JS_ReadObjectAtoms(BCReaderState *s)
if (bc_get_u8(s, &v8))
return -1;
- /* XXX: could support byte swapped input */
if (v8 != BC_VERSION) {
JS_ThrowSyntaxError(s->ctx, "invalid version (%d expected=%d)",
v8, BC_VERSION);
@@ -36172,7 +37060,7 @@ static int JS_InstantiateFunctionListItem(JSContext *ctx, JSValueConst obj,
val = JS_NewInt64(ctx, e->u.i64);
break;
case JS_DEF_PROP_DOUBLE:
- val = JS_NewFloat64Impl(ctx, e->u.f64);
+ val = __JS_NewFloat64(ctx, e->u.f64);
break;
case JS_DEF_PROP_UNDEFINED:
val = JS_UNDEFINED;
@@ -36236,7 +37124,7 @@ int JS_SetModuleExportList(JSContext *ctx, JSModuleDef *m,
val = JS_NewInt64(ctx, e->u.i64);
break;
case JS_DEF_PROP_DOUBLE:
- val = JS_NewFloat64Impl(ctx, e->u.f64);
+ val = __JS_NewFloat64(ctx, e->u.f64);
break;
case JS_DEF_OBJECT:
val = JS_NewObject(ctx);
@@ -36325,12 +37213,10 @@ static JSValue js_global_isNaN(JSContext *ctx, JSValueConst this_val,
static JSValue js_global_isFinite(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
- BOOL res;
double d;
if (unlikely(JS_ToFloat64(ctx, &d, argv[0])))
return JS_EXCEPTION;
- res = isfinite(d);
- return JS_NewBool(ctx, res);
+ return JS_NewBool(ctx, isfinite(d));
}
/* Object class */
@@ -36348,10 +37234,10 @@ static JSValue JS_ToObject(JSContext *ctx, JSValueConst val)
case JS_TAG_OBJECT:
case JS_TAG_EXCEPTION:
return JS_DupValue(ctx, val);
-#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_INT:
obj = JS_NewObjectClass(ctx, JS_CLASS_BIG_INT);
goto set_value;
+#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_FLOAT:
obj = JS_NewObjectClass(ctx, JS_CLASS_BIG_FLOAT);
goto set_value;
@@ -36469,7 +37355,7 @@ static int js_obj_to_desc(JSContext *ctx, JSPropertyDescriptor *d,
return -1;
}
-static warn_unused int JS_DefinePropertyDesc(JSContext *ctx, JSValueConst obj,
+static __exception int JS_DefinePropertyDesc(JSContext *ctx, JSValueConst obj,
JSAtom prop, JSValueConst desc,
int flags)
{
@@ -36485,7 +37371,7 @@ static warn_unused int JS_DefinePropertyDesc(JSContext *ctx, JSValueConst obj,
return ret;
}
-static warn_unused int JS_ObjectDefineProperties(JSContext *ctx,
+static __exception int JS_ObjectDefineProperties(JSContext *ctx,
JSValueConst obj,
JSValueConst properties)
{
@@ -36724,13 +37610,13 @@ static JSValue js_object_getOwnPropertyDescriptor(JSContext *ctx, JSValueConst t
} else {
if (JS_DefinePropertyValue(ctx, ret, JS_ATOM_value, JS_DupValue(ctx, desc.value), flags) < 0
|| JS_DefinePropertyValue(ctx, ret, JS_ATOM_writable,
- JS_NewBool(ctx, (desc.flags & JS_PROP_WRITABLE) != 0), flags) < 0)
+ JS_NewBool(ctx, desc.flags & JS_PROP_WRITABLE), flags) < 0)
goto exception1;
}
if (JS_DefinePropertyValue(ctx, ret, JS_ATOM_enumerable,
- JS_NewBool(ctx, (desc.flags & JS_PROP_ENUMERABLE) != 0), flags) < 0
+ JS_NewBool(ctx, desc.flags & JS_PROP_ENUMERABLE), flags) < 0
|| JS_DefinePropertyValue(ctx, ret, JS_ATOM_configurable,
- JS_NewBool(ctx, (desc.flags & JS_PROP_CONFIGURABLE) != 0), flags) < 0)
+ JS_NewBool(ctx, desc.flags & JS_PROP_CONFIGURABLE), flags) < 0)
goto exception1;
js_free_desc(ctx, &desc);
}
@@ -36970,6 +37856,32 @@ static JSValue js_object_hasOwnProperty(JSContext *ctx, JSValueConst this_val,
return JS_NewBool(ctx, ret);
}
+static JSValue js_object_hasOwn(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv)
+{
+ JSValue obj;
+ JSAtom atom;
+ JSObject *p;
+ BOOL ret;
+
+ obj = JS_ToObject(ctx, argv[0]);
+ if (JS_IsException(obj))
+ return obj;
+ atom = JS_ValueToAtom(ctx, argv[1]);
+ if (unlikely(atom == JS_ATOM_NULL)) {
+ JS_FreeValue(ctx, obj);
+ return JS_EXCEPTION;
+ }
+ p = JS_VALUE_GET_OBJ(obj);
+ ret = JS_GetOwnPropertyInternal(ctx, NULL, p, atom);
+ JS_FreeAtom(ctx, atom);
+ JS_FreeValue(ctx, obj);
+ if (ret < 0)
+ return JS_EXCEPTION;
+ else
+ return JS_NewBool(ctx, ret);
+}
+
static JSValue js_object_valueOf(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
@@ -37459,7 +38371,7 @@ static JSValue js_object_propertyIsEnumerable(JSContext *ctx, JSValueConst this_
if (has_prop < 0)
goto exception;
if (has_prop) {
- res = JS_NewBool(ctx, (desc.flags & JS_PROP_ENUMERABLE) != 0);
+ res = JS_NewBool(ctx, desc.flags & JS_PROP_ENUMERABLE);
js_free_desc(ctx, &desc);
} else {
res = JS_FALSE;
@@ -37516,32 +38428,6 @@ exception:
return res;
}
-static JSValue js_object_hasOwn(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- JSValue obj;
- JSAtom atom;
- JSObject *p;
- BOOL ret;
-
- obj = JS_ToObject(ctx, argv[0]);
- if (JS_IsException(obj))
- return obj;
- atom = JS_ValueToAtom(ctx, argv[1]);
- if (unlikely(atom == JS_ATOM_NULL)) {
- JS_FreeValue(ctx, obj);
- return JS_EXCEPTION;
- }
- p = JS_VALUE_GET_OBJ(obj);
- ret = JS_GetOwnPropertyInternal(ctx, NULL, p, atom);
- JS_FreeAtom(ctx, atom);
- JS_FreeValue(ctx, obj);
- if (ret < 0)
- return JS_EXCEPTION;
- else
- return JS_NewBool(ctx, ret);
-}
-
static const JSCFunctionListEntry js_object_funcs[] = {
JS_CFUNC_DEF("create", 2, js_object_create ),
JS_CFUNC_MAGIC_DEF("getPrototypeOf", 1, js_object_getPrototypeOf, 0 ),
@@ -37550,6 +38436,7 @@ static const JSCFunctionListEntry js_object_funcs[] = {
JS_CFUNC_DEF("defineProperties", 2, js_object_defineProperties ),
JS_CFUNC_DEF("getOwnPropertyNames", 1, js_object_getOwnPropertyNames ),
JS_CFUNC_DEF("getOwnPropertySymbols", 1, js_object_getOwnPropertySymbols ),
+ JS_CFUNC_MAGIC_DEF("groupBy", 2, js_object_groupBy, 0 ),
JS_CFUNC_MAGIC_DEF("keys", 1, js_object_keys, JS_ITERATOR_KIND_KEY ),
JS_CFUNC_MAGIC_DEF("values", 1, js_object_keys, JS_ITERATOR_KIND_VALUE ),
JS_CFUNC_MAGIC_DEF("entries", 1, js_object_keys, JS_ITERATOR_KIND_KEY_AND_VALUE ),
@@ -37671,7 +38558,7 @@ static JSValue js_function_constructor(JSContext *ctx, JSValueConst new_target,
return JS_EXCEPTION;
}
-static warn_unused int js_get_length32(JSContext *ctx, uint32_t *pres,
+static __exception int js_get_length32(JSContext *ctx, uint32_t *pres,
JSValueConst obj)
{
JSValue len_val;
@@ -37683,7 +38570,7 @@ static warn_unused int js_get_length32(JSContext *ctx, uint32_t *pres,
return JS_ToUint32Free(ctx, pres, len_val);
}
-static warn_unused int js_get_length64(JSContext *ctx, int64_t *pres,
+static __exception int js_get_length64(JSContext *ctx, int64_t *pres,
JSValueConst obj)
{
JSValue len_val;
@@ -37719,7 +38606,9 @@ static JSValue *build_arg_list(JSContext *ctx, uint32_t *plen,
if (js_get_length32(ctx, &len, array_arg))
return NULL;
if (len > JS_MAX_LOCAL_VARS) {
- JS_ThrowInternalError(ctx, "too many arguments");
+ // XXX: check for stack overflow?
+ JS_ThrowRangeError(ctx, "too many arguments in function call (only %d allowed)",
+ JS_MAX_LOCAL_VARS);
return NULL;
}
/* avoid allocating 0 bytes */
@@ -37768,9 +38657,9 @@ static JSValue js_function_apply(JSContext *ctx, JSValueConst this_val,
if (!tab)
return JS_EXCEPTION;
if (magic & 1) {
- ret = JS_CallConstructor2(ctx, this_val, this_arg, len, tab);
+ ret = JS_CallConstructor2(ctx, this_val, this_arg, len, (JSValueConst *)tab);
} else {
- ret = JS_Call(ctx, this_val, this_arg, len, tab);
+ ret = JS_Call(ctx, this_val, this_arg, len, (JSValueConst *)tab);
}
free_arg_list(ctx, tab, len);
return ret;
@@ -37980,7 +38869,8 @@ static JSValue js_error_constructor(JSContext *ctx, JSValueConst new_target,
int argc, JSValueConst *argv, int magic)
{
JSValue obj, msg, proto;
- JSValueConst message;
+ JSValueConst message, options;
+ int arg_index;
if (JS_IsUndefined(new_target))
new_target = JS_GetActiveFunction(ctx);
@@ -38006,12 +38896,9 @@ static JSValue js_error_constructor(JSContext *ctx, JSValueConst new_target,
JS_FreeValue(ctx, proto);
if (JS_IsException(obj))
return obj;
- if (magic == JS_AGGREGATE_ERROR) {
- message = argv[1];
- } else {
- message = argv[0];
- }
+ arg_index = (magic == JS_AGGREGATE_ERROR);
+ message = argv[arg_index++];
if (!JS_IsUndefined(message)) {
msg = JS_ToString(ctx, message);
if (unlikely(JS_IsException(msg)))
@@ -38020,6 +38907,22 @@ static JSValue js_error_constructor(JSContext *ctx, JSValueConst new_target,
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
}
+ if (arg_index < argc) {
+ options = argv[arg_index];
+ if (JS_IsObject(options)) {
+ int present = JS_HasProperty(ctx, options, JS_ATOM_cause);
+ if (present < 0)
+ goto exception;
+ if (present) {
+ JSValue cause = JS_GetProperty(ctx, options, JS_ATOM_cause);
+ if (JS_IsException(cause))
+ goto exception;
+ JS_DefinePropertyValue(ctx, obj, JS_ATOM_cause, cause,
+ JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
+ }
+ }
+ }
+
if (magic == JS_AGGREGATE_ERROR) {
JSValue error_list = iterator_to_array(ctx, argv[0]);
if (JS_IsException(error_list))
@@ -38413,6 +39316,106 @@ static int JS_isConcatSpreadable(JSContext *ctx, JSValueConst obj)
return JS_IsArray(ctx, obj);
}
+static JSValue js_array_at(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv)
+{
+ JSValue obj, ret;
+ int64_t len, idx;
+ JSValue *arrp;
+ uint32_t count;
+
+ obj = JS_ToObject(ctx, this_val);
+ if (js_get_length64(ctx, &len, obj))
+ goto exception;
+
+ if (JS_ToInt64Sat(ctx, &idx, argv[0]))
+ goto exception;
+
+ if (idx < 0)
+ idx = len + idx;
+ if (idx < 0 || idx >= len) {
+ ret = JS_UNDEFINED;
+ } else if (js_get_fast_array(ctx, obj, &arrp, &count) && idx < count) {
+ ret = JS_DupValue(ctx, arrp[idx]);
+ } else {
+ int present = JS_TryGetPropertyInt64(ctx, obj, idx, &ret);
+ if (present < 0)
+ goto exception;
+ if (!present)
+ ret = JS_UNDEFINED;
+ }
+ JS_FreeValue(ctx, obj);
+ return ret;
+ exception:
+ JS_FreeValue(ctx, obj);
+ return JS_EXCEPTION;
+}
+
+static JSValue js_array_with(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv)
+{
+ JSValue arr, obj, ret, *arrp, *pval;
+ JSObject *p;
+ int64_t i, len, idx;
+ uint32_t count32;
+
+ ret = JS_EXCEPTION;
+ arr = JS_UNDEFINED;
+ obj = JS_ToObject(ctx, this_val);
+ if (js_get_length64(ctx, &len, obj))
+ goto exception;
+
+ if (JS_ToInt64Sat(ctx, &idx, argv[0]))
+ goto exception;
+
+ if (idx < 0)
+ idx = len + idx;
+
+ if (idx < 0 || idx >= len) {
+ JS_ThrowRangeError(ctx, "invalid array index: %" PRId64, idx);
+ goto exception;
+ }
+
+ arr = js_allocate_fast_array(ctx, len);
+ if (JS_IsException(arr))
+ goto exception;
+
+ p = JS_VALUE_GET_OBJ(arr);
+ i = 0;
+ pval = p->u.array.u.values;
+ if (js_get_fast_array(ctx, obj, &arrp, &count32) && count32 == len) {
+ for (; i < idx; i++, pval++)
+ *pval = JS_DupValue(ctx, arrp[i]);
+ *pval = JS_DupValue(ctx, argv[1]);
+ for (i++, pval++; i < len; i++, pval++)
+ *pval = JS_DupValue(ctx, arrp[i]);
+ } else {
+ for (; i < idx; i++, pval++)
+ if (-1 == JS_TryGetPropertyInt64(ctx, obj, i, pval))
+ goto fill_and_fail;
+ *pval = JS_DupValue(ctx, argv[1]);
+ for (i++, pval++; i < len; i++, pval++) {
+ if (-1 == JS_TryGetPropertyInt64(ctx, obj, i, pval)) {
+ fill_and_fail:
+ for (; i < len; i++, pval++)
+ *pval = JS_UNDEFINED;
+ goto exception;
+ }
+ }
+ }
+
+ if (JS_SetProperty(ctx, arr, JS_ATOM_length, JS_NewInt64(ctx, len)) < 0)
+ goto exception;
+
+ ret = arr;
+ arr = JS_UNDEFINED;
+
+exception:
+ JS_FreeValue(ctx, arr);
+ JS_FreeValue(ctx, obj);
+ return ret;
+}
+
static JSValue js_array_concat(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
@@ -38778,9 +39781,10 @@ static JSValue js_array_includes(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
JSValue obj, val;
- int64_t len, n, res;
+ int64_t len, n;
JSValue *arrp;
uint32_t count;
+ int res;
obj = JS_ToObject(ctx, this_val);
if (js_get_length64(ctx, &len, obj))
@@ -38911,13 +39915,21 @@ static JSValue js_array_lastIndexOf(JSContext *ctx, JSValueConst this_val,
return JS_EXCEPTION;
}
+enum {
+ ArrayFind,
+ ArrayFindIndex,
+ ArrayFindLast,
+ ArrayFindLastIndex,
+};
+
static JSValue js_array_find(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int findIndex)
+ int argc, JSValueConst *argv, int mode)
{
JSValueConst func, this_arg;
JSValueConst args[3];
JSValue obj, val, index_val, res;
- int64_t len, k;
+ int64_t len, k, end;
+ int dir;
index_val = JS_UNDEFINED;
val = JS_UNDEFINED;
@@ -38933,7 +39945,17 @@ static JSValue js_array_find(JSContext *ctx, JSValueConst this_val,
if (argc > 1)
this_arg = argv[1];
- for(k = 0; k < len; k++) {
+ k = 0;
+ dir = 1;
+ end = len;
+ if (mode == ArrayFindLast || mode == ArrayFindLastIndex) {
+ k = len - 1;
+ dir = -1;
+ end = -1;
+ }
+
+ // TODO(bnoordhuis) add fast path for fast arrays
+ for(; k != end; k += dir) {
index_val = JS_NewInt64(ctx, k);
if (JS_IsException(index_val))
goto exception;
@@ -38947,7 +39969,7 @@ static JSValue js_array_find(JSContext *ctx, JSValueConst this_val,
if (JS_IsException(res))
goto exception;
if (JS_ToBoolFree(ctx, res)) {
- if (findIndex) {
+ if (mode == ArrayFindIndex || mode == ArrayFindLastIndex) {
JS_FreeValue(ctx, val);
JS_FreeValue(ctx, obj);
return index_val;
@@ -38961,7 +39983,7 @@ static JSValue js_array_find(JSContext *ctx, JSValueConst this_val,
JS_FreeValue(ctx, index_val);
}
JS_FreeValue(ctx, obj);
- if (findIndex)
+ if (mode == ArrayFindIndex || mode == ArrayFindLastIndex)
return JS_NewInt32(ctx, -1);
else
return JS_UNDEFINED;
@@ -38984,7 +40006,8 @@ static JSValue js_array_toString(JSContext *ctx, JSValueConst this_val,
method = JS_GetProperty(ctx, obj, JS_ATOM_join);
if (JS_IsException(method)) {
ret = JS_EXCEPTION;
- } else if (!JS_IsFunction(ctx, method)) {
+ } else
+ if (!JS_IsFunction(ctx, method)) {
/* Use intrinsic Object.prototype.toString */
JS_FreeValue(ctx, method);
ret = js_object_toString(ctx, obj, 0, NULL);
@@ -39211,6 +40234,61 @@ static JSValue js_array_reverse(JSContext *ctx, JSValueConst this_val,
return JS_EXCEPTION;
}
+// Note: a.toReversed() is a.slice().reverse() with the twist that a.slice()
+// leaves holes in sparse arrays intact whereas a.toReversed() replaces them
+// with undefined, thus in effect creating a dense array.
+// Does not use Array[@@species], always returns a base Array.
+static JSValue js_array_toReversed(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv)
+{
+ JSValue arr, obj, ret, *arrp, *pval;
+ JSObject *p;
+ int64_t i, len;
+ uint32_t count32;
+
+ ret = JS_EXCEPTION;
+ arr = JS_UNDEFINED;
+ obj = JS_ToObject(ctx, this_val);
+ if (js_get_length64(ctx, &len, obj))
+ goto exception;
+
+ arr = js_allocate_fast_array(ctx, len);
+ if (JS_IsException(arr))
+ goto exception;
+
+ if (len > 0) {
+ p = JS_VALUE_GET_OBJ(arr);
+
+ i = len - 1;
+ pval = p->u.array.u.values;
+ if (js_get_fast_array(ctx, obj, &arrp, &count32) && count32 == len) {
+ for (; i >= 0; i--, pval++)
+ *pval = JS_DupValue(ctx, arrp[i]);
+ } else {
+ // Query order is observable; test262 expects descending order.
+ for (; i >= 0; i--, pval++) {
+ if (-1 == JS_TryGetPropertyInt64(ctx, obj, i, pval)) {
+ // Exception; initialize remaining elements.
+ for (; i >= 0; i--, pval++)
+ *pval = JS_UNDEFINED;
+ goto exception;
+ }
+ }
+ }
+
+ if (JS_SetProperty(ctx, arr, JS_ATOM_length, JS_NewInt64(ctx, len)) < 0)
+ goto exception;
+ }
+
+ ret = arr;
+ arr = JS_UNDEFINED;
+
+exception:
+ JS_FreeValue(ctx, arr);
+ JS_FreeValue(ctx, obj);
+ return ret;
+}
+
static JSValue js_array_slice(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv, int splice)
{
@@ -39232,7 +40310,8 @@ static JSValue js_array_slice(JSContext *ctx, JSValueConst this_val,
if (argc == 0) {
item_count = 0;
del_count = 0;
- } else if (argc == 1) {
+ } else
+ if (argc == 1) {
item_count = 0;
del_count = len - start;
} else {
@@ -39317,6 +40396,92 @@ static JSValue js_array_slice(JSContext *ctx, JSValueConst this_val,
return JS_EXCEPTION;
}
+static JSValue js_array_toSpliced(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv)
+{
+ JSValue arr, obj, ret, *arrp, *pval, *last;
+ JSObject *p;
+ int64_t i, j, len, newlen, start, add, del;
+ uint32_t count32;
+
+ pval = NULL;
+ last = NULL;
+ ret = JS_EXCEPTION;
+ arr = JS_UNDEFINED;
+
+ obj = JS_ToObject(ctx, this_val);
+ if (js_get_length64(ctx, &len, obj))
+ goto exception;
+
+ start = 0;
+ if (argc > 0)
+ if (JS_ToInt64Clamp(ctx, &start, argv[0], 0, len, len))
+ goto exception;
+
+ del = 0;
+ if (argc > 0)
+ del = len - start;
+ if (argc > 1)
+ if (JS_ToInt64Clamp(ctx, &del, argv[1], 0, del, 0))
+ goto exception;
+
+ add = 0;
+ if (argc > 2)
+ add = argc - 2;
+
+ newlen = len + add - del;
+ if (newlen > MAX_SAFE_INTEGER) {
+ JS_ThrowTypeError(ctx, "invalid array length");
+ goto exception;
+ }
+
+ arr = js_allocate_fast_array(ctx, newlen);
+ if (JS_IsException(arr))
+ goto exception;
+
+ if (newlen <= 0)
+ goto done;
+
+ p = JS_VALUE_GET_OBJ(arr);
+ pval = &p->u.array.u.values[0];
+ last = &p->u.array.u.values[newlen];
+
+ if (js_get_fast_array(ctx, obj, &arrp, &count32) && count32 == len) {
+ for (i = 0; i < start; i++, pval++)
+ *pval = JS_DupValue(ctx, arrp[i]);
+ for (j = 0; j < add; j++, pval++)
+ *pval = JS_DupValue(ctx, argv[2 + j]);
+ for (i += del; i < len; i++, pval++)
+ *pval = JS_DupValue(ctx, arrp[i]);
+ } else {
+ for (i = 0; i < start; i++, pval++)
+ if (-1 == JS_TryGetPropertyInt64(ctx, obj, i, pval))
+ goto exception;
+ for (j = 0; j < add; j++, pval++)
+ *pval = JS_DupValue(ctx, argv[2 + j]);
+ for (i += del; i < len; i++, pval++)
+ if (-1 == JS_TryGetPropertyInt64(ctx, obj, i, pval))
+ goto exception;
+ }
+
+ assert(pval == last);
+
+ if (JS_SetProperty(ctx, arr, JS_ATOM_length, JS_NewInt64(ctx, newlen)) < 0)
+ goto exception;
+
+done:
+ ret = arr;
+ arr = JS_UNDEFINED;
+
+exception:
+ while (pval != last)
+ *pval++ = JS_UNDEFINED;
+
+ JS_FreeValue(ctx, arr);
+ JS_FreeValue(ctx, obj);
+ return ret;
+}
+
static JSValue js_array_copyWithin(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
@@ -39620,6 +40785,68 @@ fail:
return JS_EXCEPTION;
}
+// Note: a.toSorted() is a.slice().sort() with the twist that a.slice()
+// leaves holes in sparse arrays intact whereas a.toSorted() replaces them
+// with undefined, thus in effect creating a dense array.
+// Does not use Array[@@species], always returns a base Array.
+static JSValue js_array_toSorted(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv)
+{
+ JSValue arr, obj, ret, *arrp, *pval;
+ JSObject *p;
+ int64_t i, len;
+ uint32_t count32;
+ int ok;
+
+ ok = JS_IsUndefined(argv[0]) || JS_IsFunction(ctx, argv[0]);
+ if (!ok)
+ return JS_ThrowTypeError(ctx, "not a function");
+
+ ret = JS_EXCEPTION;
+ arr = JS_UNDEFINED;
+ obj = JS_ToObject(ctx, this_val);
+ if (js_get_length64(ctx, &len, obj))
+ goto exception;
+
+ arr = js_allocate_fast_array(ctx, len);
+ if (JS_IsException(arr))
+ goto exception;
+
+ if (len > 0) {
+ p = JS_VALUE_GET_OBJ(arr);
+ i = 0;
+ pval = p->u.array.u.values;
+ if (js_get_fast_array(ctx, obj, &arrp, &count32) && count32 == len) {
+ for (; i < len; i++, pval++)
+ *pval = JS_DupValue(ctx, arrp[i]);
+ } else {
+ for (; i < len; i++, pval++) {
+ if (-1 == JS_TryGetPropertyInt64(ctx, obj, i, pval)) {
+ for (; i < len; i++, pval++)
+ *pval = JS_UNDEFINED;
+ goto exception;
+ }
+ }
+ }
+
+ if (JS_SetProperty(ctx, arr, JS_ATOM_length, JS_NewInt64(ctx, len)) < 0)
+ goto exception;
+ }
+
+ ret = js_array_sort(ctx, arr, argc, argv);
+ if (JS_IsException(ret))
+ goto exception;
+ JS_FreeValue(ctx, ret);
+
+ ret = arr;
+ arr = JS_UNDEFINED;
+
+exception:
+ JS_FreeValue(ctx, arr);
+ JS_FreeValue(ctx, obj);
+ return ret;
+}
+
typedef struct JSArrayIteratorData {
JSValue obj;
JSIteratorKindEnum kind;
@@ -39772,6 +40999,8 @@ static const JSCFunctionListEntry js_iterator_proto_funcs[] = {
};
static const JSCFunctionListEntry js_array_proto_funcs[] = {
+ JS_CFUNC_DEF("at", 1, js_array_at ),
+ JS_CFUNC_DEF("with", 2, js_array_with ),
JS_CFUNC_DEF("concat", 1, js_array_concat ),
JS_CFUNC_MAGIC_DEF("every", 1, js_array_every, special_every ),
JS_CFUNC_MAGIC_DEF("some", 1, js_array_every, special_some ),
@@ -39781,8 +41010,10 @@ static const JSCFunctionListEntry js_array_proto_funcs[] = {
JS_CFUNC_MAGIC_DEF("reduce", 1, js_array_reduce, special_reduce ),
JS_CFUNC_MAGIC_DEF("reduceRight", 1, js_array_reduce, special_reduceRight ),
JS_CFUNC_DEF("fill", 1, js_array_fill ),
- JS_CFUNC_MAGIC_DEF("find", 1, js_array_find, 0 ),
- JS_CFUNC_MAGIC_DEF("findIndex", 1, js_array_find, 1 ),
+ JS_CFUNC_MAGIC_DEF("find", 1, js_array_find, ArrayFind ),
+ JS_CFUNC_MAGIC_DEF("findIndex", 1, js_array_find, ArrayFindIndex ),
+ JS_CFUNC_MAGIC_DEF("findLast", 1, js_array_find, ArrayFindLast ),
+ JS_CFUNC_MAGIC_DEF("findLastIndex", 1, js_array_find, ArrayFindLastIndex ),
JS_CFUNC_DEF("indexOf", 1, js_array_indexOf ),
JS_CFUNC_DEF("lastIndexOf", 1, js_array_lastIndexOf ),
JS_CFUNC_DEF("includes", 1, js_array_includes ),
@@ -39794,9 +41025,12 @@ static const JSCFunctionListEntry js_array_proto_funcs[] = {
JS_CFUNC_MAGIC_DEF("shift", 0, js_array_pop, 1 ),
JS_CFUNC_MAGIC_DEF("unshift", 1, js_array_push, 1 ),
JS_CFUNC_DEF("reverse", 0, js_array_reverse ),
+ JS_CFUNC_DEF("toReversed", 0, js_array_toReversed ),
JS_CFUNC_DEF("sort", 1, js_array_sort ),
+ JS_CFUNC_DEF("toSorted", 1, js_array_toSorted ),
JS_CFUNC_MAGIC_DEF("slice", 2, js_array_slice, 0 ),
JS_CFUNC_MAGIC_DEF("splice", 2, js_array_slice, 1 ),
+ JS_CFUNC_DEF("toSpliced", 2, js_array_toSpliced ),
JS_CFUNC_DEF("copyWithin", 2, js_array_copyWithin ),
JS_CFUNC_MAGIC_DEF("flatMap", 1, js_array_flatten, 1 ),
JS_CFUNC_MAGIC_DEF("flat", 0, js_array_flatten, 0 ),
@@ -39824,17 +41058,19 @@ static JSValue js_number_constructor(JSContext *ctx, JSValueConst new_target,
if (JS_IsException(val))
return val;
switch(JS_VALUE_GET_TAG(val)) {
-#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_INT:
+#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_FLOAT:
+#endif
{
JSBigFloat *p = JS_VALUE_GET_PTR(val);
double d;
bf_get_float64(&p->num, &d, BF_RNDN);
JS_FreeValue(ctx, val);
- val = __JS_NewFloat64(ctx, d);
+ val = JS_NewFloat64(ctx, d);
}
break;
+#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_DECIMAL:
val = JS_ToStringFree(ctx, val);
if (JS_IsException(val))
@@ -39983,8 +41219,16 @@ static JSValue js_number_toString(JSContext *ctx, JSValueConst this_val,
if (base < 0)
goto fail;
}
+ if (JS_VALUE_GET_TAG(val) == JS_TAG_INT) {
+ char buf1[70], *ptr;
+ ptr = i64toa(buf1 + sizeof(buf1), JS_VALUE_GET_INT(val), base);
+ return JS_NewString(ctx, ptr);
+ }
if (JS_ToFloat64Free(ctx, &d, val))
return JS_EXCEPTION;
+ if (base != 10 && isfinite(d)) {
+ return js_dtoa_radix(ctx, d, base);
+ }
return js_dtoa(ctx, d, base, 0, JS_DTOA_VAR_FORMAT);
fail:
JS_FreeValue(ctx, val);
@@ -40008,7 +41252,7 @@ static JSValue js_number_toFixed(JSContext *ctx, JSValueConst this_val,
if (f < 0 || f > 100)
return JS_ThrowRangeError(ctx, "invalid number of digits");
if (fabs(d) >= 1e21) {
- return JS_ToStringFree(ctx, JS_NewFloat64Impl(ctx, d));
+ return JS_ToStringFree(ctx, __JS_NewFloat64(ctx, d));
} else {
return js_dtoa(ctx, d, 10, f, JS_DTOA_FRAC_FORMAT);
}
@@ -40029,7 +41273,7 @@ static JSValue js_number_toExponential(JSContext *ctx, JSValueConst this_val,
if (JS_ToInt32Sat(ctx, &f, argv[0]))
return JS_EXCEPTION;
if (!isfinite(d)) {
- return JS_ToStringFree(ctx, JS_NewFloat64Impl(ctx, d));
+ return JS_ToStringFree(ctx, __JS_NewFloat64(ctx, d));
}
if (JS_IsUndefined(argv[0])) {
flags = 0;
@@ -40061,7 +41305,7 @@ static JSValue js_number_toPrecision(JSContext *ctx, JSValueConst this_val,
return JS_EXCEPTION;
if (!isfinite(d)) {
to_string:
- return JS_ToStringFree(ctx, JS_NewFloat64Impl(ctx, d));
+ return JS_ToStringFree(ctx, __JS_NewFloat64(ctx, d));
}
if (p < 1 || p > 100)
return JS_ThrowRangeError(ctx, "invalid number of digits");
@@ -40182,17 +41426,14 @@ static int js_string_get_own_property(JSContext *ctx,
uint32_t idx, ch;
/* This is a class exotic method: obj class_id is JS_CLASS_STRING */
- if (JS_AtomIsTaggedInt(prop)) {
+ if (__JS_AtomIsTaggedInt(prop)) {
p = JS_VALUE_GET_OBJ(obj);
if (JS_VALUE_GET_TAG(p->u.object_data) == JS_TAG_STRING) {
p1 = JS_VALUE_GET_STRING(p->u.object_data);
- idx = JS_AtomToUInt32(prop);
+ idx = __JS_AtomToUInt32(prop);
if (idx < p1->len) {
if (desc) {
- if (p1->is_wide_char)
- ch = p1->u.str16[idx];
- else
- ch = p1->u.str8[idx];
+ ch = string_get(p1, idx);
desc->flags = JS_PROP_ENUMERABLE;
desc->value = js_new_string_char(ctx, ch);
desc->getter = JS_UNDEFINED;
@@ -40215,8 +41456,8 @@ static int js_string_define_own_property(JSContext *ctx,
JSObject *p;
JSString *p1, *p2;
- if (JS_AtomIsTaggedInt(prop)) {
- idx = JS_AtomToUInt32(prop);
+ if (__JS_AtomIsTaggedInt(prop)) {
+ idx = __JS_AtomToUInt32(prop);
p = JS_VALUE_GET_OBJ(this_obj);
if (JS_VALUE_GET_TAG(p->u.object_data) != JS_TAG_STRING)
goto def;
@@ -40250,8 +41491,8 @@ static int js_string_delete_property(JSContext *ctx,
{
uint32_t idx;
- if (JS_AtomIsTaggedInt(prop)) {
- idx = JS_AtomToUInt32(prop);
+ if (__JS_AtomIsTaggedInt(prop)) {
+ idx = __JS_AtomToUInt32(prop);
if (idx < js_string_obj_get_length(ctx, obj)) {
return FALSE;
}
@@ -40347,7 +41588,7 @@ static JSValue js_string_fromCodePoint(JSContext *ctx, JSValueConst this_val,
} else {
if (JS_ToFloat64(ctx, &d, argv[i]))
goto fail;
- if (d < 0 || d > 0x10ffff || (c = (int)d) != d)
+ if (isnan(d) || d < 0 || d > 0x10ffff || (c = (int)d) != d)
goto range_error;
}
if (string_buffer_putc(b, c))
@@ -40458,10 +41699,7 @@ static JSValue js_string_charCodeAt(JSContext *ctx, JSValueConst this_val,
if (idx < 0 || idx >= p->len) {
ret = JS_NAN;
} else {
- if (p->is_wide_char)
- c = p->u.str16[idx];
- else
- c = p->u.str8[idx];
+ c = string_get(p, idx);
ret = JS_NewInt32(ctx, c);
}
JS_FreeValue(ctx, val);
@@ -40469,7 +41707,7 @@ static JSValue js_string_charCodeAt(JSContext *ctx, JSValueConst this_val,
}
static JSValue js_string_charAt(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
+ int argc, JSValueConst *argv, int is_at)
{
JSValue val, ret;
JSString *p;
@@ -40483,13 +41721,15 @@ static JSValue js_string_charAt(JSContext *ctx, JSValueConst this_val,
JS_FreeValue(ctx, val);
return JS_EXCEPTION;
}
+ if (idx < 0 && is_at)
+ idx += p->len;
if (idx < 0 || idx >= p->len) {
- ret = js_new_string8(ctx, NULL, 0);
- } else {
- if (p->is_wide_char)
- c = p->u.str16[idx];
+ if (is_at)
+ ret = JS_UNDEFINED;
else
- c = p->u.str8[idx];
+ ret = js_new_string8(ctx, NULL, 0);
+ } else {
+ c = string_get(p, idx);
ret = js_new_string_char(ctx, c);
}
JS_FreeValue(ctx, val);
@@ -40597,6 +41837,80 @@ static int64_t string_advance_index(JSString *p, int64_t index, BOOL unicode)
return index;
}
+/* return the position of the first invalid character in the string or
+ -1 if none */
+static int js_string_find_invalid_codepoint(JSString *p)
+{
+ int i;
+ if (!p->is_wide_char)
+ return -1;
+ for(i = 0; i < p->len; i++) {
+ uint32_t c = p->u.str16[i];
+ if (is_surrogate(c)) {
+ if (is_hi_surrogate(c) && (i + 1) < p->len
+ && is_lo_surrogate(p->u.str16[i + 1])) {
+ i++;
+ } else {
+ return i;
+ }
+ }
+ }
+ return -1;
+}
+
+static JSValue js_string_isWellFormed(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv)
+{
+ JSValue str;
+ JSString *p;
+ BOOL ret;
+
+ str = JS_ToStringCheckObject(ctx, this_val);
+ if (JS_IsException(str))
+ return JS_EXCEPTION;
+ p = JS_VALUE_GET_STRING(str);
+ ret = (js_string_find_invalid_codepoint(p) < 0);
+ JS_FreeValue(ctx, str);
+ return JS_NewBool(ctx, ret);
+}
+
+static JSValue js_string_toWellFormed(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv)
+{
+ JSValue str, ret;
+ JSString *p;
+ int i;
+
+ str = JS_ToStringCheckObject(ctx, this_val);
+ if (JS_IsException(str))
+ return JS_EXCEPTION;
+
+ p = JS_VALUE_GET_STRING(str);
+ /* avoid reallocating the string if it is well-formed */
+ i = js_string_find_invalid_codepoint(p);
+ if (i < 0)
+ return str;
+
+ ret = js_new_string16(ctx, p->u.str16, p->len);
+ JS_FreeValue(ctx, str);
+ if (JS_IsException(ret))
+ return JS_EXCEPTION;
+
+ p = JS_VALUE_GET_STRING(ret);
+ for (; i < p->len; i++) {
+ uint32_t c = p->u.str16[i];
+ if (is_surrogate(c)) {
+ if (is_hi_surrogate(c) && (i + 1) < p->len
+ && is_lo_surrogate(p->u.str16[i + 1])) {
+ i++;
+ } else {
+ p->u.str16[i] = 0xFFFD;
+ }
+ }
+ }
+ return ret;
+}
+
static JSValue js_string_indexOf(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv, int lastIndexOf)
{
@@ -40679,7 +41993,7 @@ static JSValue js_string_includes(JSContext *ctx, JSValueConst this_val,
ret = js_is_regexp(ctx, argv[0]);
if (ret) {
if (ret > 0)
- JS_ThrowTypeError(ctx, "regex not supported");
+ JS_ThrowTypeError(ctx, "regexp not supported");
goto fail;
}
v = JS_ToString(ctx, argv[0]);
@@ -40803,7 +42117,7 @@ static JSValue js_string_match(JSContext *ctx, JSValueConst this_val,
JS_FreeValue(ctx, S);
return JS_EXCEPTION;
}
- result = JS_InvokeFree(ctx, rx, atom, 1, &S);
+ result = JS_InvokeFree(ctx, rx, atom, 1, (JSValueConst *)&S);
JS_FreeValue(ctx, S);
return result;
}
@@ -41241,7 +42555,7 @@ static JSValue js_string_pad(JSContext *ctx, JSValueConst this_val,
}
}
if (n > JS_STRING_LEN_MAX) {
- JS_ThrowInternalError(ctx, "string too long");
+ JS_ThrowRangeError(ctx, "invalid string length");
goto fail2;
}
if (string_buffer_init(ctx, b, n))
@@ -41303,8 +42617,9 @@ static JSValue js_string_repeat(JSContext *ctx, JSValueConst this_val,
len = p->len;
if (len == 0 || n == 1)
return str;
+ // XXX: potential arithmetic overflow
if (val * len > JS_STRING_LEN_MAX) {
- JS_ThrowInternalError(ctx, "string too long");
+ JS_ThrowRangeError(ctx, "invalid string length");
goto fail;
}
if (string_buffer_init2(ctx, b, n * len, p->is_wide_char))
@@ -41367,10 +42682,10 @@ static int string_prevc(JSString *p, int *pidx)
idx--;
if (p->is_wide_char) {
c = p->u.str16[idx];
- if (c >= 0xdc00 && c < 0xe000 && idx > 0) {
+ if (is_lo_surrogate(c) && idx > 0) {
c1 = p->u.str16[idx - 1];
- if (c1 >= 0xd800 && c1 <= 0xdc00) {
- c = (((c1 & 0x3ff) << 10) | (c & 0x3ff)) + 0x10000;
+ if (is_hi_surrogate(c1)) {
+ c = from_surrogate(c1, c);
idx--;
}
}
@@ -41409,26 +42724,6 @@ static BOOL test_final_sigma(JSString *p, int sigma_pos)
return !lre_is_cased(c1);
}
-static JSValue js_string_localeCompare(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- JSValue a, b;
- int cmp;
-
- a = JS_ToStringCheckObject(ctx, this_val);
- if (JS_IsException(a))
- return JS_EXCEPTION;
- b = JS_ToString(ctx, argv[0]);
- if (JS_IsException(b)) {
- JS_FreeValue(ctx, a);
- return JS_EXCEPTION;
- }
- cmp = js_string_compare(ctx, JS_VALUE_GET_STRING(a), JS_VALUE_GET_STRING(b));
- JS_FreeValue(ctx, a);
- JS_FreeValue(ctx, b);
- return JS_NewInt32(ctx, cmp);
-}
-
static JSValue js_string_toLowerCase(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv, int to_lower)
{
@@ -41514,23 +42809,38 @@ static JSValue JS_NewUTF32String(JSContext *ctx, const uint32_t *buf, int len)
return JS_EXCEPTION;
}
+static int js_string_normalize1(JSContext *ctx, uint32_t **pout_buf,
+ JSValueConst val,
+ UnicodeNormalizationEnum n_type)
+{
+ int buf_len, out_len;
+ uint32_t *buf, *out_buf;
+
+ buf_len = JS_ToUTF32String(ctx, &buf, val);
+ if (buf_len < 0)
+ return -1;
+ out_len = unicode_normalize(&out_buf, buf, buf_len, n_type,
+ ctx->rt, (DynBufReallocFunc *)js_realloc_rt);
+ js_free(ctx, buf);
+ if (out_len < 0)
+ return -1;
+ *pout_buf = out_buf;
+ return out_len;
+}
+
static JSValue js_string_normalize(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
const char *form, *p;
size_t form_len;
- int is_compat, buf_len, out_len;
+ int is_compat, out_len;
UnicodeNormalizationEnum n_type;
JSValue val;
- uint32_t *buf, *out_buf;
+ uint32_t *out_buf;
val = JS_ToStringCheckObject(ctx, this_val);
if (JS_IsException(val))
return val;
- buf_len = JS_ToUTF32String(ctx, &buf, val);
- JS_FreeValue(ctx, val);
- if (buf_len < 0)
- return JS_EXCEPTION;
if (argc == 0 || JS_IsUndefined(argv[0])) {
n_type = UNICODE_NFC;
@@ -41556,22 +42866,96 @@ static JSValue js_string_normalize(JSContext *ctx, JSValueConst this_val,
JS_FreeCString(ctx, form);
JS_ThrowRangeError(ctx, "bad normalization form");
fail1:
- js_free(ctx, buf);
+ JS_FreeValue(ctx, val);
return JS_EXCEPTION;
}
JS_FreeCString(ctx, form);
}
- out_len = unicode_normalize(&out_buf, buf, buf_len, n_type,
- ctx->rt, (DynBufReallocFunc *)js_realloc_rt);
- js_free(ctx, buf);
+ out_len = js_string_normalize1(ctx, &out_buf, val, n_type);
+ JS_FreeValue(ctx, val);
if (out_len < 0)
return JS_EXCEPTION;
val = JS_NewUTF32String(ctx, out_buf, out_len);
js_free(ctx, out_buf);
return val;
}
-#endif /* CONFIG_ALL_UNICODE */
+
+/* return < 0, 0 or > 0 */
+static int js_UTF32_compare(const uint32_t *buf1, int buf1_len,
+ const uint32_t *buf2, int buf2_len)
+{
+ int i, len, c, res;
+ len = min_int(buf1_len, buf2_len);
+ for(i = 0; i < len; i++) {
+ /* Note: range is limited so a subtraction is valid */
+ c = buf1[i] - buf2[i];
+ if (c != 0)
+ return c;
+ }
+ if (buf1_len == buf2_len)
+ res = 0;
+ else if (buf1_len < buf2_len)
+ res = -1;
+ else
+ res = 1;
+ return res;
+}
+
+static JSValue js_string_localeCompare(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv)
+{
+ JSValue a, b;
+ int cmp, a_len, b_len;
+ uint32_t *a_buf, *b_buf;
+
+ a = JS_ToStringCheckObject(ctx, this_val);
+ if (JS_IsException(a))
+ return JS_EXCEPTION;
+ b = JS_ToString(ctx, argv[0]);
+ if (JS_IsException(b)) {
+ JS_FreeValue(ctx, a);
+ return JS_EXCEPTION;
+ }
+ a_len = js_string_normalize1(ctx, &a_buf, a, UNICODE_NFC);
+ JS_FreeValue(ctx, a);
+ if (a_len < 0) {
+ JS_FreeValue(ctx, b);
+ return JS_EXCEPTION;
+ }
+
+ b_len = js_string_normalize1(ctx, &b_buf, b, UNICODE_NFC);
+ JS_FreeValue(ctx, b);
+ if (b_len < 0) {
+ js_free(ctx, a_buf);
+ return JS_EXCEPTION;
+ }
+ cmp = js_UTF32_compare(a_buf, a_len, b_buf, b_len);
+ js_free(ctx, a_buf);
+ js_free(ctx, b_buf);
+ return JS_NewInt32(ctx, cmp);
+}
+#else /* CONFIG_ALL_UNICODE */
+static JSValue js_string_localeCompare(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv)
+{
+ JSValue a, b;
+ int cmp;
+
+ a = JS_ToStringCheckObject(ctx, this_val);
+ if (JS_IsException(a))
+ return JS_EXCEPTION;
+ b = JS_ToString(ctx, argv[0]);
+ if (JS_IsException(b)) {
+ JS_FreeValue(ctx, a);
+ return JS_EXCEPTION;
+ }
+ cmp = js_string_compare(ctx, JS_VALUE_GET_STRING(a), JS_VALUE_GET_STRING(b));
+ JS_FreeValue(ctx, a);
+ JS_FreeValue(ctx, b);
+ return JS_NewInt32(ctx, cmp);
+}
+#endif /* !CONFIG_ALL_UNICODE */
/* also used for String.prototype.valueOf */
static JSValue js_string_toString(JSContext *ctx, JSValueConst this_val,
@@ -41743,10 +43127,13 @@ static const JSCFunctionListEntry js_string_funcs[] = {
static const JSCFunctionListEntry js_string_proto_funcs[] = {
JS_PROP_INT32_DEF("length", 0, JS_PROP_CONFIGURABLE ),
+ JS_CFUNC_MAGIC_DEF("at", 1, js_string_charAt, 1 ),
JS_CFUNC_DEF("charCodeAt", 1, js_string_charCodeAt ),
- JS_CFUNC_DEF("charAt", 1, js_string_charAt ),
+ JS_CFUNC_MAGIC_DEF("charAt", 1, js_string_charAt, 0 ),
JS_CFUNC_DEF("concat", 1, js_string_concat ),
JS_CFUNC_DEF("codePointAt", 1, js_string_codePointAt ),
+ JS_CFUNC_DEF("isWellFormed", 0, js_string_isWellFormed ),
+ JS_CFUNC_DEF("toWellFormed", 0, js_string_toWellFormed ),
JS_CFUNC_MAGIC_DEF("indexOf", 1, js_string_indexOf, 0 ),
JS_CFUNC_MAGIC_DEF("lastIndexOf", 1, js_string_indexOf, 1 ),
JS_CFUNC_MAGIC_DEF("includes", 1, js_string_includes, 0 ),
@@ -41852,7 +43239,7 @@ static JSValue js_math_min_max(JSContext *ctx, JSValueConst this_val,
uint32_t tag;
if (unlikely(argc == 0)) {
- return JS_NewFloat64Impl(ctx, is_max ? INFINITY : -INFINITY);
+ return __JS_NewFloat64(ctx, is_max ? INFINITY : -INFINITY);
}
tag = JS_VALUE_GET_TAG(argv[0]);
@@ -41966,14 +43353,16 @@ static double js_math_fround(double a)
static JSValue js_math_imul(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
- int a, b;
+ uint32_t a, b, c;
+ int32_t d;
- if (JS_ToInt32(ctx, &a, argv[0]))
+ if (JS_ToUint32(ctx, &a, argv[0]))
return JS_EXCEPTION;
- if (JS_ToInt32(ctx, &b, argv[1]))
+ if (JS_ToUint32(ctx, &b, argv[1]))
return JS_EXCEPTION;
- /* purposely ignoring overflow */
- return JS_NewInt32(ctx, a * b);
+ c = a * b;
+ memcpy(&d, &c, sizeof(d));
+ return JS_NewInt32(ctx, d);
}
static JSValue js_math_clz32(JSContext *ctx, JSValueConst this_val,
@@ -42025,7 +43414,7 @@ static JSValue js_math_random(JSContext *ctx, JSValueConst this_val,
v = xorshift64star(&ctx->random_state);
/* 1.0 <= u.d < 2 */
u.u64 = ((uint64_t)0x3ff << 52) | (v >> 12);
- return JS_NewFloat64Impl(ctx, u.d - 1.0);
+ return __JS_NewFloat64(ctx, u.d - 1.0);
}
// MSVC inexplicably refuses to initialize the array below with
@@ -42089,47 +43478,12 @@ static const JSCFunctionListEntry js_math_obj[] = {
/* Date */
-#if 0
-/* OS dependent: return the UTC time in ms since 1970. */
-static JSValue js___date_now(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- int64_t d;
- struct timeval tv;
- gettimeofday(&tv, NULL);
- d = (int64_t)tv.tv_sec * 1000 + (tv.tv_usec / 1000);
- return JS_NewInt64(ctx, d);
-}
-#endif
-
-/* OS dependent: return the UTC time in microseconds since 1970. */
-// FIXME: Unused, remove?
-static JSValue js___date_clock(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
-{
- int64_t d;
-#ifdef _MSC_VER
- SYSTEMTIME st;
- GetSystemTime(&st);
- SystemTimeToFileTime(&st, (FILETIME *) &d);
- d /= 10;
-#else
- struct timeval tv;
- gettimeofday(&tv, NULL);
- d = (int64_t)tv.tv_sec * 1000000 + tv.tv_usec;
-#endif
- return JS_NewInt64(ctx, d);
-}
-
/* OS dependent. d = argv[0] is in ms from 1970. Return the difference
between UTC time and local time 'd' in minutes */
-static int getTimezoneOffset(int64_t time) {
-#if defined(_WIN32)
- /* XXX: TODO */
- return 0;
-#else
+static int getTimezoneOffset(int64_t time)
+{
time_t ti;
- struct tm tm;
+ int res;
time /= 1000; /* convert to seconds */
if (sizeof(time_t) == 4) {
@@ -42153,9 +43507,27 @@ static int getTimezoneOffset(int64_t time) {
}
}
ti = time;
- localtime_r(&ti, &tm);
- return -tm.tm_gmtoff / 60;
+#if defined(_WIN32)
+ {
+ struct tm *tm;
+ time_t gm_ti, loc_ti;
+
+ tm = gmtime(&ti);
+ gm_ti = mktime(tm);
+
+ tm = localtime(&ti);
+ loc_ti = mktime(tm);
+
+ res = (gm_ti - loc_ti) / 60;
+ }
+#else
+ {
+ struct tm tm;
+ localtime_r(&ti, &tm);
+ res = -tm.tm_gmtoff / 60;
+ }
#endif
+ return res;
}
#if 0
@@ -42167,7 +43539,7 @@ static JSValue js___date_getTimezoneOffset(JSContext *ctx, JSValueConst this_val
if (JS_ToFloat64(ctx, &dd, argv[0]))
return JS_EXCEPTION;
if (isnan(dd))
- return __JS_NewFloat64(ctx, dd);
+ return JS_NewFloat64(ctx, dd);
else
return JS_NewInt32(ctx, getTimezoneOffset((int64_t)dd));
}
@@ -42232,6 +43604,9 @@ static JSValue js_compile_regexp(JSContext *ctx, JSValueConst pattern,
/* XXX: re_flags = LRE_FLAG_OCTAL unless strict mode? */
for (i = 0; i < len; i++) {
switch(str[i]) {
+ case 'd':
+ mask = LRE_FLAG_INDICES;
+ break;
case 'g':
mask = LRE_FLAG_GLOBAL;
break;
@@ -42245,7 +43620,7 @@ static JSValue js_compile_regexp(JSContext *ctx, JSValueConst pattern,
mask = LRE_FLAG_DOTALL;
break;
case 'u':
- mask = LRE_FLAG_UTF16;
+ mask = LRE_FLAG_UNICODE;
break;
case 'y':
mask = LRE_FLAG_STICKY;
@@ -42263,7 +43638,7 @@ static JSValue js_compile_regexp(JSContext *ctx, JSValueConst pattern,
JS_FreeCString(ctx, str);
}
- str = JS_ToCStringLen2(ctx, &len, pattern, !(re_flags & LRE_FLAG_UTF16));
+ str = JS_ToCStringLen2(ctx, &len, pattern, !(re_flags & LRE_FLAG_UNICODE));
if (!str)
return JS_EXCEPTION;
re_bytecode_buf = lre_compile(&re_bytecode_len, error_msg,
@@ -42564,7 +43939,7 @@ static JSValue js_regexp_get_flag(JSContext *ctx, JSValueConst this_val, int mas
}
flags = lre_get_flags(re->bytecode->u.str8);
- return JS_NewBool(ctx, (flags & mask) != 0);
+ return JS_NewBool(ctx, flags & mask);
}
static JSValue js_regexp_get_flags(JSContext *ctx, JSValueConst this_val)
@@ -42575,6 +43950,11 @@ static JSValue js_regexp_get_flags(JSContext *ctx, JSValueConst this_val)
if (JS_VALUE_GET_TAG(this_val) != JS_TAG_OBJECT)
return JS_ThrowTypeErrorNotAnObject(ctx);
+ res = JS_ToBoolFree(ctx, JS_GetPropertyStr(ctx, this_val, "hasIndices"));
+ if (res < 0)
+ goto exception;
+ if (res)
+ *p++ = 'd';
res = JS_ToBoolFree(ctx, JS_GetProperty(ctx, this_val, JS_ATOM_global));
if (res < 0)
goto exception;
@@ -42654,25 +44034,32 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val,
{
JSRegExp *re = js_get_regexp(ctx, this_val, TRUE);
JSString *str;
- JSValue str_val, obj, val, groups = JS_UNDEFINED;
+ JSValue t, ret, str_val, obj, val, groups;
+ JSValue indices, indices_groups;
uint8_t *re_bytecode;
- int ret;
uint8_t **capture, *str_buf;
- int capture_count, shift, i, re_flags;
+ int rc, capture_count, shift, i, re_flags;
int64_t last_index;
const char *group_name_ptr;
if (!re)
return JS_EXCEPTION;
+
str_val = JS_ToString(ctx, argv[0]);
if (JS_IsException(str_val))
- return str_val;
- val = JS_GetProperty(ctx, this_val, JS_ATOM_lastIndex);
- if (JS_IsException(val) ||
- JS_ToLengthFree(ctx, &last_index, val)) {
- JS_FreeValue(ctx, str_val);
return JS_EXCEPTION;
- }
+
+ ret = JS_EXCEPTION;
+ obj = JS_NULL;
+ groups = JS_UNDEFINED;
+ indices = JS_UNDEFINED;
+ indices_groups = JS_UNDEFINED;
+ capture = NULL;
+
+ val = JS_GetProperty(ctx, this_val, JS_ATOM_lastIndex);
+ if (JS_IsException(val) || JS_ToLengthFree(ctx, &last_index, val))
+ goto fail;
+
re_bytecode = re->bytecode->u.str8;
re_flags = lre_get_flags(re_bytecode);
if ((re_flags & (LRE_FLAG_GLOBAL | LRE_FLAG_STICKY)) == 0) {
@@ -42680,27 +44067,23 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val,
}
str = JS_VALUE_GET_STRING(str_val);
capture_count = lre_get_capture_count(re_bytecode);
- capture = NULL;
if (capture_count > 0) {
capture = js_malloc(ctx, sizeof(capture[0]) * capture_count * 2);
- if (!capture) {
- JS_FreeValue(ctx, str_val);
- return JS_EXCEPTION;
- }
+ if (!capture)
+ goto fail;
}
shift = str->is_wide_char;
str_buf = str->u.str8;
if (last_index > str->len) {
- ret = 2;
+ rc = 2;
} else {
- ret = lre_exec(capture, re_bytecode,
- str_buf, last_index, str->len,
- shift, ctx);
+ rc = lre_exec(capture, re_bytecode,
+ str_buf, last_index, str->len,
+ shift, ctx);
}
- obj = JS_NULL;
- if (ret != 1) {
- if (ret >= 0) {
- if (ret == 2 || (re_flags & (LRE_FLAG_GLOBAL | LRE_FLAG_STICKY))) {
+ if (rc != 1) {
+ if (rc >= 0) {
+ if (rc == 2 || (re_flags & (LRE_FLAG_GLOBAL | LRE_FLAG_STICKY))) {
if (JS_SetProperty(ctx, this_val, JS_ATOM_lastIndex,
JS_NewInt32(ctx, 0)) < 0)
goto fail;
@@ -42709,7 +44092,6 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val,
JS_ThrowInternalError(ctx, "out of memory in regexp execution");
goto fail;
}
- JS_FreeValue(ctx, str_val);
} else {
int prop_flags;
if (re_flags & (LRE_FLAG_GLOBAL | LRE_FLAG_STICKY)) {
@@ -42727,52 +44109,124 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val,
if (JS_IsException(groups))
goto fail;
}
+ if (re_flags & LRE_FLAG_INDICES) {
+ indices = JS_NewArray(ctx);
+ if (JS_IsException(indices))
+ goto fail;
+ if (group_name_ptr) {
+ indices_groups = JS_NewObjectProto(ctx, JS_NULL);
+ if (JS_IsException(indices_groups))
+ goto fail;
+ }
+ }
for(i = 0; i < capture_count; i++) {
- int start, end;
+ const char *name = NULL;
+ uint8_t **match = &capture[2 * i];
+ int start = -1;
+ int end = -1;
JSValue val;
- if (capture[2 * i] == NULL ||
- capture[2 * i + 1] == NULL) {
+
+ if (group_name_ptr && i > 0) {
+ if (*group_name_ptr) name = group_name_ptr;
+ group_name_ptr += strlen(group_name_ptr) + 1;
+ }
+
+ if (match[0] && match[1]) {
+ start = (match[0] - str_buf) >> shift;
+ end = (match[1] - str_buf) >> shift;
+ }
+
+ if (!JS_IsUndefined(indices)) {
val = JS_UNDEFINED;
- } else {
- start = (capture[2 * i] - str_buf) >> shift;
- end = (capture[2 * i + 1] - str_buf) >> shift;
+ if (start != -1) {
+ val = JS_NewArray(ctx);
+ if (JS_IsException(val))
+ goto fail;
+ if (JS_DefinePropertyValueUint32(ctx, val, 0,
+ JS_NewInt32(ctx, start),
+ prop_flags) < 0) {
+ JS_FreeValue(ctx, val);
+ goto fail;
+ }
+ if (JS_DefinePropertyValueUint32(ctx, val, 1,
+ JS_NewInt32(ctx, end),
+ prop_flags) < 0) {
+ JS_FreeValue(ctx, val);
+ goto fail;
+ }
+ }
+ if (name && !JS_IsUndefined(indices_groups)) {
+ val = JS_DupValue(ctx, val);
+ if (JS_DefinePropertyValueStr(ctx, indices_groups,
+ name, val, prop_flags) < 0) {
+ JS_FreeValue(ctx, val);
+ goto fail;
+ }
+ }
+ if (JS_DefinePropertyValueUint32(ctx, indices, i, val,
+ prop_flags) < 0) {
+ goto fail;
+ }
+ }
+
+ val = JS_UNDEFINED;
+ if (start != -1) {
val = js_sub_string(ctx, str, start, end);
if (JS_IsException(val))
goto fail;
}
- if (group_name_ptr && i > 0) {
- if (*group_name_ptr) {
- if (JS_DefinePropertyValueStr(ctx, groups, group_name_ptr,
- JS_DupValue(ctx, val),
- prop_flags) < 0) {
- JS_FreeValue(ctx, val);
- goto fail;
- }
+
+ if (name) {
+ if (JS_DefinePropertyValueStr(ctx, groups, name,
+ JS_DupValue(ctx, val),
+ prop_flags) < 0) {
+ JS_FreeValue(ctx, val);
+ goto fail;
}
- group_name_ptr += strlen(group_name_ptr) + 1;
}
+
if (JS_DefinePropertyValueUint32(ctx, obj, i, val, prop_flags) < 0)
goto fail;
}
+
+ t = groups, groups = JS_UNDEFINED;
if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_groups,
- groups, prop_flags) < 0)
+ t, prop_flags) < 0) {
goto fail;
- if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_index,
- JS_NewInt32(ctx, (capture[0] - str_buf) >> shift), prop_flags) < 0)
+ }
+
+ t = JS_NewInt32(ctx, (capture[0] - str_buf) >> shift);
+ if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_index, t, prop_flags) < 0)
goto fail;
- if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_input, str_val, prop_flags) < 0)
- goto fail1;
+
+ t = str_val, str_val = JS_UNDEFINED;
+ if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_input, t, prop_flags) < 0)
+ goto fail;
+
+ if (!JS_IsUndefined(indices)) {
+ t = indices_groups, indices_groups = JS_UNDEFINED;
+ if (JS_DefinePropertyValue(ctx, indices, JS_ATOM_groups,
+ t, prop_flags) < 0) {
+ goto fail;
+ }
+ t = indices, indices = JS_UNDEFINED;
+ if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_indices,
+ t, prop_flags) < 0) {
+ goto fail;
+ }
+ }
}
- js_free(ctx, capture);
- return obj;
+ ret = obj;
+ obj = JS_UNDEFINED;
fail:
- JS_FreeValue(ctx, groups);
+ JS_FreeValue(ctx, indices_groups);
+ JS_FreeValue(ctx, indices);
JS_FreeValue(ctx, str_val);
-fail1:
+ JS_FreeValue(ctx, groups);
JS_FreeValue(ctx, obj);
js_free(ctx, capture);
- return JS_EXCEPTION;
+ return ret;
}
/* delete portions of a string that match a given regex */
@@ -42851,7 +44305,7 @@ static JSValue JS_RegExpDelete(JSContext *ctx, JSValueConst this_val, JSValueCon
break;
}
if (end == start) {
- if (!(re_flags & LRE_FLAG_UTF16) || (unsigned)end >= str->len || !str->is_wide_char) {
+ if (!(re_flags & LRE_FLAG_UNICODE) || (unsigned)end >= str->len || !str->is_wide_char) {
end++;
} else {
string_getc(str, &end);
@@ -42924,7 +44378,7 @@ static JSValue js_regexp_Symbol_match(JSContext *ctx, JSValueConst this_val,
{
// [Symbol.match](str)
JSValueConst rx = this_val;
- JSValue A, S, result, matchStr;
+ JSValue A, S, flags, result, matchStr;
int global, n, fullUnicode, isEmpty;
JSString *p;
@@ -42932,16 +44386,23 @@ static JSValue js_regexp_Symbol_match(JSContext *ctx, JSValueConst this_val,
return JS_ThrowTypeErrorNotAnObject(ctx);
A = JS_UNDEFINED;
+ flags = JS_UNDEFINED;
result = JS_UNDEFINED;
matchStr = JS_UNDEFINED;
S = JS_ToString(ctx, argv[0]);
if (JS_IsException(S))
goto exception;
- global = JS_ToBoolFree(ctx, JS_GetProperty(ctx, rx, JS_ATOM_global));
- if (global < 0)
+ flags = JS_GetProperty(ctx, rx, JS_ATOM_flags);
+ if (JS_IsException(flags))
+ goto exception;
+ flags = JS_ToStringFree(ctx, flags);
+ if (JS_IsException(flags))
goto exception;
+ p = JS_VALUE_GET_STRING(flags);
+ // TODO(bnoordhuis) query 'u' flag the same way?
+ global = (-1 != string_indexof_char(p, 'g', 0));
if (!global) {
A = JS_RegExpExec(ctx, rx, S);
} else {
@@ -42985,12 +44446,14 @@ static JSValue js_regexp_Symbol_match(JSContext *ctx, JSValueConst this_val,
}
}
JS_FreeValue(ctx, result);
+ JS_FreeValue(ctx, flags);
JS_FreeValue(ctx, S);
return A;
exception:
JS_FreeValue(ctx, A);
JS_FreeValue(ctx, result);
+ JS_FreeValue(ctx, flags);
JS_FreeValue(ctx, S);
return JS_EXCEPTION;
}
@@ -43233,8 +44696,8 @@ static JSValue js_regexp_Symbol_replace(JSContext *ctx, JSValueConst this_val,
// [Symbol.replace](str, rep)
JSValueConst rx = this_val, rep = argv[1];
JSValueConst args[6];
- JSValue str, rep_val, matched, tab, rep_str, namedCaptures, res;
- JSString *sp, *rp;
+ JSValue flags, str, rep_val, matched, tab, rep_str, namedCaptures, res;
+ JSString *p, *sp, *rp;
StringBuffer b_s, *b = &b_s;
ValueBuffer v_b, *results = &v_b;
int nextSourcePosition, n, j, functionalReplace, is_global, fullUnicode;
@@ -43250,6 +44713,7 @@ static JSValue js_regexp_Symbol_replace(JSContext *ctx, JSValueConst this_val,
rep_val = JS_UNDEFINED;
matched = JS_UNDEFINED;
tab = JS_UNDEFINED;
+ flags = JS_UNDEFINED;
rep_str = JS_UNDEFINED;
namedCaptures = JS_UNDEFINED;
@@ -43266,10 +44730,18 @@ static JSValue js_regexp_Symbol_replace(JSContext *ctx, JSValueConst this_val,
goto exception;
rp = JS_VALUE_GET_STRING(rep_val);
}
- fullUnicode = 0;
- is_global = JS_ToBoolFree(ctx, JS_GetProperty(ctx, rx, JS_ATOM_global));
- if (is_global < 0)
+
+ flags = JS_GetProperty(ctx, rx, JS_ATOM_flags);
+ if (JS_IsException(flags))
goto exception;
+ flags = JS_ToStringFree(ctx, flags);
+ if (JS_IsException(flags))
+ goto exception;
+ p = JS_VALUE_GET_STRING(flags);
+
+ // TODO(bnoordhuis) query 'u' flag the same way?
+ fullUnicode = 0;
+ is_global = (-1 != string_indexof_char(p, 'g', 0));
if (is_global) {
fullUnicode = JS_ToBoolFree(ctx, JS_GetProperty(ctx, rx, JS_ATOM_unicode));
if (fullUnicode < 0)
@@ -43403,6 +44875,7 @@ done1:
value_buffer_free(results);
JS_FreeValue(ctx, rep_val);
JS_FreeValue(ctx, matched);
+ JS_FreeValue(ctx, flags);
JS_FreeValue(ctx, tab);
JS_FreeValue(ctx, rep_str);
JS_FreeValue(ctx, namedCaptures);
@@ -43603,12 +45076,13 @@ static const JSCFunctionListEntry js_regexp_funcs[] = {
static const JSCFunctionListEntry js_regexp_proto_funcs[] = {
JS_CGETSET_DEF("flags", js_regexp_get_flags, NULL ),
JS_CGETSET_DEF("source", js_regexp_get_source, NULL ),
- JS_CGETSET_MAGIC_DEF("global", js_regexp_get_flag, NULL, 1 ),
- JS_CGETSET_MAGIC_DEF("ignoreCase", js_regexp_get_flag, NULL, 2 ),
- JS_CGETSET_MAGIC_DEF("multiline", js_regexp_get_flag, NULL, 4 ),
- JS_CGETSET_MAGIC_DEF("dotAll", js_regexp_get_flag, NULL, 8 ),
- JS_CGETSET_MAGIC_DEF("unicode", js_regexp_get_flag, NULL, 16 ),
- JS_CGETSET_MAGIC_DEF("sticky", js_regexp_get_flag, NULL, 32 ),
+ JS_CGETSET_MAGIC_DEF("global", js_regexp_get_flag, NULL, LRE_FLAG_GLOBAL ),
+ JS_CGETSET_MAGIC_DEF("ignoreCase", js_regexp_get_flag, NULL, LRE_FLAG_IGNORECASE ),
+ JS_CGETSET_MAGIC_DEF("multiline", js_regexp_get_flag, NULL, LRE_FLAG_MULTILINE ),
+ JS_CGETSET_MAGIC_DEF("dotAll", js_regexp_get_flag, NULL, LRE_FLAG_DOTALL ),
+ JS_CGETSET_MAGIC_DEF("unicode", js_regexp_get_flag, NULL, LRE_FLAG_UNICODE ),
+ JS_CGETSET_MAGIC_DEF("sticky", js_regexp_get_flag, NULL, LRE_FLAG_STICKY ),
+ JS_CGETSET_MAGIC_DEF("hasIndices", js_regexp_get_flag, NULL, LRE_FLAG_INDICES ),
JS_CFUNC_DEF("exec", 1, js_regexp_exec ),
JS_CFUNC_DEF("compile", 2, js_regexp_compile ),
JS_CFUNC_DEF("test", 1, js_regexp_test ),
@@ -43766,7 +45240,7 @@ static JSValue json_parse_value(JSParseState *s)
case TOK_IDENT:
if (s->token.u.ident.atom == JS_ATOM_false ||
s->token.u.ident.atom == JS_ATOM_true) {
- val = JS_NewBool(ctx, (s->token.u.ident.atom == JS_ATOM_true));
+ val = JS_NewBool(ctx, s->token.u.ident.atom == JS_ATOM_true);
} else if (s->token.u.ident.atom == JS_ATOM_null) {
val = JS_NULL;
} else {
@@ -43778,7 +45252,7 @@ static JSValue json_parse_value(JSParseState *s)
default:
def_token:
if (s->token.val == TOK_EOF) {
- js_parse_error(s, "unexpected end of input");
+ js_parse_error(s, "Unexpected end of JSON input");
} else {
js_parse_error(s, "unexpected token: '%.*s'",
(int)(s->buf_ptr - s->token.ptr), s->token.ptr);
@@ -43945,24 +45419,27 @@ static JSValue js_json_check(JSContext *ctx, JSONStringifyContext *jsc,
JSValue v;
JSValueConst args[2];
- if (JS_IsObject(val)
+ /* check for object.toJSON method */
+ /* ECMA specifies this is done only for Object and BigInt */
+ /* we do it for BigFloat and BigDecimal as an extension */
+ if (JS_IsObject(val) || JS_IsBigInt(ctx, val)
#ifdef CONFIG_BIGNUM
- || JS_IsBigInt(ctx, val) /* XXX: probably useless */
+ || JS_IsBigFloat(val) || JS_IsBigDecimal(val)
#endif
) {
- JSValue f = JS_GetProperty(ctx, val, JS_ATOM_toJSON);
- if (JS_IsException(f))
+ JSValue f = JS_GetProperty(ctx, val, JS_ATOM_toJSON);
+ if (JS_IsException(f))
+ goto exception;
+ if (JS_IsFunction(ctx, f)) {
+ v = JS_CallFree(ctx, f, val, 1, &key);
+ JS_FreeValue(ctx, val);
+ val = v;
+ if (JS_IsException(val))
goto exception;
- if (JS_IsFunction(ctx, f)) {
- v = JS_CallFree(ctx, f, val, 1, &key);
- JS_FreeValue(ctx, val);
- val = v;
- if (JS_IsException(val))
- goto exception;
- } else {
- JS_FreeValue(ctx, f);
- }
+ } else {
+ JS_FreeValue(ctx, f);
}
+ }
if (!JS_IsUndefined(jsc->replacer_func)) {
args[0] = key;
@@ -43981,13 +45458,12 @@ static JSValue js_json_check(JSContext *ctx, JSONStringifyContext *jsc,
case JS_TAG_STRING:
case JS_TAG_INT:
case JS_TAG_FLOAT64:
-#ifdef CONFIG_BIGNUM
- case JS_TAG_BIG_FLOAT:
-#endif
case JS_TAG_BOOL:
case JS_TAG_NULL:
-#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_INT:
+#ifdef CONFIG_BIGNUM
+ case JS_TAG_BIG_FLOAT:
+ case JS_TAG_BIG_DECIMAL:
#endif
case JS_TAG_EXCEPTION:
return val;
@@ -44018,37 +45494,31 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc,
tab = JS_UNDEFINED;
prop = JS_UNDEFINED;
- switch (JS_VALUE_GET_NORM_TAG(val)) {
- case JS_TAG_OBJECT:
+ if (JS_IsObject(val)) {
p = JS_VALUE_GET_OBJ(val);
cl = p->class_id;
if (cl == JS_CLASS_STRING) {
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);
+ goto concat_primitive;
} 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;
- }
+ goto concat_primitive;
+ } else if (cl == JS_CLASS_BOOLEAN || cl == JS_CLASS_BIG_INT
#ifdef CONFIG_BIGNUM
- else if (cl == JS_CLASS_BIG_FLOAT) {
- return string_buffer_concat_value_free(jsc->b, val);
- } else if (cl == JS_CLASS_BIG_INT) {
- JS_ThrowTypeError(ctx, "bigint are forbidden in JSON.stringify");
- goto exception;
- }
+ || cl == JS_CLASS_BIG_FLOAT
+ || cl == JS_CLASS_BIG_DECIMAL
#endif
- v = js_array_includes(ctx, jsc->stack, 1, &val);
+ )
+ {
+ /* This will thow the same error as for the primitive object */
+ set_value(ctx, &val, JS_DupValue(ctx, p->u.object_data));
+ goto concat_primitive;
+ }
+ v = js_array_includes(ctx, jsc->stack, 1, (JSValueConst *)&val);
if (JS_IsException(v))
goto exception;
if (JS_ToBoolFree(ctx, v)) {
@@ -44069,7 +45539,7 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc,
sep = JS_DupValue(ctx, jsc->empty);
sep1 = JS_DupValue(ctx, jsc->empty);
}
- v = js_array_push(ctx, jsc->stack, 1, &val, 0);
+ v = js_array_push(ctx, jsc->stack, 1, (JSValueConst *)&val, 0);
if (check_exception_free(ctx, v))
goto exception;
ret = JS_IsArray(ctx, val);
@@ -44109,7 +45579,7 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc,
if (!JS_IsUndefined(jsc->property_list))
tab = JS_DupValue(ctx, jsc->property_list);
else
- tab = js_object_keys(ctx, JS_UNDEFINED, 1, &val, JS_ITERATOR_KIND_KEY);
+ tab = js_object_keys(ctx, JS_UNDEFINED, 1, (JSValueConst *)&val, JS_ITERATOR_KIND_KEY);
if (JS_IsException(tab))
goto exception;
if (js_get_length64(ctx, &len, tab))
@@ -44144,7 +45614,7 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc,
has_content = TRUE;
}
}
- if (has_content && JS_VALUE_GET_STRING(jsc->gap)->len != 0) {
+ if (has_content && !JS_IsEmptyString(jsc->gap)) {
string_buffer_putc8(jsc->b, '\n');
string_buffer_concat_value(jsc->b, indent);
}
@@ -44159,6 +45629,9 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc,
JS_FreeValue(ctx, indent1);
JS_FreeValue(ctx, prop);
return 0;
+ }
+ concat_primitive:
+ switch (JS_VALUE_GET_NORM_TAG(val)) {
case JS_TAG_STRING:
val = JS_ToQuotedStringFree(ctx, val);
if (JS_IsException(val))
@@ -44170,18 +45643,18 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc,
}
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:
- JS_ThrowTypeError(ctx, "bigint are forbidden in JSON.stringify");
- goto exception;
+#ifdef CONFIG_BIGNUM
+ case JS_TAG_BIG_FLOAT:
+ case JS_TAG_BIG_DECIMAL:
#endif
+ /* reject big numbers: use toJSON method to override */
+ JS_ThrowTypeError(ctx, "Do not know how to serialize a BigInt");
+ goto exception;
default:
JS_FreeValue(ctx, val);
return 0;
@@ -44257,7 +45730,7 @@ JSValue JS_JSONStringify(JSContext *ctx, JSValueConst obj,
continue;
}
present = js_array_includes(ctx, jsc->property_list,
- 1, &v);
+ 1, (JSValueConst *)&v);
if (JS_IsException(present)) {
JS_FreeValue(ctx, v);
goto exception;
@@ -44381,7 +45854,7 @@ static JSValue js_reflect_construct(JSContext *ctx, JSValueConst this_val,
tab = build_arg_list(ctx, &len, array_arg);
if (!tab)
return JS_EXCEPTION;
- ret = JS_CallConstructor2(ctx, func, new_target, len, tab);
+ ret = JS_CallConstructor2(ctx, func, new_target, len, (JSValueConst *)tab);
free_arg_list(ctx, tab, len);
return ret;
}
@@ -44471,8 +45944,8 @@ static JSValue js_reflect_set(JSContext *ctx, JSValueConst this_val,
atom = JS_ValueToAtom(ctx, prop);
if (unlikely(atom == JS_ATOM_NULL))
return JS_EXCEPTION;
- ret = JS_SetPropertyGeneric(ctx, obj, atom,
- JS_DupValue(ctx, val), receiver, 0);
+ ret = JS_SetPropertyInternal(ctx, obj, atom,
+ JS_DupValue(ctx, val), receiver, 0);
JS_FreeAtom(ctx, atom);
if (ret < 0)
return JS_EXCEPTION;
@@ -44586,7 +46059,7 @@ static JSValue js_proxy_getPrototypeOf(JSContext *ctx, JSValueConst obj)
return JS_EXCEPTION;
if (JS_IsUndefined(method))
return JS_GetPrototype(ctx, s->target);
- ret = JS_CallFree(ctx, method, s->handler, 1, &s->target);
+ ret = JS_CallFree(ctx, method, s->handler, 1, (JSValueConst *)&s->target);
if (JS_IsException(ret))
return ret;
if (JS_VALUE_GET_TAG(ret) != JS_TAG_NULL &&
@@ -44673,7 +46146,7 @@ static int js_proxy_isExtensible(JSContext *ctx, JSValueConst obj)
return -1;
if (JS_IsUndefined(method))
return JS_IsExtensible(ctx, s->target);
- ret = JS_CallFree(ctx, method, s->handler, 1, &s->target);
+ ret = JS_CallFree(ctx, method, s->handler, 1, (JSValueConst *)&s->target);
if (JS_IsException(ret))
return -1;
res = JS_ToBoolFree(ctx, ret);
@@ -44699,7 +46172,7 @@ static int js_proxy_preventExtensions(JSContext *ctx, JSValueConst obj)
return -1;
if (JS_IsUndefined(method))
return JS_PreventExtensions(ctx, s->target);
- ret = JS_CallFree(ctx, method, s->handler, 1, &s->target);
+ ret = JS_CallFree(ctx, method, s->handler, 1, (JSValueConst *)&s->target);
if (JS_IsException(ret))
return -1;
res = JS_ToBoolFree(ctx, ret);
@@ -44819,9 +46292,9 @@ static int js_proxy_set(JSContext *ctx, JSValueConst obj, JSAtom atom,
if (!s)
return -1;
if (JS_IsUndefined(method)) {
- return JS_SetPropertyGeneric(ctx, s->target, atom,
- JS_DupValue(ctx, value), receiver,
- flags);
+ return JS_SetPropertyInternal(ctx, s->target, atom,
+ JS_DupValue(ctx, value), receiver,
+ flags);
}
atom_val = JS_AtomToValue(ctx, atom);
if (JS_IsException(atom_val)) {
@@ -44887,17 +46360,17 @@ static JSValue js_create_desc(JSContext *ctx, JSValueConst val,
}
if (flags & JS_PROP_HAS_WRITABLE) {
JS_DefinePropertyValue(ctx, ret, JS_ATOM_writable,
- JS_NewBool(ctx, (flags & JS_PROP_WRITABLE) != 0),
+ JS_NewBool(ctx, flags & JS_PROP_WRITABLE),
JS_PROP_C_W_E);
}
if (flags & JS_PROP_HAS_ENUMERABLE) {
JS_DefinePropertyValue(ctx, ret, JS_ATOM_enumerable,
- JS_NewBool(ctx, (flags & JS_PROP_ENUMERABLE) != 0),
+ JS_NewBool(ctx, flags & JS_PROP_ENUMERABLE),
JS_PROP_C_W_E);
}
if (flags & JS_PROP_HAS_CONFIGURABLE) {
JS_DefinePropertyValue(ctx, ret, JS_ATOM_configurable,
- JS_NewBool(ctx, (flags & JS_PROP_CONFIGURABLE) != 0),
+ JS_NewBool(ctx, flags & JS_PROP_CONFIGURABLE),
JS_PROP_C_W_E);
}
return ret;
@@ -45183,7 +46656,7 @@ static int js_proxy_get_own_property_names(JSContext *ctx,
JS_VALUE_GET_OBJ(s->target),
JS_GPN_STRING_MASK | JS_GPN_SYMBOL_MASK);
}
- prop_array = JS_CallFree(ctx, method, s->handler, 1, &s->target);
+ prop_array = JS_CallFree(ctx, method, s->handler, 1, (JSValueConst *)&s->target);
if (JS_IsException(prop_array))
return -1;
tab = NULL;
@@ -45349,20 +46822,35 @@ static JSValue js_proxy_call(JSContext *ctx, JSValueConst func_obj,
return ret;
}
-static int js_proxy_isArray(JSContext *ctx, JSValueConst obj)
-{
- JSProxyData *s = JS_GetOpaque(obj, JS_CLASS_PROXY);
- if (!s)
- return FALSE;
- if (js_check_stack_overflow(ctx->rt, 0)) {
- JS_ThrowStackOverflow(ctx);
- return -1;
- }
- if (s->is_revoked) {
- JS_ThrowTypeErrorRevokedProxy(ctx);
- return -1;
+/* `js_resolve_proxy`: resolve the proxy chain
+ `*pval` is updated with to ultimate proxy target
+ `throw_exception` controls whether exceptions are thown or not
+ - return -1 in case of error
+ - otherwise return 0
+ */
+static int js_resolve_proxy(JSContext *ctx, JSValueConst *pval, BOOL throw_exception) {
+ int depth = 0;
+ JSObject *p;
+ JSProxyData *s;
+
+ while (JS_VALUE_GET_TAG(*pval) == JS_TAG_OBJECT) {
+ p = JS_VALUE_GET_OBJ(*pval);
+ if (p->class_id != JS_CLASS_PROXY)
+ break;
+ if (depth++ > 1000) {
+ if (throw_exception)
+ JS_ThrowStackOverflow(ctx);
+ return -1;
+ }
+ s = p->u.opaque;
+ if (s->is_revoked) {
+ if (throw_exception)
+ JS_ThrowTypeErrorRevokedProxy(ctx);
+ return -1;
+ }
+ *pval = s->target;
}
- return JS_IsArray(ctx, s->target);
+ return 0;
}
static const JSClassExoticMethods js_proxy_exotic_methods = {
@@ -45523,7 +47011,7 @@ static JSValue js_symbol_toString(JSContext *ctx, JSValueConst this_val,
if (JS_IsException(val))
return val;
/* XXX: use JS_ToStringInternal() with a flags */
- ret = js_string_constructor(ctx, JS_UNDEFINED, 1, &val);
+ ret = js_string_constructor(ctx, JS_UNDEFINED, 1, (JSValueConst *)&val);
JS_FreeValue(ctx, val);
return ret;
}
@@ -45673,7 +47161,7 @@ static JSValue js_map_constructor(JSContext *ctx, JSValueConst new_target,
break;
}
if (is_set) {
- ret = JS_Call(ctx, adder, obj, 1, &item);
+ ret = JS_Call(ctx, adder, obj, 1, (JSValueConst *)&item);
if (JS_IsException(ret)) {
JS_FreeValue(ctx, item);
goto fail;
@@ -45757,7 +47245,7 @@ static uint32_t map_hash_key(JSContext *ctx, JSValueConst key)
h = (uintptr_t)JS_VALUE_GET_PTR(key) * 3163;
break;
case JS_TAG_INT:
- d = JS_VALUE_GET_INT(key) * 3163;
+ d = JS_VALUE_GET_INT(key);
goto hash_float64;
case JS_TAG_FLOAT64:
d = JS_VALUE_GET_FLOAT64(key);
@@ -45767,7 +47255,7 @@ static uint32_t map_hash_key(JSContext *ctx, JSValueConst key)
hash_float64:
u.d = d;
h = (u.u32[0] ^ u.u32[1]) * 3163;
- break;
+ return h ^= JS_TAG_FLOAT64;
default:
h = 0; /* XXX: bignum support */
break;
@@ -45991,7 +47479,7 @@ static JSValue js_map_has(JSContext *ctx, JSValueConst this_val,
return JS_EXCEPTION;
key = map_normalize_key(ctx, argv[0]);
mr = map_find_record(ctx, s, key);
- return JS_NewBool(ctx, (mr != NULL));
+ return JS_NewBool(ctx, mr != NULL);
}
static JSValue js_map_delete(JSContext *ctx, JSValueConst this_val,
@@ -46083,6 +47571,123 @@ static JSValue js_map_forEach(JSContext *ctx, JSValueConst this_val,
return JS_UNDEFINED;
}
+static JSValue js_object_groupBy(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv, int is_map)
+{
+ JSValueConst cb, args[2];
+ JSValue res, iter, next, groups, key, v, prop;
+ JSAtom key_atom = JS_ATOM_NULL;
+ int64_t idx;
+ BOOL done;
+
+ // "is function?" check must be observed before argv[0] is accessed
+ cb = argv[1];
+ if (check_function(ctx, cb))
+ return JS_EXCEPTION;
+
+ iter = JS_GetIterator(ctx, argv[0], /*is_async*/FALSE);
+ if (JS_IsException(iter))
+ return JS_EXCEPTION;
+
+ key = JS_UNDEFINED;
+ key_atom = JS_ATOM_NULL;
+ v = JS_UNDEFINED;
+ prop = JS_UNDEFINED;
+ groups = JS_UNDEFINED;
+
+ next = JS_GetProperty(ctx, iter, JS_ATOM_next);
+ if (JS_IsException(next))
+ goto exception;
+
+ if (is_map) {
+ groups = js_map_constructor(ctx, JS_UNDEFINED, 0, NULL, 0);
+ } else {
+ groups = JS_NewObjectProto(ctx, JS_NULL);
+ }
+ if (JS_IsException(groups))
+ goto exception;
+
+ for (idx = 0; ; idx++) {
+ if (idx >= MAX_SAFE_INTEGER) {
+ JS_ThrowTypeError(ctx, "too many elements");
+ goto iterator_close_exception;
+ }
+ v = JS_IteratorNext(ctx, iter, next, 0, NULL, &done);
+ if (JS_IsException(v))
+ goto exception;
+ if (done)
+ break; // v is JS_UNDEFINED
+
+ args[0] = v;
+ args[1] = JS_NewInt64(ctx, idx);
+ key = JS_Call(ctx, cb, ctx->global_obj, 2, args);
+ if (JS_IsException(key))
+ goto iterator_close_exception;
+
+ if (is_map) {
+ prop = js_map_get(ctx, groups, 1, (JSValueConst *)&key, 0);
+ } else {
+ key_atom = JS_ValueToAtom(ctx, key);
+ JS_FreeValue(ctx, key);
+ key = JS_UNDEFINED;
+ if (key_atom == JS_ATOM_NULL)
+ goto iterator_close_exception;
+ prop = JS_GetProperty(ctx, groups, key_atom);
+ }
+ if (JS_IsException(prop))
+ goto exception;
+
+ if (JS_IsUndefined(prop)) {
+ prop = JS_NewArray(ctx);
+ if (JS_IsException(prop))
+ goto exception;
+ if (is_map) {
+ args[0] = key;
+ args[1] = prop;
+ res = js_map_set(ctx, groups, 2, args, 0);
+ if (JS_IsException(res))
+ goto exception;
+ JS_FreeValue(ctx, res);
+ } else {
+ prop = JS_DupValue(ctx, prop);
+ if (JS_DefinePropertyValue(ctx, groups, key_atom, prop,
+ JS_PROP_C_W_E) < 0) {
+ goto exception;
+ }
+ }
+ }
+ res = js_array_push(ctx, prop, 1, (JSValueConst *)&v, /*unshift*/0);
+ if (JS_IsException(res))
+ goto exception;
+ // res is an int64
+
+ JS_FreeValue(ctx, prop);
+ JS_FreeValue(ctx, key);
+ JS_FreeAtom(ctx, key_atom);
+ JS_FreeValue(ctx, v);
+ prop = JS_UNDEFINED;
+ key = JS_UNDEFINED;
+ key_atom = JS_ATOM_NULL;
+ v = JS_UNDEFINED;
+ }
+
+ JS_FreeValue(ctx, iter);
+ JS_FreeValue(ctx, next);
+ return groups;
+
+ iterator_close_exception:
+ JS_IteratorClose(ctx, iter, TRUE);
+ exception:
+ JS_FreeAtom(ctx, key_atom);
+ JS_FreeValue(ctx, prop);
+ JS_FreeValue(ctx, key);
+ JS_FreeValue(ctx, v);
+ JS_FreeValue(ctx, groups);
+ JS_FreeValue(ctx, iter);
+ JS_FreeValue(ctx, next);
+ return JS_EXCEPTION;
+}
+
static void js_map_finalizer(JSRuntime *rt, JSValue val)
{
JSObject *p;
@@ -46263,6 +47868,7 @@ static JSValue js_map_iterator_next(JSContext *ctx, JSValueConst this_val,
}
static const JSCFunctionListEntry js_map_funcs[] = {
+ JS_CFUNC_MAGIC_DEF("groupBy", 2, js_object_groupBy, 1 ),
JS_CGETSET_DEF("[Symbol.species]", js_get_this, NULL ),
};
@@ -46383,12 +47989,6 @@ static const JSCFunctionListEntry js_generator_proto_funcs[] = {
/* Promise */
-typedef enum JSPromiseStateEnum {
- JS_PROMISE_PENDING,
- JS_PROMISE_FULFILLED,
- JS_PROMISE_REJECTED,
-} JSPromiseStateEnum;
-
typedef struct JSPromiseData {
JSPromiseStateEnum promise_state;
/* 0=fulfill, 1=reject, list of JSPromiseReactionData.link */
@@ -46413,6 +48013,22 @@ typedef struct JSPromiseReactionData {
JSValue handler;
} JSPromiseReactionData;
+JSPromiseStateEnum JS_PromiseState(JSContext *ctx, JSValue promise)
+{
+ JSPromiseData *s = JS_GetOpaque(promise, JS_CLASS_PROMISE);
+ if (!s)
+ return -1;
+ return s->promise_state;
+}
+
+JSValue JS_PromiseResult(JSContext *ctx, JSValue promise)
+{
+ JSPromiseData *s = JS_GetOpaque(promise, JS_CLASS_PROMISE);
+ if (!s)
+ return JS_UNDEFINED;
+ return JS_DupValue(ctx, s->promise_result);
+}
+
static int js_create_resolving_functions(JSContext *ctx, JSValue *args,
JSValueConst promise);
@@ -46458,7 +48074,7 @@ static JSValue promise_reaction_job(JSContext *ctx, int argc,
functions */
if (!JS_IsUndefined(func)) {
res2 = JS_Call(ctx, func, JS_UNDEFINED,
- 1, &res);
+ 1, (JSValueConst *)&res);
} else {
res2 = JS_UNDEFINED;
}
@@ -46541,7 +48157,7 @@ static JSValue js_promise_resolve_thenable_job(JSContext *ctx,
res = JS_Call(ctx, then, thenable, 2, (JSValueConst *)args);
if (JS_IsException(res)) {
JSValue error = JS_GetException(ctx);
- res = JS_Call(ctx, args[1], JS_UNDEFINED, 1, &error);
+ res = JS_Call(ctx, args[1], JS_UNDEFINED, 1, (JSValueConst *)&error);
JS_FreeValue(ctx, error);
}
JS_FreeValue(ctx, args[0]);
@@ -46741,7 +48357,7 @@ static JSValue js_promise_constructor(JSContext *ctx, JSValueConst new_target,
if (JS_IsException(ret)) {
JSValue ret2, error;
error = JS_GetException(ctx);
- ret2 = JS_Call(ctx, args[1], JS_UNDEFINED, 1, &error);
+ ret2 = JS_Call(ctx, args[1], JS_UNDEFINED, 1, (JSValueConst *)&error);
JS_FreeValue(ctx, error);
if (JS_IsException(ret2))
goto fail1;
@@ -46798,10 +48414,10 @@ static JSValue js_new_promise_capability(JSContext *ctx,
if (JS_IsUndefined(ctor)) {
result_promise = js_promise_constructor(ctx, ctor, 1,
- &executor);
+ (JSValueConst *)&executor);
} else {
result_promise = JS_CallConstructor(ctx, ctor, 1,
- &executor);
+ (JSValueConst *)&executor);
}
if (JS_IsException(result_promise))
goto fail;
@@ -46858,17 +48474,14 @@ 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)
+static JSValue js_promise_withResolvers(JSContext *ctx,
+ JSValueConst this_val,
+ int argc, JSValueConst *argv)
{
JSValue result_promise, resolving_funcs[2], obj;
- JSValueConst ctor;
- ctor = argv[0];
- if (!JS_IsObject(ctor))
+ if (!JS_IsObject(this_val))
return JS_ThrowTypeErrorNotAnObject(ctx);
- result_promise = js_new_promise_capability(ctx, resolving_funcs, ctor);
+ result_promise = js_new_promise_capability(ctx, resolving_funcs, this_val);
if (JS_IsException(result_promise))
return result_promise;
obj = JS_NewObject(ctx);
@@ -46883,9 +48496,8 @@ 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 warn_unused int remainingElementsCount_add(JSContext *ctx,
+static __exception int remainingElementsCount_add(JSContext *ctx,
JSValueConst resolve_element_env,
int addend)
{
@@ -46966,10 +48578,10 @@ static JSValue js_promise_all_resolve_element(JSContext *ctx,
error = js_aggregate_error_constructor(ctx, values);
if (JS_IsException(error))
return JS_EXCEPTION;
- ret = JS_Call(ctx, resolve, JS_UNDEFINED, 1, &error);
+ ret = JS_Call(ctx, resolve, JS_UNDEFINED, 1, (JSValueConst *)&error);
JS_FreeValue(ctx, error);
} else {
- ret = JS_Call(ctx, resolve, JS_UNDEFINED, 1, &values);
+ ret = JS_Call(ctx, resolve, JS_UNDEFINED, 1, (JSValueConst *)&values);
}
if (JS_IsException(ret))
return ret;
@@ -47005,7 +48617,7 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val,
fail_reject:
error = JS_GetException(ctx);
ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED, 1,
- &error);
+ (JSValueConst *)&error);
JS_FreeValue(ctx, error);
if (JS_IsException(ret))
goto fail;
@@ -47036,7 +48648,7 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val,
if (done)
break;
next_promise = JS_Call(ctx, promise_resolve,
- this_val, 1, &item);
+ this_val, 1, (JSValueConst *)&item);
JS_FreeValue(ctx, item);
if (JS_IsException(next_promise)) {
fail_reject1:
@@ -47104,7 +48716,7 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val,
values = error;
}
ret = JS_Call(ctx, resolving_funcs[is_promise_any], JS_UNDEFINED,
- 1, &values);
+ 1, (JSValueConst *)&values);
if (check_exception_free(ctx, ret))
goto fail_reject;
}
@@ -47147,7 +48759,7 @@ static JSValue js_promise_race(JSContext *ctx, JSValueConst this_val,
fail_reject:
error = JS_GetException(ctx);
ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED, 1,
- &error);
+ (JSValueConst *)&error);
JS_FreeValue(ctx, error);
if (JS_IsException(ret))
goto fail;
@@ -47166,7 +48778,7 @@ static JSValue js_promise_race(JSContext *ctx, JSValueConst this_val,
if (done)
break;
next_promise = JS_Call(ctx, promise_resolve,
- this_val, 1, &item);
+ this_val, 1, (JSValueConst *)&item);
JS_FreeValue(ctx, item);
if (JS_IsException(next_promise)) {
fail_reject1:
@@ -47193,7 +48805,7 @@ static JSValue js_promise_race(JSContext *ctx, JSValueConst this_val,
goto done;
}
-static warn_unused int perform_promise_then(JSContext *ctx,
+static __exception int perform_promise_then(JSContext *ctx,
JSValueConst promise,
JSValueConst *resolve_reject,
JSValueConst *cap_resolving_funcs)
@@ -47311,7 +48923,7 @@ static JSValue js_promise_then_finally_func(JSContext *ctx, JSValueConst this_va
res = JS_Call(ctx, onFinally, JS_UNDEFINED, 0, NULL);
if (JS_IsException(res))
return res;
- promise = js_promise_resolve(ctx, ctor, 1, &res, 0);
+ promise = js_promise_resolve(ctx, ctor, 1, (JSValueConst *)&res, 0);
JS_FreeValue(ctx, res);
if (JS_IsException(promise))
return promise;
@@ -47326,7 +48938,7 @@ static JSValue js_promise_then_finally_func(JSContext *ctx, JSValueConst this_va
JS_FreeValue(ctx, promise);
return then_func;
}
- ret = JS_InvokeFree(ctx, promise, JS_ATOM_then, 1, &then_func);
+ ret = JS_InvokeFree(ctx, promise, JS_ATOM_then, 1, (JSValueConst *)&then_func);
JS_FreeValue(ctx, then_func);
return ret;
}
@@ -47373,7 +48985,7 @@ static const JSCFunctionListEntry js_promise_funcs[] = {
JS_CFUNC_MAGIC_DEF("allSettled", 1, js_promise_all, PROMISE_MAGIC_allSettled ),
JS_CFUNC_MAGIC_DEF("any", 1, js_promise_all, PROMISE_MAGIC_any ),
JS_CFUNC_DEF("race", 1, js_promise_race ),
- //JS_CFUNC_DEF("__newPromiseCapability", 1, js_promise___newPromiseCapability ),
+ JS_CFUNC_DEF("withResolvers", 0, js_promise_withResolvers ),
JS_CGETSET_DEF("[Symbol.species]", js_get_this, NULL),
};
@@ -47526,7 +49138,7 @@ static JSValue js_async_from_sync_iterator_next(JSContext *ctx, JSValueConst thi
is_reject = 1;
done_resolve:
res2 = JS_Call(ctx, resolving_funcs[is_reject], JS_UNDEFINED,
- 1, &err);
+ 1, (JSValueConst *)&err);
JS_FreeValue(ctx, err);
JS_FreeValue(ctx, res2);
JS_FreeValue(ctx, resolving_funcs[0]);
@@ -47538,7 +49150,7 @@ static JSValue js_async_from_sync_iterator_next(JSContext *ctx, JSValueConst thi
int res;
value_wrapper_promise = js_promise_resolve(ctx, ctx->promise_ctor,
- 1, &value, 0);
+ 1, (JSValueConst *)&value, 0);
if (JS_IsException(value_wrapper_promise)) {
JS_FreeValue(ctx, value);
goto reject;
@@ -47786,8 +49398,7 @@ static JSValue js_global_decodeURI(JSContext *ctx, JSValueConst this_val,
}
c = (c << 6) | (c1 & 0x3f);
}
- if (c < c_min || c > 0x10FFFF ||
- (c >= 0xd800 && c < 0xe000)) {
+ if (c < c_min || c > 0x10FFFF || is_surrogate(c)) {
js_throw_URIError(ctx, "malformed UTF-8");
goto fail;
}
@@ -47862,21 +49473,21 @@ static JSValue js_global_encodeURI(JSContext *ctx, JSValueConst this_val,
if (isURIUnescaped(c, isComponent)) {
string_buffer_putc16(b, c);
} else {
- if (c >= 0xdc00 && c <= 0xdfff) {
+ if (is_lo_surrogate(c)) {
js_throw_URIError(ctx, "invalid character");
goto fail;
- } else if (c >= 0xd800 && c <= 0xdbff) {
+ } else if (is_hi_surrogate(c)) {
if (k >= p->len) {
js_throw_URIError(ctx, "expecting surrogate pair");
goto fail;
}
c1 = string_get(p, k);
k++;
- if (c1 < 0xdc00 || c1 > 0xdfff) {
+ if (!is_lo_surrogate(c1)) {
js_throw_URIError(ctx, "expecting surrogate pair");
goto fail;
}
- c = (((c & 0x3ff) << 10) | (c1 & 0x3ff)) + 0x10000;
+ c = from_surrogate(c, c1);
}
if (c < 0x80) {
encodeURI_hex(b, c);
@@ -47984,12 +49595,7 @@ static const JSCFunctionListEntry js_global_funcs[] = {
JS_PROP_DOUBLE_DEF("Infinity", 1.0 / 0.0, 0 ),
JS_PROP_DOUBLE_DEF("NaN", NAN, 0 ),
JS_PROP_UNDEFINED_DEF("undefined", 0 ),
-
- /* for the 'Date' implementation */
- JS_CFUNC_DEF("__date_clock", 0, js___date_clock ),
- //JS_CFUNC_DEF("__date_now", 0, js___date_now ),
- //JS_CFUNC_DEF("__date_getTimezoneOffset", 1, js___date_getTimezoneOffset ),
- //JS_CFUNC_DEF("__date_create", 3, js___date_create ),
+ JS_PROP_STRING_DEF("[Symbol.toStringTag]", "global", JS_PROP_CONFIGURABLE ),
};
/* Date */
@@ -48009,7 +49615,7 @@ static int64_t floor_div(int64_t a, int64_t b) {
static JSValue js_Date_parse(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv);
-static warn_unused int JS_ThisTimeValue(JSContext *ctx, double *valp, JSValueConst this_val)
+static __exception int JS_ThisTimeValue(JSContext *ctx, double *valp, JSValueConst this_val)
{
if (JS_VALUE_GET_TAG(this_val) == JS_TAG_OBJECT) {
JSObject *p = JS_VALUE_GET_OBJ(this_val);
@@ -48069,8 +49675,8 @@ static int const month_days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
static char const month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
static char const day_names[] = "SunMonTueWedThuFriSat";
-static warn_unused int get_date_fields(JSContext *ctx, JSValueConst obj,
- double fields[9], int is_local, int force)
+static __exception int get_date_fields(JSContext *ctx, JSValueConst obj,
+ double fields[minimum_length(9)], int is_local, int force)
{
double dval;
int64_t d, days, wd, y, i, md, h, m, s, ms, tz = 0;
@@ -48083,7 +49689,7 @@ static warn_unused int get_date_fields(JSContext *ctx, JSValueConst obj,
return FALSE; /* NaN */
d = 0; /* initialize all fields to 0 */
} else {
- d = dval;
+ d = dval; /* assuming -8.64e15 <= dval <= -8.64e15 */
if (is_local) {
tz = -getTimezoneOffset(d);
d += tz * 60000;
@@ -48129,33 +49735,63 @@ static double time_clip(double t) {
return NAN;
}
-/* The spec mandates the use of 'double' and it fixes the order
+/* The spec mandates the use of 'double' and it specifies the order
of the operations */
-static double set_date_fields(const double fields[], int is_local) {
- int64_t y;
- double days, d, h, m1;
- int i, m, md;
-
- m1 = fields[1];
- m = fmod(m1, 12);
- if (m < 0)
- m += 12;
- y = (int64_t)(fields[0] + floor(m1 / 12));
- days = days_from_year(y);
-
- for(i = 0; i < m; i++) {
- md = month_days[i];
+static double set_date_fields(double fields[minimum_length(7)], int is_local) {
+ double y, m, dt, ym, mn, day, h, s, milli, time, tv;
+ int yi, mi, i;
+ int64_t days;
+ volatile double temp; /* enforce evaluation order */
+
+ /* emulate 21.4.1.15 MakeDay ( year, month, date ) */
+ y = fields[0];
+ m = fields[1];
+ dt = fields[2];
+ ym = y + floor(m / 12);
+ mn = fmod(m, 12);
+ if (mn < 0)
+ mn += 12;
+ if (ym < -271821 || ym > 275760)
+ return NAN;
+
+ yi = ym;
+ mi = mn;
+ days = days_from_year(yi);
+ for(i = 0; i < mi; i++) {
+ days += month_days[i];
if (i == 1)
- md += days_in_year(y) - 365;
- days += md;
+ days += days_in_year(yi) - 365;
+ }
+ day = days + dt - 1;
+
+ /* emulate 21.4.1.14 MakeTime ( hour, min, sec, ms ) */
+ h = fields[3];
+ m = fields[4];
+ s = fields[5];
+ milli = fields[6];
+ /* Use a volatile intermediary variable to ensure order of evaluation
+ * as specified in ECMA. This fixes a test262 error on
+ * test262/test/built-ins/Date/UTC/fp-evaluation-order.js.
+ * Without the volatile qualifier, the compile can generate code
+ * that performs the computation in a different order or with instructions
+ * that produce a different result such as FMA (float multiply and add).
+ */
+ time = h * 3600000;
+ time += (temp = m * 60000);
+ time += (temp = s * 1000);
+ time += milli;
+
+ /* emulate 21.4.1.16 MakeDate ( day, time ) */
+ tv = (temp = day * 86400000) + time; /* prevent generation of FMA */
+ if (!isfinite(tv))
+ return NAN;
+
+ /* adjust for local time and clip */
+ if (is_local) {
+ int64_t ti = tv < INT64_MIN ? INT64_MIN : tv >= 0x1p63 ? INT64_MAX : (int64_t)tv;
+ tv += getTimezoneOffset(ti) * 60000;
}
- days += fields[2] - 1;
- h = fields[3] * 3600000 + fields[4] * 60000 +
- fields[5] * 1000 + fields[6];
- d = days * 86400000 + h;
- if (is_local)
- d += getTimezoneOffset(d) * 60000;
- return time_clip(d);
+ return time_clip(tv);
}
static JSValue get_date_field(JSContext *ctx, JSValueConst this_val,
@@ -48195,20 +49831,19 @@ static JSValue set_date_field(JSContext *ctx, JSValueConst this_val,
res = get_date_fields(ctx, this_val, fields, is_local, first_field == 0);
if (res < 0)
return JS_EXCEPTION;
- if (res && argc > 0) {
- n = end_field - first_field;
- if (argc < n)
- n = argc;
- for(i = 0; i < n; i++) {
- if (JS_ToFloat64(ctx, &a, argv[i]))
- return JS_EXCEPTION;
- if (!isfinite(a))
- goto done;
- fields[first_field + i] = trunc(a);
- }
- d = set_date_fields(fields, is_local);
+
+ // Argument coercion is observable and must be done unconditionally.
+ n = min_int(argc, end_field - first_field);
+ for(i = 0; i < n; i++) {
+ if (JS_ToFloat64(ctx, &a, argv[i]))
+ return JS_EXCEPTION;
+ if (!isfinite(a))
+ res = FALSE;
+ fields[first_field + i] = trunc(a);
}
-done:
+ if (res && argc > 0)
+ d = set_date_fields(fields, is_local);
+
return JS_SetThisTimeValue(ctx, this_val, d);
}
@@ -48318,7 +49953,7 @@ static JSValue get_date_string(JSContext *ctx, JSValueConst this_val,
break;
case 3:
pos += snprintf(buf + pos, sizeof(buf) - pos,
- "%02d:%02d:%02d %cM", (h + 1) % 12 - 1, m, s,
+ "%02d:%02d:%02d %cM", (h + 11) % 12 + 1, m, s,
(h < 12) ? 'A' : 'P');
break;
}
@@ -48369,7 +50004,7 @@ static JSValue js_date_constructor(JSContext *ctx, JSValueConst new_target,
}
v = JS_ToPrimitive(ctx, argv[0], HINT_NONE);
if (JS_IsString(v)) {
- dv = js_Date_parse(ctx, JS_UNDEFINED, 1, &v);
+ dv = js_Date_parse(ctx, JS_UNDEFINED, 1, (JSValueConst *)&v);
JS_FreeValue(ctx, v);
if (JS_IsException(dv))
return JS_EXCEPTION;
@@ -48442,142 +50077,418 @@ static JSValue js_Date_UTC(JSContext *ctx, JSValueConst this_val,
return JS_NewFloat64(ctx, set_date_fields(fields, 0));
}
-static void string_skip_spaces(JSString *sp, int *pp) {
- while (*pp < sp->len && string_get(sp, *pp) == ' ')
+/* Date string parsing */
+
+static BOOL string_skip_char(const uint8_t *sp, int *pp, int c) {
+ if (sp[*pp] == c) {
*pp += 1;
+ return TRUE;
+ } else {
+ return FALSE;
+ }
}
-static void string_skip_non_spaces(JSString *sp, int *pp) {
- while (*pp < sp->len && string_get(sp, *pp) != ' ')
+/* skip spaces, update offset, return next char */
+static int string_skip_spaces(const uint8_t *sp, int *pp) {
+ int c;
+ while ((c = sp[*pp]) == ' ')
*pp += 1;
+ return c;
}
-/* parse a numeric field with an optional sign if accept_sign is TRUE */
-static int string_get_digits(JSString *sp, int *pp, int64_t *pval) {
- int64_t v = 0;
+/* skip dashes dots and commas */
+static int string_skip_separators(const uint8_t *sp, int *pp) {
+ int c;
+ while ((c = sp[*pp]) == '-' || c == '/' || c == '.' || c == ',')
+ *pp += 1;
+ return c;
+}
+
+/* skip a word, stop on spaces, digits and separators, update offset */
+static int string_skip_until(const uint8_t *sp, int *pp, const char *stoplist) {
+ int c;
+ while (!strchr(stoplist, c = sp[*pp]))
+ *pp += 1;
+ return c;
+}
+
+/* parse a numeric field (max_digits = 0 -> no maximum) */
+static BOOL string_get_digits(const uint8_t *sp, int *pp, int *pval,
+ int min_digits, int max_digits)
+{
+ int v = 0;
int c, p = *pp, p_start;
- if (p >= sp->len)
- return -1;
p_start = p;
- while (p < sp->len) {
- c = string_get(sp, p);
- if (!(c >= '0' && c <= '9')) {
- if (p == p_start)
- return -1;
- else
- break;
- }
+ while ((c = sp[p]) >= '0' && c <= '9') {
v = v * 10 + c - '0';
p++;
+ if (p - p_start == max_digits)
+ break;
}
+ if (p - p_start < min_digits)
+ return FALSE;
*pval = v;
*pp = p;
- return 0;
+ return TRUE;
}
-static int string_get_signed_digits(JSString *sp, int *pp, int64_t *pval) {
- int res, sgn, p = *pp;
-
- if (p >= sp->len)
- return -1;
+static BOOL string_get_milliseconds(const uint8_t *sp, int *pp, int *pval) {
+ /* parse optional fractional part as milliseconds and truncate. */
+ /* spec does not indicate which rounding should be used */
+ int mul = 100, ms = 0, c, p_start, p = *pp;
- sgn = string_get(sp, p);
- if (sgn == '-' || sgn == '+')
+ c = sp[p];
+ if (c == '.' || c == ',') {
p++;
+ p_start = p;
+ while ((c = sp[p]) >= '0' && c <= '9') {
+ ms += (c - '0') * mul;
+ mul /= 10;
+ p++;
+ if (p - p_start == 9)
+ break;
+ }
+ if (p > p_start) {
+ /* only consume the separator if digits are present */
+ *pval = ms;
+ *pp = p;
+ }
+ }
+ return TRUE;
+}
- res = string_get_digits(sp, &p, pval);
- if (res == 0 && sgn == '-')
- *pval = -*pval;
- *pp = p;
- return res;
+static uint8_t upper_ascii(uint8_t c) {
+ return c >= 'a' && c <= 'z' ? c - 'a' + 'A' : c;
}
-/* parse a fixed width numeric field */
-static int string_get_fixed_width_digits(JSString *sp, int *pp, int n, int64_t *pval) {
- int64_t v = 0;
- int i, c, p = *pp;
+static BOOL string_get_tzoffset(const uint8_t *sp, int *pp, int *tzp, BOOL strict) {
+ int tz = 0, sgn, hh, mm, p = *pp;
- for(i = 0; i < n; i++) {
- if (p >= sp->len)
- return -1;
- c = string_get(sp, p);
- if (!(c >= '0' && c <= '9'))
- return -1;
- v = v * 10 + c - '0';
- p++;
+ sgn = sp[p++];
+ if (sgn == '+' || sgn == '-') {
+ int n = p;
+ if (!string_get_digits(sp, &p, &hh, 1, 9))
+ return FALSE;
+ n = p - n;
+ if (strict && n != 2 && n != 4)
+ return FALSE;
+ while (n > 4) {
+ n -= 2;
+ hh /= 100;
+ }
+ if (n > 2) {
+ mm = hh % 100;
+ hh = hh / 100;
+ } else {
+ mm = 0;
+ if (string_skip_char(sp, &p, ':') /* optional separator */
+ && !string_get_digits(sp, &p, &mm, 2, 2))
+ return FALSE;
+ }
+ if (hh > 23 || mm > 59)
+ return FALSE;
+ tz = hh * 60 + mm;
+ if (sgn != '+')
+ tz = -tz;
+ } else
+ if (sgn != 'Z') {
+ return FALSE;
}
- *pval = v;
*pp = p;
- return 0;
+ *tzp = tz;
+ return TRUE;
}
-static int string_get_milliseconds(JSString *sp, int *pp, int64_t *pval) {
- /* 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, p = *pp, c, p_start;
- if (p >= sp->len)
- return -1;
- p_start = p;
- while (p < sp->len) {
- c = string_get(sp, p);
- if (!(c >= '0' && c <= '9')) {
- if (p == p_start)
- return -1;
- else
- break;
- }
- if (mul == 1 && c >= '5')
- ms += 1;
- ms += (c - '0') * (mul /= 10);
+static BOOL string_match(const uint8_t *sp, int *pp, const char *s) {
+ int p = *pp;
+ while (*s != '\0') {
+ if (upper_ascii(sp[p]) != upper_ascii(*s++))
+ return FALSE;
p++;
}
- *pval = ms;
*pp = p;
- return 0;
+ return TRUE;
}
-
-static int find_abbrev(JSString *sp, int p, const char *list, int count) {
+static int find_abbrev(const uint8_t *sp, int p, const char *list, int count) {
int n, i;
- if (p + 3 <= sp->len) {
- for (n = 0; n < count; n++) {
- for (i = 0; i < 3; i++) {
- if (string_get(sp, p + i) != month_names[n * 3 + i])
- goto next;
- }
- return n;
- next:;
+ for (n = 0; n < count; n++) {
+ for (i = 0;; i++) {
+ if (upper_ascii(sp[p + i]) != upper_ascii(list[n * 3 + i]))
+ break;
+ if (i == 2)
+ return n;
}
}
return -1;
}
-static int string_get_month(JSString *sp, int *pp, int64_t *pval) {
+static BOOL string_get_month(const uint8_t *sp, int *pp, int *pval) {
int n;
- string_skip_spaces(sp, pp);
n = find_abbrev(sp, *pp, month_names, 12);
if (n < 0)
- return -1;
+ return FALSE;
- *pval = n;
+ *pval = n + 1;
*pp += 3;
- return 0;
+ return TRUE;
+}
+
+/* parse toISOString format */
+static BOOL js_date_parse_isostring(const uint8_t *sp, int fields[9], BOOL *is_local) {
+ int sgn, i, p = 0;
+
+ /* initialize fields to the beginning of the Epoch */
+ for (i = 0; i < 9; i++) {
+ fields[i] = (i == 2);
+ }
+ *is_local = FALSE;
+
+ /* year is either yyyy digits or [+-]yyyyyy */
+ sgn = sp[p];
+ if (sgn == '-' || sgn == '+') {
+ p++;
+ if (!string_get_digits(sp, &p, &fields[0], 6, 6))
+ return FALSE;
+ if (sgn == '-') {
+ if (fields[0] == 0)
+ return FALSE; // reject -000000
+ fields[0] = -fields[0];
+ }
+ } else {
+ if (!string_get_digits(sp, &p, &fields[0], 4, 4))
+ return FALSE;
+ }
+ if (string_skip_char(sp, &p, '-')) {
+ if (!string_get_digits(sp, &p, &fields[1], 2, 2)) /* month */
+ return FALSE;
+ if (fields[1] < 1)
+ return FALSE;
+ fields[1] -= 1;
+ if (string_skip_char(sp, &p, '-')) {
+ if (!string_get_digits(sp, &p, &fields[2], 2, 2)) /* day */
+ return FALSE;
+ if (fields[2] < 1)
+ return FALSE;
+ }
+ }
+ if (string_skip_char(sp, &p, 'T')) {
+ *is_local = TRUE;
+ if (!string_get_digits(sp, &p, &fields[3], 2, 2) /* hour */
+ || !string_skip_char(sp, &p, ':')
+ || !string_get_digits(sp, &p, &fields[4], 2, 2)) { /* minute */
+ fields[3] = 100; // reject unconditionally
+ return TRUE;
+ }
+ if (string_skip_char(sp, &p, ':')) {
+ if (!string_get_digits(sp, &p, &fields[5], 2, 2)) /* second */
+ return FALSE;
+ string_get_milliseconds(sp, &p, &fields[6]);
+ }
+ }
+ /* parse the time zone offset if present: [+-]HH:mm or [+-]HHmm */
+ if (sp[p]) {
+ *is_local = FALSE;
+ if (!string_get_tzoffset(sp, &p, &fields[8], TRUE))
+ return FALSE;
+ }
+ /* error if extraneous characters */
+ return sp[p] == '\0';
+}
+
+static struct {
+ char name[6];
+ int16_t offset;
+} const js_tzabbr[] = {
+ { "GMT", 0 }, // Greenwich Mean Time
+ { "UTC", 0 }, // Coordinated Universal Time
+ { "UT", 0 }, // Universal Time
+ { "Z", 0 }, // Zulu Time
+ { "EDT", -4 * 60 }, // Eastern Daylight Time
+ { "EST", -5 * 60 }, // Eastern Standard Time
+ { "CDT", -5 * 60 }, // Central Daylight Time
+ { "CST", -6 * 60 }, // Central Standard Time
+ { "MDT", -6 * 60 }, // Mountain Daylight Time
+ { "MST", -7 * 60 }, // Mountain Standard Time
+ { "PDT", -7 * 60 }, // Pacific Daylight Time
+ { "PST", -8 * 60 }, // Pacific Standard Time
+ { "WET", +0 * 60 }, // Western European Time
+ { "WEST", +1 * 60 }, // Western European Summer Time
+ { "CET", +1 * 60 }, // Central European Time
+ { "CEST", +2 * 60 }, // Central European Summer Time
+ { "EET", +2 * 60 }, // Eastern European Time
+ { "EEST", +3 * 60 }, // Eastern European Summer Time
+};
+
+static BOOL string_get_tzabbr(const uint8_t *sp, int *pp, int *offset) {
+ for (size_t i = 0; i < countof(js_tzabbr); i++) {
+ if (string_match(sp, pp, js_tzabbr[i].name)) {
+ *offset = js_tzabbr[i].offset;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/* parse toString, toUTCString and other formats */
+static BOOL js_date_parse_otherstring(const uint8_t *sp,
+ int fields[minimum_length(9)],
+ BOOL *is_local) {
+ int c, i, val, p = 0, p_start;
+ int num[3];
+ BOOL has_year = FALSE;
+ BOOL has_mon = FALSE;
+ BOOL has_time = FALSE;
+ int num_index = 0;
+
+ /* initialize fields to the beginning of 2001-01-01 */
+ fields[0] = 2001;
+ fields[1] = 1;
+ fields[2] = 1;
+ for (i = 3; i < 9; i++) {
+ fields[i] = 0;
+ }
+ *is_local = TRUE;
+
+ while (string_skip_spaces(sp, &p)) {
+ p_start = p;
+ if ((c = sp[p]) == '+' || c == '-') {
+ if (has_time && string_get_tzoffset(sp, &p, &fields[8], FALSE)) {
+ *is_local = FALSE;
+ } else {
+ p++;
+ if (string_get_digits(sp, &p, &val, 1, 9)) {
+ if (c == '-') {
+ if (val == 0)
+ return FALSE;
+ val = -val;
+ }
+ fields[0] = val;
+ has_year = TRUE;
+ }
+ }
+ } else
+ if (string_get_digits(sp, &p, &val, 1, 9)) {
+ if (string_skip_char(sp, &p, ':')) {
+ /* time part */
+ fields[3] = val;
+ if (!string_get_digits(sp, &p, &fields[4], 1, 2))
+ return FALSE;
+ if (string_skip_char(sp, &p, ':')) {
+ if (!string_get_digits(sp, &p, &fields[5], 1, 2))
+ return FALSE;
+ string_get_milliseconds(sp, &p, &fields[6]);
+ }
+ has_time = TRUE;
+ } else {
+ if (p - p_start > 2) {
+ fields[0] = val;
+ has_year = TRUE;
+ } else
+ if (val < 1 || val > 31) {
+ fields[0] = val + (val < 100) * 1900 + (val < 50) * 100;
+ has_year = TRUE;
+ } else {
+ if (num_index == 3)
+ return FALSE;
+ num[num_index++] = val;
+ }
+ }
+ } else
+ if (string_get_month(sp, &p, &fields[1])) {
+ has_mon = TRUE;
+ string_skip_until(sp, &p, "0123456789 -/(");
+ } else
+ if (has_time && string_match(sp, &p, "PM")) {
+ if (fields[3] < 12)
+ fields[3] += 12;
+ continue;
+ } else
+ if (has_time && string_match(sp, &p, "AM")) {
+ if (fields[3] == 12)
+ fields[3] -= 12;
+ continue;
+ } else
+ if (string_get_tzabbr(sp, &p, &fields[8])) {
+ *is_local = FALSE;
+ continue;
+ } else
+ if (c == '(') { /* skip parenthesized phrase */
+ int level = 0;
+ while ((c = sp[p]) != '\0') {
+ p++;
+ level += (c == '(');
+ level -= (c == ')');
+ if (!level)
+ break;
+ }
+ if (level > 0)
+ return FALSE;
+ } else
+ if (c == ')') {
+ return FALSE;
+ } else {
+ if (has_year + has_mon + has_time + num_index)
+ return FALSE;
+ /* skip a word */
+ string_skip_until(sp, &p, " -/(");
+ }
+ string_skip_separators(sp, &p);
+ }
+ if (num_index + has_year + has_mon > 3)
+ return FALSE;
+
+ switch (num_index) {
+ case 0:
+ if (!has_year)
+ return FALSE;
+ break;
+ case 1:
+ if (has_mon)
+ fields[2] = num[0];
+ else
+ fields[1] = num[0];
+ break;
+ case 2:
+ if (has_year) {
+ fields[1] = num[0];
+ fields[2] = num[1];
+ } else
+ if (has_mon) {
+ fields[0] = num[1] + (num[1] < 100) * 1900 + (num[1] < 50) * 100;
+ fields[2] = num[0];
+ } else {
+ fields[1] = num[0];
+ fields[2] = num[1];
+ }
+ break;
+ case 3:
+ fields[0] = num[2] + (num[2] < 100) * 1900 + (num[2] < 50) * 100;
+ fields[1] = num[0];
+ fields[2] = num[1];
+ break;
+ default:
+ return FALSE;
+ }
+ if (fields[1] < 1 || fields[2] < 1)
+ return FALSE;
+ fields[1] -= 1;
+ return TRUE;
}
static JSValue js_Date_parse(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
- // parse(s)
JSValue s, rv;
- int64_t fields[] = { 0, 1, 1, 0, 0, 0, 0 };
- double fields1[7];
- int64_t tz, hh, mm;
+ int fields[9];
+ double fields1[9];
double d;
- int p, i, c, sgn, l;
+ int i, c;
JSString *sp;
+ uint8_t buf[128];
BOOL is_local;
rv = JS_NAN;
@@ -48587,145 +50498,33 @@ static JSValue js_Date_parse(JSContext *ctx, JSValueConst this_val,
return JS_EXCEPTION;
sp = JS_VALUE_GET_STRING(s);
- p = 0;
- if (p < sp->len && (((c = string_get(sp, p)) >= '0' && c <= '9') || c == '+' || c == '-')) {
- /* ISO format */
- /* year field can be negative */
- if (string_get_signed_digits(sp, &p, &fields[0]))
- goto done;
-
- for (i = 1; i < 7; i++) {
- if (p >= sp->len)
- break;
- switch(i) {
- case 1:
- case 2:
- c = '-';
- break;
- case 3:
- c = 'T';
- break;
- case 4:
- case 5:
- c = ':';
- break;
- case 6:
- c = '.';
- break;
- }
- if (string_get(sp, p) != c)
- break;
- p++;
- if (i == 6) {
- if (string_get_milliseconds(sp, &p, &fields[i]))
- goto done;
- } else {
- if (string_get_digits(sp, &p, &fields[i]))
- goto done;
- }
- }
- /* no time: UTC by default */
- is_local = (i > 3);
- fields[1] -= 1;
-
- /* parse the time zone offset if present: [+-]HH:mm or [+-]HHmm */
- tz = 0;
- if (p < sp->len) {
- sgn = string_get(sp, p);
- if (sgn == '+' || sgn == '-') {
- p++;
- l = sp->len - p;
- if (l != 4 && l != 5)
- goto done;
- if (string_get_fixed_width_digits(sp, &p, 2, &hh))
- goto done;
- if (l == 5) {
- if (string_get(sp, p) != ':')
- goto done;
- p++;
- }
- if (string_get_fixed_width_digits(sp, &p, 2, &mm))
- goto done;
- tz = hh * 60 + mm;
- if (sgn == '-')
- tz = -tz;
- is_local = FALSE;
- } else if (sgn == 'Z') {
- p++;
- is_local = FALSE;
- } else {
- goto done;
- }
- /* error if extraneous characters */
- if (p != sp->len)
- goto done;
- }
- } else {
- /* toString or toUTCString format */
- /* skip the day of the week */
- string_skip_non_spaces(sp, &p);
- string_skip_spaces(sp, &p);
- if (p >= sp->len)
- goto done;
- c = string_get(sp, p);
- if (c >= '0' && c <= '9') {
- /* day of month first */
- if (string_get_digits(sp, &p, &fields[2]))
- goto done;
- if (string_get_month(sp, &p, &fields[1]))
- goto done;
- } else {
- /* month first */
- if (string_get_month(sp, &p, &fields[1]))
- goto done;
- string_skip_spaces(sp, &p);
- if (string_get_digits(sp, &p, &fields[2]))
- goto done;
- }
- /* year */
- string_skip_spaces(sp, &p);
- if (string_get_signed_digits(sp, &p, &fields[0]))
- goto done;
-
- /* hour, min, seconds */
- string_skip_spaces(sp, &p);
- for(i = 0; i < 3; i++) {
- if (i == 1 || i == 2) {
- if (p >= sp->len)
- goto done;
- if (string_get(sp, p) != ':')
- goto done;
- p++;
- }
- if (string_get_digits(sp, &p, &fields[3 + i]))
- goto done;
- }
- // XXX: parse optional milliseconds?
-
- /* parse the time zone offset if present: [+-]HHmm */
- is_local = FALSE;
- tz = 0;
- for (tz = 0; p < sp->len; p++) {
- sgn = string_get(sp, p);
- if (sgn == '+' || sgn == '-') {
- p++;
- if (string_get_fixed_width_digits(sp, &p, 2, &hh))
- goto done;
- if (string_get_fixed_width_digits(sp, &p, 2, &mm))
- goto done;
- tz = hh * 60 + mm;
- if (sgn == '-')
- tz = -tz;
- break;
- }
+ /* convert the string as a byte array */
+ for (i = 0; i < sp->len && i < (int)countof(buf) - 1; i++) {
+ c = string_get(sp, i);
+ if (c > 255)
+ c = (c == 0x2212) ? '-' : 'x';
+ buf[i] = c;
+ }
+ buf[i] = '\0';
+ if (js_date_parse_isostring(buf, fields, &is_local)
+ || js_date_parse_otherstring(buf, fields, &is_local)) {
+ static int const field_max[6] = { 0, 11, 31, 24, 59, 59 };
+ BOOL valid = TRUE;
+ /* check field maximum values */
+ for (i = 1; i < 6; i++) {
+ if (fields[i] > field_max[i])
+ valid = FALSE;
+ }
+ /* special case 24:00:00.000 */
+ if (fields[3] == 24 && (fields[4] | fields[5] | fields[6]))
+ valid = FALSE;
+ if (valid) {
+ for(i = 0; i < 7; i++)
+ fields1[i] = fields[i];
+ d = set_date_fields(fields1, is_local) - fields[8] * 60000;
+ rv = JS_NewFloat64(ctx, d);
}
}
- for(i = 0; i < 7; i++)
- fields1[i] = fields[i];
- d = set_date_fields(fields1, is_local) - tz * 60000;
- rv = JS_NewFloat64(ctx, d);
-
-done:
JS_FreeValue(ctx, s);
return rv;
}
@@ -48756,9 +50555,7 @@ static JSValue js_date_Symbol_toPrimitive(JSContext *ctx, JSValueConst this_val,
}
switch (hint) {
case JS_ATOM_number:
-#ifdef CONFIG_BIGNUM
case JS_ATOM_integer:
-#endif
hint_num = HINT_NUMBER;
break;
case JS_ATOM_string:
@@ -48782,6 +50579,7 @@ static JSValue js_date_getTimezoneOffset(JSContext *ctx, JSValueConst this_val,
if (isnan(v))
return JS_NAN;
else
+ /* assuming -8.64e15 <= v <= -8.64e15 */
return JS_NewInt64(ctx, getTimezoneOffset((int64_t)trunc(v)));
}
@@ -48920,6 +50718,23 @@ static const JSCFunctionListEntry js_date_proto_funcs[] = {
JS_CFUNC_DEF("toJSON", 1, js_date_toJSON ),
};
+JSValue JS_NewDate(JSContext *ctx, double epoch_ms)
+{
+ JSValue obj = js_create_from_ctor(ctx, JS_UNDEFINED, JS_CLASS_DATE);
+ if (JS_IsException(obj))
+ return JS_EXCEPTION;
+ JS_SetObjectData(ctx, obj, __JS_NewFloat64(ctx, time_clip(epoch_ms)));
+ return obj;
+}
+
+JS_BOOL JS_IsDate(JSValue v)
+{
+ JSObject *p;
+ if (JS_VALUE_GET_TAG(v) != JS_TAG_OBJECT)
+ return FALSE;
+ return JS_VALUE_GET_OBJ(v)->class_id == JS_CLASS_DATE;
+}
+
void JS_AddIntrinsicDate(JSContext *ctx)
{
JSValueConst obj;
@@ -48937,7 +50752,7 @@ void JS_AddIntrinsicDate(JSContext *ctx)
void JS_AddIntrinsicEval(JSContext *ctx)
{
- ctx->eval_internal = JS_EvalInternalImpl;
+ ctx->eval_internal = __JS_EvalInternal;
}
#ifdef CONFIG_BIGNUM
@@ -49239,6 +51054,7 @@ void JS_AddIntrinsicOperators(JSContext *ctx)
js_operators_set_default(ctx, ctx->class_proto[JS_CLASS_BIG_FLOAT]);
js_operators_set_default(ctx, ctx->class_proto[JS_CLASS_BIG_DECIMAL]);
}
+#endif /* CONFIG_BIGNUM */
/* BigInt */
@@ -49256,14 +51072,20 @@ static JSValue JS_ToBigIntCtorFree(JSContext *ctx, JSValue val)
case JS_TAG_BIG_INT:
break;
case JS_TAG_FLOAT64:
+#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_FLOAT:
+#endif
{
bf_t *a, a_s;
a = JS_ToBigFloat(ctx, &a_s, val);
+ if (!a) {
+ JS_FreeValue(ctx, val);
+ return JS_EXCEPTION;
+ }
if (!bf_is_finite(a)) {
JS_FreeValue(ctx, val);
- val = JS_ThrowRangeError(ctx, "cannot convert NaN or Infinity to bigint");
+ val = JS_ThrowRangeError(ctx, "cannot convert NaN or Infinity to BigInt");
} else {
JSValue val1 = JS_NewBigInt(ctx);
bf_t *r;
@@ -49281,7 +51103,7 @@ static JSValue JS_ToBigIntCtorFree(JSContext *ctx, JSValue val)
val = JS_ThrowOutOfMemory(ctx);
} else if (ret & BF_ST_INEXACT) {
JS_FreeValue(ctx, val1);
- val = JS_ThrowRangeError(ctx, "cannot convert to bigint: not an integer");
+ val = JS_ThrowRangeError(ctx, "cannot convert to BigInt: not an integer");
} else {
val = JS_CompactBigInt(ctx, val1);
}
@@ -49290,11 +51112,13 @@ static JSValue JS_ToBigIntCtorFree(JSContext *ctx, JSValue val)
bf_delete(a);
}
break;
+#ifdef CONFIG_BIGNUM
case JS_TAG_BIG_DECIMAL:
val = JS_ToStringFree(ctx, val);
- if (JS_IsException(val))
+ if (JS_IsException(val))
break;
goto redo;
+#endif
case JS_TAG_STRING:
val = JS_StringToBigIntErr(ctx, val);
break;
@@ -49307,7 +51131,7 @@ static JSValue JS_ToBigIntCtorFree(JSContext *ctx, JSValue val)
case JS_TAG_UNDEFINED:
default:
JS_FreeValue(ctx, val);
- return JS_ThrowTypeError(ctx, "cannot convert to bigint");
+ return JS_ThrowTypeError(ctx, "cannot convert to BigInt");
}
return val;
}
@@ -49333,7 +51157,7 @@ static JSValue js_thisBigIntValue(JSContext *ctx, JSValueConst this_val)
return JS_DupValue(ctx, p->u.object_data);
}
}
- return JS_ThrowTypeError(ctx, "not a bigint");
+ return JS_ThrowTypeError(ctx, "not a BigInt");
}
static JSValue js_bigint_toString(JSContext *ctx, JSValueConst this_val,
@@ -49367,6 +51191,7 @@ static JSValue js_bigint_valueOf(JSContext *ctx, JSValueConst this_val,
return js_thisBigIntValue(ctx, this_val);
}
+#ifdef CONFIG_BIGNUM
static JSValue js_bigint_div(JSContext *ctx,
JSValueConst this_val,
int argc, JSValueConst *argv, int magic)
@@ -49495,6 +51320,7 @@ static JSValue js_bigint_op1(JSContext *ctx,
JS_FreeBigInt(ctx, a, &a_s);
return JS_NewBigInt64(ctx, res);
}
+#endif
static JSValue js_bigint_asUintN(JSContext *ctx,
JSValueConst this_val,
@@ -49539,6 +51365,7 @@ static JSValue js_bigint_asUintN(JSContext *ctx,
static const JSCFunctionListEntry js_bigint_funcs[] = {
JS_CFUNC_MAGIC_DEF("asUintN", 2, js_bigint_asUintN, 0 ),
JS_CFUNC_MAGIC_DEF("asIntN", 2, js_bigint_asUintN, 1 ),
+#ifdef CONFIG_BIGNUM
/* QuickJS extensions */
JS_CFUNC_MAGIC_DEF("tdiv", 2, js_bigint_div, BF_RNDZ ),
JS_CFUNC_MAGIC_DEF("fdiv", 2, js_bigint_div, BF_RNDD ),
@@ -49552,6 +51379,7 @@ static const JSCFunctionListEntry js_bigint_funcs[] = {
JS_CFUNC_MAGIC_DEF("sqrtrem", 1, js_bigint_sqrt, 1 ),
JS_CFUNC_MAGIC_DEF("floorLog2", 1, js_bigint_op1, 0 ),
JS_CFUNC_MAGIC_DEF("ctz", 1, js_bigint_op1, 1 ),
+#endif
};
static const JSCFunctionListEntry js_bigint_proto_funcs[] = {
@@ -49581,6 +51409,8 @@ void JS_AddIntrinsicBigInt(JSContext *ctx)
countof(js_bigint_funcs));
}
+#ifdef CONFIG_BIGNUM
+
/* BigFloat */
static JSValue js_thisBigFloatValue(JSContext *ctx, JSValueConst this_val)
@@ -50054,6 +51884,10 @@ static JSValue js_bigfloat_fop(JSContext *ctx, JSValueConst this_val,
if (JS_IsException(op1))
return op1;
a = JS_ToBigFloat(ctx, &a_s, op1);
+ if (!a) {
+ JS_FreeValue(ctx, op1);
+ return JS_EXCEPTION;
+ }
fe = &ctx->fp_env;
if (argc > 1) {
fe = JS_GetOpaque2(ctx, argv[1], JS_CLASS_FLOAT_ENV);
@@ -50152,7 +51986,11 @@ static JSValue js_bigfloat_fop2(JSContext *ctx, JSValueConst this_val,
return op2;
}
a = JS_ToBigFloat(ctx, &a_s, op1);
+ if (!a)
+ goto fail1;
b = JS_ToBigFloat(ctx, &b_s, op2);
+ if (!b)
+ goto fail2;
fe = &ctx->fp_env;
if (argc > 2) {
fe = JS_GetOpaque2(ctx, argv[2], JS_CLASS_FLOAT_ENV);
@@ -50162,10 +52000,12 @@ static JSValue js_bigfloat_fop2(JSContext *ctx, JSValueConst this_val,
res = JS_NewBigFloat(ctx);
if (JS_IsException(res)) {
fail:
- if (a == &a_s)
- bf_delete(a);
if (b == &b_s)
bf_delete(b);
+ fail2:
+ if (a == &a_s)
+ bf_delete(a);
+ fail1:
JS_FreeValue(ctx, op1);
JS_FreeValue(ctx, op2);
return JS_EXCEPTION;
@@ -50358,9 +52198,9 @@ static JSValue js_float_env_proto_get_status(JSContext *ctx, JSValueConst this_v
case FE_RNDMODE:
return JS_NewInt32(ctx, fe->flags & BF_RND_MASK);
case FE_SUBNORMAL:
- return JS_NewBool(ctx, (fe->flags & BF_FLAG_SUBNORMAL) != 0);
+ return JS_NewBool(ctx, fe->flags & BF_FLAG_SUBNORMAL);
default:
- return JS_NewBool(ctx, (fe->status & magic) != 0);
+ return JS_NewBool(ctx, fe->status & magic);
}
}
@@ -51057,7 +52897,7 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx)
JS_PROP_HAS_GET | JS_PROP_HAS_SET |
JS_PROP_HAS_CONFIGURABLE | JS_PROP_CONFIGURABLE);
JS_FreeValue(ctx, obj1);
- JS_FreeValue(ctx, js_object_seal(ctx, JS_UNDEFINED, 1, &ctx->throw_type_error, 1));
+ JS_FreeValue(ctx, js_object_seal(ctx, JS_UNDEFINED, 1, (JSValueConst *)&ctx->throw_type_error, 1));
ctx->global_obj = JS_NewObject(ctx);
ctx->global_var_obj = JS_NewObjectProto(ctx, JS_NULL);
@@ -51083,11 +52923,13 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx)
JS_NewGlobalCConstructor2(ctx, obj1,
"Error", ctx->class_proto[JS_CLASS_ERROR]);
+ /* Used to squelch a -Wcast-function-type warning. */
+ JSCFunctionType ft = { .generic_magic = js_error_constructor };
for(i = 0; i < JS_NATIVE_ERROR_COUNT; i++) {
JSValue func_obj;
int n_args;
n_args = 1 + (i == JS_AGGREGATE_ERROR);
- func_obj = JS_NewCFunction3(ctx, (JSCFunction *)js_error_constructor,
+ func_obj = JS_NewCFunction3(ctx, ft.generic,
native_error_name[i], n_args,
JS_CFUNC_constructor_or_func_magic, i, obj1);
JS_NewGlobalCConstructor2(ctx, func_obj, native_error_name[i],
@@ -51114,8 +52956,22 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx)
/* XXX: create auto_initializer */
{
/* initialize Array.prototype[Symbol.unscopables] */
- char const unscopables[] = "copyWithin" "\0" "entries" "\0" "fill" "\0" "find" "\0"
- "findIndex" "\0" "flat" "\0" "flatMap" "\0" "includes" "\0" "keys" "\0" "values" "\0";
+ static const char unscopables[] =
+ "copyWithin" "\0"
+ "entries" "\0"
+ "fill" "\0"
+ "find" "\0"
+ "findIndex" "\0"
+ "findLast" "\0"
+ "findLastIndex" "\0"
+ "flat" "\0"
+ "flatMap" "\0"
+ "includes" "\0"
+ "keys" "\0"
+ "toReversed" "\0"
+ "toSorted" "\0"
+ "toSpliced" "\0"
+ "values" "\0";
const char *p = unscopables;
obj1 = JS_NewObjectProto(ctx, JS_NULL);
for(p = unscopables; *p; p += strlen(p) + 1) {
@@ -51239,9 +53095,7 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx)
static uint8_t const typed_array_size_log2[JS_TYPED_ARRAY_COUNT] = {
0, 0, 0, 1, 1, 2, 2,
-#ifdef CONFIG_BIGNUM
3, 3, /* BigInt64Array, BigUint64Array */
-#endif
2, 3
};
@@ -51371,11 +53225,26 @@ static void js_array_buffer_finalizer(JSRuntime *rt, JSValue val)
{
JSObject *p = JS_VALUE_GET_OBJ(val);
JSArrayBuffer *abuf = p->u.array_buffer;
+ struct list_head *el, *el1;
+
if (abuf) {
/* The ArrayBuffer finalizer may be called before the typed
array finalizers using it, so abuf->array_list is not
necessarily empty. */
- // assert(list_empty(&abuf->array_list));
+ list_for_each_safe(el, el1, &abuf->array_list) {
+ JSTypedArray *ta;
+ JSObject *p1;
+
+ ta = list_entry(el, JSTypedArray, link);
+ ta->link.prev = NULL;
+ ta->link.next = NULL;
+ p1 = ta->obj;
+ /* Note: the typed array length and offset fields are not modified */
+ if (p1->class_id != JS_CLASS_DATAVIEW) {
+ p1->u.array.count = 0;
+ p1->u.array.u.ptr = NULL;
+ }
+ }
if (abuf->shared && rt->sab_funcs.sab_free) {
rt->sab_funcs.sab_free(rt->sab_funcs.sab_opaque, abuf->data);
} else {
@@ -51685,6 +53554,16 @@ static JSValue js_typed_array_get_byteOffset(JSContext *ctx,
return JS_NewInt32(ctx, ta->offset);
}
+JSValue JS_NewTypedArray(JSContext *ctx, int argc, JSValueConst *argv,
+ JSTypedArrayEnum type)
+{
+ if (type < JS_TYPED_ARRAY_UINT8C || type > JS_TYPED_ARRAY_FLOAT64)
+ return JS_ThrowRangeError(ctx, "invalid typed array type");
+
+ return js_typed_array_constructor(ctx, JS_UNDEFINED, argc, argv,
+ JS_CLASS_UINT8C_ARRAY + type);
+}
+
/* Return the buffer associated to the typed array or an exception if
it is not a typed array or if the buffer is detached. pbyte_offset,
pbyte_length or pbytes_per_element can be NULL. */
@@ -51802,6 +53681,69 @@ fail:
return JS_EXCEPTION;
}
+static JSValue js_typed_array_at(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv)
+{
+ JSObject *p;
+ int64_t idx, len;
+
+ p = get_typed_array(ctx, this_val, 0);
+ if (!p)
+ return JS_EXCEPTION;
+
+ if (typed_array_is_detached(ctx, p)) {
+ JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
+ return JS_EXCEPTION;
+ }
+
+ if (JS_ToInt64Sat(ctx, &idx, argv[0]))
+ return JS_EXCEPTION;
+
+ len = p->u.array.count;
+ if (idx < 0)
+ idx = len + idx;
+ if (idx < 0 || idx >= len)
+ return JS_UNDEFINED;
+ return JS_GetPropertyInt64(ctx, this_val, idx);
+}
+
+static JSValue js_typed_array_with(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv)
+{
+ JSValue arr, val;
+ JSObject *p;
+ int64_t idx, len;
+
+ p = get_typed_array(ctx, this_val, /*is_dataview*/0);
+ if (!p)
+ return JS_EXCEPTION;
+
+ if (JS_ToInt64Sat(ctx, &idx, argv[0]))
+ return JS_EXCEPTION;
+
+ len = p->u.array.count;
+ if (idx < 0)
+ idx = len + idx;
+ if (idx < 0 || idx >= len)
+ return JS_ThrowRangeError(ctx, "invalid array index");
+
+ val = JS_ToPrimitive(ctx, argv[1], HINT_NUMBER);
+ if (JS_IsException(val))
+ return JS_EXCEPTION;
+
+ arr = js_typed_array_constructor_ta(ctx, JS_UNDEFINED, this_val,
+ p->class_id);
+ if (JS_IsException(arr)) {
+ JS_FreeValue(ctx, val);
+ return JS_EXCEPTION;
+ }
+ if (JS_SetPropertyInt64(ctx, arr, idx, val) < 0) {
+ JS_FreeValue(ctx, arr);
+ return JS_EXCEPTION;
+ }
+ return arr;
+}
+
static JSValue js_typed_array_set(JSContext *ctx,
JSValueConst this_val,
int argc, JSValueConst *argv)
@@ -52091,14 +54033,10 @@ static JSValue js_typed_array_fill(JSContext *ctx, JSValueConst this_val,
if (JS_ToUint32(ctx, &v, argv[0]))
return JS_EXCEPTION;
v64 = v;
- } else
-#ifdef CONFIG_BIGNUM
- if (p->class_id <= JS_CLASS_BIG_UINT64_ARRAY) {
+ } else if (p->class_id <= JS_CLASS_BIG_UINT64_ARRAY) {
if (JS_ToBigInt64(ctx, (int64_t *)&v64, argv[0]))
return JS_EXCEPTION;
- } else
-#endif
- {
+ } else {
double d;
if (JS_ToFloat64(ctx, &d, argv[0]))
return JS_EXCEPTION;
@@ -52160,12 +54098,13 @@ static JSValue js_typed_array_fill(JSContext *ctx, JSValueConst this_val,
}
static JSValue js_typed_array_find(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int findIndex)
+ int argc, JSValueConst *argv, int mode)
{
JSValueConst func, this_arg;
JSValueConst args[3];
JSValue val, index_val, res;
- int len, k;
+ int len, k, end;
+ int dir;
val = JS_UNDEFINED;
len = js_typed_array_get_length_internal(ctx, this_val);
@@ -52180,7 +54119,16 @@ static JSValue js_typed_array_find(JSContext *ctx, JSValueConst this_val,
if (argc > 1)
this_arg = argv[1];
- for(k = 0; k < len; k++) {
+ k = 0;
+ dir = 1;
+ end = len;
+ if (mode == ArrayFindLast || mode == ArrayFindLastIndex) {
+ k = len - 1;
+ dir = -1;
+ end = -1;
+ }
+
+ for(; k != end; k += dir) {
index_val = JS_NewInt32(ctx, k);
val = JS_GetPropertyValue(ctx, this_val, index_val);
if (JS_IsException(val))
@@ -52192,7 +54140,7 @@ static JSValue js_typed_array_find(JSContext *ctx, JSValueConst this_val,
if (JS_IsException(res))
goto exception;
if (JS_ToBoolFree(ctx, res)) {
- if (findIndex) {
+ if (mode == ArrayFindIndex || mode == ArrayFindLastIndex) {
JS_FreeValue(ctx, val);
return index_val;
} else {
@@ -52201,7 +54149,7 @@ static JSValue js_typed_array_find(JSContext *ctx, JSValueConst this_val,
}
JS_FreeValue(ctx, val);
}
- if (findIndex)
+ if (mode == ArrayFindIndex || mode == ArrayFindLastIndex)
return JS_NewInt32(ctx, -1);
else
return JS_UNDEFINED;
@@ -52213,7 +54161,7 @@ exception:
#define special_indexOf 0
#define special_lastIndexOf 1
-#define special_includes (-1)
+#define special_includes -1
static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv, int special)
@@ -52280,13 +54228,14 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val,
is_int = 1;
v64 = JS_VALUE_GET_INT(argv[0]);
d = v64;
- } else if (tag == JS_TAG_FLOAT64) {
- d = JS_VALUE_GET_FLOAT64(argv[0]);
- v64 = d;
- is_int = (v64 == d);
} else
-#ifdef CONFIG_BIGNUM
- if (tag == JS_TAG_BIG_INT) {
+ if (tag == JS_TAG_FLOAT64) {
+ d = JS_VALUE_GET_FLOAT64(argv[0]);
+ if (d >= INT64_MIN && d < 0x1p63) {
+ v64 = d;
+ is_int = (v64 == d);
+ }
+ } else if (tag == JS_TAG_BIG_INT) {
JSBigFloat *p1 = JS_VALUE_GET_PTR(argv[0]);
if (p->class_id == JS_CLASS_BIG_INT64_ARRAY) {
@@ -52300,9 +54249,7 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val,
}
d = 0;
is_bigint = 1;
- } else
-#endif
- {
+ } else {
goto done;
}
@@ -52419,7 +54366,6 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val,
}
}
break;
-#ifdef CONFIG_BIGNUM
case JS_CLASS_BIG_INT64_ARRAY:
if (is_bigint || (is_math_mode(ctx) && is_int &&
v64 >= -MAX_SAFE_INTEGER &&
@@ -52443,7 +54389,6 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val,
}
}
break;
-#endif
}
done:
@@ -52578,6 +54523,24 @@ static JSValue js_typed_array_reverse(JSContext *ctx, JSValueConst this_val,
return JS_DupValue(ctx, this_val);
}
+static JSValue js_typed_array_toReversed(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv)
+{
+ JSValue arr, ret;
+ JSObject *p;
+
+ p = get_typed_array(ctx, this_val, /*is_dataview*/0);
+ if (!p)
+ return JS_EXCEPTION;
+ arr = js_typed_array_constructor_ta(ctx, JS_UNDEFINED, this_val,
+ p->class_id);
+ if (JS_IsException(arr))
+ return JS_EXCEPTION;
+ ret = js_typed_array_reverse(ctx, arr, argc, argv);
+ JS_FreeValue(ctx, arr);
+ return ret;
+}
+
static JSValue js_typed_array_slice(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
@@ -52724,7 +54687,6 @@ static int js_TA_cmp_uint32(const void *a, const void *b, void *opaque) {
return (y < x) - (y > x);
}
-#ifdef CONFIG_BIGNUM
static int js_TA_cmp_int64(const void *a, const void *b, void *opaque) {
int64_t x = *(const int64_t *)a;
int64_t y = *(const int64_t *)b;
@@ -52736,7 +54698,6 @@ static int js_TA_cmp_uint64(const void *a, const void *b, void *opaque) {
uint64_t y = *(const uint64_t *)b;
return (y < x) - (y > x);
}
-#endif
static int js_TA_cmp_float32(const void *a, const void *b, void *opaque) {
return js_cmp_doubles(*(const float *)a, *(const float *)b);
@@ -52770,7 +54731,6 @@ static JSValue js_TA_get_uint32(JSContext *ctx, const void *a) {
return JS_NewUint32(ctx, *(const uint32_t *)a);
}
-#ifdef CONFIG_BIGNUM
static JSValue js_TA_get_int64(JSContext *ctx, const void *a) {
return JS_NewBigInt64(ctx, *(int64_t *)a);
}
@@ -52778,19 +54738,18 @@ static JSValue js_TA_get_int64(JSContext *ctx, const void *a) {
static JSValue js_TA_get_uint64(JSContext *ctx, const void *a) {
return JS_NewBigUint64(ctx, *(uint64_t *)a);
}
-#endif
static JSValue js_TA_get_float32(JSContext *ctx, const void *a) {
- return JS_NewFloat64Impl(ctx, *(const float *)a);
+ return __JS_NewFloat64(ctx, *(const float *)a);
}
static JSValue js_TA_get_float64(JSContext *ctx, const void *a) {
- return JS_NewFloat64Impl(ctx, *(const double *)a);
+ return __JS_NewFloat64(ctx, *(const double *)a);
}
struct TA_sort_context {
JSContext *ctx;
- int exception;
+ int exception; /* 1 = exception, 2 = detached typed array */
JSValueConst arr;
JSValueConst cmp;
JSValue (*getfun)(JSContext *ctx, const void *a);
@@ -52808,6 +54767,8 @@ static int js_TA_cmp_generic(const void *a, const void *b, void *opaque) {
cmp = 0;
if (!psc->exception) {
+ /* Note: the typed array can be detached without causing an
+ error */
a_idx = *(uint32_t *)a;
b_idx = *(uint32_t *)b;
argv[0] = psc->getfun(ctx, psc->array_ptr +
@@ -52835,8 +54796,9 @@ static int js_TA_cmp_generic(const void *a, const void *b, void *opaque) {
/* 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;
+ if (unlikely(typed_array_is_detached(ctx,
+ JS_VALUE_GET_PTR(psc->arr)))) {
+ psc->exception = 2;
}
done:
JS_FreeValue(ctx, argv[0]);
@@ -52860,11 +54822,11 @@ static JSValue js_typed_array_sort(JSContext *ctx, JSValueConst this_val,
tsc.arr = this_val;
tsc.cmp = argv[0];
+ if (!JS_IsUndefined(tsc.cmp) && check_function(ctx, tsc.cmp))
+ return JS_EXCEPTION;
len = js_typed_array_get_length_internal(ctx, this_val);
if (len < 0)
return JS_EXCEPTION;
- if (!JS_IsUndefined(tsc.cmp) && check_function(ctx, tsc.cmp))
- return JS_EXCEPTION;
if (len > 1) {
p = JS_VALUE_GET_OBJ(this_val);
@@ -52894,7 +54856,6 @@ static JSValue js_typed_array_sort(JSContext *ctx, JSValueConst this_val,
tsc.getfun = js_TA_get_uint32;
cmpfun = js_TA_cmp_uint32;
break;
-#ifdef CONFIG_BIGNUM
case JS_CLASS_BIG_INT64_ARRAY:
tsc.getfun = js_TA_get_int64;
cmpfun = js_TA_cmp_int64;
@@ -52903,7 +54864,6 @@ static JSValue js_typed_array_sort(JSContext *ctx, JSValueConst this_val,
tsc.getfun = js_TA_get_uint64;
cmpfun = js_TA_cmp_uint64;
break;
-#endif
case JS_CLASS_FLOAT32_ARRAY:
tsc.getfun = js_TA_get_float32;
cmpfun = js_TA_cmp_float32;
@@ -52932,44 +54892,48 @@ static JSValue js_typed_array_sort(JSContext *ctx, JSValueConst this_val,
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];
+ if (tsc.exception) {
+ if (tsc.exception == 1)
+ goto fail;
+ /* detached typed array during the sort: no error */
+ } else {
+ array_tmp = js_malloc(ctx, len * elt_size);
+ if (!array_tmp) {
+ fail:
+ js_free(ctx, array_idx);
+ return JS_EXCEPTION;
}
- break;
- case 8:
- for(i = 0; i < len; i++) {
- j = array_idx[i];
- ((uint64_t *)array_ptr)[i] = ((uint64_t *)array_tmp)[j];
+ 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();
}
- break;
- default:
- abort();
+ js_free(ctx, array_tmp);
}
- js_free(ctx, array_tmp);
js_free(ctx, array_idx);
} else {
rqsort(array_ptr, len, elt_size, cmpfun, &tsc);
@@ -52980,6 +54944,24 @@ static JSValue js_typed_array_sort(JSContext *ctx, JSValueConst this_val,
return JS_DupValue(ctx, this_val);
}
+static JSValue js_typed_array_toSorted(JSContext *ctx, JSValueConst this_val,
+ int argc, JSValueConst *argv)
+{
+ JSValue arr, ret;
+ JSObject *p;
+
+ p = get_typed_array(ctx, this_val, /*is_dataview*/0);
+ if (!p)
+ return JS_EXCEPTION;
+ arr = js_typed_array_constructor_ta(ctx, JS_UNDEFINED, this_val,
+ p->class_id);
+ if (JS_IsException(arr))
+ return JS_EXCEPTION;
+ ret = js_typed_array_sort(ctx, arr, argc, argv);
+ JS_FreeValue(ctx, arr);
+ return ret;
+}
+
static const JSCFunctionListEntry js_typed_array_base_funcs[] = {
JS_CFUNC_DEF("from", 1, js_typed_array_from ),
JS_CFUNC_DEF("of", 0, js_typed_array_of ),
@@ -52991,6 +54973,8 @@ static const JSCFunctionListEntry js_typed_array_base_funcs[] = {
static const JSCFunctionListEntry js_typed_array_base_proto_funcs[] = {
JS_CGETSET_DEF("length", js_typed_array_get_length, NULL ),
+ JS_CFUNC_DEF("at", 1, js_typed_array_at ),
+ JS_CFUNC_DEF("with", 2, js_typed_array_with ),
JS_CGETSET_MAGIC_DEF("buffer", js_typed_array_get_buffer, NULL, 0 ),
JS_CGETSET_MAGIC_DEF("byteLength", js_typed_array_get_byteLength, NULL, 0 ),
JS_CGETSET_MAGIC_DEF("byteOffset", js_typed_array_get_byteOffset, NULL, 0 ),
@@ -53009,12 +54993,16 @@ static const JSCFunctionListEntry js_typed_array_base_proto_funcs[] = {
JS_CFUNC_MAGIC_DEF("reduce", 1, js_array_reduce, special_reduce | special_TA ),
JS_CFUNC_MAGIC_DEF("reduceRight", 1, js_array_reduce, special_reduceRight | special_TA ),
JS_CFUNC_DEF("fill", 1, js_typed_array_fill ),
- JS_CFUNC_MAGIC_DEF("find", 1, js_typed_array_find, 0 ),
- JS_CFUNC_MAGIC_DEF("findIndex", 1, js_typed_array_find, 1 ),
+ JS_CFUNC_MAGIC_DEF("find", 1, js_typed_array_find, ArrayFind ),
+ JS_CFUNC_MAGIC_DEF("findIndex", 1, js_typed_array_find, ArrayFindIndex ),
+ JS_CFUNC_MAGIC_DEF("findLast", 1, js_typed_array_find, ArrayFindLast ),
+ JS_CFUNC_MAGIC_DEF("findLastIndex", 1, js_typed_array_find, ArrayFindLastIndex ),
JS_CFUNC_DEF("reverse", 0, js_typed_array_reverse ),
+ JS_CFUNC_DEF("toReversed", 0, js_typed_array_toReversed ),
JS_CFUNC_DEF("slice", 2, js_typed_array_slice ),
JS_CFUNC_DEF("subarray", 2, js_typed_array_subarray ),
JS_CFUNC_DEF("sort", 1, js_typed_array_sort ),
+ JS_CFUNC_DEF("toSorted", 1, js_typed_array_toSorted ),
JS_CFUNC_MAGIC_DEF("join", 1, js_typed_array_join, 0 ),
JS_CFUNC_MAGIC_DEF("toLocaleString", 0, js_typed_array_join, 1 ),
JS_CFUNC_MAGIC_DEF("indexOf", 1, js_typed_array_indexOf, special_indexOf ),
@@ -53161,7 +55149,7 @@ static JSValue js_typed_array_constructor_ta(JSContext *ctx,
{
JSObject *p, *src_buffer;
JSTypedArray *ta;
- JSValue ctor, obj, buffer;
+ JSValue obj, buffer;
uint32_t len, i;
int size_log2;
JSArrayBuffer *src_abuf, *abuf;
@@ -53178,19 +55166,9 @@ static JSValue js_typed_array_constructor_ta(JSContext *ctx,
len = p->u.array.count;
src_buffer = ta->buffer;
src_abuf = src_buffer->u.array_buffer;
- if (!src_abuf->shared) {
- ctor = JS_SpeciesConstructor(ctx, JS_MKPTR(JS_TAG_OBJECT, src_buffer),
- JS_UNDEFINED);
- if (JS_IsException(ctor))
- goto fail;
- } else {
- /* force ArrayBuffer default constructor */
- ctor = JS_UNDEFINED;
- }
size_log2 = typed_array_size_log2(classid);
- buffer = js_array_buffer_constructor1(ctx, ctor,
+ buffer = js_array_buffer_constructor1(ctx, JS_UNDEFINED,
(uint64_t)len << size_log2);
- JS_FreeValue(ctx, ctor);
if (JS_IsException(buffer))
goto fail;
/* necessary because it could have been detached */
@@ -53296,7 +55274,7 @@ static void js_typed_array_finalizer(JSRuntime *rt, JSValue val)
if (ta) {
/* during the GC the finalizers are called in an arbitrary
order so the ArrayBuffer finalizer may have been called */
- if (JS_IsLiveObject(rt, JS_MKPTR(JS_TAG_OBJECT, ta->buffer))) {
+ if (ta->link.next) {
list_del(&ta->link);
}
JS_FreeValueRT(rt, JS_MKPTR(JS_TAG_OBJECT, ta->buffer));
@@ -53379,7 +55357,8 @@ static JSValue js_dataview_getValue(JSContext *ctx,
{
JSTypedArray *ta;
JSArrayBuffer *abuf;
- int is_swap, size;
+ BOOL littleEndian, is_swap;
+ int size;
uint8_t *ptr;
uint32_t v;
uint64_t pos;
@@ -53390,12 +55369,8 @@ static JSValue js_dataview_getValue(JSContext *ctx,
size = 1 << typed_array_size_log2(class_id);
if (JS_ToIndex(ctx, &pos, argv[0]))
return JS_EXCEPTION;
- is_swap = FALSE;
- if (argc > 1)
- is_swap = JS_ToBool(ctx, argv[1]);
-#ifndef WORDS_BIGENDIAN
- is_swap ^= 1;
-#endif
+ littleEndian = argc > 1 && JS_ToBool(ctx, argv[1]);
+ is_swap = littleEndian ^ !is_be();
abuf = ta->buffer->u.array_buffer;
if (abuf->detached)
return JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
@@ -53407,7 +55382,7 @@ static JSValue js_dataview_getValue(JSContext *ctx,
case JS_CLASS_INT8_ARRAY:
return JS_NewInt32(ctx, *(int8_t *)ptr);
case JS_CLASS_UINT8_ARRAY:
- return JS_NewInt32(ctx, *ptr);
+ return JS_NewInt32(ctx, *(uint8_t *)ptr);
case JS_CLASS_INT16_ARRAY:
v = get_u16(ptr);
if (is_swap)
@@ -53428,7 +55403,6 @@ static JSValue js_dataview_getValue(JSContext *ctx,
if (is_swap)
v = bswap32(v);
return JS_NewUint32(ctx, v);
-#ifdef CONFIG_BIGNUM
case JS_CLASS_BIG_INT64_ARRAY:
{
uint64_t v;
@@ -53447,7 +55421,6 @@ static JSValue js_dataview_getValue(JSContext *ctx,
return JS_NewBigUint64(ctx, v);
}
break;
-#endif
case JS_CLASS_FLOAT32_ARRAY:
{
union {
@@ -53458,7 +55431,7 @@ static JSValue js_dataview_getValue(JSContext *ctx,
if (is_swap)
v = bswap32(v);
u.i = v;
- return JS_NewFloat64Impl(ctx, u.f);
+ return __JS_NewFloat64(ctx, u.f);
}
case JS_CLASS_FLOAT64_ARRAY:
{
@@ -53469,7 +55442,7 @@ static JSValue js_dataview_getValue(JSContext *ctx,
u.i = get_u64(ptr);
if (is_swap)
u.i = bswap64(u.i);
- return JS_NewFloat64Impl(ctx, u.f);
+ return __JS_NewFloat64(ctx, u.f);
}
default:
abort();
@@ -53482,7 +55455,8 @@ static JSValue js_dataview_setValue(JSContext *ctx,
{
JSTypedArray *ta;
JSArrayBuffer *abuf;
- int is_swap, size;
+ BOOL littleEndian, is_swap;
+ int size;
uint8_t *ptr;
uint64_t v64;
uint32_t v;
@@ -53501,14 +55475,10 @@ static JSValue js_dataview_setValue(JSContext *ctx,
if (class_id <= JS_CLASS_UINT32_ARRAY) {
if (JS_ToUint32(ctx, &v, val))
return JS_EXCEPTION;
- } else
-#ifdef CONFIG_BIGNUM
- if (class_id <= JS_CLASS_BIG_UINT64_ARRAY) {
+ } else if (class_id <= JS_CLASS_BIG_UINT64_ARRAY) {
if (JS_ToBigInt64(ctx, (int64_t *)&v64, val))
return JS_EXCEPTION;
- } else
-#endif
- {
+ } else {
double d;
if (JS_ToFloat64(ctx, &d, val))
return JS_EXCEPTION;
@@ -53525,12 +55495,8 @@ static JSValue js_dataview_setValue(JSContext *ctx,
v64 = u.u64;
}
}
- is_swap = FALSE;
- if (argc > 2)
- is_swap = JS_ToBool(ctx, argv[2]);
-#ifndef WORDS_BIGENDIAN
- is_swap ^= 1;
-#endif
+ littleEndian = argc > 2 && JS_ToBool(ctx, argv[2]);
+ is_swap = littleEndian ^ !is_be();
abuf = ta->buffer->u.array_buffer;
if (abuf->detached)
return JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
@@ -53556,10 +55522,8 @@ static JSValue js_dataview_setValue(JSContext *ctx,
v = bswap32(v);
put_u32(ptr, v);
break;
-#ifdef CONFIG_BIGNUM
case JS_CLASS_BIG_INT64_ARRAY:
case JS_CLASS_BIG_UINT64_ARRAY:
-#endif
case JS_CLASS_FLOAT64_ARRAY:
if (is_swap)
v64 = bswap64(v64);
@@ -53581,10 +55545,8 @@ static const JSCFunctionListEntry js_dataview_proto_funcs[] = {
JS_CFUNC_MAGIC_DEF("getUint16", 1, js_dataview_getValue, JS_CLASS_UINT16_ARRAY ),
JS_CFUNC_MAGIC_DEF("getInt32", 1, js_dataview_getValue, JS_CLASS_INT32_ARRAY ),
JS_CFUNC_MAGIC_DEF("getUint32", 1, js_dataview_getValue, JS_CLASS_UINT32_ARRAY ),
-#ifdef CONFIG_BIGNUM
JS_CFUNC_MAGIC_DEF("getBigInt64", 1, js_dataview_getValue, JS_CLASS_BIG_INT64_ARRAY ),
JS_CFUNC_MAGIC_DEF("getBigUint64", 1, js_dataview_getValue, JS_CLASS_BIG_UINT64_ARRAY ),
-#endif
JS_CFUNC_MAGIC_DEF("getFloat32", 1, js_dataview_getValue, JS_CLASS_FLOAT32_ARRAY ),
JS_CFUNC_MAGIC_DEF("getFloat64", 1, js_dataview_getValue, JS_CLASS_FLOAT64_ARRAY ),
JS_CFUNC_MAGIC_DEF("setInt8", 2, js_dataview_setValue, JS_CLASS_INT8_ARRAY ),
@@ -53593,10 +55555,8 @@ static const JSCFunctionListEntry js_dataview_proto_funcs[] = {
JS_CFUNC_MAGIC_DEF("setUint16", 2, js_dataview_setValue, JS_CLASS_UINT16_ARRAY ),
JS_CFUNC_MAGIC_DEF("setInt32", 2, js_dataview_setValue, JS_CLASS_INT32_ARRAY ),
JS_CFUNC_MAGIC_DEF("setUint32", 2, js_dataview_setValue, JS_CLASS_UINT32_ARRAY ),
-#ifdef CONFIG_BIGNUM
JS_CFUNC_MAGIC_DEF("setBigInt64", 2, js_dataview_setValue, JS_CLASS_BIG_INT64_ARRAY ),
JS_CFUNC_MAGIC_DEF("setBigUint64", 2, js_dataview_setValue, JS_CLASS_BIG_UINT64_ARRAY ),
-#endif
JS_CFUNC_MAGIC_DEF("setFloat32", 2, js_dataview_setValue, JS_CLASS_FLOAT32_ARRAY ),
JS_CFUNC_MAGIC_DEF("setFloat64", 2, js_dataview_setValue, JS_CLASS_FLOAT64_ARRAY ),
JS_PROP_STRING_DEF("[Symbol.toStringTag]", "DataView", JS_PROP_CONFIGURABLE ),
@@ -53633,20 +55593,12 @@ 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);
-#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");
@@ -53688,11 +55640,7 @@ 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;
@@ -53706,7 +55654,6 @@ static JSValue js_atomics_op(JSContext *ctx,
if (op == ATOMICS_OP_LOAD) {
v = 0;
} else {
-#ifdef CONFIG_BIGNUM
if (size_log2 == 3) {
int64_t v64;
if (JS_ToBigInt64(ctx, &v64, argv[2]))
@@ -53717,9 +55664,7 @@ static JSValue js_atomics_op(JSContext *ctx,
return JS_EXCEPTION;
rep_val = v64;
}
- } else
-#endif
- {
+ } else {
uint32_t v32;
if (JS_ToUint32(ctx, &v32, argv[2]))
return JS_EXCEPTION;
@@ -53736,7 +55681,6 @@ static JSValue js_atomics_op(JSContext *ctx,
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); \
@@ -53750,18 +55694,7 @@ static JSValue js_atomics_op(JSContext *ctx,
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)
@@ -53779,11 +55712,9 @@ 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):
{
@@ -53806,7 +55737,6 @@ static JSValue js_atomics_op(JSContext *ctx,
a = v1;
}
break;
-#ifdef CONFIG_BIGNUM
case ATOMICS_OP_COMPARE_EXCHANGE | (3 << 3):
{
uint64_t v1 = v;
@@ -53814,7 +55744,6 @@ static JSValue js_atomics_op(JSContext *ctx,
a = v1;
}
break;
-#endif
default:
abort();
}
@@ -53839,14 +55768,12 @@ 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();
}
@@ -53866,7 +55793,6 @@ static JSValue js_atomics_store(JSContext *ctx,
argv[0], argv[1], 0);
if (!ptr)
return JS_EXCEPTION;
-#ifdef CONFIG_BIGNUM
if (size_log2 == 3) {
int64_t v64;
ret = JS_ToBigIntValueFree(ctx, JS_DupValue(ctx, argv[2]));
@@ -53879,9 +55805,7 @@ static JSValue js_atomics_store(JSContext *ctx,
if (abuf->detached)
return JS_ThrowTypeErrorDetachedArrayBuffer(ctx);
atomic_store((_Atomic(uint64_t) *)ptr, v64);
- } else
-#endif
- {
+ } else {
uint32_t v;
/* XXX: spec, would be simpler to return the written value */
ret = JS_ToIntegerFree(ctx, JS_DupValue(ctx, argv[2]));
@@ -53917,11 +55841,7 @@ 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
-#ifdef CONFIG_BIGNUM
- || v == 8
-#endif
- );
+ ret = (v == 1 || v == 2 || v == 4 || v == 8);
return JS_NewBool(ctx, ret);
}
@@ -53953,20 +55873,18 @@ static JSValue js_atomics_wait(JSContext *ctx,
argv[0], argv[1], 2);
if (!ptr)
return JS_EXCEPTION;
-#ifdef CONFIG_BIGNUM
if (size_log2 == 3) {
if (JS_ToBigInt64(ctx, &v, argv[2]))
return JS_EXCEPTION;
- } else
-#endif
- {
+ } else {
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)
+ /* must use INT64_MAX + 1 because INT64_MAX cannot be exactly represented as a double */
+ if (isnan(d) || d >= 0x1p63)
timeout = INT64_MAX;
else if (d < 0)
timeout = 0;
@@ -54144,6 +56062,8 @@ void JS_AddIntrinsicTypedArrays(JSContext *ctx)
countof(js_typed_array_base_funcs));
JS_SetConstructor(ctx, typed_array_base_func, typed_array_base_proto);
+ /* Used to squelch a -Wcast-function-type warning. */
+ JSCFunctionType ft = { .generic_magic = js_typed_array_constructor };
for(i = JS_CLASS_UINT8C_ARRAY; i < JS_CLASS_UINT8C_ARRAY + JS_TYPED_ARRAY_COUNT; i++) {
JSValue func_obj;
char buf[ATOM_GET_STR_BUF_SIZE];
@@ -54156,7 +56076,7 @@ void JS_AddIntrinsicTypedArrays(JSContext *ctx)
0);
name = JS_AtomGetStr(ctx, buf, sizeof(buf),
JS_ATOM_Uint8ClampedArray + i - JS_CLASS_UINT8C_ARRAY);
- func_obj = JS_NewCFunction3(ctx, (JSCFunction *)js_typed_array_constructor,
+ func_obj = JS_NewCFunction3(ctx, ft.generic,
name, 3, JS_CFUNC_constructor_magic, i,
typed_array_base_func);
JS_NewGlobalCConstructor2(ctx, func_obj, name, ctx->class_proto[i]);
@@ -54269,7 +56189,7 @@ void JS_FreeValue(JSContext *ctx, JSValue v) {
notifyRefCountDecrease(p);
#endif
if (--p->ref_count <= 0) {
- JS_FreeValueImpl(ctx, v);
+ __JS_FreeValue(ctx, v);
}
}
}
@@ -54280,7 +56200,7 @@ void JS_FreeValueRT(JSRuntime *rt, JSValue v) {
notifyRefCountDecrease(p);
#endif
if (--p->ref_count <= 0) {
- JS_FreeValueRTImpl(rt, v);
+ __JS_FreeValueRT(rt, v);
}
}
}
@@ -54301,7 +56221,7 @@ JSValue JS_NewInt64(JSContext *ctx, int64_t val) {
if (val == (int32_t)val) {
v = JS_NewInt32(ctx, (int32_t)val);
} else {
- v = JS_NewFloat64Impl(ctx, (double)val);
+ v = __JS_NewFloat64(ctx, (double)val);
}
return v;
}
@@ -54310,29 +56230,29 @@ JSValue JS_NewUint32(JSContext *ctx, uint32_t val) {
if (val <= 0x7fffffff) {
v = JS_NewInt32(ctx, val);
} else {
- v = JS_NewFloat64Impl(ctx, val);
+ v = __JS_NewFloat64(ctx, val);
}
return v;
}
-JSValue JS_NewFloat64(JSContext *ctx, double d) {
- JSValue v;
+JSValue JS_NewFloat64(JSContext *ctx, double d)
+{
int32_t val;
union {
double d;
uint64_t u;
} u, t;
- u.d = d;
- val = (int32_t)d;
- t.d = val;
- /* -0 cannot be represented as integer, so we compare the bit
- representation */
- if (u.u == t.u) {
- v = JS_MKVAL(JS_TAG_INT, val);
- } else {
- v = JS_NewFloat64Impl(ctx, d);
+ if (d >= INT32_MIN && d <= INT32_MAX) {
+ u.d = d;
+ val = (int32_t)d;
+ t.d = val;
+ /* -0 cannot be represented as integer, so we compare the bit
+ representation */
+ if (u.u == t.u)
+ return JS_MKVAL(JS_TAG_INT, val);
}
- return v;
+ return __JS_NewFloat64(ctx, d);
}
+
JSValue JS_NewCFunction(JSContext *ctx, JSCFunction *func, const char *name,
int length) {
return JS_NewCFunction2(ctx, func, name, length, JS_CFUNC_generic, 0);
@@ -54345,23 +56265,3 @@ JS_BOOL JS_IsRegExp(JSContext *ctx, JSValue val)
return FALSE;
return JS_VALUE_GET_OBJ(val)->class_id == JS_CLASS_REGEXP;
}
-
-int JS_IsDate(JSValue v)
-{
- JSObject *p;
- if (JS_VALUE_GET_TAG(v) != JS_TAG_OBJECT)
- return FALSE;
- return JS_VALUE_GET_OBJ(v)->class_id == JS_CLASS_DATE;
-}
-
-JSValue JS_NewDate(JSContext *ctx, const char *s)
-{
- JSValue dateString = JS_NewString(ctx, s);
- JSAtom constrAtom = JS_NewAtom(ctx, "Date");
- JSValue constr = JS_GetGlobalVar(ctx, constrAtom, FALSE);
- JSValue date = js_date_constructor(ctx, constr, 1, &dateString);
- JS_FreeValue(ctx, constr);
- JS_FreeValue(ctx, dateString);
- JS_FreeAtom(ctx, constrAtom);
- return date;
-}
diff --git a/src/shared/quickjs/quickjs.diff b/src/shared/quickjs/quickjs.diff
deleted file mode 100644
index e87999050..000000000
--- a/src/shared/quickjs/quickjs.diff
+++ /dev/null
@@ -1,4061 +0,0 @@
-diff --git a/cutils.c b/cutils.c
-index a02fb76..1f66fff 100644
---- a/cutils.c
-+++ b/cutils.c
-@@ -166,8 +166,7 @@ int dbuf_putstr(DynBuf *s, const char *str)
- return dbuf_put(s, (const uint8_t *)str, strlen(str));
- }
-
--int __attribute__((format(printf, 2, 3))) dbuf_printf(DynBuf *s,
-- const char *fmt, ...)
-+int FORMAT_ATTR(2, 3) dbuf_printf(DynBuf *s, const char *fmt, ...)
- {
- va_list ap;
- char buf[128];
-diff --git a/cutils.h b/cutils.h
-index 31f7cd8..ee0ce4a 100644
---- a/cutils.h
-+++ b/cutils.h
-@@ -28,14 +28,33 @@
- #include <stdlib.h>
- #include <inttypes.h>
-
-+#if defined(_MSC_VER)
-+#include <BaseTsd.h>
-+typedef SSIZE_T ssize_t;
-+#else
-+#include <sys/types.h>
-+#endif
-+
- /* set if CPU is big endian */
- #undef WORDS_BIGENDIAN
-
-+#ifdef __GNUC__
- #define likely(x) __builtin_expect(!!(x), 1)
- #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 maybe_unused __attribute__((unused))
-+#else
-+#define likely(x) (x)
-+#define unlikely(x) (x)
-+#define force_inline
-+#define no_inline
-+#define maybe_unused
-+#endif
-+
-+#ifdef _MSC_VER
-+#define alloca _alloca
-+#endif
-
- #define xglue(x, y) x ## y
- #define glue(x, y) xglue(x, y)
-@@ -114,38 +133,24 @@ static inline int64_t min_int64(int64_t a, int64_t b)
- /* WARNING: undefined if a = 0 */
- static inline int clz32(unsigned int a)
- {
-+#ifdef _MSC_VER
-+ return (int) __lzcnt(a);
-+#else
- return __builtin_clz(a);
-+#endif
- }
-
--/* WARNING: undefined if a = 0 */
--static inline int clz64(uint64_t a)
--{
-- return __builtin_clzll(a);
--}
--
--/* WARNING: undefined if a = 0 */
--static inline int ctz32(unsigned int a)
--{
-- return __builtin_ctz(a);
--}
--
--/* WARNING: undefined if a = 0 */
--static inline int ctz64(uint64_t a)
--{
-- return __builtin_ctzll(a);
--}
--
--struct __attribute__((packed)) packed_u64 {
-+#pragma pack(push, 1)
-+struct packed_u64 {
- uint64_t v;
- };
--
--struct __attribute__((packed)) packed_u32 {
-+struct packed_u32 {
- uint32_t v;
- };
--
--struct __attribute__((packed)) packed_u16 {
-+struct packed_u16 {
- uint16_t v;
- };
-+#pragma pack(pop)
-
- static inline uint64_t get_u64(const uint8_t *tab)
- {
-@@ -262,8 +267,15 @@ static inline int dbuf_put_u64(DynBuf *s, uint64_t val)
- {
- return dbuf_put(s, (uint8_t *)&val, 8);
- }
--int __attribute__((format(printf, 2, 3))) dbuf_printf(DynBuf *s,
-- const char *fmt, ...);
-+
-+#ifdef __GNUC__
-+#define FORMAT_ATTR(x, y) __attribute__((format(printf, x, y)))
-+#else
-+#define FORMAT_ATTR(x, y)
-+#endif
-+
-+int FORMAT_ATTR(2, 3) dbuf_printf(DynBuf *s, const char *fmt, ...);
-+
- void dbuf_free(DynBuf *s);
- static inline BOOL dbuf_error(DynBuf *s) {
- return s->error;
-diff --git a/libregexp.c b/libregexp.c
-index 379bfc7..ad91f78 100644
---- a/libregexp.c
-+++ b/libregexp.c
-@@ -271,7 +271,7 @@ static int cr_canonicalize(CharRange *cr)
- }
-
- #ifdef DUMP_REOP
--static __maybe_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;
-@@ -427,7 +427,7 @@ static void re_emit_op_u16(REParseState *s, int op, uint32_t val)
- dbuf_put_u16(&s->byte_code, val);
- }
-
--static int __attribute__((format(printf, 2, 3))) re_parse_error(REParseState *s, const char *fmt, ...)
-+static int FORMAT_ATTR(2, 3) re_parse_error(REParseState *s, const char *fmt, ...)
- {
- va_list ap;
- va_start(ap, fmt);
-@@ -1472,7 +1472,7 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
- default:
- parse_class_atom:
- c = get_class_atom(s, cr, &p, FALSE);
-- if ((int)c < 0)
-+ if (c < 0)
- return -1;
- normal_char:
- last_atom_start = s->byte_code.size;
-@@ -1924,17 +1924,17 @@ static BOOL is_word_char(uint32_t c)
- #define GET_CHAR(c, cptr, cbuf_end) \
- do { \
- if (cbuf_type == 0) { \
-- c = *cptr++; \
-+ (c) = *(cptr)++; \
- } else { \
- uint32_t __c1; \
-- c = *(uint16_t *)cptr; \
-- cptr += 2; \
-- if (c >= 0xd800 && c < 0xdc00 && \
-- cbuf_type == 2 && cptr < cbuf_end) { \
-- __c1 = *(uint16_t *)cptr; \
-+ (c) = *(uint16_t *)(cptr); \
-+ (cptr) += 2; \
-+ if ((c) >= 0xd800 && (c) < 0xdc00 && \
-+ cbuf_type == 2 && (cptr) < (cbuf_end)) { \
-+ __c1 = *(uint16_t *)(cptr); \
- if (__c1 >= 0xdc00 && __c1 < 0xe000) { \
-- c = (((c & 0x3ff) << 10) | (__c1 & 0x3ff)) + 0x10000; \
-- cptr += 2; \
-+ (c) = ((((c) & 0x3ff) << 10) | (__c1 & 0x3ff)) + 0x10000; \
-+ (cptr) += 2; \
- } \
- } \
- } \
-@@ -1943,15 +1943,15 @@ static BOOL is_word_char(uint32_t c)
- #define PEEK_CHAR(c, cptr, cbuf_end) \
- do { \
- if (cbuf_type == 0) { \
-- c = cptr[0]; \
-+ (c) = (cptr)[0]; \
- } else { \
- uint32_t __c1; \
-- c = ((uint16_t *)cptr)[0]; \
-- if (c >= 0xd800 && c < 0xdc00 && \
-- cbuf_type == 2 && (cptr + 2) < cbuf_end) { \
-- __c1 = ((uint16_t *)cptr)[1]; \
-+ (c) = ((uint16_t *)(cptr))[0]; \
-+ if ((c) >= 0xd800 && (c) < 0xdc00 && \
-+ cbuf_type == 2 && ((cptr) + 2) < (cbuf_end)) { \
-+ __c1 = ((uint16_t *)(cptr))[1]; \
- if (__c1 >= 0xdc00 && __c1 < 0xe000) { \
-- c = (((c & 0x3ff) << 10) | (__c1 & 0x3ff)) + 0x10000; \
-+ (c) = ((((c) & 0x3ff) << 10) | (__c1 & 0x3ff)) + 0x10000; \
- } \
- } \
- } \
-@@ -1960,15 +1960,15 @@ static BOOL is_word_char(uint32_t c)
- #define PEEK_PREV_CHAR(c, cptr, cbuf_start) \
- do { \
- if (cbuf_type == 0) { \
-- c = cptr[-1]; \
-+ (c) = (cptr)[-1]; \
- } else { \
- uint32_t __c1; \
-- c = ((uint16_t *)cptr)[-1]; \
-- if (c >= 0xdc00 && c < 0xe000 && \
-- cbuf_type == 2 && (cptr - 4) >= cbuf_start) { \
-- __c1 = ((uint16_t *)cptr)[-2]; \
-+ (c) = ((uint16_t *)(cptr))[-1]; \
-+ if ((c) >= 0xdc00 && (c) < 0xe000 && \
-+ cbuf_type == 2 && ((cptr) - 4) >= (cbuf_start)) { \
-+ __c1 = ((uint16_t *)(cptr))[-2]; \
- if (__c1 >= 0xd800 && __c1 < 0xdc00 ) { \
-- c = (((__c1 & 0x3ff) << 10) | (c & 0x3ff)) + 0x10000; \
-+ (c) = (((__c1 & 0x3ff) << 10) | ((c) & 0x3ff)) + 0x10000; \
- } \
- } \
- } \
-@@ -1977,18 +1977,18 @@ static BOOL is_word_char(uint32_t c)
- #define GET_PREV_CHAR(c, cptr, cbuf_start) \
- do { \
- if (cbuf_type == 0) { \
-- cptr--; \
-- c = cptr[0]; \
-+ (cptr)--; \
-+ (c) = (cptr)[0]; \
- } else { \
- uint32_t __c1; \
-- cptr -= 2; \
-- c = ((uint16_t *)cptr)[0]; \
-- if (c >= 0xdc00 && c < 0xe000 && \
-- cbuf_type == 2 && cptr > cbuf_start) { \
-- __c1 = ((uint16_t *)cptr)[-1]; \
-+ (cptr) -= 2; \
-+ (c) = ((uint16_t *)(cptr))[0]; \
-+ if ((c) >= 0xdc00 && (c) < 0xe000 && \
-+ cbuf_type == 2 && (cptr) > (cbuf_start)) { \
-+ __c1 = ((uint16_t *)(cptr))[-1]; \
- if (__c1 >= 0xd800 && __c1 < 0xdc00 ) { \
-- cptr -= 2; \
-- c = (((__c1 & 0x3ff) << 10) | (c & 0x3ff)) + 0x10000; \
-+ (cptr) -= 2; \
-+ (c) = (((__c1 & 0x3ff) << 10) | ((c) & 0x3ff)) + 0x10000; \
- } \
- } \
- } \
-@@ -1997,15 +1997,15 @@ static BOOL is_word_char(uint32_t c)
- #define PREV_CHAR(cptr, cbuf_start) \
- do { \
- if (cbuf_type == 0) { \
-- cptr--; \
-+ (cptr)--; \
- } else { \
-- cptr -= 2; \
-+ (cptr) -= 2; \
- if (cbuf_type == 2) { \
-- c = ((uint16_t *)cptr)[0]; \
-- if (c >= 0xdc00 && c < 0xe000 && cptr > cbuf_start) { \
-- c = ((uint16_t *)cptr)[-1]; \
-+ c = ((uint16_t *)(cptr))[0]; \
-+ if (c >= 0xdc00 && c < 0xe000 && (cptr) > (cbuf_start)) { \
-+ c = ((uint16_t *)(cptr))[-1]; \
- if (c >= 0xd800 && c < 0xdc00) \
-- cptr -= 2; \
-+ (cptr) -= 2; \
- } \
- } \
- } \
-@@ -2049,7 +2049,7 @@ typedef struct {
-
- static int push_state(REExecContext *s,
- uint8_t **capture,
-- StackInt *stack, size_t stack_len,
-+ const StackInt *stack, size_t stack_len,
- const uint8_t *pc, const uint8_t *cptr,
- REExecStateEnum type, size_t count)
- {
-diff --git a/libunicode.c b/libunicode.c
-index 63c12a0..112da72 100644
---- a/libunicode.c
-+++ b/libunicode.c
-@@ -271,7 +271,7 @@ BOOL lre_is_case_ignorable(uint32_t c)
-
- /* character range */
-
--static __maybe_unused void cr_dump(CharRange *cr)
-+static maybe_unused void cr_dump(CharRange *cr)
- {
- int i;
- for(i = 0; i < cr->len; i++)
-@@ -1315,11 +1315,13 @@ static int unicode_prop_ops(CharRange *cr, ...)
- }
- }
- done:
-+ va_end(ap);
- assert(stack_len == 1);
- ret = cr_copy(cr, &stack[0]);
- cr_free(&stack[0]);
- return ret;
- fail:
-+ va_end(ap);
- for(i = 0; i < stack_len; i++)
- cr_free(&stack[i]);
- return -1;
-diff --git a/list.h b/list.h
-index 0a1bc5a..e7f51a9 100644
---- a/list.h
-+++ b/list.h
-@@ -46,7 +46,7 @@ static inline void init_list_head(struct list_head *head)
- }
-
- /* insert 'el' between 'prev' and 'next' */
--static inline void __list_add(struct list_head *el,
-+static inline void list_add_impl(struct list_head *el,
- struct list_head *prev, struct list_head *next)
- {
- prev->next = el;
-@@ -58,13 +58,13 @@ static inline void __list_add(struct list_head *el,
- /* add 'el' at the head of the list 'head' (= after element head) */
- static inline void list_add(struct list_head *el, struct list_head *head)
- {
-- __list_add(el, head, head->next);
-+ list_add_impl(el, head, head->next);
- }
-
- /* add 'el' at the end of the list 'head' (= before element head) */
- static inline void list_add_tail(struct list_head *el, struct list_head *head)
- {
-- __list_add(el, head->prev, head);
-+ list_add_impl(el, head->prev, head);
- }
-
- static inline void list_del(struct list_head *el)
-diff --git a/quickjs.c b/quickjs.c
-index 7916013..f90fb9e 100644
---- a/quickjs.c
-+++ b/quickjs.c
-@@ -28,7 +28,9 @@
- #include <inttypes.h>
- #include <string.h>
- #include <assert.h>
-+#ifndef _MSC_VER
- #include <sys/time.h>
-+#endif
- #include <time.h>
- #include <fenv.h>
- #include <math.h>
-@@ -40,6 +42,18 @@
- #include <malloc_np.h>
- #endif
-
-+#ifdef _MSC_VER
-+#include <intrin.h>
-+#include <windows.h>
-+#endif
-+
-+#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) \
-+ || defined(__APPLE__)
-+#include <xlocale.h>
-+#else
-+#include <locale.h>
-+#endif
-+
- #include "cutils.h"
- #include "list.h"
- #include "quickjs.h"
-@@ -48,9 +62,9 @@
- #include "libbf.h"
- #endif
-
--#define OPTIMIZE 1
-+#define OPTIMIZE 0
- #define SHORT_OPCODES 1
--#if defined(EMSCRIPTEN)
-+#if defined(EMSCRIPTEN) || defined(_MSC_VER)
- #define DIRECT_DISPATCH 0
- #else
- #define DIRECT_DISPATCH 1
-@@ -69,7 +83,7 @@
-
- /* define to include Atomics.* operations which depend on the OS
- threads */
--#if !defined(EMSCRIPTEN)
-+#if !defined(EMSCRIPTEN) && !defined(_MSC_VER)
- #define CONFIG_ATOMICS
- #endif
-
-@@ -78,7 +92,6 @@
- #define CONFIG_STACK_CHECK
- #endif
-
--
- /* dump object free */
- //#define DUMP_FREE
- //#define DUMP_CLOSURE
-@@ -115,6 +128,25 @@
- #include <errno.h>
- #endif
-
-+static double safe_strtod(const char *restrict nptr, char **restrict endptr)
-+{
-+#if defined(_MSC_VER) || defined(__MINGW32__)
-+ _configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
-+ setlocale(LC_NUMERIC, "C");
-+#else
-+ const locale_t tempLoc = newlocale(LC_NUMERIC_MASK, "C", 0);
-+ uselocale(tempLoc);
-+#endif
-+ double d = strtod(nptr, endptr);
-+#if defined(_MSC_VER) || defined(__MINGW32__)
-+ _configthreadlocale(_DISABLE_PER_THREAD_LOCALE);
-+#else
-+ uselocale(LC_GLOBAL_LOCALE);
-+ freelocale(tempLoc);
-+#endif
-+ return d;
-+}
-+
- enum {
- /* classid tag */ /* union usage | properties */
- JS_CLASS_OBJECT = 1, /* must be first */
-@@ -204,7 +236,11 @@ typedef enum JSErrorEnum {
- #define JS_STACK_SIZE_MAX 65534
- #define JS_STRING_LEN_MAX ((1 << 30) - 1)
-
--#define __exception __attribute__((warn_unused_result))
-+#ifdef __GNUC__
-+#define warn_unused __attribute__((warn_unused_result))
-+#else
-+#define warn_unused
-+#endif
-
- typedef struct JSShape JSShape;
- typedef struct JSString JSString;
-@@ -362,8 +398,8 @@ typedef struct JSVarRef {
- union {
- JSGCObjectHeader header; /* must come first */
- struct {
-- int __gc_ref_count; /* corresponds to header.ref_count */
-- uint8_t __gc_mark; /* corresponds to header.mark/gc_obj_type */
-+ int _gc_ref_count; /* corresponds to header.ref_count */
-+ uint8_t _gc_mark; /* corresponds to header.mark/gc_obj_type */
-
- /* 0 : the JSVarRef is on the stack. header.link is an element
- of JSStackFrame.var_ref_list.
-@@ -455,8 +491,12 @@ struct JSContext {
- /* if NULL, eval is not supported */
- JSValue (*eval_internal)(JSContext *ctx, JSValueConst this_obj,
- const char *input, size_t input_len,
-- const char *filename, int flags, int scope_idx);
-+ const char *filename, int line, int flags, int scope_idx);
- void *user_opaque;
-+ ScopeLookup *scopeLookup;
-+ FoundUndefinedHandler *handleUndefined;
-+ FunctionEnteredHandler *handleFunctionEntered;
-+ FunctionExitedHandler *handleFunctionExited;
- };
-
- typedef union JSFloat64Union {
-@@ -867,8 +907,8 @@ struct JSObject {
- union {
- JSGCObjectHeader header;
- struct {
-- int __gc_ref_count; /* corresponds to header.ref_count */
-- uint8_t __gc_mark; /* corresponds to header.mark/gc_obj_type */
-+ int _gc_ref_count; /* corresponds to header.ref_count */
-+ uint8_t _gc_mark; /* corresponds to header.mark/gc_obj_type */
-
- uint8_t extensible : 1;
- uint8_t free_mark : 1; /* only used when freeing objects with cycles */
-@@ -950,7 +990,7 @@ struct JSObject {
- /* byte sizes: 40/48/72 */
- };
- enum {
-- __JS_ATOM_NULL = JS_ATOM_NULL,
-+ JS_ATOM_NULL_ = JS_ATOM_NULL,
- #define DEF(name, str) JS_ATOM_ ## name,
- #include "quickjs-atom.h"
- #undef DEF
-@@ -996,7 +1036,7 @@ enum OPCodeEnum {
- };
-
- static int JS_InitAtoms(JSRuntime *rt);
--static JSAtom __JS_NewAtomInit(JSRuntime *rt, const char *str, int len,
-+static JSAtom JS_NewAtomInitImpl(JSRuntime *rt, const char *str, int len,
- int atom_type);
- static void JS_FreeAtomStruct(JSRuntime *rt, JSAtomStruct *p);
- static void free_function_bytecode(JSRuntime *rt, JSFunctionBytecode *b);
-@@ -1017,24 +1057,23 @@ static JSValue JS_CallFree(JSContext *ctx, JSValue func_obj, JSValueConst this_o
- int argc, JSValueConst *argv);
- static JSValue JS_InvokeFree(JSContext *ctx, JSValue this_val, JSAtom atom,
- int argc, JSValueConst *argv);
--static __exception int JS_ToArrayLengthFree(JSContext *ctx, uint32_t *plen,
-+static warn_unused int JS_ToArrayLengthFree(JSContext *ctx, uint32_t *plen,
- JSValue val, BOOL is_array_ctor);
- 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 __maybe_unused void JS_DumpAtoms(JSRuntime *rt);
--static __maybe_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 __maybe_unused void JS_DumpObjectHeader(JSRuntime *rt);
--static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p);
--static __maybe_unused void JS_DumpGCObject(JSRuntime *rt, JSGCObjectHeader *p);
--static __maybe_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_DumpGCObject(JSRuntime *rt, JSGCObjectHeader *p);
-+static maybe_unused void JS_DumpValueShort(JSRuntime *rt,
- JSValueConst val);
--static __maybe_unused void JS_DumpValue(JSContext *ctx, JSValueConst val);
--static __maybe_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 __maybe_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);
-@@ -1148,7 +1187,6 @@ static JSValue JS_ToBigDecimalFree(JSContext *ctx, JSValue val,
- BOOL allow_null_or_undefined);
- static bfdec_t *JS_ToBigDecimal(JSContext *ctx, JSValueConst val);
- #endif
--JSValue JS_ThrowOutOfMemory(JSContext *ctx);
- static JSValue JS_ThrowTypeErrorRevokedProxy(JSContext *ctx);
- static JSValue js_proxy_getPrototypeOf(JSContext *ctx, JSValueConst obj);
- static int js_proxy_setPrototypeOf(JSContext *ctx, JSValueConst obj,
-@@ -1187,7 +1225,7 @@ static void js_async_function_resolve_mark(JSRuntime *rt, JSValueConst val,
- JS_MarkFunc *mark_func);
- static JSValue JS_EvalInternal(JSContext *ctx, JSValueConst this_obj,
- const char *input, size_t input_len,
-- const char *filename, int flags, int scope_idx);
-+ const char *filename, int line, int flags, int scope_idx);
- static void js_free_module_def(JSContext *ctx, JSModuleDef *m);
- static void js_mark_module_def(JSRuntime *rt, JSModuleDef *m,
- JS_MarkFunc *mark_func);
-@@ -1197,7 +1235,7 @@ static void free_var_ref(JSRuntime *rt, JSVarRef *var_ref);
- static JSValue js_new_promise_capability(JSContext *ctx,
- JSValue *resolving_funcs,
- JSValueConst ctor);
--static __exception int perform_promise_then(JSContext *ctx,
-+static warn_unused int perform_promise_then(JSContext *ctx,
- JSValueConst promise,
- JSValueConst *resolve_reject,
- JSValueConst *cap_resolving_funcs);
-@@ -1222,9 +1260,9 @@ static void js_free_shape_null(JSRuntime *rt, JSShape *sh);
- static int js_shape_prepare_update(JSContext *ctx, JSObject *p,
- JSShapeProperty **pprs);
- static int init_shape_hash(JSRuntime *rt);
--static __exception int js_get_length32(JSContext *ctx, uint32_t *pres,
-+static warn_unused int js_get_length32(JSContext *ctx, uint32_t *pres,
- JSValueConst obj);
--static __exception int js_get_length64(JSContext *ctx, int64_t *pres,
-+static warn_unused 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,
-@@ -1582,10 +1620,27 @@ static inline BOOL js_check_stack_overflow(JSRuntime *rt, size_t alloca_size)
- return FALSE;
- }
- #else
--/* Note: OS and CPU dependent */
-+// Uses code from LLVM project.
- static inline uintptr_t js_get_stack_pointer(void)
- {
-+#ifdef _MSC_VER
-+ return (uintptr_t) _AddressOfReturnAddress();
-+#elif defined __has_builtin
-+#if __has_builtin(__builtin_frame_address)
- return (uintptr_t) __builtin_frame_address(0);
-+#endif
-+#elif defined __GNUC__
-+ return (uintptr_t) __builtin_frame_address(0);
-+#else
-+ char CharOnStack = 0;
-+ // The volatile store here is intended to escape the local variable, to
-+ // prevent the compiler from optimizing CharOnStack into anything other
-+ // than a char on the stack.
-+ //
-+ // Tested on: MSVC 2015 - 2019, GCC 4.9 - 9, Clang 3.2 - 9, ICC 13 - 19.
-+ char *volatile Ptr = &CharOnStack;
-+ return (uintptr_t) Ptr;
-+#endif
- }
-
- static inline BOOL js_check_stack_overflow(JSRuntime *rt, size_t alloca_size)
-@@ -1980,6 +2035,7 @@ void JS_FreeRuntime(JSRuntime *rt)
- printf("Secondary object leaks: %d\n", count);
- }
- #endif
-+ fflush(stdout);
- assert(list_empty(&rt->gc_obj_list));
-
- /* free the classes */
-@@ -2386,7 +2442,7 @@ static inline BOOL is_math_mode(JSContext *ctx)
- /* return the max count from the hash size */
- #define JS_ATOM_COUNT_RESIZE(n) ((n) * 2)
-
--static inline BOOL __JS_AtomIsConst(JSAtom v)
-+static inline BOOL JS_AtomIsConst(JSAtom v)
- {
- #if defined(DUMP_LEAKS) && DUMP_LEAKS > 1
- return (int32_t)v <= 0;
-@@ -2395,17 +2451,17 @@ static inline BOOL __JS_AtomIsConst(JSAtom v)
- #endif
- }
-
--static inline BOOL __JS_AtomIsTaggedInt(JSAtom v)
-+static inline BOOL JS_AtomIsTaggedInt(JSAtom v)
- {
- return (v & JS_ATOM_TAG_INT) != 0;
- }
-
--static inline JSAtom __JS_AtomFromUInt32(uint32_t v)
-+static inline JSAtom JS_AtomFromUInt32(uint32_t v)
- {
- return v | JS_ATOM_TAG_INT;
- }
-
--static inline uint32_t __JS_AtomToUInt32(JSAtom atom)
-+static inline uint32_t JS_AtomToUInt32(JSAtom atom)
- {
- return atom & ~JS_ATOM_TAG_INT;
- }
-@@ -2485,7 +2541,7 @@ static uint32_t hash_string(const JSString *str, uint32_t h)
- return h;
- }
-
--static __maybe_unused void JS_DumpString(JSRuntime *rt,
-+static maybe_unused void JS_DumpString(JSRuntime *rt,
- const JSString *p)
- {
- int i, c, sep;
-@@ -2517,7 +2573,7 @@ static __maybe_unused void JS_DumpString(JSRuntime *rt,
- putchar(sep);
- }
-
--static __maybe_unused void JS_DumpAtoms(JSRuntime *rt)
-+static maybe_unused void JS_DumpAtoms(JSRuntime *rt)
- {
- JSAtomStruct *p;
- int h, i;
-@@ -2604,7 +2660,7 @@ static int JS_InitAtoms(JSRuntime *rt)
- else
- atom_type = JS_ATOM_TYPE_STRING;
- len = strlen(p);
-- if (__JS_NewAtomInit(rt, p, len, atom_type) == JS_ATOM_NULL)
-+ if (JS_NewAtomInitImpl(rt, p, len, atom_type) == JS_ATOM_NULL)
- return -1;
- p = p + len + 1;
- }
-@@ -2615,7 +2671,7 @@ static JSAtom JS_DupAtomRT(JSRuntime *rt, JSAtom v)
- {
- JSAtomStruct *p;
-
-- if (!__JS_AtomIsConst(v)) {
-+ if (!JS_AtomIsConst(v)) {
- p = rt->atom_array[v];
- p->header.ref_count++;
- }
-@@ -2627,7 +2683,7 @@ JSAtom JS_DupAtom(JSContext *ctx, JSAtom v)
- JSRuntime *rt;
- JSAtomStruct *p;
-
-- if (!__JS_AtomIsConst(v)) {
-+ if (!JS_AtomIsConst(v)) {
- rt = ctx->rt;
- p = rt->atom_array[v];
- p->header.ref_count++;
-@@ -2641,7 +2697,7 @@ static JSAtomKindEnum JS_AtomGetKind(JSContext *ctx, JSAtom v)
- JSAtomStruct *p;
-
- rt = ctx->rt;
-- if (__JS_AtomIsTaggedInt(v))
-+ if (JS_AtomIsTaggedInt(v))
- return JS_ATOM_KIND_STRING;
- p = rt->atom_array[v];
- switch(p->atom_type) {
-@@ -2687,7 +2743,7 @@ static JSAtom js_get_atom_index(JSRuntime *rt, JSAtomStruct *p)
-
- /* string case (internal). Return JS_ATOM_NULL if error. 'str' is
- freed. */
--static JSAtom __JS_NewAtom(JSRuntime *rt, JSString *str, int atom_type)
-+static JSAtom JS_NewAtomImpl(JSRuntime *rt, JSString *str, int atom_type)
- {
- uint32_t h, h1, i;
- JSAtomStruct *p;
-@@ -2702,7 +2758,7 @@ static JSAtom __JS_NewAtom(JSRuntime *rt, JSString *str, int atom_type)
- /* str is the atom, return its index */
- i = js_get_atom_index(rt, str);
- /* reduce string refcount and increase atom's unless constant */
-- if (__JS_AtomIsConst(i))
-+ if (JS_AtomIsConst(i))
- str->header.ref_count--;
- return i;
- }
-@@ -2718,7 +2774,7 @@ static JSAtom __JS_NewAtom(JSRuntime *rt, JSString *str, int atom_type)
- p->atom_type == atom_type &&
- p->len == len &&
- js_string_memcmp(p, str, len) == 0) {
-- if (!__JS_AtomIsConst(i))
-+ if (!JS_AtomIsConst(i))
- p->header.ref_count++;
- goto done;
- }
-@@ -2843,7 +2899,7 @@ static JSAtom __JS_NewAtom(JSRuntime *rt, JSString *str, int atom_type)
- }
-
- /* only works with zero terminated 8 bit strings */
--static JSAtom __JS_NewAtomInit(JSRuntime *rt, const char *str, int len,
-+static JSAtom JS_NewAtomInitImpl(JSRuntime *rt, const char *str, int len,
- int atom_type)
- {
- JSString *p;
-@@ -2852,10 +2908,10 @@ static JSAtom __JS_NewAtomInit(JSRuntime *rt, const char *str, int len,
- return JS_ATOM_NULL;
- memcpy(p->u.str8, str, len);
- p->u.str8[len] = '\0';
-- return __JS_NewAtom(rt, p, atom_type);
-+ return JS_NewAtomImpl(rt, p, atom_type);
- }
-
--static JSAtom __JS_FindAtom(JSRuntime *rt, const char *str, size_t len,
-+static JSAtom JS_FindAtom(JSRuntime *rt, const char *str, size_t len,
- int atom_type)
- {
- uint32_t h, h1, i;
-@@ -2872,7 +2928,7 @@ static JSAtom __JS_FindAtom(JSRuntime *rt, const char *str, size_t len,
- p->len == len &&
- p->is_wide_char == 0 &&
- memcmp(p->u.str8, str, len) == 0) {
-- if (!__JS_AtomIsConst(i))
-+ if (!JS_AtomIsConst(i))
- p->header.ref_count++;
- return i;
- }
-@@ -2924,7 +2980,7 @@ static void JS_FreeAtomStruct(JSRuntime *rt, JSAtomStruct *p)
- assert(rt->atom_count >= 0);
- }
-
--static void __JS_FreeAtom(JSRuntime *rt, uint32_t i)
-+static void JS_FreeAtomImpl(JSRuntime *rt, uint32_t i)
- {
- JSAtomStruct *p;
-
-@@ -2942,11 +2998,11 @@ static JSAtom JS_NewAtomStr(JSContext *ctx, JSString *p)
- if (is_num_string(&n, p)) {
- if (n <= JS_ATOM_MAX_INT) {
- js_free_string(rt, p);
-- return __JS_AtomFromUInt32(n);
-+ return JS_AtomFromUInt32(n);
- }
- }
- /* XXX: should generate an exception */
-- return __JS_NewAtom(rt, p, JS_ATOM_TYPE_STRING);
-+ return JS_NewAtomImpl(rt, p, JS_ATOM_TYPE_STRING);
- }
-
- JSAtom JS_NewAtomLen(JSContext *ctx, const char *str, size_t len)
-@@ -2954,7 +3010,7 @@ JSAtom JS_NewAtomLen(JSContext *ctx, const char *str, size_t len)
- JSValue val;
-
- if (len == 0 || !is_digit(*str)) {
-- JSAtom atom = __JS_FindAtom(ctx->rt, str, len, JS_ATOM_TYPE_STRING);
-+ JSAtom atom = JS_FindAtom(ctx->rt, str, len, JS_ATOM_TYPE_STRING);
- if (atom)
- return atom;
- }
-@@ -2972,7 +3028,7 @@ JSAtom JS_NewAtom(JSContext *ctx, const char *str)
- JSAtom JS_NewAtomUInt32(JSContext *ctx, uint32_t n)
- {
- if (n <= JS_ATOM_MAX_INT) {
-- return __JS_AtomFromUInt32(n);
-+ return JS_AtomFromUInt32(n);
- } else {
- char buf[11];
- JSValue val;
-@@ -2980,7 +3036,7 @@ JSAtom JS_NewAtomUInt32(JSContext *ctx, uint32_t n)
- val = JS_NewString(ctx, buf);
- if (JS_IsException(val))
- return JS_ATOM_NULL;
-- return __JS_NewAtom(ctx->rt, JS_VALUE_GET_STRING(val),
-+ return JS_NewAtomImpl(ctx->rt, JS_VALUE_GET_STRING(val),
- JS_ATOM_TYPE_STRING);
- }
- }
-@@ -2988,7 +3044,7 @@ JSAtom JS_NewAtomUInt32(JSContext *ctx, uint32_t n)
- static JSAtom JS_NewAtomInt64(JSContext *ctx, int64_t n)
- {
- if ((uint64_t)n <= JS_ATOM_MAX_INT) {
-- return __JS_AtomFromUInt32((uint32_t)n);
-+ return JS_AtomFromUInt32((uint32_t)n);
- } else {
- char buf[24];
- JSValue val;
-@@ -2996,7 +3052,7 @@ static JSAtom JS_NewAtomInt64(JSContext *ctx, int64_t n)
- val = JS_NewString(ctx, buf);
- if (JS_IsException(val))
- return JS_ATOM_NULL;
-- return __JS_NewAtom(ctx->rt, JS_VALUE_GET_STRING(val),
-+ return JS_NewAtomImpl(ctx->rt, JS_VALUE_GET_STRING(val),
- JS_ATOM_TYPE_STRING);
- }
- }
-@@ -3006,7 +3062,7 @@ static JSValue JS_NewSymbol(JSContext *ctx, JSString *p, int atom_type)
- {
- JSRuntime *rt = ctx->rt;
- JSAtom atom;
-- atom = __JS_NewAtom(rt, p, atom_type);
-+ atom = JS_NewAtomImpl(rt, p, atom_type);
- if (atom == JS_ATOM_NULL)
- return JS_ThrowOutOfMemory(ctx);
- return JS_MKPTR(JS_TAG_SYMBOL, rt->atom_array[atom]);
-@@ -3019,7 +3075,7 @@ static JSValue JS_NewSymbolFromAtom(JSContext *ctx, JSAtom descr,
- JSRuntime *rt = ctx->rt;
- JSString *p;
-
-- assert(!__JS_AtomIsTaggedInt(descr));
-+ assert(!JS_AtomIsTaggedInt(descr));
- assert(descr < rt->atom_size);
- p = rt->atom_array[descr];
- JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, p));
-@@ -3032,8 +3088,8 @@ static JSValue JS_NewSymbolFromAtom(JSContext *ctx, JSAtom descr,
- static const char *JS_AtomGetStrRT(JSRuntime *rt, char *buf, int buf_size,
- JSAtom atom)
- {
-- if (__JS_AtomIsTaggedInt(atom)) {
-- snprintf(buf, buf_size, "%u", __JS_AtomToUInt32(atom));
-+ if (JS_AtomIsTaggedInt(atom)) {
-+ snprintf(buf, buf_size, "%u", JS_AtomToUInt32(atom));
- } else {
- JSAtomStruct *p;
- assert(atom < rt->atom_size);
-@@ -3083,12 +3139,12 @@ static const char *JS_AtomGetStr(JSContext *ctx, char *buf, int buf_size, JSAtom
- return JS_AtomGetStrRT(ctx->rt, buf, buf_size, atom);
- }
-
--static JSValue __JS_AtomToValue(JSContext *ctx, JSAtom atom, BOOL force_string)
-+static JSValue JS_AtomToValueImpl(JSContext *ctx, JSAtom atom, BOOL force_string)
- {
- char buf[ATOM_GET_STR_BUF_SIZE];
-
-- if (__JS_AtomIsTaggedInt(atom)) {
-- snprintf(buf, sizeof(buf), "%u", __JS_AtomToUInt32(atom));
-+ if (JS_AtomIsTaggedInt(atom)) {
-+ snprintf(buf, sizeof(buf), "%u", JS_AtomToUInt32(atom));
- return JS_NewString(ctx, buf);
- } else {
- JSRuntime *rt = ctx->rt;
-@@ -3112,20 +3168,20 @@ static JSValue __JS_AtomToValue(JSContext *ctx, JSAtom atom, BOOL force_string)
-
- JSValue JS_AtomToValue(JSContext *ctx, JSAtom atom)
- {
-- return __JS_AtomToValue(ctx, atom, FALSE);
-+ return JS_AtomToValueImpl(ctx, atom, FALSE);
- }
-
- JSValue JS_AtomToString(JSContext *ctx, JSAtom atom)
- {
-- return __JS_AtomToValue(ctx, atom, TRUE);
-+ return JS_AtomToValueImpl(ctx, atom, TRUE);
- }
-
- /* 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);
-+ if (JS_AtomIsTaggedInt(atom)) {
-+ *pval = JS_AtomToUInt32(atom);
- return TRUE;
- } else {
- JSRuntime *rt = ctx->rt;
-@@ -3156,8 +3212,8 @@ static JSValue JS_AtomIsNumericIndex1(JSContext *ctx, JSAtom atom)
- int c, len, ret;
- JSValue num, str;
-
-- if (__JS_AtomIsTaggedInt(atom))
-- return JS_NewInt32(ctx, __JS_AtomToUInt32(atom));
-+ if (JS_AtomIsTaggedInt(atom))
-+ return JS_NewInt32(ctx, JS_AtomToUInt32(atom));
- assert(atom < rt->atom_size);
- p1 = rt->atom_array[atom];
- if (p1->atom_type != JS_ATOM_TYPE_STRING)
-@@ -3199,7 +3255,7 @@ static JSValue JS_AtomIsNumericIndex1(JSContext *ctx, JSAtom atom)
- /* -0 case is specific */
- if (c == '0' && len == 2) {
- minus_zero:
-- return __JS_NewFloat64(ctx, -0.0);
-+ return JS_NewFloat64Impl(ctx, -0.0);
- }
- }
- if (!is_num(c)) {
-@@ -3244,14 +3300,14 @@ static int JS_AtomIsNumericIndex(JSContext *ctx, JSAtom atom)
-
- void JS_FreeAtom(JSContext *ctx, JSAtom v)
- {
-- if (!__JS_AtomIsConst(v))
-- __JS_FreeAtom(ctx->rt, v);
-+ if (!JS_AtomIsConst(v))
-+ JS_FreeAtomImpl(ctx->rt, v);
- }
-
- void JS_FreeAtomRT(JSRuntime *rt, JSAtom v)
- {
-- if (!__JS_AtomIsConst(v))
-- __JS_FreeAtom(rt, v);
-+ if (!JS_AtomIsConst(v))
-+ JS_FreeAtomImpl(rt, v);
- }
-
- /* return TRUE if 'v' is a symbol with a string description */
-@@ -3261,7 +3317,7 @@ static BOOL JS_AtomSymbolHasDescription(JSContext *ctx, JSAtom v)
- JSAtomStruct *p;
-
- rt = ctx->rt;
-- if (__JS_AtomIsTaggedInt(v))
-+ if (JS_AtomIsTaggedInt(v))
- return FALSE;
- p = rt->atom_array[v];
- return (((p->atom_type == JS_ATOM_TYPE_SYMBOL &&
-@@ -3270,7 +3326,7 @@ static BOOL JS_AtomSymbolHasDescription(JSContext *ctx, JSAtom v)
- !(p->len == 0 && p->is_wide_char != 0));
- }
-
--static __maybe_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;
-@@ -3445,9 +3501,9 @@ int JS_NewClass(JSRuntime *rt, JSClassID class_id, const JSClassDef *class_def)
- JSAtom name;
-
- len = strlen(class_def->class_name);
-- name = __JS_FindAtom(rt, class_def->class_name, len, JS_ATOM_TYPE_STRING);
-+ name = JS_FindAtom(rt, class_def->class_name, len, JS_ATOM_TYPE_STRING);
- if (name == JS_ATOM_NULL) {
-- name = __JS_NewAtomInit(rt, class_def->class_name, len, JS_ATOM_TYPE_STRING);
-+ name = JS_NewAtomInitImpl(rt, class_def->class_name, len, JS_ATOM_TYPE_STRING);
- if (name == JS_ATOM_NULL)
- return -1;
- }
-@@ -4614,7 +4670,7 @@ static int add_shape_property(JSContext *ctx, JSShape **psh,
- pr = &prop[sh->prop_count++];
- pr->atom = JS_DupAtom(ctx, atom);
- pr->flags = prop_flags;
-- sh->has_small_array_index |= __JS_AtomIsTaggedInt(atom);
-+ sh->has_small_array_index |= JS_AtomIsTaggedInt(atom);
- /* add in hash table */
- hash_mask = sh->prop_hash_mask;
- h = atom & hash_mask;
-@@ -4675,7 +4731,7 @@ static JSShape *find_hashed_shape_prop(JSRuntime *rt, JSShape *sh,
- return NULL;
- }
-
--static __maybe_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;
-@@ -4691,7 +4747,7 @@ static __maybe_unused void JS_DumpShape(JSRuntime *rt, int i, JSShape *sh)
- printf("\n");
- }
-
--static __maybe_unused void JS_DumpShapes(JSRuntime *rt)
-+static maybe_unused void JS_DumpShapes(JSRuntime *rt)
- {
- int i;
- JSShape *sh;
-@@ -5471,7 +5527,7 @@ static void free_zero_refcount(JSRuntime *rt)
- }
-
- /* called with the ref_count of 'v' reaches zero. */
--void __JS_FreeValueRT(JSRuntime *rt, JSValue v)
-+static void JS_FreeValueRTImpl(JSRuntime *rt, JSValue v)
- {
- uint32_t tag = JS_VALUE_GET_TAG(v);
-
-@@ -5546,9 +5602,9 @@ void __JS_FreeValueRT(JSRuntime *rt, JSValue v)
- }
- }
-
--void __JS_FreeValue(JSContext *ctx, JSValue v)
-+static void JS_FreeValueImpl(JSContext *ctx, JSValue v)
- {
-- __JS_FreeValueRT(ctx->rt, v);
-+ JS_FreeValueRTImpl(ctx->rt, v);
- }
-
- /* garbage collection */
-@@ -6469,7 +6525,7 @@ static const char *get_func_name(JSContext *ctx, JSValueConst func)
-
- /* if filename != NULL, an additional level is added with the filename
- and line number information (used for parse error). */
--static void build_backtrace(JSContext *ctx, JSValueConst error_obj,
-+void build_backtrace(JSContext *ctx, JSValueConst error_obj,
- const char *filename, int line_num,
- int backtrace_flags)
- {
-@@ -6569,7 +6625,7 @@ JSValue JS_NewError(JSContext *ctx)
- static JSValue JS_ThrowError2(JSContext *ctx, JSErrorEnum error_num,
- const char *fmt, va_list ap, BOOL add_backtrace)
- {
-- char buf[256];
-+ char buf[8192];
- JSValue obj, ret;
-
- vsnprintf(buf, sizeof(buf), fmt, ap);
-@@ -6604,7 +6660,7 @@ static JSValue JS_ThrowError(JSContext *ctx, JSErrorEnum error_num,
- return JS_ThrowError2(ctx, error_num, fmt, ap, add_backtrace);
- }
-
--JSValue __attribute__((format(printf, 2, 3))) JS_ThrowSyntaxError(JSContext *ctx, const char *fmt, ...)
-+JSValue FORMAT_ATTR(2, 3) JS_ThrowSyntaxError(JSContext *ctx, const char *fmt, ...)
- {
- JSValue val;
- va_list ap;
-@@ -6615,7 +6671,7 @@ JSValue __attribute__((format(printf, 2, 3))) JS_ThrowSyntaxError(JSContext *ctx
- return val;
- }
-
--JSValue __attribute__((format(printf, 2, 3))) JS_ThrowTypeError(JSContext *ctx, const char *fmt, ...)
-+JSValue FORMAT_ATTR(2, 3) JS_ThrowTypeError(JSContext *ctx, const char *fmt, ...)
- {
- JSValue val;
- va_list ap;
-@@ -6626,7 +6682,7 @@ JSValue __attribute__((format(printf, 2, 3))) JS_ThrowTypeError(JSContext *ctx,
- return val;
- }
-
--static int __attribute__((format(printf, 3, 4))) JS_ThrowTypeErrorOrFalse(JSContext *ctx, int flags, const char *fmt, ...)
-+static int FORMAT_ATTR(3, 4) JS_ThrowTypeErrorOrFalse(JSContext *ctx, int flags, const char *fmt, ...)
- {
- va_list ap;
-
-@@ -6642,7 +6698,7 @@ static int __attribute__((format(printf, 3, 4))) JS_ThrowTypeErrorOrFalse(JSCont
- }
-
- /* never use it directly */
--static JSValue __attribute__((format(printf, 3, 4))) __JS_ThrowTypeErrorAtom(JSContext *ctx, JSAtom atom, const char *fmt, ...)
-+static JSValue FORMAT_ATTR(3, 4) JS_ThrowTypeErrorAtomImpl(JSContext *ctx, JSAtom atom, const char *fmt, ...)
- {
- char buf[ATOM_GET_STR_BUF_SIZE];
- return JS_ThrowTypeError(ctx, fmt,
-@@ -6650,7 +6706,7 @@ static JSValue __attribute__((format(printf, 3, 4))) __JS_ThrowTypeErrorAtom(JSC
- }
-
- /* never use it directly */
--static JSValue __attribute__((format(printf, 3, 4))) __JS_ThrowSyntaxErrorAtom(JSContext *ctx, JSAtom atom, const char *fmt, ...)
-+static JSValue FORMAT_ATTR(3, 4) JS_ThrowSyntaxErrorAtomImpl(JSContext *ctx, JSAtom atom, const char *fmt, ...)
- {
- char buf[ATOM_GET_STR_BUF_SIZE];
- return JS_ThrowSyntaxError(ctx, fmt,
-@@ -6659,8 +6715,8 @@ static JSValue __attribute__((format(printf, 3, 4))) __JS_ThrowSyntaxErrorAtom(J
-
- /* %s is replaced by 'atom'. The macro is used so that gcc can check
- the format string. */
--#define JS_ThrowTypeErrorAtom(ctx, fmt, atom) __JS_ThrowTypeErrorAtom(ctx, atom, fmt, "")
--#define JS_ThrowSyntaxErrorAtom(ctx, fmt, atom) __JS_ThrowSyntaxErrorAtom(ctx, atom, fmt, "")
-+#define JS_ThrowTypeErrorAtom(ctx, fmt, atom) JS_ThrowTypeErrorAtomImpl(ctx, atom, fmt, "")
-+#define JS_ThrowSyntaxErrorAtom(ctx, fmt, atom) JS_ThrowSyntaxErrorAtomImpl(ctx, atom, fmt, "")
-
- static int JS_ThrowTypeErrorReadOnly(JSContext *ctx, int flags, JSAtom atom)
- {
-@@ -6673,7 +6729,7 @@ static int JS_ThrowTypeErrorReadOnly(JSContext *ctx, int flags, JSAtom atom)
- }
- }
-
--JSValue __attribute__((format(printf, 2, 3))) JS_ThrowReferenceError(JSContext *ctx, const char *fmt, ...)
-+JSValue FORMAT_ATTR(2, 3) JS_ThrowReferenceError(JSContext *ctx, const char *fmt, ...)
- {
- JSValue val;
- va_list ap;
-@@ -6684,7 +6740,7 @@ JSValue __attribute__((format(printf, 2, 3))) JS_ThrowReferenceError(JSContext *
- return val;
- }
-
--JSValue __attribute__((format(printf, 2, 3))) JS_ThrowRangeError(JSContext *ctx, const char *fmt, ...)
-+JSValue FORMAT_ATTR(2, 3) JS_ThrowRangeError(JSContext *ctx, const char *fmt, ...)
- {
- JSValue val;
- va_list ap;
-@@ -6695,7 +6751,7 @@ JSValue __attribute__((format(printf, 2, 3))) JS_ThrowRangeError(JSContext *ctx,
- return val;
- }
-
--JSValue __attribute__((format(printf, 2, 3))) JS_ThrowInternalError(JSContext *ctx, const char *fmt, ...)
-+JSValue FORMAT_ATTR(2, 3) JS_ThrowInternalError(JSContext *ctx, const char *fmt, ...)
- {
- JSValue val;
- va_list ap;
-@@ -6770,7 +6826,7 @@ static JSValue JS_ThrowTypeErrorInvalidClass(JSContext *ctx, int class_id)
- return JS_ThrowTypeErrorAtom(ctx, "%s object expected", name);
- }
-
--static no_inline __exception int __js_poll_interrupts(JSContext *ctx)
-+static no_inline warn_unused int js_poll_interrupts_impl(JSContext *ctx)
- {
- JSRuntime *rt = ctx->rt;
- ctx->interrupt_counter = JS_INTERRUPT_COUNTER_INIT;
-@@ -6785,10 +6841,10 @@ static no_inline __exception int __js_poll_interrupts(JSContext *ctx)
- return 0;
- }
-
--static inline __exception int js_poll_interrupts(JSContext *ctx)
-+static inline warn_unused int js_poll_interrupts(JSContext *ctx)
- {
- if (unlikely(--ctx->interrupt_counter <= 0)) {
-- return __js_poll_interrupts(ctx);
-+ return js_poll_interrupts_impl(ctx);
- } else {
- return 0;
- }
-@@ -7092,9 +7148,9 @@ JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj,
- case JS_TAG_STRING:
- {
- JSString *p1 = JS_VALUE_GET_STRING(obj);
-- if (__JS_AtomIsTaggedInt(prop)) {
-+ if (JS_AtomIsTaggedInt(prop)) {
- uint32_t idx, ch;
-- idx = __JS_AtomToUInt32(prop);
-+ idx = JS_AtomToUInt32(prop);
- if (idx < p1->len) {
- if (p1->is_wide_char)
- ch = p1->u.str16[idx];
-@@ -7144,14 +7200,16 @@ JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj,
- continue;
- }
- } else {
-+ if (JS_IsUndefined(pr->u.value) && ctx->handleUndefined)
-+ ctx->handleUndefined(ctx);
- return JS_DupValue(ctx, pr->u.value);
- }
- }
- if (unlikely(p->is_exotic)) {
- /* exotic behaviors */
- if (p->fast_array) {
-- if (__JS_AtomIsTaggedInt(prop)) {
-- uint32_t idx = __JS_AtomToUInt32(prop);
-+ if (JS_AtomIsTaggedInt(prop)) {
-+ uint32_t idx = JS_AtomToUInt32(prop);
- if (idx < p->u.array.count) {
- /* we avoid duplicating the code */
- return JS_GetPropertyUint32(ctx, JS_MKPTR(JS_TAG_OBJECT, p), idx);
-@@ -7242,7 +7300,7 @@ static int JS_DefinePrivateField(JSContext *ctx, JSValueConst obj,
- JS_ThrowTypeErrorNotASymbol(ctx);
- goto fail;
- }
-- prop = js_symbol_to_atom(ctx, (JSValue)name);
-+ prop = js_symbol_to_atom(ctx, name);
- p = JS_VALUE_GET_OBJ(obj);
- prs = find_own_property(&pr, p, prop);
- if (prs) {
-@@ -7273,7 +7331,7 @@ static JSValue JS_GetPrivateField(JSContext *ctx, JSValueConst obj,
- /* safety check */
- if (unlikely(JS_VALUE_GET_TAG(name) != JS_TAG_SYMBOL))
- return JS_ThrowTypeErrorNotASymbol(ctx);
-- prop = js_symbol_to_atom(ctx, (JSValue)name);
-+ prop = js_symbol_to_atom(ctx, name);
- p = JS_VALUE_GET_OBJ(obj);
- prs = find_own_property(&pr, p, prop);
- if (!prs) {
-@@ -7300,7 +7358,7 @@ static int JS_SetPrivateField(JSContext *ctx, JSValueConst obj,
- JS_ThrowTypeErrorNotASymbol(ctx);
- goto fail;
- }
-- prop = js_symbol_to_atom(ctx, (JSValue)name);
-+ prop = js_symbol_to_atom(ctx, name);
- p = JS_VALUE_GET_OBJ(obj);
- prs = find_own_property(&pr, p, prop);
- if (!prs) {
-@@ -7390,7 +7448,7 @@ static int JS_CheckBrand(JSContext *ctx, JSValueConst obj, JSValueConst func)
- 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));
-+ prs = find_own_property(&pr, p, js_symbol_to_atom(ctx, brand));
- if (!prs) {
- JS_ThrowTypeError(ctx, "invalid brand on object");
- return -1;
-@@ -7445,7 +7503,7 @@ static void js_free_prop_enum(JSContext *ctx, JSPropertyEnum *tab, uint32_t len)
-
- /* 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,
-+static int warn_unused JS_GetOwnPropertyNamesInternal(JSContext *ctx,
- JSPropertyEnum **ptab,
- uint32_t *plen,
- JSObject *p, int flags)
-@@ -7595,7 +7653,7 @@ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx,
- len = js_string_obj_get_length(ctx, JS_MKPTR(JS_TAG_OBJECT, p));
- add_array_keys:
- for(i = 0; i < len; i++) {
-- tab_atom[num_index].atom = __JS_AtomFromUInt32(i);
-+ tab_atom[num_index].atom = JS_AtomFromUInt32(i);
- if (tab_atom[num_index].atom == JS_ATOM_NULL) {
- js_free_prop_enum(ctx, tab_atom, num_index);
- return -1;
-@@ -7703,9 +7761,9 @@ retry:
- if (p->is_exotic) {
- if (p->fast_array) {
- /* specific case for fast arrays */
-- if (__JS_AtomIsTaggedInt(prop)) {
-+ if (JS_AtomIsTaggedInt(prop)) {
- uint32_t idx;
-- idx = __JS_AtomToUInt32(prop);
-+ idx = JS_AtomToUInt32(prop);
- if (idx < p->u.array.count) {
- if (desc) {
- desc->flags = JS_PROP_WRITABLE | JS_PROP_ENUMERABLE |
-@@ -7825,7 +7883,7 @@ JSAtom JS_ValueToAtom(JSContext *ctx, JSValueConst val)
- if (tag == JS_TAG_INT &&
- (uint32_t)JS_VALUE_GET_INT(val) <= JS_ATOM_MAX_INT) {
- /* fast path for integer values */
-- atom = __JS_AtomFromUInt32(JS_VALUE_GET_INT(val));
-+ atom = JS_AtomFromUInt32(JS_VALUE_GET_INT(val));
- } else if (tag == JS_TAG_SYMBOL) {
- JSAtomStruct *p = JS_VALUE_GET_PTR(val);
- atom = JS_DupAtom(ctx, js_get_atom_index(ctx->rt, p));
-@@ -7856,7 +7914,7 @@ static JSValue JS_GetPropertyValue(JSContext *ctx, JSValueConst this_obj,
- /* fast path for array access */
- p = JS_VALUE_GET_OBJ(this_obj);
- idx = JS_VALUE_GET_INT(prop);
-- len = (uint32_t)p->u.array.count;
-+ len = p->u.array.count;
- if (unlikely(idx >= len))
- goto slow_path;
- switch(p->class_id) {
-@@ -7883,9 +7941,9 @@ static JSValue JS_GetPropertyValue(JSContext *ctx, JSValueConst this_obj,
- return JS_NewBigUint64(ctx, p->u.array.u.uint64_ptr[idx]);
- #endif
- case JS_CLASS_FLOAT32_ARRAY:
-- return __JS_NewFloat64(ctx, p->u.array.u.float_ptr[idx]);
-+ return JS_NewFloat64Impl(ctx, p->u.array.u.float_ptr[idx]);
- case JS_CLASS_FLOAT64_ARRAY:
-- return __JS_NewFloat64(ctx, p->u.array.u.double_ptr[idx]);
-+ return JS_NewFloat64Impl(ctx, p->u.array.u.double_ptr[idx]);
- default:
- goto slow_path;
- }
-@@ -7920,7 +7978,7 @@ static int JS_TryGetPropertyInt64(JSContext *ctx, JSValueConst obj, int64_t idx,
-
- if (likely((uint64_t)idx <= JS_ATOM_MAX_INT)) {
- /* fast path */
-- present = JS_HasProperty(ctx, obj, __JS_AtomFromUInt32(idx));
-+ present = JS_HasProperty(ctx, obj, JS_AtomFromUInt32(idx));
- if (present > 0) {
- val = JS_GetPropertyValue(ctx, obj, JS_NewInt32(ctx, idx));
- if (unlikely(JS_IsException(val)))
-@@ -8017,7 +8075,7 @@ static JSProperty *add_property(JSContext *ctx,
-
- /* can be called on Array or Arguments objects. return < 0 if
- memory alloc error. */
--static no_inline __exception int convert_fast_array_to_array(JSContext *ctx,
-+static no_inline warn_unused int convert_fast_array_to_array(JSContext *ctx,
- JSObject *p)
- {
- JSProperty *pr;
-@@ -8039,8 +8097,8 @@ static no_inline __exception int convert_fast_array_to_array(JSContext *ctx,
- tab = p->u.array.u.values;
- for(i = 0; i < len; i++) {
- /* add_property cannot fail here but
-- __JS_AtomFromUInt32(i) fails for i > INT32_MAX */
-- pr = add_property(ctx, p, __JS_AtomFromUInt32(i), JS_PROP_C_W_E);
-+ JS_AtomFromUInt32(i) fails for i > INT32_MAX */
-+ pr = add_property(ctx, p, JS_AtomFromUInt32(i), JS_PROP_C_W_E);
- pr->u.value = *tab++;
- }
- js_free(ctx, p->u.array.u.values);
-@@ -8145,7 +8203,7 @@ static int call_setter(JSContext *ctx, JSObject *setter,
- func = JS_MKPTR(JS_TAG_OBJECT, setter);
- /* Note: the field could be removed in the setter */
- func = JS_DupValue(ctx, func);
-- ret = JS_CallFree(ctx, func, this_obj, 1, (JSValueConst *)&val);
-+ ret = JS_CallFree(ctx, func, this_obj, 1, &val);
- JS_FreeValue(ctx, val);
- if (JS_IsException(ret))
- return -1;
-@@ -8489,8 +8547,8 @@ retry:
- for(;;) {
- if (p1->is_exotic) {
- if (p1->fast_array) {
-- if (__JS_AtomIsTaggedInt(prop)) {
-- uint32_t idx = __JS_AtomToUInt32(prop);
-+ if (JS_AtomIsTaggedInt(prop)) {
-+ uint32_t idx = JS_AtomToUInt32(prop);
- if (idx < p1->u.array.count) {
- if (unlikely(p == p1))
- return JS_SetPropertyValue(ctx, this_obj, JS_NewInt32(ctx, idx), val, flags);
-@@ -8610,8 +8668,8 @@ retry:
-
- if (p->is_exotic) {
- if (p->class_id == JS_CLASS_ARRAY && p->fast_array &&
-- __JS_AtomIsTaggedInt(prop)) {
-- uint32_t idx = __JS_AtomToUInt32(prop);
-+ JS_AtomIsTaggedInt(prop)) {
-+ uint32_t idx = JS_AtomToUInt32(prop);
- if (idx == p->u.array.count) {
- /* fast case */
- return add_fast_array_element(ctx, p, val, flags);
-@@ -8662,7 +8720,7 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj,
- JSShape *sh1;
-
- /* fast path to add an element to the array */
-- if (idx != (uint32_t)p->u.array.count ||
-+ if (idx != p->u.array.count ||
- !p->fast_array || !p->extensible)
- goto slow_path;
- /* check if prototype chain has a numeric property */
-@@ -8837,8 +8895,8 @@ static int JS_CreateProperty(JSContext *ctx, JSObject *p,
- uint32_t idx, len;
-
- if (p->fast_array) {
-- if (__JS_AtomIsTaggedInt(prop)) {
-- idx = __JS_AtomToUInt32(prop);
-+ if (JS_AtomIsTaggedInt(prop)) {
-+ idx = JS_AtomToUInt32(prop);
- if (idx == p->u.array.count) {
- if (!p->extensible)
- goto not_extensible;
-@@ -9042,7 +9100,7 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
- return -1;
- }
- /* this code relies on the fact that Uint32 are never allocated */
-- val = (JSValueConst)JS_NewUint32(ctx, array_length);
-+ val = JS_NewUint32(ctx, array_length);
- /* prs may have been modified */
- prs = find_own_property(&pr, p, prop);
- assert(prs != NULL);
-@@ -9214,8 +9272,8 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
- uint32_t idx;
- uint32_t prop_flags;
- if (p->class_id == JS_CLASS_ARRAY) {
-- if (__JS_AtomIsTaggedInt(prop)) {
-- idx = __JS_AtomToUInt32(prop);
-+ if (JS_AtomIsTaggedInt(prop)) {
-+ idx = JS_AtomToUInt32(prop);
- if (idx < p->u.array.count) {
- prop_flags = get_prop_flags(flags, JS_PROP_C_W_E);
- if (prop_flags != JS_PROP_C_W_E)
-@@ -9238,7 +9296,7 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
- JSValue num;
- int ret;
-
-- if (!__JS_AtomIsTaggedInt(prop)) {
-+ if (!JS_AtomIsTaggedInt(prop)) {
- /* slow path with to handle all numeric indexes */
- num = JS_AtomIsNumericIndex1(ctx, prop);
- if (JS_IsUndefined(num))
-@@ -9259,10 +9317,10 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
- if (ret) {
- return JS_ThrowTypeErrorOrFalse(ctx, flags, "negative index in typed array");
- }
-- if (!__JS_AtomIsTaggedInt(prop))
-+ if (!JS_AtomIsTaggedInt(prop))
- goto typed_array_oob;
- }
-- idx = __JS_AtomToUInt32(prop);
-+ idx = JS_AtomToUInt32(prop);
- /* if the typed array is detached, p->u.array.count = 0 */
- if (idx >= typed_array_get_length(ctx, p)) {
- typed_array_oob:
-@@ -9563,6 +9621,11 @@ static JSValue JS_GetGlobalVar(JSContext *ctx, JSAtom prop,
- return JS_ThrowReferenceErrorUninitialized(ctx, prs->atom);
- return JS_DupValue(ctx, pr->u.value);
- }
-+ if (ctx->scopeLookup) {
-+ struct LookupResult result = ctx->scopeLookup(ctx, prop);
-+ if (result.useResult)
-+ return result.value;
-+ }
- return JS_GetPropertyInternal(ctx, ctx->global_obj, prop,
- ctx->global_obj, throw_ref_error);
- }
-@@ -9658,6 +9721,15 @@ static int JS_SetGlobalVar(JSContext *ctx, JSAtom prop, JSValue val,
- flags = JS_PROP_THROW_STRICT;
- if (is_strict_mode(ctx))
- flags |= JS_PROP_NO_ADD;
-+
-+ if (ctx->scopeLookup) {
-+ struct LookupResult result = ctx->scopeLookup(ctx, prop);
-+ if (result.useResult) {
-+ JS_FreeValue(ctx, result.value);
-+ return JS_SetPropertyInternal(ctx, result.scope, prop, val, flags);
-+ }
-+ }
-+
- return JS_SetPropertyInternal(ctx, ctx->global_obj, prop, val, flags);
- }
-
-@@ -9693,7 +9765,7 @@ int JS_DeletePropertyInt64(JSContext *ctx, JSValueConst obj, int64_t idx, int fl
-
- if ((uint64_t)idx <= JS_ATOM_MAX_INT) {
- /* fast path for fast arrays */
-- return JS_DeleteProperty(ctx, obj, __JS_AtomFromUInt32(idx), flags);
-+ return JS_DeleteProperty(ctx, obj, JS_AtomFromUInt32(idx), flags);
- }
- prop = JS_NewAtomInt64(ctx, idx);
- if (prop == JS_ATOM_NULL)
-@@ -9853,7 +9925,7 @@ static JSValue JS_ToPrimitiveFree(JSContext *ctx, JSValue val, int hint)
- break;
- }
- arg = JS_AtomToString(ctx, atom);
-- ret = JS_CallFree(ctx, method, val, 1, (JSValueConst *)&arg);
-+ ret = JS_CallFree(ctx, method, val, 1, &arg);
- JS_FreeValue(ctx, arg);
- if (JS_IsException(ret))
- goto exception;
-@@ -10057,7 +10129,7 @@ static double js_strtod(const char *p, int radix, BOOL is_float)
- if (is_neg)
- d = -d;
- } else {
-- d = strtod(p, NULL);
-+ d = safe_strtod(p, NULL);
- }
- return d;
- }
-@@ -10237,7 +10309,7 @@ static JSValue js_atof(JSContext *ctx, const char *str, const char **pp,
- } else
- #endif
- {
-- double d = 1.0 / 0.0;
-+ double d = INFINITY;
- if (is_neg)
- d = -d;
- val = JS_NewFloat64(ctx, d);
-@@ -10270,11 +10342,8 @@ static JSValue js_atof(JSContext *ctx, const char *str, const char **pp,
- ((*p == 'p' || *p == 'P') && (radix == 2 || radix == 8 || radix == 16)))) {
- const char *p1 = p + 1;
- is_float = TRUE;
-- if (*p1 == '+') {
-- p1++;
-- } else if (*p1 == '-') {
-+ if (*p1 == '+' || *p1 == '-')
- p1++;
-- }
- if (is_digit((uint8_t)*p1)) {
- p = p1 + 1;
- while (is_digit((uint8_t)*p) || (*p == sep && is_digit((uint8_t)p[1])))
-@@ -10509,7 +10578,7 @@ static JSValue JS_ToNumeric(JSContext *ctx, JSValueConst val)
- return JS_ToNumericFree(ctx, JS_DupValue(ctx, val));
- }
-
--static __exception int __JS_ToFloat64Free(JSContext *ctx, double *pres,
-+static warn_unused int JS_ToFloat64FreeImpl(JSContext *ctx, double *pres,
- JSValue val)
- {
- double d;
-@@ -10560,7 +10629,7 @@ static inline int JS_ToFloat64Free(JSContext *ctx, double *pres, JSValue val)
- *pres = JS_VALUE_GET_FLOAT64(val);
- return 0;
- } else {
-- return __JS_ToFloat64Free(ctx, pres, val);
-+ return JS_ToFloat64FreeImpl(ctx, pres, val);
- }
- }
-
-@@ -10575,7 +10644,7 @@ static JSValue JS_ToNumber(JSContext *ctx, JSValueConst val)
- }
-
- /* same as JS_ToNumber() but return 0 in case of NaN/Undefined */
--static __maybe_unused JSValue JS_ToIntegerFree(JSContext *ctx, JSValue val)
-+static maybe_unused JSValue JS_ToIntegerFree(JSContext *ctx, JSValue val)
- {
- uint32_t tag;
- JSValue ret;
-@@ -10990,7 +11059,7 @@ static int JS_ToUint8ClampFree(JSContext *ctx, int32_t *pres, JSValue val)
- return 0;
- }
-
--static __exception int JS_ToArrayLengthFree(JSContext *ctx, uint32_t *plen,
-+static warn_unused int JS_ToArrayLengthFree(JSContext *ctx, uint32_t *plen,
- JSValue val, BOOL is_array_ctor)
- {
- uint32_t tag, len;
-@@ -11092,7 +11161,7 @@ int JS_ToIndex(JSContext *ctx, uint64_t *plen, JSValueConst val)
-
- /* convert a value to a length between 0 and MAX_SAFE_INTEGER.
- return -1 for exception */
--static __exception int JS_ToLengthFree(JSContext *ctx, int64_t *plen,
-+static warn_unused int JS_ToLengthFree(JSContext *ctx, int64_t *plen,
- JSValue val)
- {
- int res = JS_ToInt64Clamp(ctx, plen, val, 0, MAX_SAFE_INTEGER, 0);
-@@ -11338,7 +11407,7 @@ static int js_ecvt(double d, int n_digits, int *decpt, int *sign, char *buf,
- n_digits = (n_digits_min + n_digits_max) / 2;
- js_ecvt1(d, n_digits, decpt, sign, buf, FE_TONEAREST,
- buf_tmp, sizeof(buf_tmp));
-- if (strtod(buf_tmp, NULL) == d) {
-+ if (safe_strtod(buf_tmp, NULL) == d) {
- /* no need to keep the trailing zeros */
- while (n_digits >= 2 && buf[n_digits - 1] == '0')
- n_digits--;
-@@ -11700,14 +11769,14 @@ static JSValue JS_ToQuotedString(JSContext *ctx, JSValueConst val1)
- return JS_EXCEPTION;
- }
-
--static __maybe_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 __maybe_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];
-@@ -11784,7 +11853,7 @@ static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p)
- printf("[autoinit %p %d %p]",
- (void *)js_autoinit_get_realm(pr),
- js_autoinit_get_id(pr),
-- (void *)pr->u.init.opaque);
-+ pr->u.init.opaque);
- } else {
- JS_DumpValueShort(rt, pr->u.value);
- }
-@@ -11813,7 +11882,7 @@ static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p)
- printf("\n");
- }
-
--static __maybe_unused void JS_DumpGCObject(JSRuntime *rt, JSGCObjectHeader *p)
-+static maybe_unused void JS_DumpGCObject(JSRuntime *rt, JSGCObjectHeader *p)
- {
- if (p->gc_obj_type == JS_GC_OBJ_TYPE_JS_OBJECT) {
- JS_DumpObject(rt, (JSObject *)p);
-@@ -11845,7 +11914,7 @@ static __maybe_unused void JS_DumpGCObject(JSRuntime *rt, JSGCObjectHeader *p)
- }
- }
-
--static __maybe_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);
-@@ -11950,13 +12019,13 @@ static __maybe_unused void JS_DumpValueShort(JSRuntime *rt,
- }
- }
-
--static __maybe_unused void JS_DumpValue(JSContext *ctx,
-+static maybe_unused void JS_DumpValue(JSContext *ctx,
- JSValueConst val)
- {
- JS_DumpValueShort(ctx->rt, val);
- }
-
--static __maybe_unused void JS_PrintValue(JSContext *ctx,
-+static maybe_unused void JS_PrintValue(JSContext *ctx,
- const char *str,
- JSValueConst val)
- {
-@@ -12439,7 +12508,7 @@ static JSObject *find_binary_op(JSBinaryOperatorDef *def,
-
- /* return -1 if exception, 0 if no operator overloading, 1 if
- overloaded operator called */
--static __exception int js_call_binary_op_fallback(JSContext *ctx,
-+static WARN_UNUSED int js_call_binary_op_fallback(JSContext *ctx,
- JSValue *pret,
- JSValueConst op1,
- JSValueConst op2,
-@@ -12568,7 +12637,7 @@ static __exception int js_call_binary_op_fallback(JSContext *ctx,
-
- /* try to call the operation on the operatorSet field of 'obj'. Only
- used for "/" and "**" on the BigInt prototype in math mode */
--static __exception int js_call_binary_op_simple(JSContext *ctx,
-+static WARN_UNUSED int js_call_binary_op_simple(JSContext *ctx,
- JSValue *pret,
- JSValueConst obj,
- JSValueConst op1,
-@@ -12625,7 +12694,7 @@ static __exception int js_call_binary_op_simple(JSContext *ctx,
-
- /* return -1 if exception, 0 if no operator overloading, 1 if
- overloaded operator called */
--static __exception int js_call_unary_op_fallback(JSContext *ctx,
-+static WARN_UNUSED int js_call_unary_op_fallback(JSContext *ctx,
- JSValue *pret,
- JSValueConst op1,
- OPCodeEnum op)
-@@ -12835,7 +12904,7 @@ static int js_unary_arith_bigdecimal(JSContext *ctx,
- return 0;
- }
-
--static no_inline __exception int js_unary_arith_slow(JSContext *ctx,
-+static no_inline WARN_UNUSED int js_unary_arith_slow(JSContext *ctx,
- JSValue *sp,
- OPCodeEnum op)
- {
-@@ -12933,7 +13002,7 @@ static no_inline __exception int js_unary_arith_slow(JSContext *ctx,
- return -1;
- }
-
--static __exception int js_post_inc_slow(JSContext *ctx,
-+static WARN_UNUSED int js_post_inc_slow(JSContext *ctx,
- JSValue *sp, OPCodeEnum op)
- {
- JSValue op1;
-@@ -13288,7 +13357,7 @@ static int js_binary_arith_bigdecimal(JSContext *ctx, OPCodeEnum op,
- return -1;
- }
-
--static no_inline __exception int js_binary_arith_slow(JSContext *ctx, JSValue *sp,
-+static no_inline WARN_UNUSED int js_binary_arith_slow(JSContext *ctx, JSValue *sp,
- OPCodeEnum op)
- {
- JSValue op1, op2, res;
-@@ -13452,7 +13521,7 @@ static no_inline __exception int js_binary_arith_slow(JSContext *ctx, JSValue *s
- return -1;
- }
-
--static no_inline __exception int js_add_slow(JSContext *ctx, JSValue *sp)
-+static no_inline WARN_UNUSED int js_add_slow(JSContext *ctx, JSValue *sp)
- {
- JSValue op1, op2, res;
- uint32_t tag1, tag2;
-@@ -13566,7 +13635,7 @@ static no_inline __exception int js_add_slow(JSContext *ctx, JSValue *sp)
- return -1;
- }
-
--static no_inline __exception int js_binary_logic_slow(JSContext *ctx,
-+static no_inline WARN_UNUSED int js_binary_logic_slow(JSContext *ctx,
- JSValue *sp,
- OPCodeEnum op)
- {
-@@ -13916,7 +13985,7 @@ static BOOL tag_is_number(uint32_t tag)
- tag == JS_TAG_BIG_DECIMAL);
- }
-
--static no_inline __exception int js_eq_slow(JSContext *ctx, JSValue *sp,
-+static no_inline WARN_UNUSED int js_eq_slow(JSContext *ctx, JSValue *sp,
- BOOL is_neq)
- {
- JSValue op1, op2, ret;
-@@ -14192,7 +14261,7 @@ int JS_ToBigInt64(JSContext *ctx, int64_t *pres, JSValueConst val)
- return -1;
- }
-
--static no_inline __exception int js_unary_arith_slow(JSContext *ctx,
-+static no_inline warn_unused int js_unary_arith_slow(JSContext *ctx,
- JSValue *sp,
- OPCodeEnum op)
- {
-@@ -14224,7 +14293,7 @@ static no_inline __exception int js_unary_arith_slow(JSContext *ctx,
- }
-
- /* specific case necessary for correct return value semantics */
--static __exception int js_post_inc_slow(JSContext *ctx,
-+static warn_unused int js_post_inc_slow(JSContext *ctx,
- JSValue *sp, OPCodeEnum op)
- {
- JSValue op1;
-@@ -14241,7 +14310,7 @@ static __exception int js_post_inc_slow(JSContext *ctx,
- return 0;
- }
-
--static no_inline __exception int js_binary_arith_slow(JSContext *ctx, JSValue *sp,
-+static no_inline warn_unused int js_binary_arith_slow(JSContext *ctx, JSValue *sp,
- OPCodeEnum op)
- {
- JSValue op1, op2;
-@@ -14283,7 +14352,7 @@ static no_inline __exception int js_binary_arith_slow(JSContext *ctx, JSValue *s
- return -1;
- }
-
--static no_inline __exception int js_add_slow(JSContext *ctx, JSValue *sp)
-+static no_inline warn_unused int js_add_slow(JSContext *ctx, JSValue *sp)
- {
- JSValue op1, op2;
- uint32_t tag1, tag2;
-@@ -14331,7 +14400,7 @@ static no_inline __exception int js_add_slow(JSContext *ctx, JSValue *sp)
- return -1;
- }
-
--static no_inline __exception int js_binary_logic_slow(JSContext *ctx,
-+static no_inline warn_unused int js_binary_logic_slow(JSContext *ctx,
- JSValue *sp,
- OPCodeEnum op)
- {
-@@ -14458,7 +14527,7 @@ static no_inline int js_relational_slow(JSContext *ctx, JSValue *sp,
- return -1;
- }
-
--static no_inline __exception int js_eq_slow(JSContext *ctx, JSValue *sp,
-+static no_inline warn_unused int js_eq_slow(JSContext *ctx, JSValue *sp,
- BOOL is_neq)
- {
- JSValue op1, op2;
-@@ -14744,7 +14813,7 @@ static no_inline int js_strict_eq_slow(JSContext *ctx, JSValue *sp,
- return 0;
- }
-
--static __exception int js_operator_in(JSContext *ctx, JSValue *sp)
-+static warn_unused int js_operator_in(JSContext *ctx, JSValue *sp)
- {
- JSValue op1, op2;
- JSAtom atom;
-@@ -14770,7 +14839,7 @@ static __exception int js_operator_in(JSContext *ctx, JSValue *sp)
- return 0;
- }
-
--static __exception int js_has_unscopable(JSContext *ctx, JSValueConst obj,
-+static warn_unused int js_has_unscopable(JSContext *ctx, JSValueConst obj,
- JSAtom atom)
- {
- JSValue arr, val;
-@@ -14788,7 +14857,7 @@ static __exception int js_has_unscopable(JSContext *ctx, JSValueConst obj,
- return ret;
- }
-
--static __exception int js_operator_instanceof(JSContext *ctx, JSValue *sp)
-+static warn_unused int js_operator_instanceof(JSContext *ctx, JSValue *sp)
- {
- JSValue op1, op2;
- BOOL ret;
-@@ -14804,7 +14873,7 @@ static __exception int js_operator_instanceof(JSContext *ctx, JSValue *sp)
- return 0;
- }
-
--static __exception int js_operator_typeof(JSContext *ctx, JSValueConst op1)
-+static warn_unused int js_operator_typeof(JSContext *ctx, JSValueConst op1)
- {
- JSAtom atom;
- uint32_t tag;
-@@ -14861,7 +14930,7 @@ static __exception int js_operator_typeof(JSContext *ctx, JSValueConst op1)
- return atom;
- }
-
--static __exception int js_operator_delete(JSContext *ctx, JSValue *sp)
-+static warn_unused int js_operator_delete(JSContext *ctx, JSValue *sp)
- {
- JSValue op1, op2;
- JSAtom atom;
-@@ -15016,7 +15085,7 @@ static JSValue js_build_mapped_arguments(JSContext *ctx, int argc,
- var_ref = get_var_ref(ctx, sf, i, TRUE);
- if (!var_ref)
- goto fail;
-- pr = add_property(ctx, p, __JS_AtomFromUInt32(i), JS_PROP_C_W_E | JS_PROP_VARREF);
-+ pr = add_property(ctx, p, JS_AtomFromUInt32(i), JS_PROP_C_W_E | JS_PROP_VARREF);
- if (!pr) {
- free_var_ref(ctx->rt, var_ref);
- goto fail;
-@@ -15188,7 +15257,7 @@ static JSValue build_for_in_iterator(JSContext *ctx, JSValue obj)
- }
-
- /* obj -> enum_obj */
--static __exception int js_for_in_start(JSContext *ctx, JSValue *sp)
-+static warn_unused int js_for_in_start(JSContext *ctx, JSValue *sp)
- {
- sp[-1] = build_for_in_iterator(ctx, sp[-1]);
- if (JS_IsException(sp[-1]))
-@@ -15197,7 +15266,7 @@ static __exception int js_for_in_start(JSContext *ctx, JSValue *sp)
- }
-
- /* enum_obj -> enum_obj value done */
--static __exception int js_for_in_next(JSContext *ctx, JSValue *sp)
-+static warn_unused int js_for_in_next(JSContext *ctx, JSValue *sp)
- {
- JSValueConst enum_obj;
- JSObject *p;
-@@ -15218,7 +15287,7 @@ static __exception int js_for_in_next(JSContext *ctx, JSValue *sp)
- if (it->is_array) {
- if (it->idx >= it->array_length)
- goto done;
-- prop = __JS_AtomFromUInt32(it->idx);
-+ prop = JS_AtomFromUInt32(it->idx);
- it->idx++;
- } else {
- JSShape *sh = p->shape;
-@@ -15411,7 +15480,7 @@ static int JS_IteratorClose(JSContext *ctx, JSValueConst enum_obj,
- }
-
- /* obj -> enum_rec (3 slots) */
--static __exception int js_for_of_start(JSContext *ctx, JSValue *sp,
-+static warn_unused int js_for_of_start(JSContext *ctx, JSValue *sp,
- BOOL is_async)
- {
- JSValue op1, obj, method;
-@@ -15432,7 +15501,7 @@ static __exception int js_for_of_start(JSContext *ctx, JSValue *sp,
- objs. If 'done' is true or in case of exception, 'enum_rec' is set
- to undefined. If 'done' is true, 'value' is always set to
- undefined. */
--static __exception int js_for_of_next(JSContext *ctx, JSValue *sp, int offset)
-+static warn_unused int js_for_of_next(JSContext *ctx, JSValue *sp, int offset)
- {
- JSValue value = JS_UNDEFINED;
- int done = 1;
-@@ -15478,7 +15547,7 @@ static JSValue JS_IteratorGetCompleteValue(JSContext *ctx, JSValueConst obj,
- return JS_EXCEPTION;
- }
-
--static __exception int js_iterator_get_value_done(JSContext *ctx, JSValue *sp)
-+static warn_unused int js_iterator_get_value_done(JSContext *ctx, JSValue *sp)
- {
- JSValue obj, value;
- BOOL done;
-@@ -15554,7 +15623,7 @@ static BOOL js_get_fast_array(JSContext *ctx, JSValueConst obj,
- return FALSE;
- }
-
--static __exception int js_append_enumerate(JSContext *ctx, JSValue *sp)
-+static warn_unused int js_append_enumerate(JSContext *ctx, JSValue *sp)
- {
- JSValue iterator, enumobj, method, value;
- int is_array_iterator;
-@@ -15634,7 +15703,7 @@ exception:
- return -1;
- }
-
--static __exception int JS_CopyDataProperties(JSContext *ctx,
-+static warn_unused int JS_CopyDataProperties(JSContext *ctx,
- JSValueConst target,
- JSValueConst source,
- JSValueConst excluded,
-@@ -16043,7 +16112,7 @@ static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj,
- #else
- sf->js_mode = 0;
- #endif
-- sf->cur_func = (JSValue)func_obj;
-+ sf->cur_func = func_obj;
- sf->arg_count = argc;
- arg_buf = argv;
-
-@@ -16056,7 +16125,7 @@ static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj,
- arg_buf[i] = JS_UNDEFINED;
- sf->arg_count = arg_count;
- }
-- sf->arg_buf = (JSValue*)arg_buf;
-+ sf->arg_buf = arg_buf;
-
- func = p->u.cfunc.c_function;
- switch(cproto) {
-@@ -16226,7 +16295,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
- #include "quickjs-opcode.h"
- [ OP_COUNT ... 255 ] = &&case_default
- };
--#define SWITCH(pc) goto *dispatch_table[opcode = *pc++];
-+#define SWITCH(pc) goto *dispatch_table[opcode = *(pc)++];
- #define CASE(op) case_ ## op
- #define DEFAULT case_default
- #define BREAK SWITCH(pc)
-@@ -16269,7 +16338,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
- return JS_ThrowTypeError(caller_ctx, "not a function");
- }
- return call_func(caller_ctx, func_obj, this_obj, argc,
-- (JSValueConst *)argv, flags);
-+ argv, flags);
- }
- b = p->u.func.function_bytecode;
-
-@@ -16287,7 +16356,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
- sf->js_mode = b->js_mode;
- arg_buf = argv;
- sf->arg_count = argc;
-- sf->cur_func = (JSValue)func_obj;
-+ sf->cur_func = func_obj;
- init_list_head(&sf->var_ref_list);
- var_refs = p->u.func.var_refs;
-
-@@ -16315,6 +16384,9 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
- rt->current_stack_frame = sf;
- ctx = b->realm; /* set the current realm */
-
-+ if (ctx->handleFunctionEntered)
-+ ctx->handleFunctionEntered(ctx, this_obj);
-+
- restart:
- for(;;) {
- int call_argc;
-@@ -16420,12 +16492,12 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
- int arg = *pc++;
- switch(arg) {
- case OP_SPECIAL_OBJECT_ARGUMENTS:
-- *sp++ = js_build_arguments(ctx, argc, (JSValueConst *)argv);
-+ *sp++ = js_build_arguments(ctx, argc, 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,
-+ *sp++ = js_build_mapped_arguments(ctx, argc, argv,
- sf, min_int(argc, b->arg_count));
- if (unlikely(JS_IsException(sp[-1])))
- goto exception;
-@@ -16465,7 +16537,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
- {
- int first = get_u16(pc);
- pc += 2;
-- *sp++ = js_build_rest(ctx, first, argc, (JSValueConst *)argv);
-+ *sp++ = js_build_rest(ctx, first, argc, argv);
- if (unlikely(JS_IsException(sp[-1])))
- goto exception;
- }
-@@ -16698,7 +16770,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
- goto exception;
- call_argv = sp - call_argc;
- for(i = 0; i < call_argc; i++) {
-- ret = JS_DefinePropertyValue(ctx, ret_val, __JS_AtomFromUInt32(i), call_argv[i],
-+ ret = JS_DefinePropertyValue(ctx, ret_val, JS_AtomFromUInt32(i), call_argv[i],
- JS_PROP_C_W_E | JS_PROP_THROW);
- call_argv[i] = JS_UNDEFINED;
- if (ret < 0) {
-@@ -16717,7 +16789,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
- magic = get_u16(pc);
- pc += 2;
-
-- ret_val = js_function_apply(ctx, sp[-3], 2, (JSValueConst *)&sp[-2], magic);
-+ ret_val = js_function_apply(ctx, sp[-3], 2, &sp[-2], magic);
- if (unlikely(JS_IsException(ret_val)))
- goto exception;
- JS_FreeValue(ctx, sp[-3]);
-@@ -16850,7 +16922,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
- JS_EVAL_TYPE_DIRECT, scope_idx);
- } else {
- ret_val = JS_Call(ctx, sp[-2], JS_UNDEFINED, len,
-- (JSValueConst *)tab);
-+ tab);
- }
- free_arg_list(ctx, tab, len);
- if (unlikely(JS_IsException(ret_val)))
-@@ -17474,7 +17546,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
- {
- JSValue ret;
- ret = JS_Call(ctx, sp[-3], sp[-4],
-- 1, (JSValueConst *)(sp - 1));
-+ 1, (sp - 1));
- if (JS_IsException(ret))
- goto exception;
- JS_FreeValue(ctx, sp[-1]);
-@@ -17502,7 +17574,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
- 0, NULL);
- } else {
- ret = JS_CallFree(ctx, method, sp[-4],
-- 1, (JSValueConst *)(sp - 1));
-+ 1, (sp - 1));
- }
- if (JS_IsException(ret))
- goto exception;
-@@ -17925,7 +17997,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
- sp[-2] = JS_NewInt32(ctx, r);
- sp--;
- } else if (JS_VALUE_IS_BOTH_FLOAT(op1, op2)) {
-- sp[-2] = __JS_NewFloat64(ctx, JS_VALUE_GET_FLOAT64(op1) +
-+ sp[-2] = JS_NewFloat64Impl(ctx, JS_VALUE_GET_FLOAT64(op1) +
- JS_VALUE_GET_FLOAT64(op2));
- sp--;
- } else {
-@@ -17990,7 +18062,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
- sp[-2] = JS_NewInt32(ctx, r);
- sp--;
- } else if (JS_VALUE_IS_BOTH_FLOAT(op1, op2)) {
-- sp[-2] = __JS_NewFloat64(ctx, JS_VALUE_GET_FLOAT64(op1) -
-+ sp[-2] = JS_NewFloat64Impl(ctx, JS_VALUE_GET_FLOAT64(op1) -
- JS_VALUE_GET_FLOAT64(op2));
- sp--;
- } else {
-@@ -18033,7 +18105,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
- #endif
- d = JS_VALUE_GET_FLOAT64(op1) * JS_VALUE_GET_FLOAT64(op2);
- mul_fp_res:
-- sp[-2] = __JS_NewFloat64(ctx, d);
-+ sp[-2] = JS_NewFloat64Impl(ctx, d);
- sp--;
- } else {
- goto binary_arith_slow;
-@@ -18125,7 +18197,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
- } else if (JS_TAG_IS_FLOAT64(tag)) {
- d = -JS_VALUE_GET_FLOAT64(op1);
- neg_fp_res:
-- sp[-1] = __JS_NewFloat64(ctx, d);
-+ sp[-1] = JS_NewFloat64Impl(ctx, d);
- } else {
- if (js_unary_arith_slow(ctx, sp, opcode))
- goto exception;
-@@ -18659,6 +18731,13 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
- }
- }
- exception:
-+ if (JS_IsString(rt->current_exception)) {
-+ JSValue error_obj = JS_NewError(ctx);
-+ JSAtom msgProp = JS_NewAtom(ctx, "message");
-+ JS_DefinePropertyValue(ctx, error_obj, msgProp, rt->current_exception, 0);
-+ rt->current_exception = error_obj;
-+ JS_FreeAtom(ctx, msgProp);
-+ }
- if (is_backtrace_needed(ctx, rt->current_exception)) {
- /* add the backtrace information now (it is not done
- before if the exception happens in a bytecode
-@@ -18706,6 +18785,8 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
- }
- }
- rt->current_stack_frame = sf->prev_frame;
-+ if (ctx->handleFunctionExited)
-+ ctx->handleFunctionExited(ctx);
- return ret_val;
- }
-
-@@ -18713,14 +18794,14 @@ JSValue JS_Call(JSContext *ctx, JSValueConst func_obj, JSValueConst this_obj,
- int argc, JSValueConst *argv)
- {
- return JS_CallInternal(ctx, func_obj, this_obj, JS_UNDEFINED,
-- argc, (JSValue *)argv, JS_CALL_FLAG_COPY_ARGV);
-+ argc, argv, JS_CALL_FLAG_COPY_ARGV);
- }
-
- static JSValue JS_CallFree(JSContext *ctx, JSValue func_obj, JSValueConst this_obj,
- int argc, JSValueConst *argv)
- {
- JSValue res = JS_CallInternal(ctx, func_obj, this_obj, JS_UNDEFINED,
-- argc, (JSValue *)argv, JS_CALL_FLAG_COPY_ARGV);
-+ argc, argv, JS_CALL_FLAG_COPY_ARGV);
- JS_FreeValue(ctx, func_obj);
- return res;
- }
-@@ -18825,7 +18906,7 @@ static JSValue JS_CallConstructorInternal(JSContext *ctx,
- return JS_ThrowTypeError(ctx, "not a function");
- }
- return call_func(ctx, func_obj, new_target, argc,
-- (JSValueConst *)argv, flags);
-+ argv, flags);
- }
-
- b = p->u.func.function_bytecode;
-@@ -18854,7 +18935,7 @@ JSValue JS_CallConstructor2(JSContext *ctx, JSValueConst func_obj,
- int argc, JSValueConst *argv)
- {
- return JS_CallConstructorInternal(ctx, func_obj, new_target,
-- argc, (JSValue *)argv,
-+ argc, argv,
- JS_CALL_FLAG_COPY_ARGV);
- }
-
-@@ -18862,7 +18943,7 @@ JSValue JS_CallConstructor(JSContext *ctx, JSValueConst func_obj,
- int argc, JSValueConst *argv)
- {
- return JS_CallConstructorInternal(ctx, func_obj, func_obj,
-- argc, (JSValue *)argv,
-+ argc, argv,
- JS_CALL_FLAG_COPY_ARGV);
- }
-
-@@ -18885,7 +18966,7 @@ static JSValue JS_InvokeFree(JSContext *ctx, JSValue this_val, JSAtom atom,
- }
-
- /* JSAsyncFunctionState (used by generator and async functions) */
--static __exception int async_func_init(JSContext *ctx, JSAsyncFunctionState *s,
-+static warn_unused int async_func_init(JSContext *ctx, JSAsyncFunctionState *s,
- JSValueConst func_obj, JSValueConst this_obj,
- int argc, JSValueConst *argv)
- {
-@@ -19227,7 +19308,7 @@ static void js_async_function_resume(JSContext *ctx, JSAsyncFunctionData *s)
- fail:
- error = JS_GetException(ctx);
- ret2 = JS_Call(ctx, s->resolving_funcs[1], JS_UNDEFINED,
-- 1, (JSValueConst *)&error);
-+ 1, &error);
- JS_FreeValue(ctx, error);
- js_async_function_terminate(ctx->rt, s);
- JS_FreeValue(ctx, ret2); /* XXX: what to do if exception ? */
-@@ -19238,7 +19319,7 @@ static void js_async_function_resume(JSContext *ctx, JSAsyncFunctionData *s)
- if (JS_IsUndefined(func_ret)) {
- /* function returned */
- ret2 = JS_Call(ctx, s->resolving_funcs[0], JS_UNDEFINED,
-- 1, (JSValueConst *)&value);
-+ 1, &value);
- JS_FreeValue(ctx, ret2); /* XXX: what to do if exception ? */
- JS_FreeValue(ctx, value);
- js_async_function_terminate(ctx->rt, s);
-@@ -19249,7 +19330,7 @@ static void js_async_function_resume(JSContext *ctx, JSAsyncFunctionData *s)
- /* await */
- JS_FreeValue(ctx, func_ret); /* not used */
- promise = js_promise_resolve(ctx, ctx->promise_ctor,
-- 1, (JSValueConst *)&value, 0);
-+ 1, &value, 0);
- JS_FreeValue(ctx, value);
- if (JS_IsException(promise))
- goto fail;
-@@ -19531,7 +19612,7 @@ static int js_async_generator_completed_return(JSContext *ctx,
- int res;
-
- promise = js_promise_resolve(ctx, ctx->promise_ctor,
-- 1, (JSValueConst *)&value, 0);
-+ 1, &value, 0);
- if (JS_IsException(promise))
- return -1;
- if (js_async_generator_resolve_function_create(ctx,
-@@ -19703,7 +19784,7 @@ static JSValue js_async_generator_next(JSContext *ctx, JSValueConst this_val,
- JS_ThrowTypeError(ctx, "not an AsyncGenerator object");
- err = JS_GetException(ctx);
- res2 = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED,
-- 1, (JSValueConst *)&err);
-+ 1, &err);
- JS_FreeValue(ctx, err);
- JS_FreeValue(ctx, res2);
- JS_FreeValue(ctx, resolving_funcs[0]);
-@@ -20138,7 +20219,7 @@ static const JSOpCode opcode_info[OP_COUNT + (OP_TEMP_END - OP_TEMP_START)] = {
- #define short_opcode_info(op) opcode_info[op]
- #endif
-
--static __exception int next_token(JSParseState *s);
-+static warn_unused int next_token(JSParseState *s);
-
- static void free_token(JSParseState *s, JSToken *token)
- {
-@@ -20169,7 +20250,7 @@ static void free_token(JSParseState *s, JSToken *token)
- }
- }
-
--static void __attribute((unused)) dump_token(JSParseState *s,
-+static void maybe_unused dump_token(JSParseState *s,
- const JSToken *token)
- {
- switch(token->val) {
-@@ -20230,7 +20311,7 @@ static void __attribute((unused)) dump_token(JSParseState *s,
- }
- }
-
--int __attribute__((format(printf, 2, 3))) js_parse_error(JSParseState *s, const char *fmt, ...)
-+int FORMAT_ATTR(2, 3) js_parse_error(JSParseState *s, const char *fmt, ...)
- {
- JSContext *ctx = s->ctx;
- va_list ap;
-@@ -20276,7 +20357,7 @@ static int js_parse_error_reserved_identifier(JSParseState *s)
- s->token.u.ident.atom));
- }
-
--static __exception int js_parse_template_part(JSParseState *s, const uint8_t *p)
-+static warn_unused int js_parse_template_part(JSParseState *s, const uint8_t *p)
- {
- uint32_t c;
- StringBuffer b_s, *b = &b_s;
-@@ -20337,7 +20418,7 @@ static __exception int js_parse_template_part(JSParseState *s, const uint8_t *p)
- return -1;
- }
-
--static __exception int js_parse_string(JSParseState *s, int sep,
-+static warn_unused int js_parse_string(JSParseState *s, int sep,
- BOOL do_throw, const uint8_t *p,
- JSToken *token, const uint8_t **pp)
- {
-@@ -20482,7 +20563,7 @@ static inline BOOL token_is_pseudo_keyword(JSParseState *s, JSAtom atom) {
- !s->token.u.ident.has_escape;
- }
-
--static __exception int js_parse_regexp(JSParseState *s)
-+static warn_unused int js_parse_regexp(JSParseState *s)
- {
- const uint8_t *p;
- BOOL in_class;
-@@ -20580,8 +20661,8 @@ static __exception int js_parse_regexp(JSParseState *s)
- return -1;
- }
-
--static __exception int ident_realloc(JSContext *ctx, char **pbuf, size_t *psize,
-- char *static_buf)
-+static warn_unused int ident_realloc(JSContext *ctx, char **pbuf, size_t *psize,
-+ const char *static_buf)
- {
- char *buf, *new_buf;
- size_t size, new_size;
-@@ -20656,7 +20737,7 @@ static JSAtom parse_ident(JSParseState *s, const uint8_t **pp,
- }
-
-
--static __exception int next_token(JSParseState *s)
-+static warn_unused int next_token(JSParseState *s)
- {
- const uint8_t *p;
- int c;
-@@ -21204,7 +21285,7 @@ static JSAtom json_parse_ident(JSParseState *s, const uint8_t **pp, int c)
- return atom;
- }
-
--static __exception int json_next_token(JSParseState *s)
-+static warn_unused int json_next_token(JSParseState *s)
- {
- const uint8_t *p;
- int c;
-@@ -21644,7 +21725,7 @@ static int cpool_add(JSParseState *s, JSValue val)
- return fd->cpool_count - 1;
- }
-
--static __exception int emit_push_const(JSParseState *s, JSValueConst val,
-+static warn_unused int emit_push_const(JSParseState *s, JSValueConst val,
- BOOL as_atom)
- {
- int idx;
-@@ -21654,7 +21735,7 @@ static __exception int emit_push_const(JSParseState *s, JSValueConst val,
- /* warning: JS_NewAtomStr frees the string value */
- JS_DupValue(s->ctx, val);
- atom = JS_NewAtomStr(s->ctx, JS_VALUE_GET_STRING(val));
-- if (atom != JS_ATOM_NULL && !__JS_AtomIsTaggedInt(atom)) {
-+ if (atom != JS_ATOM_NULL && !JS_AtomIsTaggedInt(atom)) {
- emit_op(s, OP_push_atom_value);
- emit_u32(s, atom);
- return 0;
-@@ -22118,14 +22199,14 @@ static int add_private_class_field(JSParseState *s, JSFunctionDef *fd,
- return idx;
- }
-
--static __exception int js_parse_expr(JSParseState *s);
--static __exception int js_parse_function_decl(JSParseState *s,
-+static warn_unused int js_parse_expr(JSParseState *s);
-+static warn_unused int js_parse_function_decl(JSParseState *s,
- JSParseFunctionEnum func_type,
- 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,
-+static warn_unused int js_parse_function_decl2(JSParseState *s,
- JSParseFunctionEnum func_type,
- JSFunctionKindEnum func_kind,
- JSAtom func_name,
-@@ -22133,9 +22214,9 @@ static __exception int js_parse_function_decl2(JSParseState *s,
- int function_line_num,
- JSParseExportEnum export_flag,
- JSFunctionDef **pfd);
--static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags);
--static __exception int js_parse_assign_expr(JSParseState *s);
--static __exception int js_parse_unary(JSParseState *s, int parse_flags);
-+static warn_unused int js_parse_assign_expr2(JSParseState *s, int parse_flags);
-+static warn_unused int js_parse_assign_expr(JSParseState *s);
-+static warn_unused int js_parse_unary(JSParseState *s, int parse_flags);
- static void push_break_entry(JSFunctionDef *fd, BlockEnv *be,
- JSAtom label_name,
- int label_break, int label_cont,
-@@ -22162,7 +22243,7 @@ static int seal_template_obj(JSContext *ctx, JSValueConst obj)
- return 0;
- }
-
--static __exception int js_parse_template(JSParseState *s, int call, int *argc)
-+static warn_unused int js_parse_template(JSParseState *s, int call, int *argc)
- {
- JSContext *ctx = s->ctx;
- JSValue raw_array, template_object;
-@@ -22293,7 +22374,7 @@ 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,
-+static int warn_unused js_parse_property_name(JSParseState *s,
- JSAtom *pname,
- BOOL allow_method, BOOL allow_var,
- BOOL allow_private)
-@@ -22435,7 +22516,7 @@ static int js_parse_get_pos(JSParseState *s, JSParsePos *sp)
- return 0;
- }
-
--static __exception int js_parse_seek_token(JSParseState *s, const JSParsePos *sp)
-+static warn_unused int js_parse_seek_token(JSParseState *s, const JSParsePos *sp)
- {
- s->token.line_num = sp->last_line_num;
- s->line_num = sp->line_num;
-@@ -22480,7 +22561,8 @@ static int js_parse_skip_parens_token(JSParseState *s, int *pbits, BOOL no_line_
- size_t level = 0;
- JSParsePos pos;
- int last_tok, tok = TOK_EOF;
-- int c, tok_len, bits = 0;
-+ int tok_len, bits = 0;
-+ char c;
-
- /* protect from underflow */
- state[level++] = 0;
-@@ -22640,7 +22722,7 @@ static void set_object_name_computed(JSParseState *s)
- }
- }
-
--static __exception int js_parse_object_literal(JSParseState *s)
-+static warn_unused int js_parse_object_literal(JSParseState *s)
- {
- JSAtom name = JS_ATOM_NULL;
- const uint8_t *start_ptr;
-@@ -22765,15 +22847,15 @@ static __exception int js_parse_object_literal(JSParseState *s)
- /* forbid the exponentiation operator in js_parse_unary() */
- #define PF_POW_FORBIDDEN (1 << 4)
-
--static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags);
-+static warn_unused int js_parse_postfix_expr(JSParseState *s, int parse_flags);
-
--static __exception int js_parse_left_hand_side_expr(JSParseState *s)
-+static warn_unused int js_parse_left_hand_side_expr(JSParseState *s)
- {
- return js_parse_postfix_expr(s, PF_POSTFIX_CALL);
- }
-
- /* XXX: could generate specific bytecode */
--static __exception int js_parse_class_default_ctor(JSParseState *s,
-+static warn_unused int js_parse_class_default_ctor(JSParseState *s,
- BOOL has_super,
- JSFunctionDef **pfd)
- {
-@@ -22864,7 +22946,7 @@ typedef struct {
- int brand_push_pos;
- } ClassFieldsDef;
-
--static __exception int emit_class_init_start(JSParseState *s,
-+static warn_unused int emit_class_init_start(JSParseState *s,
- ClassFieldsDef *cf)
- {
- int label_add_brand;
-@@ -22897,7 +22979,7 @@ static __exception int emit_class_init_start(JSParseState *s,
- return 0;
- }
-
--static __exception int add_brand(JSParseState *s, ClassFieldsDef *cf)
-+static warn_unused int add_brand(JSParseState *s, ClassFieldsDef *cf)
- {
- if (!cf->has_brand) {
- /* define the brand field in 'this' of the initializer */
-@@ -22929,7 +23011,7 @@ static void emit_class_init_end(JSParseState *s, ClassFieldsDef *cf)
- }
-
-
--static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr,
-+static warn_unused int js_parse_class(JSParseState *s, BOOL is_class_expr,
- JSParseExportEnum export_flag)
- {
- JSContext *ctx = s->ctx;
-@@ -23374,7 +23456,7 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr,
- return -1;
- }
-
--static __exception int js_parse_array_literal(JSParseState *s)
-+static warn_unused int js_parse_array_literal(JSParseState *s)
- {
- uint32_t idx;
- BOOL need_length;
-@@ -23410,7 +23492,7 @@ static __exception int js_parse_array_literal(JSParseState *s)
- if (js_parse_assign_expr(s))
- return -1;
- emit_op(s, OP_define_field);
-- emit_u32(s, __JS_AtomFromUInt32(idx));
-+ emit_u32(s, JS_AtomFromUInt32(idx));
- need_length = FALSE;
- }
- idx++;
-@@ -23520,7 +23602,7 @@ static BOOL has_with_scope(JSFunctionDef *s, int scope_level)
- return FALSE;
- }
-
--static __exception int get_lvalue(JSParseState *s, int *popcode, int *pscope,
-+static warn_unused int get_lvalue(JSParseState *s, int *popcode, int *pscope,
- JSAtom *pname, int *plabel, int *pdepth, BOOL keep,
- int tok)
- {
-@@ -23760,7 +23842,7 @@ static void put_lvalue(JSParseState *s, int opcode, int scope,
- }
- }
-
--static __exception int js_parse_expr_paren(JSParseState *s)
-+static warn_unused int js_parse_expr_paren(JSParseState *s)
- {
- if (js_parse_expect(s, '('))
- return -1;
-@@ -23778,7 +23860,7 @@ static int js_unsupported_keyword(JSParseState *s, JSAtom atom)
- JS_AtomGetStr(s->ctx, buf, sizeof(buf), atom));
- }
-
--static __exception int js_define_var(JSParseState *s, JSAtom name, int tok)
-+static warn_unused int js_define_var(JSParseState *s, JSAtom name, int tok)
- {
- JSFunctionDef *fd = s->cur_func;
- JSVarDefEnum var_def_type;
-@@ -24327,7 +24409,7 @@ static void optional_chain_test(JSParseState *s, int *poptional_chaining_label,
- }
-
- /* allowed parse_flags: PF_POSTFIX_CALL, PF_ARROW_FUNC */
--static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags)
-+static warn_unused int js_parse_postfix_expr(JSParseState *s, int parse_flags)
- {
- FuncCallType call_type;
- int optional_chaining_label;
-@@ -24963,17 +25045,16 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags)
- return 0;
- }
-
--static __exception int js_parse_delete(JSParseState *s)
-+static warn_unused int js_parse_delete(JSParseState *s)
- {
- JSFunctionDef *fd = s->cur_func;
- JSAtom name;
-- int opcode;
-
- if (next_token(s))
- return -1;
- if (js_parse_unary(s, PF_POW_FORBIDDEN))
- return -1;
-- switch(opcode = get_prev_opcode(fd)) {
-+ switch (get_prev_opcode(fd)) {
- case OP_get_field:
- {
- JSValue val;
-@@ -25024,7 +25105,7 @@ static __exception int js_parse_delete(JSParseState *s)
- }
-
- /* allowed parse_flags: PF_ARROW_FUNC, PF_POW_ALLOWED, PF_POW_FORBIDDEN */
--static __exception int js_parse_unary(JSParseState *s, int parse_flags)
-+static warn_unused int js_parse_unary(JSParseState *s, int parse_flags)
- {
- int op;
-
-@@ -25172,7 +25253,7 @@ static __exception int js_parse_unary(JSParseState *s, int parse_flags)
- }
-
- /* allowed parse_flags: PF_ARROW_FUNC, PF_IN_ACCEPTED */
--static __exception int js_parse_expr_binary(JSParseState *s, int level,
-+static warn_unused int js_parse_expr_binary(JSParseState *s, int level,
- int parse_flags)
- {
- int op, opcode;
-@@ -25319,7 +25400,7 @@ static __exception int js_parse_expr_binary(JSParseState *s, int level,
- }
-
- /* allowed parse_flags: PF_ARROW_FUNC, PF_IN_ACCEPTED */
--static __exception int js_parse_logical_and_or(JSParseState *s, int op,
-+static warn_unused int js_parse_logical_and_or(JSParseState *s, int op,
- int parse_flags)
- {
- int label1;
-@@ -25361,7 +25442,7 @@ static __exception int js_parse_logical_and_or(JSParseState *s, int op,
- return 0;
- }
-
--static __exception int js_parse_coalesce_expr(JSParseState *s, int parse_flags)
-+static warn_unused int js_parse_coalesce_expr(JSParseState *s, int parse_flags)
- {
- int label1;
-
-@@ -25389,7 +25470,7 @@ static __exception int js_parse_coalesce_expr(JSParseState *s, int parse_flags)
- }
-
- /* allowed parse_flags: PF_ARROW_FUNC, PF_IN_ACCEPTED */
--static __exception int js_parse_cond_expr(JSParseState *s, int parse_flags)
-+static warn_unused int js_parse_cond_expr(JSParseState *s, int parse_flags)
- {
- int label1, label2;
-
-@@ -25420,7 +25501,7 @@ static __exception int js_parse_cond_expr(JSParseState *s, int parse_flags)
- static void emit_return(JSParseState *s, BOOL hasval);
-
- /* allowed parse_flags: PF_IN_ACCEPTED */
--static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags)
-+static warn_unused int js_parse_assign_expr2(JSParseState *s, int parse_flags)
- {
- int opcode, op, scope;
- JSAtom name0 = JS_ATOM_NULL;
-@@ -25666,13 +25747,13 @@ static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags)
- return 0;
- }
-
--static __exception int js_parse_assign_expr(JSParseState *s)
-+static warn_unused int js_parse_assign_expr(JSParseState *s)
- {
- return js_parse_assign_expr2(s, PF_IN_ACCEPTED);
- }
-
- /* allowed parse_flags: PF_IN_ACCEPTED */
--static __exception int js_parse_expr2(JSParseState *s, int parse_flags)
-+static warn_unused int js_parse_expr2(JSParseState *s, int parse_flags)
- {
- BOOL comma = FALSE;
- for(;;) {
-@@ -25696,7 +25777,7 @@ static __exception int js_parse_expr2(JSParseState *s, int parse_flags)
- return 0;
- }
-
--static __exception int js_parse_expr(JSParseState *s)
-+static warn_unused int js_parse_expr(JSParseState *s)
- {
- return js_parse_expr2(s, PF_IN_ACCEPTED);
- }
-@@ -25724,7 +25805,7 @@ static void pop_break_entry(JSFunctionDef *fd)
- fd->top_break = be->prev;
- }
-
--static __exception int emit_break(JSParseState *s, JSAtom name, int is_cont)
-+static warn_unused int emit_break(JSParseState *s, JSAtom name, int is_cont)
- {
- BlockEnv *top;
- int i, scope_level;
-@@ -25873,15 +25954,15 @@ static void emit_return(JSParseState *s, BOOL hasval)
- #define DECL_MASK_OTHER (1 << 2) /* all other declarations */
- #define DECL_MASK_ALL (DECL_MASK_FUNC | DECL_MASK_FUNC_WITH_LABEL | DECL_MASK_OTHER)
-
--static __exception int js_parse_statement_or_decl(JSParseState *s,
-+static warn_unused int js_parse_statement_or_decl(JSParseState *s,
- int decl_mask);
-
--static __exception int js_parse_statement(JSParseState *s)
-+static warn_unused int js_parse_statement(JSParseState *s)
- {
- return js_parse_statement_or_decl(s, 0);
- }
-
--static __exception int js_parse_block(JSParseState *s)
-+static warn_unused int js_parse_block(JSParseState *s)
- {
- if (js_parse_expect(s, '{'))
- return -1;
-@@ -25901,7 +25982,7 @@ static __exception int js_parse_block(JSParseState *s)
- }
-
- /* allowed parse_flags: PF_IN_ACCEPTED */
--static __exception int js_parse_var(JSParseState *s, int parse_flags, int tok,
-+static warn_unused int js_parse_var(JSParseState *s, int parse_flags, int tok,
- BOOL export_flag)
- {
- JSContext *ctx = s->ctx;
-@@ -26052,7 +26133,7 @@ static int is_let(JSParseState *s, int decl_mask)
-
- /* XXX: handle IteratorClose when exiting the loop before the
- enumeration is done */
--static __exception int js_parse_for_in_of(JSParseState *s, int label_name,
-+static warn_unused int js_parse_for_in_of(JSParseState *s, int label_name,
- BOOL is_async)
- {
- JSContext *ctx = s->ctx;
-@@ -26283,7 +26364,7 @@ static void set_eval_ret_undefined(JSParseState *s)
- }
- }
-
--static __exception int js_parse_statement_or_decl(JSParseState *s,
-+static warn_unused int js_parse_statement_or_decl(JSParseState *s,
- int decl_mask)
- {
- JSContext *ctx = s->ctx;
-@@ -27603,7 +27684,7 @@ static int find_exported_name(GetExportNamesState *s, JSAtom name)
- return -1;
- }
-
--static __exception int get_exported_names(JSContext *ctx,
-+static warn_unused int get_exported_names(JSContext *ctx,
- GetExportNamesState *s,
- JSModuleDef *m, BOOL from_star)
- {
-@@ -27744,7 +27825,6 @@ static JSValue js_build_module_ns(JSContext *ctx, JSModuleDef *m)
- 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];
- }
- }
-@@ -28237,7 +28317,7 @@ static JSValue js_dynamic_import_job(JSContext *ctx,
- goto exception;
-
- ret = JS_Call(ctx, resolving_funcs[0], JS_UNDEFINED,
-- 1, (JSValueConst *)&ns);
-+ 1, &ns);
- JS_FreeValue(ctx, ret); /* XXX: what to do if exception ? */
- JS_FreeValue(ctx, ns);
- JS_FreeCString(ctx, basename);
-@@ -28246,7 +28326,7 @@ static JSValue js_dynamic_import_job(JSContext *ctx,
-
- err = JS_GetException(ctx);
- ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED,
-- 1, (JSValueConst *)&err);
-+ 1, &err);
- JS_FreeValue(ctx, ret); /* XXX: what to do if exception ? */
- JS_FreeValue(ctx, err);
- JS_FreeCString(ctx, basename);
-@@ -28343,7 +28423,7 @@ static JSValue js_evaluate_module(JSContext *ctx, JSModuleDef *m)
- return ret_val;
- }
-
--static __exception JSAtom js_parse_from_clause(JSParseState *s)
-+static warn_unused JSAtom js_parse_from_clause(JSParseState *s)
- {
- JSAtom module_name;
- if (!token_is_pseudo_keyword(s, JS_ATOM_from)) {
-@@ -28366,7 +28446,7 @@ static __exception JSAtom js_parse_from_clause(JSParseState *s)
- return module_name;
- }
-
--static __exception int js_parse_export(JSParseState *s)
-+static warn_unused int js_parse_export(JSParseState *s)
- {
- JSContext *ctx = s->ctx;
- JSModuleDef *m = s->cur_func->module;
-@@ -28569,7 +28649,7 @@ static int add_import(JSParseState *s, JSModuleDef *m,
- return 0;
- }
-
--static __exception int js_parse_import(JSParseState *s)
-+static warn_unused int js_parse_import(JSParseState *s)
- {
- JSContext *ctx = s->ctx;
- JSModuleDef *m = s->cur_func->module;
-@@ -28684,7 +28764,7 @@ static __exception int js_parse_import(JSParseState *s)
- return js_parse_expect_semi(s);
- }
-
--static __exception int js_parse_source_element(JSParseState *s)
-+static warn_unused int js_parse_source_element(JSParseState *s)
- {
- JSFunctionDef *fd = s->cur_func;
- int tok;
-@@ -29608,8 +29688,7 @@ static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s,
- }
- var_idx = idx;
- break;
-- } else
-- if (vd->var_name == JS_ATOM__with_ && !is_pseudo_var) {
-+ } else if (vd->var_name == JS_ATOM__with_ && !is_pseudo_var) {
- dbuf_putc(bc, OP_get_loc);
- dbuf_put_u16(bc, idx);
- var_object_test(ctx, s, var_name, op, bc, &label_done, 1);
-@@ -30359,7 +30438,7 @@ static void set_closure_from_var(JSContext *ctx, JSClosureVar *cv,
-
- /* for direct eval compilation: add references to the variables of the
- calling function */
--static __exception int add_closure_variables(JSContext *ctx, JSFunctionDef *s,
-+static warn_unused int add_closure_variables(JSContext *ctx, JSFunctionDef *s,
- JSFunctionBytecode *b, int scope_idx)
- {
- int i, count;
-@@ -30779,7 +30858,7 @@ static int get_label_pos(JSFunctionDef *s, int label)
-
- /* convert global variable accesses to local variables or closure
- variables when necessary */
--static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s)
-+static warn_unused int resolve_variables(JSContext *ctx, JSFunctionDef *s)
- {
- int pos, pos_next, bc_len, op, len, i, idx, line_num;
- uint8_t *bc_buf;
-@@ -31343,7 +31422,7 @@ static void put_short_code(DynBuf *bc_out, int op, int idx)
- }
-
- /* peephole optimizations and resolve goto/labels */
--static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s)
-+static warn_unused int resolve_labels(JSContext *ctx, JSFunctionDef *s)
- {
- int pos, pos_next, bc_len, op, op1, len, i, line_num;
- const uint8_t *bc_buf;
-@@ -32152,8 +32231,7 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s)
- bc_out.buf[pos - 1] = jp->op = OP_if_false8 + (op - OP_if_false);
- }
- goto shrink;
-- } else
-- if (diff == (int16_t)diff && op == OP_goto) {
-+ } else if (diff == (int16_t)diff && op == OP_goto) {
- //put_u16(bc_out.buf + pos, diff);
- jp->size = 2;
- delta = 2;
-@@ -32236,7 +32314,7 @@ typedef struct StackSizeState {
- } StackSizeState;
-
- /* 'op' is only used for error indication */
--static __exception int ss_check(JSContext *ctx, StackSizeState *s,
-+static warn_unused int ss_check(JSContext *ctx, StackSizeState *s,
- int pos, int op, int stack_len)
- {
- if ((unsigned)pos >= s->bc_len) {
-@@ -32272,7 +32350,7 @@ static __exception int ss_check(JSContext *ctx, StackSizeState *s,
- return 0;
- }
-
--static __exception int compute_stack_size(JSContext *ctx,
-+static warn_unused int compute_stack_size(JSContext *ctx,
- JSFunctionDef *fd,
- int *pstack_size)
- {
-@@ -32593,7 +32671,9 @@ static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd)
- }
- } else {
- b->vardefs = (void *)((uint8_t*)b + vardefs_offset);
-+ if (fd->arg_count)
- memcpy(b->vardefs, fd->args, fd->arg_count * sizeof(fd->args[0]));
-+ if (fd->var_count)
- memcpy(b->vardefs + fd->arg_count, fd->vars, fd->var_count * sizeof(fd->vars[0]));
- }
- b->var_count = fd->var_count;
-@@ -32721,7 +32801,7 @@ static void free_function_bytecode(JSRuntime *rt, JSFunctionBytecode *b)
- }
- }
-
--static __exception int js_parse_directives(JSParseState *s)
-+static warn_unused int js_parse_directives(JSParseState *s)
- {
- char str[20];
- JSParsePos pos;
-@@ -32895,7 +32975,7 @@ static JSFunctionDef *js_parse_function_class_fields_init(JSParseState *s)
-
- /* 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,
-+static warn_unused int js_parse_function_decl2(JSParseState *s,
- JSParseFunctionEnum func_type,
- JSFunctionKindEnum func_kind,
- JSAtom func_name,
-@@ -33443,7 +33523,7 @@ done:
- return -1;
- }
-
--static __exception int js_parse_function_decl(JSParseState *s,
-+static warn_unused int js_parse_function_decl(JSParseState *s,
- JSParseFunctionEnum func_type,
- JSFunctionKindEnum func_kind,
- JSAtom func_name,
-@@ -33455,7 +33535,7 @@ static __exception int js_parse_function_decl(JSParseState *s,
- NULL);
- }
-
--static __exception int js_parse_program(JSParseState *s)
-+static warn_unused int js_parse_program(JSParseState *s)
- {
- JSFunctionDef *fd = s->cur_func;
- int idx;
-@@ -33497,12 +33577,12 @@ static __exception int js_parse_program(JSParseState *s)
-
- static void js_parse_init(JSContext *ctx, JSParseState *s,
- const char *input, size_t input_len,
-- const char *filename)
-+ const char *filename, int line)
- {
- memset(s, 0, sizeof(*s));
- s->ctx = ctx;
- s->filename = filename;
-- s->line_num = 1;
-+ s->line_num = line;
- s->buf_ptr = (const uint8_t *)input;
- s->buf_end = s->buf_ptr + input_len;
- s->token.val = ' ';
-@@ -33573,9 +33653,9 @@ static void skip_shebang(JSParseState *s)
- }
-
- /* 'input' must be zero terminated i.e. input[input_len] = '\0'. */
--static JSValue __JS_EvalInternal(JSContext *ctx, JSValueConst this_obj,
-+static JSValue JS_EvalInternalImpl(JSContext *ctx, JSValueConst this_obj,
- const char *input, size_t input_len,
-- const char *filename, int flags, int scope_idx)
-+ const char *filename, int line, int flags, int scope_idx)
- {
- JSParseState s1, *s = &s1;
- int err, js_mode, eval_type;
-@@ -33586,7 +33666,7 @@ static JSValue __JS_EvalInternal(JSContext *ctx, JSValueConst this_obj,
- JSFunctionDef *fd;
- JSModuleDef *m;
-
-- js_parse_init(ctx, s, input, input_len, filename);
-+ js_parse_init(ctx, s, input, input_len, filename, line);
- skip_shebang(s);
-
- eval_type = flags & JS_EVAL_TYPE_MASK;
-@@ -33620,7 +33700,7 @@ static JSValue __JS_EvalInternal(JSContext *ctx, JSValueConst this_obj,
- js_mode |= JS_MODE_STRICT;
- }
- }
-- fd = js_new_function_def(ctx, NULL, TRUE, FALSE, filename, 1);
-+ fd = js_new_function_def(ctx, NULL, TRUE, FALSE, filename, line);
- if (!fd)
- goto fail1;
- s->cur_func = fd;
-@@ -33686,12 +33766,12 @@ static JSValue __JS_EvalInternal(JSContext *ctx, JSValueConst this_obj,
- /* the indirection is needed to make 'eval' optional */
- static JSValue JS_EvalInternal(JSContext *ctx, JSValueConst this_obj,
- const char *input, size_t input_len,
-- const char *filename, int flags, int scope_idx)
-+ const char *filename, int line, int flags, int scope_idx)
- {
- if (unlikely(!ctx->eval_internal)) {
- return JS_ThrowTypeError(ctx, "eval is not supported");
- }
-- return ctx->eval_internal(ctx, this_obj, input, input_len, filename,
-+ return ctx->eval_internal(ctx, this_obj, input, input_len, filename, line,
- flags, scope_idx);
- }
-
-@@ -33707,7 +33787,7 @@ static JSValue JS_EvalObject(JSContext *ctx, JSValueConst this_obj,
- str = JS_ToCStringLen(ctx, &len, val);
- if (!str)
- return JS_EXCEPTION;
-- ret = JS_EvalInternal(ctx, this_obj, str, len, "<input>", flags, scope_idx);
-+ ret = JS_EvalInternal(ctx, this_obj, str, len, "<input>", 1, flags, scope_idx);
- JS_FreeCString(ctx, str);
- return ret;
-
-@@ -33715,14 +33795,14 @@ static JSValue JS_EvalObject(JSContext *ctx, JSValueConst this_obj,
-
- JSValue JS_EvalThis(JSContext *ctx, JSValueConst this_obj,
- const char *input, size_t input_len,
-- const char *filename, int eval_flags)
-+ const char *filename, int line, int eval_flags)
- {
- int eval_type = eval_flags & JS_EVAL_TYPE_MASK;
- JSValue ret;
-
- assert(eval_type == JS_EVAL_TYPE_GLOBAL ||
- eval_type == JS_EVAL_TYPE_MODULE);
-- ret = JS_EvalInternal(ctx, this_obj, input, input_len, filename,
-+ ret = JS_EvalInternal(ctx, this_obj, input, input_len, filename, line,
- eval_flags, -1);
- return ret;
- }
-@@ -33730,7 +33810,7 @@ JSValue JS_EvalThis(JSContext *ctx, JSValueConst this_obj,
- JSValue JS_Eval(JSContext *ctx, const char *input, size_t input_len,
- const char *filename, int eval_flags)
- {
-- return JS_EvalThis(ctx, ctx->global_obj, input, input_len, filename,
-+ return JS_EvalThis(ctx, ctx->global_obj, input, input_len, filename, 1,
- eval_flags);
- }
-
-@@ -33948,7 +34028,7 @@ static void bc_put_u16(BCWriterState *s, uint16_t v)
- dbuf_put_u16(&s->dbuf, v);
- }
-
--static __maybe_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);
-@@ -33982,7 +34062,7 @@ static int bc_atom_to_idx(BCWriterState *s, uint32_t *pres, JSAtom atom)
- {
- uint32_t v;
-
-- if (atom < s->first_atom || __JS_AtomIsTaggedInt(atom)) {
-+ if (atom < s->first_atom || JS_AtomIsTaggedInt(atom)) {
- *pres = atom;
- return 0;
- }
-@@ -34022,8 +34102,8 @@ static int bc_put_atom(BCWriterState *s, JSAtom atom)
- {
- uint32_t v;
-
-- if (__JS_AtomIsTaggedInt(atom)) {
-- v = (__JS_AtomToUInt32(atom) << 1) | 1;
-+ if (JS_AtomIsTaggedInt(atom)) {
-+ v = (JS_AtomToUInt32(atom) << 1) | 1;
- } else {
- if (bc_atom_to_idx(s, &v, atom))
- return -1;
-@@ -34142,7 +34222,7 @@ static int JS_WriteFunctionBytecode(BCWriterState *s,
- static void JS_WriteString(BCWriterState *s, JSString *p)
- {
- int i;
-- bc_put_leb128(s, ((uint32_t)p->len << 1) | p->is_wide_char);
-+ bc_put_leb128(s, (p->len << 1) | p->is_wide_char);
- if (p->is_wide_char) {
- for(i = 0; i < p->len; i++)
- bc_put_u16(s, p->u.str16[i]);
-@@ -34800,7 +34880,7 @@ typedef struct BCReaderState {
- } BCReaderState;
-
- #ifdef DUMP_READ_OBJECT
--static void __attribute__((format(printf, 2, 3))) bc_read_trace(BCReaderState *s, const char *fmt, ...) {
-+static void FORMAT_ATTR(2, 3) bc_read_trace(BCReaderState *s, const char *fmt, ...) {
- va_list ap;
- int i, n, n0;
-
-@@ -34863,7 +34943,7 @@ static int bc_get_u16(BCReaderState *s, uint16_t *pval)
- return 0;
- }
-
--static __maybe_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 */
-@@ -34937,7 +35017,7 @@ static int bc_idx_to_atom(BCReaderState *s, JSAtom *patom, uint32_t idx)
- {
- JSAtom atom;
-
-- if (__JS_AtomIsTaggedInt(idx)) {
-+ if (JS_AtomIsTaggedInt(idx)) {
- atom = idx;
- } else if (idx < s->first_atom) {
- atom = JS_DupAtom(s->ctx, idx);
-@@ -34961,7 +35041,7 @@ static int bc_get_atom(BCReaderState *s, JSAtom *patom)
- if (bc_get_leb128(s, &v))
- return -1;
- if (v & 1) {
-- *patom = __JS_AtomFromUInt32(v >> 1);
-+ *patom = JS_AtomFromUInt32(v >> 1);
- return 0;
- } else {
- return bc_idx_to_atom(s, patom, v >> 1);
-@@ -35776,7 +35856,7 @@ static JSValue JS_ReadObjectRec(BCReaderState *s)
- if (bc_get_u64(s, &u.u64))
- return JS_EXCEPTION;
- bc_read_trace(s, "%g\n", u.d);
-- obj = __JS_NewFloat64(ctx, u.d);
-+ obj = JS_NewFloat64Impl(ctx, u.d);
- }
- break;
- case BC_TAG_STRING:
-@@ -36084,7 +36164,7 @@ static int JS_InstantiateFunctionListItem(JSContext *ctx, JSValueConst obj,
- val = JS_NewInt64(ctx, e->u.i64);
- break;
- case JS_DEF_PROP_DOUBLE:
-- val = __JS_NewFloat64(ctx, e->u.f64);
-+ val = JS_NewFloat64Impl(ctx, e->u.f64);
- break;
- case JS_DEF_PROP_UNDEFINED:
- val = JS_UNDEFINED;
-@@ -36148,7 +36228,7 @@ int JS_SetModuleExportList(JSContext *ctx, JSModuleDef *m,
- val = JS_NewInt64(ctx, e->u.i64);
- break;
- case JS_DEF_PROP_DOUBLE:
-- val = __JS_NewFloat64(ctx, e->u.f64);
-+ val = JS_NewFloat64Impl(ctx, e->u.f64);
- break;
- case JS_DEF_OBJECT:
- val = JS_NewObject(ctx);
-@@ -36381,7 +36461,7 @@ static int js_obj_to_desc(JSContext *ctx, JSPropertyDescriptor *d,
- return -1;
- }
-
--static __exception int JS_DefinePropertyDesc(JSContext *ctx, JSValueConst obj,
-+static warn_unused int JS_DefinePropertyDesc(JSContext *ctx, JSValueConst obj,
- JSAtom prop, JSValueConst desc,
- int flags)
- {
-@@ -36397,7 +36477,7 @@ static __exception int JS_DefinePropertyDesc(JSContext *ctx, JSValueConst obj,
- return ret;
- }
-
--static __exception int JS_ObjectDefineProperties(JSContext *ctx,
-+static warn_unused int JS_ObjectDefineProperties(JSContext *ctx,
- JSValueConst obj,
- JSValueConst properties)
- {
-@@ -36882,32 +36962,6 @@ static JSValue js_object_hasOwnProperty(JSContext *ctx, JSValueConst this_val,
- return JS_NewBool(ctx, ret);
- }
-
--static JSValue js_object_hasOwn(JSContext *ctx, JSValueConst this_val,
-- int argc, JSValueConst *argv)
--{
-- JSValue obj;
-- JSAtom atom;
-- JSObject *p;
-- BOOL ret;
--
-- obj = JS_ToObject(ctx, argv[0]);
-- if (JS_IsException(obj))
-- return obj;
-- atom = JS_ValueToAtom(ctx, argv[1]);
-- if (unlikely(atom == JS_ATOM_NULL)) {
-- JS_FreeValue(ctx, obj);
-- return JS_EXCEPTION;
-- }
-- p = JS_VALUE_GET_OBJ(obj);
-- ret = JS_GetOwnPropertyInternal(ctx, NULL, p, atom);
-- JS_FreeAtom(ctx, atom);
-- JS_FreeValue(ctx, obj);
-- if (ret < 0)
-- return JS_EXCEPTION;
-- else
-- return JS_NewBool(ctx, ret);
--}
--
- static JSValue js_object_valueOf(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
- {
-@@ -37447,6 +37501,32 @@ exception:
- return res;
- }
-
-+static JSValue js_object_hasOwn(JSContext *ctx, JSValueConst this_val,
-+ int argc, JSValueConst *argv)
-+{
-+ JSValue obj;
-+ JSAtom atom;
-+ JSObject *p;
-+ BOOL ret;
-+
-+ obj = JS_ToObject(ctx, argv[0]);
-+ if (JS_IsException(obj))
-+ return obj;
-+ atom = JS_ValueToAtom(ctx, argv[1]);
-+ if (unlikely(atom == JS_ATOM_NULL)) {
-+ JS_FreeValue(ctx, obj);
-+ return JS_EXCEPTION;
-+ }
-+ p = JS_VALUE_GET_OBJ(obj);
-+ ret = JS_GetOwnPropertyInternal(ctx, NULL, p, atom);
-+ JS_FreeAtom(ctx, atom);
-+ JS_FreeValue(ctx, obj);
-+ if (ret < 0)
-+ return JS_EXCEPTION;
-+ else
-+ return JS_NewBool(ctx, ret);
-+}
-+
- static const JSCFunctionListEntry js_object_funcs[] = {
- JS_CFUNC_DEF("create", 2, js_object_create ),
- JS_CFUNC_MAGIC_DEF("getPrototypeOf", 1, js_object_getPrototypeOf, 0 ),
-@@ -37576,7 +37656,7 @@ static JSValue js_function_constructor(JSContext *ctx, JSValueConst new_target,
- return JS_EXCEPTION;
- }
-
--static __exception int js_get_length32(JSContext *ctx, uint32_t *pres,
-+static warn_unused int js_get_length32(JSContext *ctx, uint32_t *pres,
- JSValueConst obj)
- {
- JSValue len_val;
-@@ -37588,7 +37668,7 @@ static __exception int js_get_length32(JSContext *ctx, uint32_t *pres,
- return JS_ToUint32Free(ctx, pres, len_val);
- }
-
--static __exception int js_get_length64(JSContext *ctx, int64_t *pres,
-+static warn_unused int js_get_length64(JSContext *ctx, int64_t *pres,
- JSValueConst obj)
- {
- JSValue len_val;
-@@ -37673,9 +37753,9 @@ static JSValue js_function_apply(JSContext *ctx, JSValueConst this_val,
- if (!tab)
- return JS_EXCEPTION;
- if (magic & 1) {
-- ret = JS_CallConstructor2(ctx, this_val, this_arg, len, (JSValueConst *)tab);
-+ ret = JS_CallConstructor2(ctx, this_val, this_arg, len, tab);
- } else {
-- ret = JS_Call(ctx, this_val, this_arg, len, (JSValueConst *)tab);
-+ ret = JS_Call(ctx, this_val, this_arg, len, tab);
- }
- free_arg_list(ctx, tab, len);
- return ret;
-@@ -38889,8 +38969,7 @@ static JSValue js_array_toString(JSContext *ctx, JSValueConst this_val,
- method = JS_GetProperty(ctx, obj, JS_ATOM_join);
- if (JS_IsException(method)) {
- ret = JS_EXCEPTION;
-- } else
-- if (!JS_IsFunction(ctx, method)) {
-+ } else if (!JS_IsFunction(ctx, method)) {
- /* Use intrinsic Object.prototype.toString */
- JS_FreeValue(ctx, method);
- ret = js_object_toString(ctx, obj, 0, NULL);
-@@ -39138,8 +39217,7 @@ static JSValue js_array_slice(JSContext *ctx, JSValueConst this_val,
- if (argc == 0) {
- item_count = 0;
- del_count = 0;
-- } else
-- if (argc == 1) {
-+ } else if (argc == 1) {
- item_count = 0;
- del_count = len - start;
- } else {
-@@ -39283,8 +39361,8 @@ static int64_t JS_FlattenIntoArray(JSContext *ctx, JSValueConst target,
- if (!JS_IsUndefined(mapperFunction)) {
- JSValueConst args[3] = { element, JS_NewInt64(ctx, sourceIndex), source };
- element = JS_Call(ctx, mapperFunction, thisArg, 3, args);
-- JS_FreeValue(ctx, (JSValue)args[0]);
-- JS_FreeValue(ctx, (JSValue)args[1]);
-+ JS_FreeValue(ctx, args[0]);
-+ JS_FreeValue(ctx, args[1]);
- if (JS_IsException(element))
- return -1;
- }
-@@ -39915,7 +39993,7 @@ static JSValue js_number_toFixed(JSContext *ctx, JSValueConst this_val,
- if (f < 0 || f > 100)
- return JS_ThrowRangeError(ctx, "invalid number of digits");
- if (fabs(d) >= 1e21) {
-- return JS_ToStringFree(ctx, __JS_NewFloat64(ctx, d));
-+ return JS_ToStringFree(ctx, JS_NewFloat64Impl(ctx, d));
- } else {
- return js_dtoa(ctx, d, 10, f, JS_DTOA_FRAC_FORMAT);
- }
-@@ -39936,7 +40014,7 @@ static JSValue js_number_toExponential(JSContext *ctx, JSValueConst this_val,
- if (JS_ToInt32Sat(ctx, &f, argv[0]))
- return JS_EXCEPTION;
- if (!isfinite(d)) {
-- return JS_ToStringFree(ctx, __JS_NewFloat64(ctx, d));
-+ return JS_ToStringFree(ctx, JS_NewFloat64Impl(ctx, d));
- }
- if (JS_IsUndefined(argv[0])) {
- flags = 0;
-@@ -39968,7 +40046,7 @@ static JSValue js_number_toPrecision(JSContext *ctx, JSValueConst this_val,
- return JS_EXCEPTION;
- if (!isfinite(d)) {
- to_string:
-- return JS_ToStringFree(ctx, __JS_NewFloat64(ctx, d));
-+ return JS_ToStringFree(ctx, JS_NewFloat64Impl(ctx, d));
- }
- if (p < 1 || p > 100)
- return JS_ThrowRangeError(ctx, "invalid number of digits");
-@@ -40089,11 +40167,11 @@ static int js_string_get_own_property(JSContext *ctx,
- uint32_t idx, ch;
-
- /* This is a class exotic method: obj class_id is JS_CLASS_STRING */
-- if (__JS_AtomIsTaggedInt(prop)) {
-+ if (JS_AtomIsTaggedInt(prop)) {
- p = JS_VALUE_GET_OBJ(obj);
- if (JS_VALUE_GET_TAG(p->u.object_data) == JS_TAG_STRING) {
- p1 = JS_VALUE_GET_STRING(p->u.object_data);
-- idx = __JS_AtomToUInt32(prop);
-+ idx = JS_AtomToUInt32(prop);
- if (idx < p1->len) {
- if (desc) {
- if (p1->is_wide_char)
-@@ -40122,8 +40200,8 @@ static int js_string_define_own_property(JSContext *ctx,
- JSObject *p;
- JSString *p1, *p2;
-
-- if (__JS_AtomIsTaggedInt(prop)) {
-- idx = __JS_AtomToUInt32(prop);
-+ if (JS_AtomIsTaggedInt(prop)) {
-+ idx = JS_AtomToUInt32(prop);
- p = JS_VALUE_GET_OBJ(this_obj);
- if (JS_VALUE_GET_TAG(p->u.object_data) != JS_TAG_STRING)
- goto def;
-@@ -40157,8 +40235,8 @@ static int js_string_delete_property(JSContext *ctx,
- {
- uint32_t idx;
-
-- if (__JS_AtomIsTaggedInt(prop)) {
-- idx = __JS_AtomToUInt32(prop);
-+ if (JS_AtomIsTaggedInt(prop)) {
-+ idx = JS_AtomToUInt32(prop);
- if (idx < js_string_obj_get_length(ctx, obj)) {
- return FALSE;
- }
-@@ -40701,7 +40779,7 @@ static JSValue js_string_match(JSContext *ctx, JSValueConst this_val,
- str = JS_NewString(ctx, "g");
- if (JS_IsException(str))
- goto fail;
-- args[args_len++] = (JSValueConst)str;
-+ args[args_len++] = str;
- }
- rx = JS_CallConstructor(ctx, ctx->regexp_ctor, args_len, args);
- JS_FreeValue(ctx, str);
-@@ -40710,7 +40788,7 @@ static JSValue js_string_match(JSContext *ctx, JSValueConst this_val,
- JS_FreeValue(ctx, S);
- return JS_EXCEPTION;
- }
-- result = JS_InvokeFree(ctx, rx, atom, 1, (JSValueConst *)&S);
-+ result = JS_InvokeFree(ctx, rx, atom, 1, &S);
- JS_FreeValue(ctx, S);
- return result;
- }
-@@ -41759,7 +41837,7 @@ static JSValue js_math_min_max(JSContext *ctx, JSValueConst this_val,
- uint32_t tag;
-
- if (unlikely(argc == 0)) {
-- return __JS_NewFloat64(ctx, is_max ? -1.0 / 0.0 : 1.0 / 0.0);
-+ return JS_NewFloat64Impl(ctx, is_max ? INFINITY : -INFINITY);
- }
-
- tag = JS_VALUE_GET_TAG(argv[0]);
-@@ -41911,9 +41989,13 @@ static uint64_t xorshift64star(uint64_t *pstate)
-
- static void js_random_init(JSContext *ctx)
- {
-+#ifdef _MSC_VER
-+ ctx->random_state = time(NULL);
-+#else
- struct timeval tv;
- gettimeofday(&tv, NULL);
- ctx->random_state = ((int64_t)tv.tv_sec * 1000000) + tv.tv_usec;
-+#endif
- /* the state must be non zero */
- if (ctx->random_state == 0)
- ctx->random_state = 1;
-@@ -41928,15 +42010,21 @@ static JSValue js_math_random(JSContext *ctx, JSValueConst this_val,
- v = xorshift64star(&ctx->random_state);
- /* 1.0 <= u.d < 2 */
- u.u64 = ((uint64_t)0x3ff << 52) | (v >> 12);
-- return __JS_NewFloat64(ctx, u.d - 1.0);
-+ return JS_NewFloat64Impl(ctx, u.d - 1.0);
- }
-
-+// MSVC inexplicably refuses to initialize the array below with
-+// these functions, so use wrappers.
-+static double floorWrapper(double x) { return floor(x); }
-+static double ceilWrapper(double x) { return ceil(x); }
-+static double log2Wrapper(double x) { return log2(x); }
-+
- static const JSCFunctionListEntry js_math_funcs[] = {
- JS_CFUNC_MAGIC_DEF("min", 2, js_math_min_max, 0 ),
- JS_CFUNC_MAGIC_DEF("max", 2, js_math_min_max, 1 ),
- JS_CFUNC_SPECIAL_DEF("abs", 1, f_f, fabs ),
-- JS_CFUNC_SPECIAL_DEF("floor", 1, f_f, floor ),
-- JS_CFUNC_SPECIAL_DEF("ceil", 1, f_f, ceil ),
-+ JS_CFUNC_SPECIAL_DEF("floor", 1, f_f, floorWrapper ),
-+ JS_CFUNC_SPECIAL_DEF("ceil", 1, f_f, ceilWrapper ),
- JS_CFUNC_SPECIAL_DEF("round", 1, f_f, js_math_round ),
- JS_CFUNC_SPECIAL_DEF("sqrt", 1, f_f, sqrt ),
-
-@@ -41961,7 +42049,7 @@ static const JSCFunctionListEntry js_math_funcs[] = {
- JS_CFUNC_SPECIAL_DEF("atanh", 1, f_f, atanh ),
- JS_CFUNC_SPECIAL_DEF("expm1", 1, f_f, expm1 ),
- JS_CFUNC_SPECIAL_DEF("log1p", 1, f_f, log1p ),
-- JS_CFUNC_SPECIAL_DEF("log2", 1, f_f, log2 ),
-+ JS_CFUNC_SPECIAL_DEF("log2", 1, f_f, log2Wrapper ),
- JS_CFUNC_SPECIAL_DEF("log10", 1, f_f, log10 ),
- JS_CFUNC_SPECIAL_DEF("cbrt", 1, f_f, cbrt ),
- JS_CFUNC_DEF("hypot", 2, js_math_hypot ),
-@@ -42004,9 +42092,16 @@ static JSValue js___date_clock(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv)
- {
- int64_t d;
-+#ifdef _MSC_VER
-+ SYSTEMTIME st;
-+ GetSystemTime(&st);
-+ SystemTimeToFileTime(&st, (FILETIME *) &d);
-+ d /= 10;
-+#else
- struct timeval tv;
- gettimeofday(&tv, NULL);
- d = (int64_t)tv.tv_sec * 1000000 + tv.tv_usec;
-+#endif
- return JS_NewInt64(ctx, d);
- }
-
-@@ -43686,7 +43781,7 @@ JSValue JS_ParseJSON2(JSContext *ctx, const char *buf, size_t buf_len,
- JSParseState s1, *s = &s1;
- JSValue val = JS_UNDEFINED;
-
-- js_parse_init(ctx, s, buf, buf_len, filename);
-+ js_parse_init(ctx, s, buf, buf_len, filename, 1);
- s->ext_json = ((flags & JS_PARSE_JSON_EXT) != 0);
- if (json_next_token(s))
- goto fail;
-@@ -43937,7 +44032,7 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc,
- goto exception;
- }
- #endif
-- v = js_array_includes(ctx, jsc->stack, 1, (JSValueConst *)&val);
-+ v = js_array_includes(ctx, jsc->stack, 1, &val);
- if (JS_IsException(v))
- goto exception;
- if (JS_ToBoolFree(ctx, v)) {
-@@ -43958,7 +44053,7 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc,
- sep = JS_DupValue(ctx, jsc->empty);
- sep1 = JS_DupValue(ctx, jsc->empty);
- }
-- v = js_array_push(ctx, jsc->stack, 1, (JSValueConst *)&val, 0);
-+ v = js_array_push(ctx, jsc->stack, 1, &val, 0);
- if (check_exception_free(ctx, v))
- goto exception;
- ret = JS_IsArray(ctx, val);
-@@ -43998,7 +44093,7 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc,
- if (!JS_IsUndefined(jsc->property_list))
- tab = JS_DupValue(ctx, jsc->property_list);
- else
-- tab = js_object_keys(ctx, JS_UNDEFINED, 1, (JSValueConst *)&val, JS_ITERATOR_KIND_KEY);
-+ tab = js_object_keys(ctx, JS_UNDEFINED, 1, &val, JS_ITERATOR_KIND_KEY);
- if (JS_IsException(tab))
- goto exception;
- if (js_get_length64(ctx, &len, tab))
-@@ -44146,7 +44241,7 @@ JSValue JS_JSONStringify(JSContext *ctx, JSValueConst obj,
- continue;
- }
- present = js_array_includes(ctx, jsc->property_list,
-- 1, (JSValueConst *)&v);
-+ 1, &v);
- if (JS_IsException(present)) {
- JS_FreeValue(ctx, v);
- goto exception;
-@@ -44270,7 +44365,7 @@ static JSValue js_reflect_construct(JSContext *ctx, JSValueConst this_val,
- tab = build_arg_list(ctx, &len, array_arg);
- if (!tab)
- return JS_EXCEPTION;
-- ret = JS_CallConstructor2(ctx, func, new_target, len, (JSValueConst *)tab);
-+ ret = JS_CallConstructor2(ctx, func, new_target, len, tab);
- free_arg_list(ctx, tab, len);
- return ret;
- }
-@@ -44475,7 +44570,7 @@ static JSValue js_proxy_getPrototypeOf(JSContext *ctx, JSValueConst obj)
- return JS_EXCEPTION;
- if (JS_IsUndefined(method))
- return JS_GetPrototype(ctx, s->target);
-- ret = JS_CallFree(ctx, method, s->handler, 1, (JSValueConst *)&s->target);
-+ ret = JS_CallFree(ctx, method, s->handler, 1, &s->target);
- if (JS_IsException(ret))
- return ret;
- if (JS_VALUE_GET_TAG(ret) != JS_TAG_NULL &&
-@@ -44562,7 +44657,7 @@ static int js_proxy_isExtensible(JSContext *ctx, JSValueConst obj)
- return -1;
- if (JS_IsUndefined(method))
- return JS_IsExtensible(ctx, s->target);
-- ret = JS_CallFree(ctx, method, s->handler, 1, (JSValueConst *)&s->target);
-+ ret = JS_CallFree(ctx, method, s->handler, 1, &s->target);
- if (JS_IsException(ret))
- return -1;
- res = JS_ToBoolFree(ctx, ret);
-@@ -44588,7 +44683,7 @@ static int js_proxy_preventExtensions(JSContext *ctx, JSValueConst obj)
- return -1;
- if (JS_IsUndefined(method))
- return JS_PreventExtensions(ctx, s->target);
-- ret = JS_CallFree(ctx, method, s->handler, 1, (JSValueConst *)&s->target);
-+ ret = JS_CallFree(ctx, method, s->handler, 1, &s->target);
- if (JS_IsException(ret))
- return -1;
- res = JS_ToBoolFree(ctx, ret);
-@@ -45072,7 +45167,7 @@ static int js_proxy_get_own_property_names(JSContext *ctx,
- JS_VALUE_GET_OBJ(s->target),
- JS_GPN_STRING_MASK | JS_GPN_SYMBOL_MASK);
- }
-- prop_array = JS_CallFree(ctx, method, s->handler, 1, (JSValueConst *)&s->target);
-+ prop_array = JS_CallFree(ctx, method, s->handler, 1, &s->target);
- if (JS_IsException(prop_array))
- return -1;
- tab = NULL;
-@@ -45408,7 +45503,7 @@ static JSValue js_symbol_toString(JSContext *ctx, JSValueConst this_val,
- if (JS_IsException(val))
- return val;
- /* XXX: use JS_ToStringInternal() with a flags */
-- ret = js_string_constructor(ctx, JS_UNDEFINED, 1, (JSValueConst *)&val);
-+ ret = js_string_constructor(ctx, JS_UNDEFINED, 1, &val);
- JS_FreeValue(ctx, val);
- return ret;
- }
-@@ -45558,7 +45653,7 @@ static JSValue js_map_constructor(JSContext *ctx, JSValueConst new_target,
- break;
- }
- if (is_set) {
-- ret = JS_Call(ctx, adder, obj, 1, (JSValueConst *)&item);
-+ ret = JS_Call(ctx, adder, obj, 1, &item);
- if (JS_IsException(ret)) {
- JS_FreeValue(ctx, item);
- goto fail;
-@@ -45729,7 +45824,7 @@ static JSMapRecord *map_add_record(JSContext *ctx, JSMapState *s,
- } else {
- JS_DupValue(ctx, key);
- }
-- mr->key = (JSValue)key;
-+ mr->key = key;
- h = map_hash_key(ctx, key) & (s->hash_size - 1);
- list_add_tail(&mr->hash_link, &s->hash_table[h]);
- list_add_tail(&mr->link, &s->records);
-@@ -45951,7 +46046,7 @@ static JSValue js_map_forEach(JSContext *ctx, JSValueConst this_val,
- args[0] = args[1];
- else
- args[0] = JS_DupValue(ctx, mr->value);
-- args[2] = (JSValue)this_val;
-+ args[2] = this_val;
- ret = JS_Call(ctx, func, this_arg, 3, (JSValueConst *)args);
- JS_FreeValue(ctx, args[0]);
- if (!magic)
-@@ -46343,7 +46438,7 @@ static JSValue promise_reaction_job(JSContext *ctx, int argc,
- functions */
- if (!JS_IsUndefined(func)) {
- res2 = JS_Call(ctx, func, JS_UNDEFINED,
-- 1, (JSValueConst *)&res);
-+ 1, &res);
- } else {
- res2 = JS_UNDEFINED;
- }
-@@ -46426,7 +46521,7 @@ static JSValue js_promise_resolve_thenable_job(JSContext *ctx,
- res = JS_Call(ctx, then, thenable, 2, (JSValueConst *)args);
- if (JS_IsException(res)) {
- JSValue error = JS_GetException(ctx);
-- res = JS_Call(ctx, args[1], JS_UNDEFINED, 1, (JSValueConst *)&error);
-+ res = JS_Call(ctx, args[1], JS_UNDEFINED, 1, &error);
- JS_FreeValue(ctx, error);
- }
- JS_FreeValue(ctx, args[0]);
-@@ -46626,7 +46721,7 @@ static JSValue js_promise_constructor(JSContext *ctx, JSValueConst new_target,
- if (JS_IsException(ret)) {
- JSValue ret2, error;
- error = JS_GetException(ctx);
-- ret2 = JS_Call(ctx, args[1], JS_UNDEFINED, 1, (JSValueConst *)&error);
-+ ret2 = JS_Call(ctx, args[1], JS_UNDEFINED, 1, &error);
- JS_FreeValue(ctx, error);
- if (JS_IsException(ret2))
- goto fail1;
-@@ -46683,10 +46778,10 @@ static JSValue js_new_promise_capability(JSContext *ctx,
-
- if (JS_IsUndefined(ctor)) {
- result_promise = js_promise_constructor(ctx, ctor, 1,
-- (JSValueConst *)&executor);
-+ &executor);
- } else {
- result_promise = JS_CallConstructor(ctx, ctor, 1,
-- (JSValueConst *)&executor);
-+ &executor);
- }
- if (JS_IsException(result_promise))
- goto fail;
-@@ -46770,7 +46865,7 @@ static JSValue js_promise___newPromiseCapability(JSContext *ctx,
- }
- #endif
-
--static __exception int remainingElementsCount_add(JSContext *ctx,
-+static warn_unused int remainingElementsCount_add(JSContext *ctx,
- JSValueConst resolve_element_env,
- int addend)
- {
-@@ -46851,10 +46946,10 @@ static JSValue js_promise_all_resolve_element(JSContext *ctx,
- error = js_aggregate_error_constructor(ctx, values);
- if (JS_IsException(error))
- return JS_EXCEPTION;
-- ret = JS_Call(ctx, resolve, JS_UNDEFINED, 1, (JSValueConst *)&error);
-+ ret = JS_Call(ctx, resolve, JS_UNDEFINED, 1, &error);
- JS_FreeValue(ctx, error);
- } else {
-- ret = JS_Call(ctx, resolve, JS_UNDEFINED, 1, (JSValueConst *)&values);
-+ ret = JS_Call(ctx, resolve, JS_UNDEFINED, 1, &values);
- }
- if (JS_IsException(ret))
- return ret;
-@@ -46890,7 +46985,7 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val,
- fail_reject:
- error = JS_GetException(ctx);
- ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED, 1,
-- (JSValueConst *)&error);
-+ &error);
- JS_FreeValue(ctx, error);
- if (JS_IsException(ret))
- goto fail;
-@@ -46921,7 +47016,7 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val,
- if (done)
- break;
- next_promise = JS_Call(ctx, promise_resolve,
-- this_val, 1, (JSValueConst *)&item);
-+ this_val, 1, &item);
- JS_FreeValue(ctx, item);
- if (JS_IsException(next_promise)) {
- fail_reject1:
-@@ -46929,7 +47024,7 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val,
- goto fail_reject;
- }
- resolve_element_data[0] = JS_NewBool(ctx, FALSE);
-- resolve_element_data[1] = (JSValueConst)JS_NewInt32(ctx, index);
-+ resolve_element_data[1] = JS_NewInt32(ctx, index);
- resolve_element_data[2] = values;
- resolve_element_data[3] = resolving_funcs[is_promise_any];
- resolve_element_data[4] = resolve_element_env;
-@@ -46989,7 +47084,7 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val,
- values = error;
- }
- ret = JS_Call(ctx, resolving_funcs[is_promise_any], JS_UNDEFINED,
-- 1, (JSValueConst *)&values);
-+ 1, &values);
- if (check_exception_free(ctx, ret))
- goto fail_reject;
- }
-@@ -47032,7 +47127,7 @@ static JSValue js_promise_race(JSContext *ctx, JSValueConst this_val,
- fail_reject:
- error = JS_GetException(ctx);
- ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED, 1,
-- (JSValueConst *)&error);
-+ &error);
- JS_FreeValue(ctx, error);
- if (JS_IsException(ret))
- goto fail;
-@@ -47051,7 +47146,7 @@ static JSValue js_promise_race(JSContext *ctx, JSValueConst this_val,
- if (done)
- break;
- next_promise = JS_Call(ctx, promise_resolve,
-- this_val, 1, (JSValueConst *)&item);
-+ this_val, 1, &item);
- JS_FreeValue(ctx, item);
- if (JS_IsException(next_promise)) {
- fail_reject1:
-@@ -47078,7 +47173,7 @@ static JSValue js_promise_race(JSContext *ctx, JSValueConst this_val,
- goto done;
- }
-
--static __exception int perform_promise_then(JSContext *ctx,
-+static warn_unused int perform_promise_then(JSContext *ctx,
- JSValueConst promise,
- JSValueConst *resolve_reject,
- JSValueConst *cap_resolving_funcs)
-@@ -47196,7 +47291,7 @@ static JSValue js_promise_then_finally_func(JSContext *ctx, JSValueConst this_va
- res = JS_Call(ctx, onFinally, JS_UNDEFINED, 0, NULL);
- if (JS_IsException(res))
- return res;
-- promise = js_promise_resolve(ctx, ctor, 1, (JSValueConst *)&res, 0);
-+ promise = js_promise_resolve(ctx, ctor, 1, &res, 0);
- JS_FreeValue(ctx, res);
- if (JS_IsException(promise))
- return promise;
-@@ -47211,7 +47306,7 @@ static JSValue js_promise_then_finally_func(JSContext *ctx, JSValueConst this_va
- JS_FreeValue(ctx, promise);
- return then_func;
- }
-- ret = JS_InvokeFree(ctx, promise, JS_ATOM_then, 1, (JSValueConst *)&then_func);
-+ ret = JS_InvokeFree(ctx, promise, JS_ATOM_then, 1, &then_func);
- JS_FreeValue(ctx, then_func);
- return ret;
- }
-@@ -47288,7 +47383,7 @@ static JSValue js_async_from_sync_iterator_unwrap_func_create(JSContext *ctx,
- {
- JSValueConst func_data[1];
-
-- func_data[0] = (JSValueConst)JS_NewBool(ctx, done);
-+ func_data[0] = JS_NewBool(ctx, done);
- return JS_NewCFunctionData(ctx, js_async_from_sync_iterator_unwrap,
- 1, 0, 1, func_data);
- }
-@@ -47411,7 +47506,7 @@ static JSValue js_async_from_sync_iterator_next(JSContext *ctx, JSValueConst thi
- is_reject = 1;
- done_resolve:
- res2 = JS_Call(ctx, resolving_funcs[is_reject], JS_UNDEFINED,
-- 1, (JSValueConst *)&err);
-+ 1, &err);
- JS_FreeValue(ctx, err);
- JS_FreeValue(ctx, res2);
- JS_FreeValue(ctx, resolving_funcs[0]);
-@@ -47423,7 +47518,7 @@ static JSValue js_async_from_sync_iterator_next(JSContext *ctx, JSValueConst thi
- int res;
-
- value_wrapper_promise = js_promise_resolve(ctx, ctx->promise_ctor,
-- 1, (JSValueConst *)&value, 0);
-+ 1, &value, 0);
- if (JS_IsException(value_wrapper_promise)) {
- JS_FreeValue(ctx, value);
- goto reject;
-@@ -47593,7 +47688,7 @@ static int isURIReserved(int c) {
- return c < 0x100 && memchr(";/?:@&=+$,#", c, sizeof(";/?:@&=+$,#") - 1) != NULL;
- }
-
--static int __attribute__((format(printf, 2, 3))) js_throw_URIError(JSContext *ctx, const char *fmt, ...)
-+static int FORMAT_ATTR(2, 3) js_throw_URIError(JSContext *ctx, const char *fmt, ...)
- {
- va_list ap;
-
-@@ -47894,7 +47989,7 @@ static int64_t floor_div(int64_t a, int64_t b) {
- static JSValue js_Date_parse(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv);
-
--static __exception int JS_ThisTimeValue(JSContext *ctx, double *valp, JSValueConst this_val)
-+static warn_unused int JS_ThisTimeValue(JSContext *ctx, double *valp, JSValueConst this_val)
- {
- if (JS_VALUE_GET_TAG(this_val) == JS_TAG_OBJECT) {
- JSObject *p = JS_VALUE_GET_OBJ(this_val);
-@@ -47954,7 +48049,7 @@ static int const month_days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
- static char const month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
- static char const day_names[] = "SunMonTueWedThuFriSat";
-
--static __exception int get_date_fields(JSContext *ctx, JSValueConst obj,
-+static warn_unused int get_date_fields(JSContext *ctx, JSValueConst obj,
- double fields[9], int is_local, int force)
- {
- double dval;
-@@ -48016,7 +48111,7 @@ static double time_clip(double t) {
-
- /* The spec mandates the use of 'double' and it fixes the order
- of the operations */
--static double set_date_fields(double fields[], int is_local) {
-+static double set_date_fields(const double fields[], int is_local) {
- int64_t y;
- double days, d, h, m1;
- int i, m, md;
-@@ -48213,9 +48308,17 @@ static JSValue get_date_string(JSContext *ctx, JSValueConst this_val,
-
- /* OS dependent: return the UTC time in ms since 1970. */
- static int64_t date_now(void) {
-+#ifdef _MSC_VER
-+ SYSTEMTIME st;
-+ GetSystemTime(&st);
-+ int64_t d;
-+ SystemTimeToFileTime(&st, (FILETIME *) &d);
-+ return d /= 10000;
-+#else
- struct timeval tv;
- gettimeofday(&tv, NULL);
- return (int64_t)tv.tv_sec * 1000 + (tv.tv_usec / 1000);
-+#endif
- }
-
- static JSValue js_date_constructor(JSContext *ctx, JSValueConst new_target,
-@@ -48246,7 +48349,7 @@ static JSValue js_date_constructor(JSContext *ctx, JSValueConst new_target,
- }
- v = JS_ToPrimitive(ctx, argv[0], HINT_NONE);
- if (JS_IsString(v)) {
-- dv = js_Date_parse(ctx, JS_UNDEFINED, 1, (JSValueConst *)&v);
-+ dv = js_Date_parse(ctx, JS_UNDEFINED, 1, &v);
- JS_FreeValue(ctx, v);
- if (JS_IsException(dv))
- return JS_EXCEPTION;
-@@ -48814,7 +48917,7 @@ void JS_AddIntrinsicDate(JSContext *ctx)
-
- void JS_AddIntrinsicEval(JSContext *ctx)
- {
-- ctx->eval_internal = __JS_EvalInternal;
-+ ctx->eval_internal = JS_EvalInternalImpl;
- }
-
- #ifdef CONFIG_BIGNUM
-@@ -50934,7 +51037,7 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx)
- JS_PROP_HAS_GET | JS_PROP_HAS_SET |
- JS_PROP_HAS_CONFIGURABLE | JS_PROP_CONFIGURABLE);
- JS_FreeValue(ctx, obj1);
-- JS_FreeValue(ctx, js_object_seal(ctx, JS_UNDEFINED, 1, (JSValueConst *)&ctx->throw_type_error, 1));
-+ JS_FreeValue(ctx, js_object_seal(ctx, JS_UNDEFINED, 1, &ctx->throw_type_error, 1));
-
- ctx->global_obj = JS_NewObject(ctx);
- ctx->global_var_obj = JS_NewObjectProto(ctx, JS_NULL);
-@@ -52090,7 +52193,7 @@ exception:
-
- #define special_indexOf 0
- #define special_lastIndexOf 1
--#define special_includes -1
-+#define special_includes (-1)
-
- static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val,
- int argc, JSValueConst *argv, int special)
-@@ -52157,8 +52260,7 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val,
- is_int = 1;
- v64 = JS_VALUE_GET_INT(argv[0]);
- d = v64;
-- } else
-- if (tag == JS_TAG_FLOAT64) {
-+ } else if (tag == JS_TAG_FLOAT64) {
- d = JS_VALUE_GET_FLOAT64(argv[0]);
- v64 = d;
- is_int = (v64 == d);
-@@ -52659,11 +52761,11 @@ static JSValue js_TA_get_uint64(JSContext *ctx, const void *a) {
- #endif
-
- static JSValue js_TA_get_float32(JSContext *ctx, const void *a) {
-- return __JS_NewFloat64(ctx, *(const float *)a);
-+ return JS_NewFloat64Impl(ctx, *(const float *)a);
- }
-
- static JSValue js_TA_get_float64(JSContext *ctx, const void *a) {
-- return __JS_NewFloat64(ctx, *(const double *)a);
-+ return JS_NewFloat64Impl(ctx, *(const double *)a);
- }
-
- struct TA_sort_context {
-@@ -52717,8 +52819,8 @@ static int js_TA_cmp_generic(const void *a, const void *b, void *opaque) {
- psc->exception = 1;
- }
- done:
-- JS_FreeValue(ctx, (JSValue)argv[0]);
-- JS_FreeValue(ctx, (JSValue)argv[1]);
-+ JS_FreeValue(ctx, argv[0]);
-+ JS_FreeValue(ctx, argv[1]);
- }
- return cmp;
- }
-@@ -53285,7 +53387,7 @@ static JSValue js_dataview_getValue(JSContext *ctx,
- case JS_CLASS_INT8_ARRAY:
- return JS_NewInt32(ctx, *(int8_t *)ptr);
- case JS_CLASS_UINT8_ARRAY:
-- return JS_NewInt32(ctx, *(uint8_t *)ptr);
-+ return JS_NewInt32(ctx, *ptr);
- case JS_CLASS_INT16_ARRAY:
- v = get_u16(ptr);
- if (is_swap)
-@@ -53336,7 +53438,7 @@ static JSValue js_dataview_getValue(JSContext *ctx,
- if (is_swap)
- v = bswap32(v);
- u.i = v;
-- return __JS_NewFloat64(ctx, u.f);
-+ return JS_NewFloat64Impl(ctx, u.f);
- }
- case JS_CLASS_FLOAT64_ARRAY:
- {
-@@ -53347,7 +53449,7 @@ static JSValue js_dataview_getValue(JSContext *ctx,
- u.i = get_u64(ptr);
- if (is_swap)
- u.i = bswap64(u.i);
-- return __JS_NewFloat64(ctx, u.f);
-+ return JS_NewFloat64Impl(ctx, u.f);
- }
- default:
- abort();
-@@ -54059,3 +54161,155 @@ void JS_AddIntrinsicTypedArrays(JSContext *ctx)
- JS_AddIntrinsicAtomics(ctx);
- #endif
- }
-+
-+#ifndef NDEBUG
-+static void *watchedRefCount = NULL;
-+
-+void notifyRefCountIncrease(JSRefCountHeader *p)
-+{
-+ if (p == watchedRefCount)
-+ fprintf(stderr, "increasing ref count %d for %p\n", p->ref_count, watchedRefCount);
-+}
-+
-+void notifyRefCountDecrease(JSRefCountHeader *p)
-+{
-+ if (p == watchedRefCount)
-+ fprintf(stderr, "decreasing ref count %d for %p\n", p->ref_count, watchedRefCount);
-+}
-+
-+void watchRefCount(void *p)
-+{
-+ watchedRefCount = p;
-+}
-+#endif
-+
-+void setScopeLookup(JSContext *ctx, ScopeLookup *scopeLookup)
-+{
-+ ctx->scopeLookup = scopeLookup;
-+}
-+
-+void setFoundUndefinedHandler(JSContext *ctx, FoundUndefinedHandler *handler)
-+{
-+ ctx->handleUndefined = handler;
-+}
-+
-+void setFunctionEnteredHandler(JSContext *ctx, FunctionEnteredHandler *handler)
-+{
-+ ctx->handleFunctionEntered = handler;
-+}
-+
-+void setFunctionExitedHandler(JSContext *ctx, FunctionExitedHandler *handler)
-+{
-+ ctx->handleFunctionExited = handler;
-+}
-+
-+int isSimpleValue(JSValue v)
-+{
-+ JSObject *p;
-+ if (JS_VALUE_GET_TAG(v) != JS_TAG_OBJECT)
-+ return 1;
-+ p = JS_VALUE_GET_OBJ(v);
-+ return p->class_id >= JS_CLASS_OBJECT && p->class_id <= JS_CLASS_BOOLEAN;
-+}
-+
-+JSValue JS_NewCFunctionMagic(JSContext *ctx, JSCFunctionMagic *func,
-+ const char *name, int length,
-+ JSCFunctionEnum cproto, int magic)
-+{
-+ return JS_NewCFunction2(ctx, (JSCFunction *)func, name, length, cproto,
-+ magic);
-+}
-+
-+JSValue mkVal(int32_t tag, int32_t val)
-+{
-+ return (JSValue){ (JSValueUnion){ .int32 = val }, tag };
-+}
-+
-+JSValue mkPtr(int32_t tag, void *p)
-+{
-+ return (JSValue){ (JSValueUnion){ .ptr = p }, tag };
-+}
-+
-+void JS_FreeValue(JSContext *ctx, JSValue v) {
-+ if (JS_VALUE_HAS_REF_COUNT(v)) {
-+ JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v);
-+#ifndef NDEBUG
-+ notifyRefCountDecrease(p);
-+#endif
-+ if (--p->ref_count <= 0) {
-+ JS_FreeValueImpl(ctx, v);
-+ }
-+ }
-+}
-+void JS_FreeValueRT(JSRuntime *rt, JSValue v) {
-+ if (JS_VALUE_HAS_REF_COUNT(v)) {
-+ JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v);
-+#ifndef NDEBUG
-+ notifyRefCountDecrease(p);
-+#endif
-+ if (--p->ref_count <= 0) {
-+ JS_FreeValueRTImpl(rt, v);
-+ }
-+ }
-+}
-+JSValue JS_NewBool(JSContext *ctx, JS_BOOL val) {
-+ (void)ctx;
-+ return JS_MKVAL(JS_TAG_BOOL, (val != 0));
-+}
-+JSValue JS_NewInt32(JSContext *ctx, int32_t val) {
-+ (void)ctx;
-+ return JS_MKVAL(JS_TAG_INT, val);
-+}
-+JSValue JS_NewCatchOffset(JSContext *ctx, int32_t val) {
-+ (void)ctx;
-+ return JS_MKVAL(JS_TAG_CATCH_OFFSET, val);
-+}
-+JSValue JS_NewInt64(JSContext *ctx, int64_t val) {
-+ JSValue v;
-+ if (val == (int32_t)val) {
-+ v = JS_NewInt32(ctx, (int32_t)val);
-+ } else {
-+ v = JS_NewFloat64Impl(ctx, (double)val);
-+ }
-+ return v;
-+}
-+JSValue JS_NewUint32(JSContext *ctx, uint32_t val) {
-+ JSValue v;
-+ if (val <= 0x7fffffff) {
-+ v = JS_NewInt32(ctx, val);
-+ } else {
-+ v = JS_NewFloat64Impl(ctx, val);
-+ }
-+ return v;
-+}
-+JSValue JS_NewFloat64(JSContext *ctx, double d) {
-+ JSValue v;
-+ int32_t val;
-+ union {
-+ double d;
-+ uint64_t u;
-+ } u, t;
-+ u.d = d;
-+ val = (int32_t)d;
-+ t.d = val;
-+ /* -0 cannot be represented as integer, so we compare the bit
-+ representation */
-+ if (u.u == t.u) {
-+ v = JS_MKVAL(JS_TAG_INT, val);
-+ } else {
-+ v = JS_NewFloat64Impl(ctx, d);
-+ }
-+ return v;
-+}
-+JSValue JS_NewCFunction(JSContext *ctx, JSCFunction *func, const char *name,
-+ int length) {
-+ return JS_NewCFunction2(ctx, func, name, length, JS_CFUNC_generic, 0);
-+}
-+
-+JS_BOOL JS_IsRegExp(JSContext *ctx, JSValue val)
-+{
-+ JSObject *p;
-+ if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT)
-+ return FALSE;
-+ return JS_VALUE_GET_OBJ(val)->class_id == JS_CLASS_REGEXP;
-+}
-diff --git a/quickjs.h b/quickjs.h
-index d4a5cd3..a5adf0c 100644
---- a/quickjs.h
-+++ b/quickjs.h
-@@ -215,15 +215,19 @@ typedef struct JSValue {
- #define JS_VALUE_GET_FLOAT64(v) ((v).u.float64)
- #define JS_VALUE_GET_PTR(v) ((v).u.ptr)
-
--#define JS_MKVAL(tag, val) (JSValue){ (JSValueUnion){ .int32 = val }, tag }
--#define JS_MKPTR(tag, p) (JSValue){ (JSValueUnion){ .ptr = p }, tag }
-+JSValue mkVal(int32_t tag, int32_t val);
-+JSValue mkPtr(int32_t tag, void *p);
-+
-+#define JS_MKVAL(tag, val) mkVal(tag, val)
-+#define JS_MKPTR(tag, p) mkPtr(tag, p)
-
- #define JS_TAG_IS_FLOAT64(tag) ((unsigned)(tag) == JS_TAG_FLOAT64)
-
- #define JS_NAN (JSValue){ .u.float64 = JS_FLOAT64_NAN, JS_TAG_FLOAT64 }
-
--static inline JSValue __JS_NewFloat64(JSContext *ctx, double d)
-+static inline JSValue JS_NewFloat64Impl(JSContext *ctx, double d)
- {
-+ (void) ctx;
- JSValue v;
- v.tag = JS_TAG_FLOAT64;
- v.u.float64 = d;
-@@ -502,66 +506,14 @@ int JS_IsRegisteredClass(JSRuntime *rt, JSClassID class_id);
-
- /* value handling */
-
--static js_force_inline JSValue JS_NewBool(JSContext *ctx, JS_BOOL val)
--{
-- return JS_MKVAL(JS_TAG_BOOL, (val != 0));
--}
--
--static js_force_inline JSValue JS_NewInt32(JSContext *ctx, int32_t val)
--{
-- return JS_MKVAL(JS_TAG_INT, val);
--}
--
--static js_force_inline JSValue JS_NewCatchOffset(JSContext *ctx, int32_t val)
--{
-- return JS_MKVAL(JS_TAG_CATCH_OFFSET, val);
--}
--
--static js_force_inline JSValue JS_NewInt64(JSContext *ctx, int64_t val)
--{
-- JSValue v;
-- if (val == (int32_t)val) {
-- v = JS_NewInt32(ctx, val);
-- } else {
-- v = __JS_NewFloat64(ctx, val);
-- }
-- return v;
--}
--
--static js_force_inline JSValue JS_NewUint32(JSContext *ctx, uint32_t val)
--{
-- JSValue v;
-- if (val <= 0x7fffffff) {
-- v = JS_NewInt32(ctx, val);
-- } else {
-- v = __JS_NewFloat64(ctx, val);
-- }
-- return v;
--}
--
-+JSValue JS_NewBool(JSContext *ctx, JS_BOOL val);
-+JSValue JS_NewInt32(JSContext *ctx, int32_t val);
-+JSValue JS_NewCatchOffset(JSContext *ctx, int32_t val);
-+JSValue JS_NewInt64(JSContext *ctx, int64_t val);
-+JSValue JS_NewUint32(JSContext *ctx, uint32_t val);
- 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)
--{
-- JSValue v;
-- int32_t val;
-- union {
-- double d;
-- uint64_t u;
-- } u, t;
-- u.d = d;
-- val = (int32_t)d;
-- t.d = val;
-- /* -0 cannot be represented as integer, so we compare the bit
-- representation */
-- if (u.u == t.u) {
-- v = JS_MKVAL(JS_TAG_INT, val);
-- } else {
-- v = __JS_NewFloat64(ctx, d);
-- }
-- return v;
--}
-+JSValue JS_NewFloat64(JSContext *ctx, double d);
-
- static inline JS_BOOL JS_IsNumber(JSValueConst v)
- {
-@@ -571,6 +523,7 @@ static inline JS_BOOL JS_IsNumber(JSValueConst v)
-
- static inline JS_BOOL JS_IsBigInt(JSContext *ctx, JSValueConst v)
- {
-+ (void) ctx;
- int tag = JS_VALUE_GET_TAG(v);
- return tag == JS_TAG_BIG_INT;
- }
-@@ -639,43 +592,38 @@ JSValue __js_printf_like(2, 3) JS_ThrowRangeError(JSContext *ctx, const char *fm
- JSValue __js_printf_like(2, 3) JS_ThrowInternalError(JSContext *ctx, const char *fmt, ...);
- JSValue JS_ThrowOutOfMemory(JSContext *ctx);
-
--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 = (JSRefCountHeader *)JS_VALUE_GET_PTR(v);
-- if (--p->ref_count <= 0) {
-- __JS_FreeValue(ctx, v);
-- }
-- }
--}
--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 = (JSRefCountHeader *)JS_VALUE_GET_PTR(v);
-- if (--p->ref_count <= 0) {
-- __JS_FreeValueRT(rt, v);
-- }
-- }
--}
-+#ifndef NDEBUG
-+void notifyRefCountIncrease(JSRefCountHeader *p);
-+void notifyRefCountDecrease(JSRefCountHeader *p);
-+#endif
-+
-+void JS_FreeValue(JSContext *ctx, JSValue v);
-+void JS_FreeValueRT(JSRuntime *rt, JSValue v);
-
- static inline JSValue JS_DupValue(JSContext *ctx, JSValueConst v)
- {
-+ (void) ctx;
- if (JS_VALUE_HAS_REF_COUNT(v)) {
- JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v);
-+#ifndef NDEBUG
-+ notifyRefCountIncrease(p);
-+#endif
- p->ref_count++;
- }
-- return (JSValue)v;
-+ return v;
- }
-
- static inline JSValue JS_DupValueRT(JSRuntime *rt, JSValueConst v)
- {
-+ (void) rt;
- if (JS_VALUE_HAS_REF_COUNT(v)) {
- JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v);
-+#ifndef NDEBUG
-+ notifyRefCountIncrease(p);
-+#endif
- p->ref_count++;
- }
-- return (JSValue)v;
-+ return v;
- }
-
- int JS_ToBool(JSContext *ctx, JSValueConst val); /* return -1 for JS_EXCEPTION */
-@@ -714,6 +662,7 @@ JSValue JS_NewObjectProto(JSContext *ctx, JSValueConst proto);
- JSValue JS_NewObject(JSContext *ctx);
-
- JS_BOOL JS_IsFunction(JSContext* ctx, JSValueConst val);
-+JS_BOOL JS_IsRegExp(JSContext* ctx, JSValueConst val);
- JS_BOOL JS_IsConstructor(JSContext* ctx, JSValueConst val);
- JS_BOOL JS_SetConstructorBit(JSContext *ctx, JSValueConst func_obj, JS_BOOL val);
-
-@@ -783,7 +732,7 @@ JSValue JS_Eval(JSContext *ctx, const char *input, size_t input_len,
- /* same as JS_Eval() but with an explicit 'this_obj' parameter */
- JSValue JS_EvalThis(JSContext *ctx, JSValueConst this_obj,
- const char *input, size_t input_len,
-- const char *filename, int eval_flags);
-+ const char *filename, int line, int eval_flags);
- JSValue JS_GetGlobalObject(JSContext *ctx);
- int JS_IsInstanceOf(JSContext *ctx, JSValueConst val, JSValueConst obj);
- int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
-@@ -945,18 +894,11 @@ JSValue JS_NewCFunctionData(JSContext *ctx, JSCFunctionData *func,
- int length, int magic, int data_len,
- JSValueConst *data);
-
--static inline JSValue JS_NewCFunction(JSContext *ctx, JSCFunction *func, const char *name,
-- int length)
--{
-- return JS_NewCFunction2(ctx, func, name, length, JS_CFUNC_generic, 0);
--}
-+JSValue JS_NewCFunction(JSContext *ctx, JSCFunction *func, const char *name,
-+ int length);
-
--static inline JSValue JS_NewCFunctionMagic(JSContext *ctx, JSCFunctionMagic *func,
-- const char *name,
-- int length, JSCFunctionEnum cproto, int magic)
--{
-- return JS_NewCFunction2(ctx, (JSCFunction *)func, name, length, cproto, magic);
--}
-+JSValue JS_NewCFunctionMagic(JSContext *ctx, JSCFunctionMagic *func,
-+ const char *name, int length, JSCFunctionEnum cproto, int magic);
- void JS_SetConstructor(JSContext *ctx, JSValueConst func_obj,
- JSValueConst proto);
-
-@@ -1039,6 +981,35 @@ int JS_SetModuleExport(JSContext *ctx, JSModuleDef *m, const char *export_name,
- int JS_SetModuleExportList(JSContext *ctx, JSModuleDef *m,
- const JSCFunctionListEntry *tab, int len);
-
-+
-+/* Qbs extensions */
-+struct LookupResult
-+{
-+ JSValue value;
-+ JSValue scope;
-+ int useResult;
-+};
-+typedef struct LookupResult ScopeLookup(JSContext *ctx, JSAtom prop);
-+void setScopeLookup(JSContext *ctx, ScopeLookup *scopeLookup);
-+
-+// Alternative: Request with throw in script engine
-+typedef void FoundUndefinedHandler(JSContext *ctx);
-+void setFoundUndefinedHandler(JSContext *ctx, FoundUndefinedHandler *handler);
-+
-+typedef void FunctionEnteredHandler(JSContext *ctx, JSValue this_val);
-+typedef void FunctionExitedHandler(JSContext *ctx);
-+void setFunctionEnteredHandler(JSContext *ctx, FunctionEnteredHandler *handler);
-+void setFunctionExitedHandler(JSContext *ctx, FunctionExitedHandler *handler);
-+int isSimpleValue(JSValue v);
-+
-+#ifndef NDEBUG
-+void watchRefCount(void *p);
-+#endif
-+
-+void build_backtrace(JSContext *ctx, JSValueConst error_obj,
-+ const char *filename, int line_num,
-+ int backtrace_flags);
-+
- #undef js_unlikely
- #undef js_force_inline
-
diff --git a/src/shared/quickjs/quickjs.h b/src/shared/quickjs/quickjs.h
index aa4a74c9c..3a22f5b7b 100644
--- a/src/shared/quickjs/quickjs.h
+++ b/src/shared/quickjs/quickjs.h
@@ -156,7 +156,7 @@ static inline double JS_VALUE_GET_FLOAT64(JSValue v)
#define JS_NAN (0x7ff8000000000000 - ((uint64_t)JS_FLOAT64_TAG_ADDEND << 32))
-static inline JSValue JS_NewFloat64Impl(JSContext *ctx, double d)
+static inline JSValue __JS_NewFloat64(JSContext *ctx, double d)
{
(void) ctx;
union {
@@ -226,7 +226,7 @@ JSValue mkPtr(int32_t tag, void *p);
#define JS_NAN (JSValue){ .u.float64 = JS_FLOAT64_NAN, JS_TAG_FLOAT64 }
-static inline JSValue JS_NewFloat64Impl(JSContext *ctx, double d)
+static inline JSValue __JS_NewFloat64(JSContext *ctx, double d)
{
(void) ctx;
JSValue v;
@@ -312,6 +312,9 @@ static inline JS_BOOL JS_VALUE_IS_NAN(JSValue v)
#define JS_EVAL_FLAG_COMPILE_ONLY (1 << 5)
/* don't include the stack frames before this eval in the Error() backtraces */
#define JS_EVAL_FLAG_BACKTRACE_BARRIER (1 << 6)
+/* allow top-level await in normal script. JS_Eval() returns a
+ promise. Only allowed with JS_EVAL_TYPE_GLOBAL */
+#define JS_EVAL_FLAG_ASYNC (1 << 7)
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);
@@ -501,7 +504,10 @@ typedef struct JSClassDef {
JSClassExoticMethods *exotic;
} JSClassDef;
+#define JS_INVALID_CLASS_ID 0
JSClassID JS_NewClassID(JSClassID *pclass_id);
+/* Returns the class ID if `v` is an object, otherwise returns JS_INVALID_CLASS_ID. */
+JSClassID JS_GetClassID(JSValue v);
int JS_NewClass(JSRuntime *rt, JSClassID class_id, const JSClassDef *class_def);
int JS_IsRegisteredClass(JSRuntime *rt, JSClassID class_id);
@@ -514,6 +520,7 @@ JSValue JS_NewInt64(JSContext *ctx, int64_t val);
JSValue JS_NewUint32(JSContext *ctx, uint32_t val);
JSValue JS_NewBigInt64(JSContext *ctx, int64_t v);
JSValue JS_NewBigUint64(JSContext *ctx, uint64_t v);
+
JSValue JS_NewFloat64(JSContext *ctx, double d);
static inline JS_BOOL JS_IsNumber(JSValueConst v)
@@ -583,7 +590,9 @@ static inline JS_BOOL JS_IsObject(JSValueConst v)
JSValue JS_Throw(JSContext *ctx, JSValue obj);
JSValue JS_GetException(JSContext *ctx);
+JS_BOOL JS_HasException(JSContext *ctx);
JS_BOOL JS_IsError(JSContext *ctx, JSValueConst val);
+void JS_SetUncatchableError(JSContext *ctx, JSValueConst val, JS_BOOL flag);
void JS_ResetUncatchableError(JSContext *ctx);
JSValue JS_NewError(JSContext *ctx);
JSValue __js_printf_like(2, 3) JS_ThrowSyntaxError(JSContext *ctx, const char *fmt, ...);
@@ -627,6 +636,10 @@ static inline JSValue JS_DupValueRT(JSRuntime *rt, JSValueConst v)
return v;
}
+JS_BOOL JS_StrictEq(JSContext *ctx, JSValueConst op1, JSValueConst op2);
+JS_BOOL JS_SameValue(JSContext *ctx, JSValueConst op1, JSValueConst op2);
+JS_BOOL JS_SameValueZero(JSContext *ctx, JSValueConst op1, JSValueConst op2);
+
int JS_ToBool(JSContext *ctx, JSValueConst val); /* return -1 for JS_EXCEPTION */
int JS_ToInt32(JSContext *ctx, int32_t *pres, JSValueConst val);
static inline int JS_ToUint32(JSContext *ctx, uint32_t *pres, JSValueConst val)
@@ -668,12 +681,12 @@ JS_BOOL JS_IsConstructor(JSContext* ctx, JSValueConst val);
JS_BOOL JS_SetConstructorBit(JSContext *ctx, JSValueConst func_obj, JS_BOOL val);
JS_BOOL JS_IsArrayBuffer(JSValueConst v);
-JSValue JS_NewDate(JSContext *ctx, const char *s);
-JS_BOOL JS_IsDate(JSValueConst v);
-
JSValue JS_NewArray(JSContext *ctx);
int JS_IsArray(JSContext *ctx, JSValueConst val);
+JSValue JS_NewDate(JSContext *ctx, double epoch_ms);
+JS_BOOL JS_IsDate(JSValueConst v);
+
JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj,
JSAtom prop, JSValueConst receiver,
JS_BOOL throw_ref_error);
@@ -687,13 +700,13 @@ JSValue JS_GetPropertyStr(JSContext *ctx, JSValueConst this_obj,
JSValue JS_GetPropertyUint32(JSContext *ctx, JSValueConst this_obj,
uint32_t idx);
-int JS_SetPropertyInternal(JSContext *ctx, JSValueConst this_obj,
- JSAtom prop, JSValue val,
+int JS_SetPropertyInternal(JSContext *ctx, JSValueConst obj,
+ JSAtom prop, JSValue val, JSValueConst this_obj,
int flags);
static inline int JS_SetProperty(JSContext *ctx, JSValueConst this_obj,
JSAtom prop, JSValue val)
{
- return JS_SetPropertyInternal(ctx, this_obj, prop, val, JS_PROP_THROW);
+ return JS_SetPropertyInternal(ctx, this_obj, prop, val, this_obj, JS_PROP_THROW);
}
int JS_SetPropertyUint32(JSContext *ctx, JSValueConst this_obj,
uint32_t idx, JSValue val);
@@ -774,6 +787,23 @@ JSValue JS_NewArrayBuffer(JSContext *ctx, uint8_t *buf, size_t len,
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);
+
+typedef enum JSTypedArrayEnum {
+ JS_TYPED_ARRAY_UINT8C = 0,
+ JS_TYPED_ARRAY_INT8,
+ JS_TYPED_ARRAY_UINT8,
+ JS_TYPED_ARRAY_INT16,
+ JS_TYPED_ARRAY_UINT16,
+ JS_TYPED_ARRAY_INT32,
+ JS_TYPED_ARRAY_UINT32,
+ JS_TYPED_ARRAY_BIG_INT64,
+ JS_TYPED_ARRAY_BIG_UINT64,
+ JS_TYPED_ARRAY_FLOAT32,
+ JS_TYPED_ARRAY_FLOAT64,
+} JSTypedArrayEnum;
+
+JSValue JS_NewTypedArray(JSContext *ctx, int argc, JSValueConst *argv,
+ JSTypedArrayEnum array_type);
JSValue JS_GetTypedArrayBuffer(JSContext *ctx, JSValueConst obj,
size_t *pbyte_offset,
size_t *pbyte_length,
@@ -787,7 +817,15 @@ typedef struct {
void JS_SetSharedArrayBufferFunctions(JSRuntime *rt,
const JSSharedArrayBufferFunctions *sf);
+typedef enum JSPromiseStateEnum {
+ JS_PROMISE_PENDING,
+ JS_PROMISE_FULFILLED,
+ JS_PROMISE_REJECTED,
+} JSPromiseStateEnum;
+
JSValue JS_NewPromiseCapability(JSContext *ctx, JSValue *resolving_funcs);
+JSPromiseStateEnum JS_PromiseState(JSContext *ctx, JSValue promise);
+JSValue JS_PromiseResult(JSContext *ctx, JSValue promise);
/* is_handled = TRUE means that the rejection is handled */
typedef void JSHostPromiseRejectionTracker(JSContext *ctx, JSValueConst promise,
@@ -821,6 +859,7 @@ void JS_SetModuleLoaderFunc(JSRuntime *rt,
/* return the import.meta object of a module */
JSValue JS_GetImportMeta(JSContext *ctx, JSModuleDef *m);
JSAtom JS_GetModuleName(JSContext *ctx, JSModuleDef *m);
+JSValue JS_GetModuleNamespace(JSContext *ctx, JSModuleDef *m);
/* JS Job support */
@@ -858,8 +897,8 @@ int JS_ResolveModule(JSContext *ctx, JSValueConst obj);
/* only exported for os.Worker() */
JSAtom JS_GetScriptOrModuleName(JSContext *ctx, int n_stack_levels);
/* only exported for os.Worker() */
-JSModuleDef *JS_RunModule(JSContext *ctx, const char *basename,
- const char *filename);
+JSValue JS_LoadModule(JSContext *ctx, const char *basename,
+ const char *filename);
/* C function definition */
typedef enum JSCFunctionEnum { /* XXX: should rename for namespace isolation */
diff --git a/src/shared/quickjs/quickjs.qbs b/src/shared/quickjs/quickjs.qbs
index 4c8112ac9..bdce37979 100644
--- a/src/shared/quickjs/quickjs.qbs
+++ b/src/shared/quickjs/quickjs.qbs
@@ -12,6 +12,8 @@ StaticLibrary {
files: [
"cutils.c",
"cutils.h",
+ "libbf.c",
+ "libbf.h",
"libregexp-opcode.h",
"libregexp.c",
"libregexp.h",
@@ -22,12 +24,11 @@ StaticLibrary {
"quickjs-atom.h",
"quickjs-opcode.h",
"quickjs.c",
- "quickjs.diff",
"quickjs.h",
]
Export {
Depends { name: "cpp" }
- cpp.includePaths: [exportingProduct.sourceDirectory]
+ cpp.systemIncludePaths: [exportingProduct.sourceDirectory]
}
}