mirror of
https://github.com/Samsung/escargot.git
synced 2026-06-22 10:01:50 +00:00
Compare commits
5 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bce02aba5e | ||
|
|
b6860b13f9 | ||
|
|
80848e9d6c | ||
|
|
a2b62f7c9f | ||
|
|
64a7e124d0 |
10 changed files with 196 additions and 365 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
|
@ -26,3 +26,6 @@
|
||||||
path = third_party/wasm/wabt
|
path = third_party/wasm/wabt
|
||||||
url = https://github.com/WebAssembly/wabt
|
url = https://github.com/WebAssembly/wabt
|
||||||
ignore = untracked
|
ignore = untracked
|
||||||
|
[submodule "test/web-tooling-benchmark"]
|
||||||
|
path = test/web-tooling-benchmark
|
||||||
|
url = https://github.com/v8/web-tooling-benchmark
|
||||||
|
|
|
||||||
117
README.md
117
README.md
|
|
@ -1,11 +1,4 @@
|
||||||
# Escargot
|
# Try-Catch Version of Escargot (Origin)
|
||||||
|
|
||||||
[](LICENSE)
|
|
||||||
[](https://github.com/Samsung/escargot/releases)
|
|
||||||

|
|
||||||
[](https://github.com/Samsung/escargot/actions)
|
|
||||||
[](https://scan.coverity.com/projects/samsung-escargot)
|
|
||||||
[](https://codecov.io/gh/Samsung/escargot)
|
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
|
|
@ -22,95 +15,47 @@ sudo apt-get install gcc-multilib g++-multilib
|
||||||
sudo apt-get install libicu-dev:i386
|
sudo apt-get install libicu-dev:i386
|
||||||
```
|
```
|
||||||
|
|
||||||
#### On macOS
|
|
||||||
|
|
||||||
```sh
|
|
||||||
brew install autoconf automake cmake icu4c libtool ninja pkg-config
|
|
||||||
```
|
|
||||||
|
|
||||||
Note: For later build steps (cmake, pkg-config) to find ICU libraries, you may
|
|
||||||
need to set the `PKG_CONFIG_PATH` environment variable, as instructed by brew.
|
|
||||||
E.g.:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
export PKG_CONFIG_PATH="/usr/local/opt/icu4c/lib/pkgconfig"
|
|
||||||
# ESCARGOT_LIBICU_SUPPORT_WITH_DLOPEN should be `OFF` to link icu lib in static
|
|
||||||
cmake -DESCARGOT_HOST=darwin -DESCARGOT_ARCH=x64 -DESCARGOT_MODE=release -DESCARGOT_LIBICU_SUPPORT_WITH_DLOPEN=OFF -DESCARGOT_OUTPUT=shell -GNinja
|
|
||||||
```
|
|
||||||
|
|
||||||
## Build Escargot
|
## Build Escargot
|
||||||
|
|
||||||
|
build core runtime of Escargot engine (excluding intl, temporal etc)
|
||||||
```sh
|
```sh
|
||||||
git clone https://github.com/Samsung/escargot.git
|
git clone https://github.com/Samsung/escargot.git -b try-catch
|
||||||
cd escargot
|
cd escargot
|
||||||
git submodule update --init third_party
|
git submodule update --init third_party
|
||||||
cmake -DESCARGOT_HOST=linux -DESCARGOT_ARCH=x64 -DESCARGOT_MODE=release -DESCARGOT_OUTPUT=shell -GNinja
|
cmake -H. -Bout/test/release -DESCARGOT_HOST=linux -DESCARGOT_ARCH=[x86|x64|arm|aarch64] -DESCARGOT_MODE=release -DESCARGOT_OUTPUT=shell -DESCARGOT_THREADING=ON -DESCARGOT_TEST=ON -GNinja
|
||||||
ninja
|
ninja -Cout/test/release
|
||||||
```
|
```
|
||||||
|
|
||||||
## Build Android version
|
|
||||||
|
|
||||||
```sh
|
|
||||||
git clone https://github.com/Samsung/escargot.git
|
|
||||||
cd escargot
|
|
||||||
git submodule update --init third_party
|
|
||||||
export ANDROID_SDK_ROOT=.... # set your android SDK root first
|
|
||||||
cd build/android/
|
|
||||||
./gradlew bundleReleaseAar # build escargot AAR
|
|
||||||
./gradlew assembleDebug # build debug test shell
|
|
||||||
./gradlew :escargot:connectedDebugAndroidTest # run escargot-jni tests on android device
|
|
||||||
./gradlew :escargot:testDebugUnitTest # run escargot-jni tests on host
|
|
||||||
./gradlew bundleHostJar # bundle jar for host
|
|
||||||
```
|
|
||||||
|
|
||||||
## Build Windows version
|
|
||||||
|
|
||||||
Install VS2022 with cmake and ninja.
|
|
||||||
Open [ x86 Native Tools Command Prompt for VS 2022 | x64 Native Tools Command Prompt for VS 2022 ]
|
|
||||||
```sh
|
|
||||||
git clone https://github.com/Samsung/escargot.git
|
|
||||||
cd escargot
|
|
||||||
git submodule update --init third_party
|
|
||||||
|
|
||||||
CMake -G "Visual Studio 17 2022" -DCMAKE_SYSTEM_NAME=[ Windows | WindowsStore ] -DCMAKE_SYSTEM_VERSION:STRING="10.0" -DCMAKE_SYSTEM_PROCESSOR=[ x86 | x64 ] -DCMAKE_GENERATOR_PLATFORM=[ Win32 | x64 ],version=10.0.18362.0 -DESCARGOT_ARCH=[ x86 | x64 ] -DESCARGOT_MODE=release -Bout -DESCARGOT_HOST=windows -DESCARGOT_OUTPUT=shell -DESCARGOT_LIBICU_SUPPORT=ON -DESCARGOT_LIBICU_SUPPORT_WITH_DLOPEN=OFF -DESCARGOT_THREADING=ON
|
|
||||||
cd out
|
|
||||||
msbuild ESCARGOT.sln /property:Configuration=Release /p:platform=[ Win32 | x64 ]
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Build options
|
|
||||||
|
|
||||||
The following build options are supported when generating ninja rules using cmake.
|
|
||||||
|
|
||||||
* -DESCARGOT_HOST=[ linux | tizen_obs | darwin | android | windows ]<br>
|
|
||||||
Compile Escargot for Linux, Tizen, macOS, or Windows platform
|
|
||||||
* -DESCARGOT_ARCH=[ x64 | x86 | arm | i686 | aarch64 ]<br>
|
|
||||||
Compile Escargot for each architecture
|
|
||||||
* -DESCARGOT_MODE=[ debug | release ]<br>
|
|
||||||
Compile Escargot for either release or debug mode
|
|
||||||
* -DESCARGOT_OUTPUT=[ shared_lib | static_lib | shell | cctest ]<br>
|
|
||||||
Define target output type
|
|
||||||
* -DESCARGOT_LIBICU_SUPPORT=[ ON | OFF ]<br>
|
|
||||||
Enable libicu library if set ON. (Optional, default = ON)
|
|
||||||
* -DESCARGOT_THREADING=[ ON | OFF ]<br>
|
|
||||||
Enable Threading support. (Optional, default = OFF)
|
|
||||||
* -DESCARGOT_CODE_CACHE=[ ON | OFF ]<br>
|
|
||||||
Enable Code cache support. (Optional, default = OFF)
|
|
||||||
* -DESCARGOT_WASM=[ ON | OFF ]<br>
|
|
||||||
Enable WASM support. (Optional, default = OFF)
|
|
||||||
* -DESCARGOT_SMALL_CONFIG=[ ON | OFF ]<br>
|
|
||||||
Enable Options for small devices. (Optional, default = OFF)
|
|
||||||
|
|
||||||
## Testing
|
## Testing
|
||||||
|
|
||||||
First, get benchmarks and tests:
|
#### octane
|
||||||
|
|
||||||
|
Using test runner
|
||||||
```sh
|
```sh
|
||||||
git submodule update --init
|
tools/run-tests.py --engine=ESCARGOT_BINARY_PATH octane
|
||||||
```
|
```
|
||||||
|
|
||||||
### Benchmarks
|
Or directly run octane benchmarks
|
||||||
|
|
||||||
Test run for each benchmark (Sunspider, Octane, V8, Chakracore, test262,
|
|
||||||
SpiderMonkey, etc.):
|
|
||||||
```sh
|
```sh
|
||||||
tools/run-tests.py --arch=x86_64 spidermonkey test262 v8
|
cd test/octane/
|
||||||
|
./escargot run.js
|
||||||
```
|
```
|
||||||
|
#### sunspider
|
||||||
|
|
||||||
|
Using test runner
|
||||||
|
```sh
|
||||||
|
tools/run-tests.py --engine=ESCARGOT_BINARY_PATH sunspider-js
|
||||||
|
```
|
||||||
|
|
||||||
|
#### kraken
|
||||||
|
|
||||||
|
download kraken benchmark
|
||||||
|
```sh
|
||||||
|
git clone https://github.com/mozilla-it/krakenbenchmark.mozilla.org.git
|
||||||
|
```
|
||||||
|
run kraken benchmark
|
||||||
|
```sh
|
||||||
|
cd krakenbenchmark.mozilla.org
|
||||||
|
./sunspider --shell ESCARGOT_BINARY_PATH --suite kraken-1.1
|
||||||
|
```
|
||||||
|
results would be stored in `kraken-1.1-results` directory
|
||||||
|
|
|
||||||
|
|
@ -71,11 +71,11 @@ IF (ESCARGOT_SMALL_CONFIG)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
IF (NOT DEFINED ESCARGOT_LIBICU_SUPPORT)
|
IF (NOT DEFINED ESCARGOT_LIBICU_SUPPORT)
|
||||||
SET (ESCARGOT_LIBICU_SUPPORT ON)
|
SET (ESCARGOT_LIBICU_SUPPORT OFF)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
IF (NOT DEFINED ESCARGOT_LIBICU_SUPPORT_WITH_DLOPEN)
|
IF (NOT DEFINED ESCARGOT_LIBICU_SUPPORT_WITH_DLOPEN)
|
||||||
SET (ESCARGOT_LIBICU_SUPPORT_WITH_DLOPEN ON)
|
SET (ESCARGOT_LIBICU_SUPPORT_WITH_DLOPEN OFF)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
#######################################################
|
#######################################################
|
||||||
|
|
|
||||||
|
|
@ -1236,21 +1236,15 @@ StringRef* DebuggerOperationsRef::BreakpointOperations::eval(StringRef* sourceCo
|
||||||
|
|
||||||
debugger->setStopState(ESCARGOT_DEBUGGER_IN_EVAL_MODE);
|
debugger->setStopState(ESCARGOT_DEBUGGER_IN_EVAL_MODE);
|
||||||
|
|
||||||
try {
|
Value asValue(toImpl(sourceCode));
|
||||||
Value asValue(toImpl(sourceCode));
|
Value evalResult(Value::ForceUninitialized);
|
||||||
Value evalResult(Value::ForceUninitialized);
|
evalResult = state->context()->globalObject()->evalLocal(*state, asValue, state->thisValue(), reinterpret_cast<ByteCodeBlock*>(weakCodeRef())->m_codeBlock, true);
|
||||||
evalResult = state->context()->globalObject()->evalLocal(*state, asValue, state->thisValue(), reinterpret_cast<ByteCodeBlock*>(weakCodeRef())->m_codeBlock, true);
|
|
||||||
|
|
||||||
if (evalResult.isObject()) {
|
if (evalResult.isObject()) {
|
||||||
result = nullptr;
|
result = nullptr;
|
||||||
objectIndex = putObject(toRef(evalResult.asObject()));
|
objectIndex = putObject(toRef(evalResult.asObject()));
|
||||||
} else {
|
} else {
|
||||||
result = evalResult.toStringWithoutException(*state);
|
result = evalResult.toStringWithoutException(*state);
|
||||||
}
|
|
||||||
} catch (const Value& val) {
|
|
||||||
result = val.toStringWithoutException(*state);
|
|
||||||
|
|
||||||
isError = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
debugger->setStopState(ESCARGOT_DEBUGGER_IN_WAIT_MODE);
|
debugger->setStopState(ESCARGOT_DEBUGGER_IN_WAIT_MODE);
|
||||||
|
|
@ -1364,13 +1358,9 @@ static void fillObjectProperties(ExecutionState* state, Object* object, Object::
|
||||||
|
|
||||||
result[start + i].key = toRef(keys[i].toStringWithoutException(*state));
|
result[start + i].key = toRef(keys[i].toStringWithoutException(*state));
|
||||||
|
|
||||||
try {
|
ObjectGetResult value = object->getOwnProperty(*state, propertyName);
|
||||||
ObjectGetResult value = object->getOwnProperty(*state, propertyName);
|
|
||||||
|
|
||||||
result[start + i].value = toRef(value.value(*state, Value(object)));
|
result[start + i].value = toRef(value.value(*state, Value(object)));
|
||||||
} catch (const Value& val) {
|
|
||||||
// The value field is optional, and not filled on error.
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1385,14 +1375,10 @@ static void fillRecordProperties(ExecutionState* state, EnvironmentRecord* recor
|
||||||
|
|
||||||
result[i].key = toRef(name.string());
|
result[i].key = toRef(name.string());
|
||||||
|
|
||||||
try {
|
EnvironmentRecord::GetBindingValueResult value = record->getBindingValue(*state, name);
|
||||||
EnvironmentRecord::GetBindingValueResult value = record->getBindingValue(*state, name);
|
ASSERT(value.m_hasBindingValue);
|
||||||
ASSERT(value.m_hasBindingValue);
|
|
||||||
|
|
||||||
result[i].value = toRef(value.m_value);
|
result[i].value = toRef(value.m_value);
|
||||||
} catch (const Value& val) {
|
|
||||||
// The value field is optional, and not filled on error.
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1407,14 +1393,10 @@ static void fillRecordProperties(ExecutionState* state, ModuleEnvironmentRecord*
|
||||||
|
|
||||||
result[i].key = toRef(name.string());
|
result[i].key = toRef(name.string());
|
||||||
|
|
||||||
try {
|
EnvironmentRecord::GetBindingValueResult value = record->getBindingValue(*state, name);
|
||||||
EnvironmentRecord::GetBindingValueResult value = record->getBindingValue(*state, name);
|
ASSERT(value.m_hasBindingValue);
|
||||||
ASSERT(value.m_hasBindingValue);
|
|
||||||
|
|
||||||
result[i].value = toRef(value.m_value);
|
result[i].value = toRef(value.m_value);
|
||||||
} catch (const Value& val) {
|
|
||||||
// The value field is optional, and not filled on error.
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1694,154 +1694,102 @@ void Scanner::scanTemplate(Scanner::ScannerResult* token, bool head)
|
||||||
size_t indexForError = this->index;
|
size_t indexForError = this->index;
|
||||||
bool tail = false;
|
bool tail = false;
|
||||||
|
|
||||||
try {
|
while (!this->eof()) {
|
||||||
while (!this->eof()) {
|
char16_t ch = this->peekCharWithoutEOF();
|
||||||
char16_t ch = this->peekCharWithoutEOF();
|
++this->index;
|
||||||
++this->index;
|
indexForError = this->index;
|
||||||
indexForError = this->index;
|
if (ch == '`') {
|
||||||
if (ch == '`') {
|
tail = true;
|
||||||
tail = true;
|
terminated = true;
|
||||||
|
break;
|
||||||
|
} else if (ch == '$') {
|
||||||
|
if (this->peekChar() == '{') {
|
||||||
|
++this->index;
|
||||||
|
indexForError = this->index;
|
||||||
terminated = true;
|
terminated = true;
|
||||||
break;
|
break;
|
||||||
} else if (ch == '$') {
|
}
|
||||||
if (this->peekChar() == '{') {
|
cooked += ch;
|
||||||
++this->index;
|
raw += ch;
|
||||||
indexForError = this->index;
|
} else if (ch == '\\') {
|
||||||
terminated = true;
|
raw += ch;
|
||||||
break;
|
ch = this->peekChar();
|
||||||
}
|
if (!isLineTerminator(ch)) {
|
||||||
cooked += ch;
|
auto currentIndex = this->index;
|
||||||
raw += ch;
|
++this->index;
|
||||||
} else if (ch == '\\') {
|
switch (ch) {
|
||||||
raw += ch;
|
case 'n':
|
||||||
ch = this->peekChar();
|
|
||||||
if (!isLineTerminator(ch)) {
|
|
||||||
auto currentIndex = this->index;
|
|
||||||
++this->index;
|
|
||||||
switch (ch) {
|
|
||||||
case 'n':
|
|
||||||
cooked += '\n';
|
|
||||||
break;
|
|
||||||
case 'r':
|
|
||||||
cooked += '\r';
|
|
||||||
break;
|
|
||||||
case 't':
|
|
||||||
cooked += '\t';
|
|
||||||
break;
|
|
||||||
case 'u':
|
|
||||||
if (this->peekChar() == '{') {
|
|
||||||
++this->index;
|
|
||||||
cooked += this->scanUnicodeCodePointEscape();
|
|
||||||
} else {
|
|
||||||
const size_t restore = this->index;
|
|
||||||
const char32_t unescaped = this->scanHexEscape(ch);
|
|
||||||
if (unescaped != EMPTY_CODE_POINT) {
|
|
||||||
ParserCharPiece piece(unescaped);
|
|
||||||
cooked += UTF16StringDataNonGCStd(piece.data, piece.length);
|
|
||||||
} else {
|
|
||||||
this->throwUnexpectedToken(Messages::InvalidHexEscapeSequence);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'x': {
|
|
||||||
const char32_t unescaped = this->scanHexEscape(ch);
|
|
||||||
if (unescaped == EMPTY_CODE_POINT) {
|
|
||||||
this->throwUnexpectedToken(Messages::InvalidHexEscapeSequence);
|
|
||||||
}
|
|
||||||
ParserCharPiece piece(unescaped);
|
|
||||||
cooked += UTF16StringDataNonGCStd(piece.data, piece.length);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'b':
|
|
||||||
cooked += '\b';
|
|
||||||
break;
|
|
||||||
case 'f':
|
|
||||||
cooked += '\f';
|
|
||||||
break;
|
|
||||||
case 'v':
|
|
||||||
cooked += '\v';
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (ch == '0') {
|
|
||||||
if (isDecimalDigit(this->peekChar())) {
|
|
||||||
// Illegal: \01 \02 and so on
|
|
||||||
this->throwUnexpectedToken(Messages::TemplateOctalLiteral);
|
|
||||||
}
|
|
||||||
cooked += (char16_t)'\0';
|
|
||||||
} else if (isOctalDigit(ch)) {
|
|
||||||
// Illegal: \1 \2
|
|
||||||
this->throwUnexpectedToken(Messages::TemplateOctalLiteral);
|
|
||||||
} else {
|
|
||||||
cooked += ch;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
auto endIndex = this->index;
|
|
||||||
for (size_t i = currentIndex; i < endIndex; i++) {
|
|
||||||
raw += this->sourceCharAt(i);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
++this->index;
|
|
||||||
indexForError = this->index;
|
|
||||||
++this->lineNumber;
|
|
||||||
if (ch == '\r' && this->peekChar() == '\n') {
|
|
||||||
++this->index;
|
|
||||||
indexForError = this->index;
|
|
||||||
}
|
|
||||||
if (ch == 0x2028 || ch == 0x2029) {
|
|
||||||
raw += ch;
|
|
||||||
} else {
|
|
||||||
raw += '\n';
|
|
||||||
}
|
|
||||||
this->lineStart = this->index;
|
|
||||||
}
|
|
||||||
} else if (isLineTerminator(ch)) {
|
|
||||||
++this->lineNumber;
|
|
||||||
if (ch == '\r' && this->peekChar() == '\n') {
|
|
||||||
++this->index;
|
|
||||||
indexForError = this->index;
|
|
||||||
}
|
|
||||||
if (ch == 0x2028 || ch == 0x2029) {
|
|
||||||
raw += ch;
|
|
||||||
cooked += ch;
|
|
||||||
} else {
|
|
||||||
raw += '\n';
|
|
||||||
cooked += '\n';
|
cooked += '\n';
|
||||||
}
|
break;
|
||||||
this->lineStart = this->index;
|
case 'r':
|
||||||
} else {
|
cooked += '\r';
|
||||||
cooked += ch;
|
break;
|
||||||
raw += ch;
|
case 't':
|
||||||
}
|
cooked += '\t';
|
||||||
}
|
break;
|
||||||
|
case 'u':
|
||||||
if (!terminated) {
|
if (this->peekChar() == '{') {
|
||||||
this->throwUnexpectedToken();
|
++this->index;
|
||||||
}
|
cooked += this->scanUnicodeCodePointEscape();
|
||||||
} catch (esprima::Error* err) {
|
} else {
|
||||||
error = new (GC) esprima::Error(*err);
|
const size_t restore = this->index;
|
||||||
delete err;
|
const char32_t unescaped = this->scanHexEscape(ch);
|
||||||
this->index = indexForError;
|
if (unescaped != EMPTY_CODE_POINT) {
|
||||||
|
ParserCharPiece piece(unescaped);
|
||||||
while (!this->eof()) {
|
cooked += UTF16StringDataNonGCStd(piece.data, piece.length);
|
||||||
char16_t ch = this->peekCharWithoutEOF();
|
} else {
|
||||||
++this->index;
|
// ignore exception
|
||||||
if (ch == '`') {
|
RELEASE_ASSERT_NOT_REACHED();
|
||||||
tail = true;
|
}
|
||||||
terminated = true;
|
}
|
||||||
break;
|
break;
|
||||||
} else if (ch == '$') {
|
case 'x': {
|
||||||
if (this->peekChar() == '{') {
|
const char32_t unescaped = this->scanHexEscape(ch);
|
||||||
++this->index;
|
if (unescaped == EMPTY_CODE_POINT) {
|
||||||
terminated = true;
|
// ignore exception
|
||||||
|
RELEASE_ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
ParserCharPiece piece(unescaped);
|
||||||
|
cooked += UTF16StringDataNonGCStd(piece.data, piece.length);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
cooked += ch;
|
case 'b':
|
||||||
raw += ch;
|
cooked += '\b';
|
||||||
} else if (isLineTerminator(ch)) {
|
break;
|
||||||
|
case 'f':
|
||||||
|
cooked += '\f';
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
cooked += '\v';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (ch == '0') {
|
||||||
|
if (isDecimalDigit(this->peekChar())) {
|
||||||
|
// Illegal: \01 \02 and so on
|
||||||
|
// ignore exception
|
||||||
|
RELEASE_ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
cooked += (char16_t)'\0';
|
||||||
|
} else if (isOctalDigit(ch)) {
|
||||||
|
// Illegal: \1 \2
|
||||||
|
// ignore exception
|
||||||
|
RELEASE_ASSERT_NOT_REACHED();
|
||||||
|
} else {
|
||||||
|
cooked += ch;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
auto endIndex = this->index;
|
||||||
|
for (size_t i = currentIndex; i < endIndex; i++) {
|
||||||
|
raw += this->sourceCharAt(i);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
++this->index;
|
||||||
|
indexForError = this->index;
|
||||||
++this->lineNumber;
|
++this->lineNumber;
|
||||||
if (ch == '\r' && this->peekChar() == '\n') {
|
if (ch == '\r' && this->peekChar() == '\n') {
|
||||||
++this->index;
|
++this->index;
|
||||||
|
indexForError = this->index;
|
||||||
}
|
}
|
||||||
if (ch == 0x2028 || ch == 0x2029) {
|
if (ch == 0x2028 || ch == 0x2029) {
|
||||||
raw += ch;
|
raw += ch;
|
||||||
|
|
@ -1849,12 +1797,32 @@ void Scanner::scanTemplate(Scanner::ScannerResult* token, bool head)
|
||||||
raw += '\n';
|
raw += '\n';
|
||||||
}
|
}
|
||||||
this->lineStart = this->index;
|
this->lineStart = this->index;
|
||||||
} else {
|
|
||||||
raw += ch;
|
|
||||||
}
|
}
|
||||||
|
} else if (isLineTerminator(ch)) {
|
||||||
|
++this->lineNumber;
|
||||||
|
if (ch == '\r' && this->peekChar() == '\n') {
|
||||||
|
++this->index;
|
||||||
|
indexForError = this->index;
|
||||||
|
}
|
||||||
|
if (ch == 0x2028 || ch == 0x2029) {
|
||||||
|
raw += ch;
|
||||||
|
cooked += ch;
|
||||||
|
} else {
|
||||||
|
raw += '\n';
|
||||||
|
cooked += '\n';
|
||||||
|
}
|
||||||
|
this->lineStart = this->index;
|
||||||
|
} else {
|
||||||
|
cooked += ch;
|
||||||
|
raw += ch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!terminated) {
|
||||||
|
// ignore exception
|
||||||
|
RELEASE_ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
ScanTemplateResult* result = new ScanTemplateResult();
|
ScanTemplateResult* result = new ScanTemplateResult();
|
||||||
result->head = head;
|
result->head = head;
|
||||||
result->tail = tail;
|
result->tail = tail;
|
||||||
|
|
|
||||||
|
|
@ -928,11 +928,7 @@ Script::ModuleExecutionResult Script::innerModuleEvaluation(ExecutionState& stat
|
||||||
ModuleEnvironmentRecord* moduleRecord = md->m_moduleRecord;
|
ModuleEnvironmentRecord* moduleRecord = md->m_moduleRecord;
|
||||||
moduleRecord->createBinding(state, state.context()->staticStrings().stringStarDefaultStar, false, false, false);
|
moduleRecord->createBinding(state, state.context()->staticStrings().stringStarDefaultStar, false, false, false);
|
||||||
|
|
||||||
try {
|
moduleRecord->initializeBinding(state, state.context()->staticStrings().stringStarDefaultStar, JSON::parse(state, sourceCode(), Value()));
|
||||||
moduleRecord->initializeBinding(state, state.context()->staticStrings().stringStarDefaultStar, JSON::parse(state, sourceCode(), Value()));
|
|
||||||
} catch (const Value& e) {
|
|
||||||
md->m_evaluationError = EncodedValue(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (md->m_pendingAsyncDependencies.hasValue() && md->m_pendingAsyncDependencies.value() > 0) {
|
} else if (md->m_pendingAsyncDependencies.hasValue() && md->m_pendingAsyncDependencies.value() > 0) {
|
||||||
// If module.[[PendingAsyncDependencies]] > 0, set module.[[AsyncEvaluating]] to true.
|
// If module.[[PendingAsyncDependencies]] > 0, set module.[[AsyncEvaluating]] to true.
|
||||||
|
|
@ -1114,12 +1110,7 @@ Script::ModuleExecutionResult Script::moduleExecute(ExecutionState& state, Optio
|
||||||
bool gotException = false;
|
bool gotException = false;
|
||||||
|
|
||||||
if (LIKELY(!m_topCodeBlock->isAsync())) {
|
if (LIKELY(!m_topCodeBlock->isAsync())) {
|
||||||
try {
|
Interpreter::interpret(newState, byteCodeBlock, reinterpret_cast<size_t>(byteCodeBlock->m_code.data()), registerFile);
|
||||||
Interpreter::interpret(newState, byteCodeBlock, reinterpret_cast<size_t>(byteCodeBlock->m_code.data()), registerFile);
|
|
||||||
} catch (const Value& e) {
|
|
||||||
resultValue = e;
|
|
||||||
gotException = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
clearStack<512>();
|
clearStack<512>();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -417,37 +417,27 @@ ScriptParser::InitializeScriptResult ScriptParser::initializeScript(String* orig
|
||||||
|
|
||||||
// Generate ByteCode
|
// Generate ByteCode
|
||||||
if (LIKELY(needByteCodeGeneration)) {
|
if (LIKELY(needByteCodeGeneration)) {
|
||||||
try {
|
|
||||||
#if defined(ENABLE_CODE_CACHE)
|
#if defined(ENABLE_CODE_CACHE)
|
||||||
// Store cache
|
// Store cache
|
||||||
if (cacheable) {
|
if (cacheable) {
|
||||||
codeCache->prepareCacheWriting(srcHash);
|
codeCache->prepareCacheWriting(srcHash);
|
||||||
|
|
||||||
// For storing cache, CodeBlockTree is firstly saved
|
// For storing cache, CodeBlockTree is firstly saved
|
||||||
codeCache->storeCodeBlockTree(topCodeBlock, m_codeBlockCacheInfo);
|
codeCache->storeCodeBlockTree(topCodeBlock, m_codeBlockCacheInfo);
|
||||||
|
|
||||||
// After CodeBlockTree, ByteCode and StringTable are stored sequentially
|
// After CodeBlockTree, ByteCode and StringTable are stored sequentially
|
||||||
topCodeBlock->m_byteCodeBlock = ByteCodeGenerator::generateByteCode(m_context, topCodeBlock, programNode, inWith, true);
|
topCodeBlock->m_byteCodeBlock = ByteCodeGenerator::generateByteCode(m_context, topCodeBlock, programNode, inWith, true);
|
||||||
|
|
||||||
codeCache->postCacheWriting(srcHash);
|
codeCache->postCacheWriting(srcHash);
|
||||||
deleteCodeBlockCacheInfo();
|
deleteCodeBlockCacheInfo();
|
||||||
|
|
||||||
ESCARGOT_LOG_INFO("[CodeCache] Store CodeCache Done (%s)\n", srcName->toUTF8StringData().data());
|
ESCARGOT_LOG_INFO("[CodeCache] Store CodeCache Done (%s)\n", srcName->toUTF8StringData().data());
|
||||||
} else {
|
} else {
|
||||||
topCodeBlock->m_byteCodeBlock = ByteCodeGenerator::generateByteCode(m_context, topCodeBlock, programNode, inWith, false);
|
topCodeBlock->m_byteCodeBlock = ByteCodeGenerator::generateByteCode(m_context, topCodeBlock, programNode, inWith, false);
|
||||||
}
|
|
||||||
#else
|
|
||||||
topCodeBlock->m_byteCodeBlock = ByteCodeGenerator::generateByteCode(m_context, topCodeBlock, programNode, inWith);
|
|
||||||
#endif
|
|
||||||
} catch (const char* message) {
|
|
||||||
m_context->astAllocator().reset();
|
|
||||||
GC_enable();
|
|
||||||
|
|
||||||
ScriptParser::InitializeScriptResult result;
|
|
||||||
result.parseErrorCode = ErrorCode::SyntaxError;
|
|
||||||
result.parseErrorMessage = String::fromASCII(message, strlen(message));
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
topCodeBlock->m_byteCodeBlock = ByteCodeGenerator::generateByteCode(m_context, topCodeBlock, programNode, inWith);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset ASTAllocator
|
// reset ASTAllocator
|
||||||
|
|
@ -488,15 +478,7 @@ void ScriptParser::generateFunctionByteCode(ExecutionState& state, InterpretedCo
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate ByteCode
|
// Generate ByteCode
|
||||||
try {
|
codeBlock->m_byteCodeBlock = ByteCodeGenerator::generateByteCode(state.context(), codeBlock, functionNode);
|
||||||
codeBlock->m_byteCodeBlock = ByteCodeGenerator::generateByteCode(state.context(), codeBlock, functionNode);
|
|
||||||
} catch (const char* message) {
|
|
||||||
// reset ASTAllocator
|
|
||||||
m_context->astAllocator().reset();
|
|
||||||
GC_enable();
|
|
||||||
ErrorObject::throwBuiltinError(state, ErrorCode::SyntaxError, message);
|
|
||||||
RELEASE_ASSERT_NOT_REACHED();
|
|
||||||
}
|
|
||||||
|
|
||||||
// reset ASTAllocator
|
// reset ASTAllocator
|
||||||
m_context->astAllocator().reset();
|
m_context->astAllocator().reset();
|
||||||
|
|
@ -570,45 +552,27 @@ ScriptParser::InitializeScriptResult ScriptParser::initializeScriptWithDebugger(
|
||||||
Script* script = nullptr;
|
Script* script = nullptr;
|
||||||
|
|
||||||
// Parsing
|
// Parsing
|
||||||
try {
|
ASTClassInfo* outerClassInfo = esprima::generateClassInfoFrom(m_context, parentCodeBlock);
|
||||||
ASTClassInfo* outerClassInfo = esprima::generateClassInfoFrom(m_context, parentCodeBlock);
|
|
||||||
|
|
||||||
programNode = esprima::parseProgram(m_context, sourceView, outerClassInfo, isModule, strictFromOutside, inWith, SIZE_MAX, allowSC, allowSP, allowNewTarget, allowArguments);
|
programNode = esprima::parseProgram(m_context, sourceView, outerClassInfo, isModule, strictFromOutside, inWith, SIZE_MAX, allowSC, allowSP, allowNewTarget, allowArguments);
|
||||||
|
|
||||||
script = new Script(srcName, source, programNode->moduleData(), !parentCodeBlock, originLineOffset);
|
script = new Script(srcName, source, programNode->moduleData(), !parentCodeBlock, originLineOffset);
|
||||||
if (parentCodeBlock) {
|
if (parentCodeBlock) {
|
||||||
programNode->scopeContext()->m_hasEval = parentCodeBlock->hasEval();
|
programNode->scopeContext()->m_hasEval = parentCodeBlock->hasEval();
|
||||||
programNode->scopeContext()->m_hasWith = parentCodeBlock->hasWith();
|
programNode->scopeContext()->m_hasWith = parentCodeBlock->hasWith();
|
||||||
programNode->scopeContext()->m_isClassConstructor = parentCodeBlock->isClassConstructor();
|
programNode->scopeContext()->m_isClassConstructor = parentCodeBlock->isClassConstructor();
|
||||||
programNode->scopeContext()->m_isDerivedClassConstructor = parentCodeBlock->isDerivedClassConstructor();
|
programNode->scopeContext()->m_isDerivedClassConstructor = parentCodeBlock->isDerivedClassConstructor();
|
||||||
programNode->scopeContext()->m_isClassMethod = parentCodeBlock->isClassMethod();
|
programNode->scopeContext()->m_isClassMethod = parentCodeBlock->isClassMethod();
|
||||||
programNode->scopeContext()->m_isClassStaticMethod = parentCodeBlock->isClassStaticMethod();
|
programNode->scopeContext()->m_isClassStaticMethod = parentCodeBlock->isClassStaticMethod();
|
||||||
programNode->scopeContext()->m_allowSuperCall = parentCodeBlock->allowSuperCall();
|
programNode->scopeContext()->m_allowSuperCall = parentCodeBlock->allowSuperCall();
|
||||||
programNode->scopeContext()->m_allowSuperProperty = parentCodeBlock->allowSuperProperty();
|
programNode->scopeContext()->m_allowSuperProperty = parentCodeBlock->allowSuperProperty();
|
||||||
topCodeBlock = generateCodeBlockTreeFromASTWalker(m_context, sourceView, script, programNode->scopeContext(), parentCodeBlock, isEvalMode, isEvalCodeInFunction);
|
topCodeBlock = generateCodeBlockTreeFromASTWalker(m_context, sourceView, script, programNode->scopeContext(), parentCodeBlock, isEvalMode, isEvalCodeInFunction);
|
||||||
} else {
|
} else {
|
||||||
topCodeBlock = generateCodeBlockTreeFromAST(m_context, sourceView, script, programNode, isEvalMode, isEvalCodeInFunction);
|
topCodeBlock = generateCodeBlockTreeFromAST(m_context, sourceView, script, programNode, isEvalMode, isEvalCodeInFunction);
|
||||||
}
|
|
||||||
|
|
||||||
generateCodeBlockTreeFromASTWalkerPostProcess(topCodeBlock);
|
|
||||||
} catch (esprima::Error* orgError) {
|
|
||||||
// reset ASTAllocator
|
|
||||||
m_context->astAllocator().reset();
|
|
||||||
|
|
||||||
if (m_context->debuggerEnabled()) {
|
|
||||||
m_context->debugger()->parseCompleted(originSource ? originSource : source, srcName, originLineOffset, orgError->message);
|
|
||||||
m_context->debugger()->clearParsingData();
|
|
||||||
m_context->debugger()->setInDebuggingCodeMode(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
GC_enable();
|
|
||||||
|
|
||||||
ScriptParser::InitializeScriptResult result;
|
|
||||||
result.parseErrorCode = orgError->errorCode;
|
|
||||||
result.parseErrorMessage = orgError->message;
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
generateCodeBlockTreeFromASTWalkerPostProcess(topCodeBlock);
|
||||||
|
|
||||||
// dump Code Block
|
// dump Code Block
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
{
|
{
|
||||||
|
|
@ -622,41 +586,22 @@ ScriptParser::InitializeScriptResult ScriptParser::initializeScriptWithDebugger(
|
||||||
script->m_topCodeBlock = topCodeBlock;
|
script->m_topCodeBlock = topCodeBlock;
|
||||||
|
|
||||||
// Generate ByteCode
|
// Generate ByteCode
|
||||||
try {
|
topCodeBlock->m_byteCodeBlock = ByteCodeGenerator::generateByteCode(m_context, topCodeBlock, programNode, inWith);
|
||||||
topCodeBlock->m_byteCodeBlock = ByteCodeGenerator::generateByteCode(m_context, topCodeBlock, programNode, inWith);
|
|
||||||
|
|
||||||
// reset ASTAllocator
|
// reset ASTAllocator
|
||||||
m_context->astAllocator().reset();
|
m_context->astAllocator().reset();
|
||||||
|
|
||||||
Debugger* debugger = m_context->debugger();
|
Debugger* debugger = m_context->debugger();
|
||||||
if (debugger != nullptr) {
|
if (debugger != nullptr) {
|
||||||
recursivelyGenerateChildrenByteCode(topCodeBlock);
|
recursivelyGenerateChildrenByteCode(topCodeBlock);
|
||||||
|
|
||||||
debugger->parseCompleted(originSource ? originSource : source, srcName, originLineOffset);
|
debugger->parseCompleted(originSource ? originSource : source, srcName, originLineOffset);
|
||||||
debugger->clearParsingData();
|
debugger->clearParsingData();
|
||||||
debugger->setInDebuggingCodeMode(false);
|
debugger->setInDebuggingCodeMode(false);
|
||||||
}
|
|
||||||
|
|
||||||
GC_enable();
|
|
||||||
} catch (const char* message) {
|
|
||||||
m_context->astAllocator().reset();
|
|
||||||
|
|
||||||
String* msg = String::fromASCII(message, strlen(message));
|
|
||||||
|
|
||||||
if (m_context->debuggerEnabled()) {
|
|
||||||
m_context->debugger()->parseCompleted(originSource ? originSource : source, srcName, originLineOffset, msg);
|
|
||||||
m_context->debugger()->clearParsingData();
|
|
||||||
m_context->debugger()->setInDebuggingCodeMode(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
GC_enable();
|
|
||||||
|
|
||||||
ScriptParser::InitializeScriptResult result;
|
|
||||||
result.parseErrorCode = ErrorCode::SyntaxError;
|
|
||||||
result.parseErrorMessage = msg;
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GC_enable();
|
||||||
|
|
||||||
ScriptParser::InitializeScriptResult result;
|
ScriptParser::InitializeScriptResult result;
|
||||||
result.script = script;
|
result.script = script;
|
||||||
return result;
|
return result;
|
||||||
|
|
|
||||||
|
|
@ -4874,7 +4874,7 @@ public:
|
||||||
template <class ASTBuilder>
|
template <class ASTBuilder>
|
||||||
ASTNode parseDebuggerStatement(ASTBuilder& builder)
|
ASTNode parseDebuggerStatement(ASTBuilder& builder)
|
||||||
{
|
{
|
||||||
ESCARGOT_LOG_ERROR("debugger keyword is not supported yet");
|
// ESCARGOT_LOG_ERROR("debugger keyword is not supported yet");
|
||||||
MetaNode node = this->createNode();
|
MetaNode node = this->createNode();
|
||||||
this->expectKeyword(KeywordKind::DebuggerKeyword);
|
this->expectKeyword(KeywordKind::DebuggerKeyword);
|
||||||
this->consumeSemicolon();
|
this->consumeSemicolon();
|
||||||
|
|
|
||||||
|
|
@ -261,13 +261,9 @@ RegExpObject::RegExpCacheEntry& RegExpObject::getCacheEntryAndCompileIfNeeded(Ex
|
||||||
} else {
|
} else {
|
||||||
const char* yarrError = nullptr;
|
const char* yarrError = nullptr;
|
||||||
JSC::Yarr::YarrPattern* yarrPattern = nullptr;
|
JSC::Yarr::YarrPattern* yarrPattern = nullptr;
|
||||||
try {
|
JSC::Yarr::ErrorCode errorCode = JSC::Yarr::ErrorCode::NoError;
|
||||||
JSC::Yarr::ErrorCode errorCode = JSC::Yarr::ErrorCode::NoError;
|
yarrPattern = JSC::Yarr::YarrPattern::createYarrPattern(source, (JSC::Yarr::RegExpFlags)option, errorCode);
|
||||||
yarrPattern = JSC::Yarr::YarrPattern::createYarrPattern(source, (JSC::Yarr::RegExpFlags)option, errorCode);
|
yarrError = JSC::Yarr::errorMessage(errorCode);
|
||||||
yarrError = JSC::Yarr::errorMessage(errorCode);
|
|
||||||
} catch (const std::bad_alloc& e) {
|
|
||||||
ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, "got too complicated RegExp pattern to process");
|
|
||||||
}
|
|
||||||
auto iter = cache->insert(std::make_pair(RegExpCacheKey(source, option), RegExpCacheEntry(yarrError, yarrPattern))).first;
|
auto iter = cache->insert(std::make_pair(RegExpCacheKey(source, option), RegExpCacheEntry(yarrError, yarrPattern))).first;
|
||||||
return iter.value();
|
return iter.value();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
1
test/web-tooling-benchmark
Submodule
1
test/web-tooling-benchmark
Submodule
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 4a12828c6a1eed02a70c011bd080445dd319a05f
|
||||||
Loading…
Add table
Add a link
Reference in a new issue