'cflags': [ '-Wfatal-errors', '-Os' ],
},
},
+ 'all_dependent_settings': {
+ 'configurations': {
+ 'Release': {
+ 'defines': ['NDEBUG'],
+ },
+ },
+ },
'conditions': [
['target_os=="tizen"', {
'target_defaults': {
IF (${ESCARGOT_HOST} STREQUAL "linux")
# default set of LDFLAGS
SET (ESCARGOT_LDFLAGS -lpthread -lrt -Wl,--gc-sections)
- IF (${ESCARGOT_ARCH} STREQUAL "x64")
+ IF ((${ESCARGOT_ARCH} STREQUAL "x64") OR (${ESCARGOT_ARCH} STREQUAL "x86_64"))
ELSEIF ((${ESCARGOT_ARCH} STREQUAL "x86") OR (${ESCARGOT_ARCH} STREQUAL "i686"))
SET (ESCARGOT_BUILD_32BIT ON)
SET (ESCARGOT_CXXFLAGS ${ESCARGOT_CXXFLAGS} -m32 -mfpmath=sse -msse -msse2)
# default set of LDFLAGS
SET (ESCARGOT_LDFLAGS -lpthread -lrt -Wl,--gc-sections)
SET (ESCARGOT_DEFINITIONS -DESCARGOT_TIZEN)
- IF (${ESCARGOT_ARCH} STREQUAL "x64")
+ IF ((${ESCARGOT_ARCH} STREQUAL "x64") OR (${ESCARGOT_ARCH} STREQUAL "x86_64"))
ELSEIF ((${ESCARGOT_ARCH} STREQUAL "x86") OR (${ESCARGOT_ARCH} STREQUAL "i686"))
SET (ESCARGOT_BUILD_32BIT ON)
SET (ESCARGOT_CXXFLAGS ${ESCARGOT_CXXFLAGS} -m32 -mfpmath=sse -msse -msse2)
#include <thread>
#include <mutex>
#include <atomic>
+#include <condition_variable>
#endif
extern "C" {
m_platform->hostImportModuleDynamically(toRef(relatedContext), toRef(referrer), toRef(src), toRef(promise));
}
+ virtual bool canBlockExecution(Context* relatedContext) override
+ {
+ return m_platform->canBlockExecution(toRef(relatedContext));
+ }
+
virtual void* allocateThreadLocalCustomData() override
{
return m_platform->allocateThreadLocalCustomData();
locData = iterMap->second;
}
+ InterpretedCodeBlock* codeBlock = byteCodeBlock->codeBlock();
size_t byteCodePosition = stackTraceData[i].second.loc.byteCodePosition;
stackTraceData[i].second.loc = byteCodeBlock->computeNodeLOCFromByteCode(state->context(), byteCodePosition, byteCodeBlock->m_codeBlock, locData);
+ stackTraceData[i].second.src = codeBlock->script()->srcName();
+ stackTraceData[i].second.sourceCode = codeBlock->script()->sourceCode();
}
Evaluator::StackTraceData t;
}
void notifyHostImportModuleDynamicallyResult(ContextRef* relatedContext, ScriptRef* referrer, StringRef* src, PromiseObjectRef* promise, LoadModuleResult loadModuleResult);
+ virtual bool canBlockExecution(ContextRef* relatedContext)
+ {
+ return true;
+ }
+
// ThreadLocal custom data
// PlatformRef should not have any member variables
// Instead, user could allocate thread-local values through following methods
return A;
}
-
-static Value builtinArrayToString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
- RESOLVE_THIS_BINDING_TO_OBJECT(thisObject, Array, toString);
- Value toString = thisObject->get(state, state.context()->staticStrings().join).value(state, thisObject);
- if (!toString.isCallable()) {
- toString = state.context()->globalObject()->objectPrototypeToString();
- }
- return Object::call(state, toString, thisObject, 0, nullptr);
-}
-
static Value builtinArrayConcat(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
{
RESOLVE_THIS_BINDING_TO_OBJECT(thisObject, Array, concat);
// Array.prototype.find ( predicate [ , thisArg ] )#
static Value builtinArrayFind(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
{
+ Value predicate = argv[0];
+ Value thisArg = argc > 1 ? argv[1] : Value();
// Let O be ? ToObject(this value).
RESOLVE_THIS_BINDING_TO_OBJECT(O, Array, find);
// Let len be ? ToLength(? Get(O, "length")).
- double len = O->length(state);
+ uint64_t len = O->length(state);
// If IsCallable(predicate) is false, throw a TypeError exception.
- if (!argv[0].isCallable()) {
+ if (!predicate.isCallable()) {
ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true, state.context()->staticStrings().find.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
}
- Value T;
- // If thisArg was supplied, let T be thisArg; else let T be undefined.
- if (argc >= 2) {
- T = argv[1];
- }
+
// Let k be 0.
- double k = 0;
+ uint64_t k = 0;
// Repeat, while k < len
while (k < len) {
// Let Pk be ! ToString(k).
// Let kValue be ? Get(O, Pk).
Value kValue = O->get(state, ObjectPropertyName(state, Value(k))).value(state, O);
- // Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).
+ // Let testResult be ToBoolean(? Call(predicate, thisArg, « kValue, k, O »)).
Value v[] = { kValue, Value(k), O };
- bool testResult = Object::call(state, argv[0], T, 3, v).toBoolean(state);
+ bool testResult = Object::call(state, argv[0], thisArg, 3, v).toBoolean(state);
// If testResult is true, return kValue.
if (testResult) {
return kValue;
// Array.prototype.findIndex ( predicate [ , thisArg ] )#
static Value builtinArrayFindIndex(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
{
+ Value predicate = argv[0];
+ Value thisArg = argc > 1 ? argv[1] : Value();
// Let O be ? ToObject(this value).
RESOLVE_THIS_BINDING_TO_OBJECT(O, Array, findIndex);
// Let len be ? ToLength(? Get(O, "length")).
- double len = O->length(state);
+ uint64_t len = O->length(state);
// If IsCallable(predicate) is false, throw a TypeError exception.
- if (!argv[0].isCallable()) {
+ if (!predicate.isCallable()) {
ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true, state.context()->staticStrings().findIndex.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
}
- Value T;
- // If thisArg was supplied, let T be thisArg; else let T be undefined.
- if (argc >= 2) {
- T = argv[1];
- }
+
// Let k be 0.
- double k = 0;
+ uint64_t k = 0;
// Repeat, while k < len
while (k < len) {
// Let Pk be ! ToString(k).
// Let kValue be ? Get(O, Pk).
Value kValue = O->get(state, ObjectPropertyName(state, Value(k))).value(state, O);
- // Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).
+ // Let testResult be ToBoolean(? Call(predicate, thisArg, « kValue, k, O »)).
Value v[] = { kValue, Value(k), O };
- bool testResult = Object::call(state, argv[0], T, 3, v).toBoolean(state);
+ bool testResult = Object::call(state, argv[0], thisArg, 3, v).toBoolean(state);
// If testResult is true, return k.
if (testResult) {
return Value(k);
static Value builtinArrayAt(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
{
- RESOLVE_THIS_BINDING_TO_OBJECT(obj, Array, entries);
+ RESOLVE_THIS_BINDING_TO_OBJECT(obj, Array, at);
size_t len = obj->length(state);
double relativeStart = argv[0].toInteger(state);
if (relativeStart < 0) {
return obj->getIndexedProperty(state, Value(relativeStart)).value(state, thisValue);
}
+static Value builtinArrayFindLast(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+ // https://tc39.es/proposal-array-find-from-last/index.html#sec-array.prototype.findlast
+ Value predicate = argv[0];
+ Value thisArg = argc > 1 ? argv[1] : Value();
+ // 1. Let O be ? ToObject(this value).
+ RESOLVE_THIS_BINDING_TO_OBJECT(O, Array, findLast);
+ // 2. Let len be ? LengthOfArrayLike(O).
+ int64_t len = static_cast<int64_t>(O->length(state));
+ // 3. If IsCallable(predicate) is false, throw a TypeError exception.
+ if (!predicate.isCallable()) {
+ ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true, state.context()->staticStrings().findLast.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
+ }
+ // 4. Let k be len - 1.
+ int64_t k = len - 1;
+ // 5. Repeat, while k ≥ 0,
+ while (k >= 0) {
+ // a. Let Pk be ! ToString(𝔽(k)).
+ // b. Let kValue be ? Get(O, Pk).
+ Value kValue = O->getIndexedProperty(state, Value(k)).value(state, O);
+ // c. Let testResult be ! ToBoolean(? Call(predicate, thisArg, « kValue, 𝔽(k), O »)).
+ Value predicateArgv[] = {
+ kValue, Value(k), Value(O)
+ };
+ bool testResult = Object::call(state, predicate, thisArg, 3, predicateArgv).toBoolean(state);
+ // d. If testResult is true, return kValue.
+ if (testResult) {
+ return kValue;
+ }
+ // e. Set k to k - 1.
+ k--;
+ }
+
+ return Value();
+}
+
+static Value builtinArrayFindLastIndex(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+ // https://tc39.es/proposal-array-find-from-last/index.html#sec-array.prototype.findlastindex
+ Value predicate = argv[0];
+ Value thisArg = argc > 1 ? argv[1] : Value();
+ // 1. Let O be ? ToObject(this value).
+ RESOLVE_THIS_BINDING_TO_OBJECT(O, Array, findLastIndex);
+ // 2. Let len be ? LengthOfArrayLike(O).
+ int64_t len = static_cast<int64_t>(O->length(state));
+ // 3. If IsCallable(predicate) is false, throw a TypeError exception.
+ if (!predicate.isCallable()) {
+ ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().Array.string(), true, state.context()->staticStrings().findLastIndex.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
+ }
+ // 4. Let k be len - 1.
+ int64_t k = len - 1;
+ // 5. Repeat, while k ≥ 0,
+ while (k >= 0) {
+ // a. Let Pk be ! ToString(𝔽(k)).
+ // b. Let kValue be ? Get(O, Pk).
+ Value kValue = O->getIndexedProperty(state, Value(k)).value(state, O);
+ // c. Let testResult be ! ToBoolean(? Call(predicate, thisArg, « kValue, 𝔽(k), O »)).
+ Value predicateArgv[] = {
+ kValue, Value(k), Value(O)
+ };
+ bool testResult = Object::call(state, predicate, thisArg, 3, predicateArgv).toBoolean(state);
+ // d. If testResult is true, return kValue.
+ if (testResult) {
+ return Value(k);
+ }
+ // e. Set k to k - 1.
+ k--;
+ }
+
+ return Value(-1);
+}
+
+void GlobalObject::initializeArray(ExecutionState& state)
+{
+ ObjectPropertyNativeGetterSetterData* nativeData = new ObjectPropertyNativeGetterSetterData(true, false, true,
+ [](ExecutionState& state, Object* self, const Value& receiver, const EncodedValue& privateDataFromObjectPrivateArea) -> Value {
+ ASSERT(self->isGlobalObject());
+ return self->asGlobalObject()->array();
+ },
+ nullptr);
+
+ defineNativeDataAccessorProperty(state, ObjectPropertyName(state.context()->staticStrings().Array), nativeData, Value(Value::EmptyValue));
+}
+
void GlobalObject::installArray(ExecutionState& state)
{
+ ASSERT(!!m_iteratorPrototype);
+ ASSERT(!!m_arrayToString);
+
m_array = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().Array, builtinArrayConstructor, 1), NativeFunctionObject::__ForBuiltinConstructor__);
m_array->setGlobalIntrinsicObject(state);
ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().shift, builtinArrayShift, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().reverse),
ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().reverse, builtinArrayReverse, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().toString),
- ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().toString, builtinArrayToString, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+ ObjectPropertyDescriptor(m_arrayToString, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().map),
ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().map, builtinArrayMap, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().some),
ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().flatMap, builtinArrayFlatMap, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().at),
ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().at, builtinArrayAt, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
+ m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().findLast),
+ ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().findLast, builtinArrayFindLast, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+ m_arrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().findLastIndex),
+ ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().findLastIndex, builtinArrayFindLastIndex, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
Object* blackList = new Object(state);
blackList->markThisObjectDontNeedStructureTransitionTable();
blackList->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().entries), ObjectPropertyDescriptor(Value(true), ObjectPropertyDescriptor::AllPresent));
blackList->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().fill), ObjectPropertyDescriptor(Value(true), ObjectPropertyDescriptor::AllPresent));
blackList->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().find), ObjectPropertyDescriptor(Value(true), ObjectPropertyDescriptor::AllPresent));
+ blackList->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().findLast), ObjectPropertyDescriptor(Value(true), ObjectPropertyDescriptor::AllPresent));
+ blackList->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().findLastIndex), ObjectPropertyDescriptor(Value(true), ObjectPropertyDescriptor::AllPresent));
blackList->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().findIndex), ObjectPropertyDescriptor(Value(true), ObjectPropertyDescriptor::AllPresent));
blackList->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().keys), ObjectPropertyDescriptor(Value(true), ObjectPropertyDescriptor::AllPresent));
blackList->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().values), ObjectPropertyDescriptor(Value(true), ObjectPropertyDescriptor::AllPresent));
m_arrayIteratorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag),
ObjectPropertyDescriptor(Value(String::fromASCII("Array Iterator")), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
- defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().Array),
- ObjectPropertyDescriptor(m_array, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+ redefineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().Array),
+ ObjectPropertyDescriptor(m_array, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
}
} // namespace Escargot
return newObject;
}
+void GlobalObject::initializeArrayBuffer(ExecutionState& state)
+{
+ ObjectPropertyNativeGetterSetterData* nativeData = new ObjectPropertyNativeGetterSetterData(true, false, true,
+ [](ExecutionState& state, Object* self, const Value& receiver, const EncodedValue& privateDataFromObjectPrivateArea) -> Value {
+ ASSERT(self->isGlobalObject());
+ return self->asGlobalObject()->arrayBuffer();
+ },
+ nullptr);
+
+ defineNativeDataAccessorProperty(state, ObjectPropertyName(state.context()->staticStrings().ArrayBuffer), nativeData, Value(Value::EmptyValue));
+}
+
void GlobalObject::installArrayBuffer(ExecutionState& state)
{
const StaticStrings* strings = &state.context()->staticStrings();
m_arrayBuffer->setFunctionPrototype(state, m_arrayBufferPrototype);
- defineOwnProperty(state, ObjectPropertyName(strings->ArrayBuffer),
- ObjectPropertyDescriptor(m_arrayBuffer, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+ redefineOwnProperty(state, ObjectPropertyName(strings->ArrayBuffer),
+ ObjectPropertyDescriptor(m_arrayBuffer, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
}
} // namespace Escargot
static Value builtinAsyncFromSyncIteratorNext(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
{
- // https://www.ecma-international.org/ecma-262/10.0/#sec-%asyncfromsynciteratorprototype%.next
+ // https://tc39.es/ecma262/#sec-%asyncfromsynciteratorprototype%.next
// Let O be the this value.
Value& O = thisValue;
// Let promiseCapability be ! NewPromiseCapability(%Promise%).
Object* result;
try {
// Let result be IteratorNext(syncIteratorRecord, value).
- result = IteratorObject::iteratorNext(state, syncIteratorRecord, argv[0]);
+ // If value is present, then
+ // a. Let result be IteratorNext(syncIteratorRecord, value).
+ // Else,
+ // a. Let result be IteratorNext(syncIteratorRecord).
+ result = IteratorObject::iteratorNext(state, syncIteratorRecord, argc ? argv[0] : Value(Value::EmptyValue));
} catch (const Value& thrownValue) {
// IfAbruptRejectPromise(result, promiseCapability).
Value argv = thrownValue;
static Value builtinAsyncFromSyncIteratorReturn(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
{
- // https://www.ecma-international.org/ecma-262/10.0/#sec-%asyncfromsynciteratorprototype%.return
+ // https://tc39.es/ecma262/#sec-%asyncfromsynciteratorprototype%.return
Value value = argv[0];
// Let O be the this value.
Value& O = thisValue;
return promiseCapability.m_promise;
}
- // Let result be Call(return, syncIterator, « value »).
Value result;
try {
- result = Object::call(state, returnVariable, syncIterator, 1, &value);
+ // If value is present, then
+ // a. Let result be Call(return, syncIterator, « value »).
+ // Else,
+ // a. Let result be Call(return, syncIterator).
+ if (argc) {
+ result = Object::call(state, returnVariable, syncIterator, 1, &value);
+ } else {
+ result = Object::call(state, returnVariable, syncIterator, 0, nullptr);
+ }
} catch (const Value& thrownValue) {
// IfAbruptRejectPromise(return, promiseCapability).
Value argv = thrownValue;
return asyncFromSyncIteratorContinuation(state, result.asObject(), promiseCapability);
}
+void GlobalObject::initializeAsyncFromSyncIterator(ExecutionState& state)
+{
+ // do nothing
+}
+
void GlobalObject::installAsyncFromSyncIterator(ExecutionState& state)
{
+ ASSERT(!!m_asyncIteratorPrototype);
+
// https://www.ecma-international.org/ecma-262/10.0/#sec-%asyncfromsynciteratorprototype%-object
m_asyncFromSyncIteratorPrototype = new Object(state, m_asyncIteratorPrototype);
m_asyncFromSyncIteratorPrototype->setGlobalIntrinsicObject(state, true);
return new ScriptAsyncFunctionObject(state, proto, functionSource.codeBlock, functionSource.outerEnvironment);
}
+void GlobalObject::initializeAsyncFunction(ExecutionState& state)
+{
+ // do nothing
+}
+
void GlobalObject::installAsyncFunction(ExecutionState& state)
{
m_asyncFunction = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().AsyncFunction, builtinAsyncFunction, 1), NativeFunctionObject::__ForBuiltinConstructor__);
return AsyncGeneratorObject::asyncGeneratorEnqueue(state, thisValue, AsyncGeneratorObject::AsyncGeneratorEnqueueType::Throw, argv[0]);
}
-void GlobalObject::installAsyncGeneratorFunction(ExecutionState& state)
+void GlobalObject::initializeAsyncGenerator(ExecutionState& state)
{
+ // do nothing
+}
+
+void GlobalObject::installAsyncGenerator(ExecutionState& state)
+{
+ ASSERT(!!m_asyncIteratorPrototype);
+
// https://www.ecma-international.org/ecma-262/10.0/index.html#sec-asyncgeneratorfunction
m_asyncGeneratorFunction = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().AsyncGeneratorFunction, builtinAsyncGeneratorFunction, 1), NativeFunctionObject::__ForBuiltinConstructor__);
m_asyncGeneratorFunction->setGlobalIntrinsicObject(state);
+++ /dev/null
-/*
- * Copyright (c) 2020-present Samsung Electronics Co., Ltd
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
- * USA
- */
-
-#include "Escargot.h"
-#include "runtime/GlobalObject.h"
-#include "runtime/Context.h"
-#include "runtime/VMInstance.h"
-#include "runtime/NativeFunctionObject.h"
-
-namespace Escargot {
-
-static Value builtinAsyncIteratorIterator(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
- return thisValue;
-}
-
-void GlobalObject::installAsyncIterator(ExecutionState& state)
-{
- // https://www.ecma-international.org/ecma-262/10.0/index.html#sec-%iteratorprototype%-object
- m_asyncIteratorPrototype = new Object(state);
- m_asyncIteratorPrototype->setGlobalIntrinsicObject(state, true);
-
- // https://www.ecma-international.org/ecma-262/10.0/index.html#sec-asynciteratorprototype-asynciterator
- m_asyncIteratorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().asyncIterator),
- ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(AtomicString(state, String::fromASCII("[Symbol.asyncIterator]")), builtinAsyncIteratorIterator, 0, NativeFunctionInfo::Strict)),
- (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-}
-} // namespace Escargot
* USA
*/
-#if defined(ENABLE_THREADING)
-
#include "Escargot.h"
#include "runtime/Context.h"
#include "runtime/VMInstance.h"
#include "runtime/TypedArrayInlines.h"
#include "runtime/Global.h"
#include "runtime/BigInt.h"
+#include "runtime/Platform.h"
#if !defined(HAVE_BUILTIN_ATOMIC_FUNCTIONS) && !defined(ENABLE_ATOMICS_GLOBAL_LOCK)
#error "without builtin atomic functions, we need to atomics global lock for implementing atomics builtin"
namespace Escargot {
+#if defined(ENABLE_THREADING)
+
enum class AtomicBinaryOps : uint8_t {
ADD,
AND,
#if defined(HAVE_BUILTIN_ATOMIC_FUNCTIONS)
uint8_t* replacementBytes = ALLOCA(8, uint8_t, state);
TypedArrayHelper::numberToRawBytes(state, type, replacement, replacementBytes);
- bool ret;
switch (type) {
case TypedArrayType::Int8:
atomicCompareExchange<int8_t>(rawStart, expectedBytes, replacementBytes);
TypedArrayType type = TA->typedArrayType();
#if defined(HAVE_BUILTIN_ATOMIC_FUNCTIONS)
- uint8_t* rawStart = TA->buffer()->data() + indexedPosition;
+ uint8_t* rawStart = buffer->data() + indexedPosition;
uint8_t* rawBytes = ALLOCA(8, uint8_t, state);
switch (type) {
case TypedArrayType::Int8:
}
#if defined(HAVE_BUILTIN_ATOMIC_FUNCTIONS)
- uint8_t* rawStart = TA->buffer()->data() + indexedPosition;
+ uint8_t* rawStart = buffer->data() + indexedPosition;
uint8_t* rawBytes = ALLOCA(8, uint8_t, state);
TypedArrayHelper::numberToRawBytes(state, type, v, rawBytes);
return atomicReadModifyWrite(state, argv[0], argv[1], argv[2], AtomicBinaryOps::XOR);
}
+static Value builtinAtomicsWait(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+ // https://tc39.es/ecma262/#sec-atomics.wait
+ // 25.4.12 Atomics.wait ( typedArray, index, value, timeout )
+ // 1. Let buffer be ? ValidateIntegerTypedArray(typedArray, true).
+ ArrayBuffer* buffer = validateIntegerTypedArray(state, argv[0], true);
+ TypedArrayObject* typedArray = argv[0].asObject()->asTypedArrayObject();
+ // 2. If IsSharedArrayBuffer(buffer) is false, throw a TypeError exception.
+ if (!buffer->isSharedArrayBufferObject()) {
+ ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Atomics.wait expects SharedArrayBuffer");
+ }
+ // 3. Let indexedPosition be ? ValidateAtomicAccess(typedArray, index).
+ size_t indexedPosition = validateAtomicAccess(state, typedArray, argv[1]);
+ // 4. Let arrayTypeName be typedArray.[[TypedArrayName]].
+ auto arrayTypeName = typedArray->typedArrayType();
+ // 5. If arrayTypeName is "BigInt64Array", let v be ? ToBigInt64(value).
+ Value v;
+ if (arrayTypeName == TypedArrayType::BigInt64) {
+ v = argv[2].toBigInt(state);
+ } else {
+ // 6. Otherwise, let v be ? ToInt32(value).
+ v = Value(argv[2].toInt32(state));
+ }
+ // 7. Let q be ? ToNumber(timeout).
+ double q = argv[3].toNumber(state);
+ // 8. If q is NaN or +∞𝔽, let t be +∞; else if q is -∞𝔽, let t be 0; else let t be max(ℝ(q), 0).
+ double t;
+ if (std::isnan(q) || q == std::numeric_limits<double>::infinity()) {
+ t = std::numeric_limits<double>::infinity();
+ } else if (q == -std::numeric_limits<double>::infinity()) {
+ t = 0;
+ } else {
+ t = std::max(q, 0.0);
+ }
+ // 9. Let B be AgentCanSuspend().
+ // 10. If B is false, throw a TypeError exception.
+ if (!Global::platform()->canBlockExecution(state.context())) {
+ ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Cannot suspend this thread");
+ }
+ // 11. Let block be buffer.[[ArrayBufferData]].
+ void* blockAddress = reinterpret_cast<int32_t*>(buffer->data()) + indexedPosition;
+ // 12. Let WL be GetWaiterList(block, indexedPosition).
+ Global::Waiter* WL = Global::waiter(blockAddress);
+ // 13. Perform EnterCriticalSection(WL).
+ WL->m_mutex.lock();
+ // 14. Let elementType be the Element Type value in Table 63 for arrayTypeName.
+ // 15. Let w be ! GetValueFromBuffer(buffer, indexedPosition, elementType, true, SeqCst).
+ Value w(Value::ForceUninitialized);
+#if defined(HAVE_BUILTIN_ATOMIC_FUNCTIONS)
+ uint8_t* rawStart = buffer->data() + indexedPosition;
+ uint8_t* rawBytes = ALLOCA(8, uint8_t, state);
+ switch (arrayTypeName) {
+ case TypedArrayType::Int32:
+ atomicLoad<int32_t>(rawStart, rawBytes);
+ break;
+ case TypedArrayType::BigInt64:
+ atomicLoad<int64_t>(rawStart, rawBytes);
+ break;
+ default:
+ RELEASE_ASSERT_NOT_REACHED();
+ break;
+ }
+ w = TypedArrayHelper::rawBytesToNumber(state, arrayTypeName, rawBytes);
+#else
+ {
+ std::lock_guard<SpinLock> guard(Global::atomicsLock());
+ w = buffer->getValueFromBuffer(state, indexedPosition, arrayTypeName);
+ }
+#endif
+ // 16. If v ≠ w, then
+ if (!v.equalsTo(state, w)) {
+ // a. Perform LeaveCriticalSection(WL).
+ WL->m_mutex.unlock();
+ // b. Return the String "not-equal".
+ return Value(state.context()->staticStrings().lazyNotEqual().string());
+ }
+ // 17. Let W be AgentSignifier().
+ // 18. Perform AddWaiter(WL, W).
+ // 19. Let notified be SuspendAgent(WL, W, t).
+ bool notified = true;
+ std::unique_lock<std::mutex> ul(WL->m_conditionVariableMutex);
+ WL->m_waiterCount++;
+ WL->m_mutex.unlock();
+ if (t == std::numeric_limits<double>::infinity()) {
+ WL->m_waiter.wait(ul);
+ } else {
+ notified = WL->m_waiter.wait_for(ul, std::chrono::milliseconds((int64_t)t)) == std::cv_status::no_timeout;
+ }
+ WL->m_mutex.lock();
+ // 20. If notified is true, then
+ // a. Assert: W is not on the list of waiters in WL.
+ // 21. Else,
+ // a. Perform RemoveWaiter(WL, W).
+ if (!notified) {
+ WL->m_waiterCount--;
+ }
+ // 22. Perform LeaveCriticalSection(WL).
+ WL->m_mutex.unlock();
+ // 23. If notified is true, return the String "ok".
+ if (notified) {
+ return Value(state.context()->staticStrings().lazyOk().string());
+ }
+ // 24. Return the String "timed-out".
+ return Value(state.context()->staticStrings().lazyTimedOut().string());
+}
+
+static Value builtinAtomicsNotify(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+ // https://tc39.es/ecma262/#sec-atomics.notify
+ // Atomics.notify ( typedArray, index, count )
+ // 1. Let buffer be ? ValidateIntegerTypedArray(typedArray, true).
+ ArrayBuffer* buffer = validateIntegerTypedArray(state, argv[0], true);
+ TypedArrayObject* typedArray = argv[0].asObject()->asTypedArrayObject();
+ // 2. Let indexedPosition be ? ValidateAtomicAccess(typedArray, index).
+ size_t indexedPosition = validateAtomicAccess(state, typedArray, argv[1]);
+ double c;
+ // 3. If count is undefined, let c be +∞.
+ if (argv[2].isUndefined()) {
+ c = std::numeric_limits<double>::infinity();
+ } else {
+ // 4. Else,
+ // a. Let intCount be ? ToIntegerOrInfinity(count).
+ auto intCount = argv[2].toInteger(state);
+ // b. Let c be max(intCount, 0).
+ c = std::max(intCount, 0.0);
+ }
+ // 5. Let block be buffer.[[ArrayBufferData]].
+ void* blockAddress = reinterpret_cast<int32_t*>(buffer->data()) + indexedPosition;
+ // 6. Let arrayTypeName be typedArray.[[TypedArrayName]].
+ // 7. If IsSharedArrayBuffer(buffer) is false, return +0𝔽.
+ if (!buffer->isSharedArrayBufferObject()) {
+ return Value(0);
+ }
+ // 8. Let WL be GetWaiterList(block, indexedPosition).
+ Global::Waiter* WL = Global::waiter(blockAddress);
+ // 9. Let n be 0.
+ double n = 0;
+ // 10. Perform EnterCriticalSection(WL).
+ WL->m_mutex.lock();
+ double count = std::min((double)WL->m_waiterCount, c);
+ WL->m_waiterCount -= count;
+ // 11. Let S be RemoveWaiters(WL, c).
+ // 12. Repeat, while S is not an empty List,
+ // a. Let W be the first agent in S.
+ // b. Remove W from the front of S.
+ // c. Perform NotifyWaiter(WL, W).
+ // d. Set n to n + 1.
+ for (n = 0; n < count; n++) {
+ WL->m_mutex.unlock();
+ WL->m_waiter.notify_one();
+ WL->m_mutex.lock();
+ }
+ // 13. Perform LeaveCriticalSection(WL).
+ WL->m_mutex.unlock();
+ // 14. Return 𝔽(n).
+ return Value(n);
+}
+
+static Value builtinAtomicsIsLockFree(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+ auto size = argv[0].toInteger(state);
+#if defined(HAVE_BUILTIN_ATOMIC_FUNCTIONS)
+ if (size == 1 || size == 2 || size == 4 || size == 8) {
+ return Value(true);
+ }
+ return Value(false);
+#else
+ // spec want to do toInteger operation
+ size;
+ return Value(false);
+#endif
+}
+
+void GlobalObject::initializeAtomics(ExecutionState& state)
+{
+ ObjectPropertyNativeGetterSetterData* nativeData = new ObjectPropertyNativeGetterSetterData(true, false, true,
+ [](ExecutionState& state, Object* self, const Value& receiver, const EncodedValue& privateDataFromObjectPrivateArea) -> Value {
+ ASSERT(self->isGlobalObject());
+ return self->asGlobalObject()->atomics();
+ },
+ nullptr);
+
+ defineNativeDataAccessorProperty(state, ObjectPropertyName(state.context()->staticStrings().Atomics), nativeData, Value(Value::EmptyValue));
+}
+
void GlobalObject::installAtomics(ExecutionState& state)
{
m_atomics = new Object(state);
m_atomics->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().stringXor),
ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().stringXor, builtinAtomicsXor, 3, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
- defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().Atomics),
- ObjectPropertyDescriptor(m_atomics, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+ m_atomics->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().isLockFree),
+ ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().isLockFree, builtinAtomicsIsLockFree, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+ m_atomics->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().wait),
+ ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().wait, builtinAtomicsWait, 4, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+ m_atomics->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().notify),
+ ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().notify, builtinAtomicsNotify, 3, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+ redefineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().Atomics),
+ ObjectPropertyDescriptor(m_atomics, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+}
+#else
+
+void GlobalObject::initializeAtomics(ExecutionState& state)
+{
+ // dummy initialize function
}
-} // namespace Escargot
#endif
+} // namespace Escargot
#endif
}
+void GlobalObject::initializeBigInt(ExecutionState& state)
+{
+ ObjectPropertyNativeGetterSetterData* nativeData = new ObjectPropertyNativeGetterSetterData(true, false, true,
+ [](ExecutionState& state, Object* self, const Value& receiver, const EncodedValue& privateDataFromObjectPrivateArea) -> Value {
+ ASSERT(self->isGlobalObject());
+ return self->asGlobalObject()->bigInt();
+ },
+ nullptr);
+
+ defineNativeDataAccessorProperty(state, ObjectPropertyName(state.context()->staticStrings().BigInt), nativeData, Value(Value::EmptyValue));
+}
+
void GlobalObject::installBigInt(ExecutionState& state)
{
m_bigInt = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().BigInt, builtinBigIntConstructor, 1), NativeFunctionObject::__ForBuiltinConstructor__);
m_bigInt->setFunctionPrototype(state, m_bigIntPrototype);
- defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().BigInt),
- ObjectPropertyDescriptor(m_bigInt, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+ m_bigIntProxyObject = new BigIntObject(state, new BigInt(UINT64_C(0)));
+
+ redefineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().BigInt),
+ ObjectPropertyDescriptor(m_bigInt, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
}
} // namespace Escargot
RELEASE_ASSERT_NOT_REACHED();
}
+void GlobalObject::initializeBoolean(ExecutionState& state)
+{
+ ObjectPropertyNativeGetterSetterData* nativeData = new ObjectPropertyNativeGetterSetterData(true, false, true,
+ [](ExecutionState& state, Object* self, const Value& receiver, const EncodedValue& privateDataFromObjectPrivateArea) -> Value {
+ ASSERT(self->isGlobalObject());
+ return self->asGlobalObject()->boolean();
+ },
+ nullptr);
+
+ defineNativeDataAccessorProperty(state, ObjectPropertyName(state.context()->staticStrings().Boolean), nativeData, Value(Value::EmptyValue));
+}
+
void GlobalObject::installBoolean(ExecutionState& state)
{
const StaticStrings* strings = &state.context()->staticStrings();
m_boolean->setFunctionPrototype(state, m_booleanPrototype);
- defineOwnProperty(state, ObjectPropertyName(strings->Boolean),
- ObjectPropertyDescriptor(m_boolean, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+ m_booleanProxyObject = new BooleanObject(state);
+
+ redefineOwnProperty(state, ObjectPropertyName(strings->Boolean),
+ ObjectPropertyDescriptor(m_boolean, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
}
} // namespace Escargot
RELEASE_ASSERT_NOT_REACHED();
}
+void GlobalObject::initializeDataView(ExecutionState& state)
+{
+ ObjectPropertyNativeGetterSetterData* nativeData = new ObjectPropertyNativeGetterSetterData(true, false, true,
+ [](ExecutionState& state, Object* self, const Value& receiver, const EncodedValue& privateDataFromObjectPrivateArea) -> Value {
+ ASSERT(self->isGlobalObject());
+ return self->asGlobalObject()->dataView();
+ },
+ nullptr);
+
+ defineNativeDataAccessorProperty(state, ObjectPropertyName(state.context()->staticStrings().DataView), nativeData, Value(Value::EmptyValue));
+}
+
void GlobalObject::installDataView(ExecutionState& state)
{
m_dataView = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().DataView, builtinDataViewConstructor, 1), NativeFunctionObject::__ForBuiltinConstructor__);
m_dataViewPrototype->defineOwnProperty(state, ObjectPropertyName(strings->byteOffset), byteOffsetDesc);
}
- defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().DataView),
- ObjectPropertyDescriptor(m_dataView, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+ redefineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().DataView),
+ ObjectPropertyDescriptor(m_dataView, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
}
} // namespace Escargot
}
#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
-#define INTL_DATE_TIME_FORMAT_FORMAT(REQUIRED, DEFUALT) \
- double x = thisObject->primitiveValue(); \
- if (std::isnan(x)) { \
- return new ASCIIString("Invalid Date"); \
- } \
- Value locales, options; \
- if (argc >= 1) { \
- locales = argv[0]; \
- } \
- if (argc >= 2) { \
- options = argv[1]; \
- } \
- auto dateTimeOption = IntlDateTimeFormat::toDateTimeOptions(state, options, String::fromASCII(REQUIRED), String::fromASCII(DEFUALT)); \
- Object* dateFormat = IntlDateTimeFormat::create(state, state.context(), locales, dateTimeOption); \
- auto result = IntlDateTimeFormat::format(state, dateFormat, x); \
+#define INTL_DATE_TIME_FORMAT_FORMAT(REQUIRED, DEFUALT) \
+ double x = thisObject->primitiveValue(); \
+ if (std::isnan(x)) { \
+ return new ASCIIString("Invalid Date"); \
+ } \
+ Value locales, options; \
+ if (argc >= 1) { \
+ locales = argv[0]; \
+ } \
+ if (argc >= 2) { \
+ options = argv[1]; \
+ } \
+ auto dateTimeOption = IntlDateTimeFormatObject::toDateTimeOptions(state, options, String::fromASCII(REQUIRED), String::fromASCII(DEFUALT)); \
+ IntlDateTimeFormatObject* dateFormat = new IntlDateTimeFormatObject(state, locales, dateTimeOption); \
+ auto result = dateFormat->format(state, x); \
return new UTF16String(result.data(), result.length());
#endif
}
}
+void GlobalObject::initializeDate(ExecutionState& state)
+{
+ ObjectPropertyNativeGetterSetterData* nativeData = new ObjectPropertyNativeGetterSetterData(true, false, true,
+ [](ExecutionState& state, Object* self, const Value& receiver, const EncodedValue& privateDataFromObjectPrivateArea) -> Value {
+ ASSERT(self->isGlobalObject());
+ return self->asGlobalObject()->date();
+ },
+ nullptr);
+
+ defineNativeDataAccessorProperty(state, ObjectPropertyName(state.context()->staticStrings().Date), nativeData, Value(Value::EmptyValue));
+}
+
void GlobalObject::installDate(ExecutionState& state)
{
m_date = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().Date, builtinDateConstructor, 7), NativeFunctionObject::__ForBuiltinConstructor__);
m_date->setFunctionPrototype(state, m_datePrototype);
- defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().Date),
- ObjectPropertyDescriptor(m_date, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+ redefineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().Date),
+ ObjectPropertyDescriptor(m_date, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
}
} // namespace Escargot
namespace Escargot {
+static void installErrorCause(ExecutionState& state, Object* obj, const Value& options)
+{
+ const AtomicString& causeString = state.context()->staticStrings().cause;
+ // 1. If Type(options) is Object and ? HasProperty(options, "cause") is true, then
+ if (options.isObject()) {
+ auto res = options.asObject()->hasProperty(state, ObjectPropertyName(causeString));
+ if (res) {
+ // Let cause be ? Get(options, "cause").
+ Value cause = res.value(state, ObjectPropertyName(causeString), options);
+ // Perform ! CreateNonEnumerableDataPropertyOrThrow(O, "cause", cause).
+ obj->defineOwnPropertyThrowsException(state, causeString,
+ ObjectPropertyDescriptor(cause, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectStructurePropertyDescriptor::ConfigurablePresent)));
+ }
+ }
+}
+
static Value builtinErrorConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
{
if (!newTarget.hasValue()) {
Value message = argv[0];
if (!message.isUndefined()) {
- obj->defineOwnPropertyThrowsExceptionWhenStrictMode(state, state.context()->staticStrings().message,
- ObjectPropertyDescriptor(message.toString(state), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectStructurePropertyDescriptor::ConfigurablePresent)));
+ obj->defineOwnPropertyThrowsException(state, state.context()->staticStrings().message,
+ ObjectPropertyDescriptor(message.toString(state), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectStructurePropertyDescriptor::ConfigurablePresent)));
}
+
+ Value options = argc > 1 ? argv[1] : Value();
+ installErrorCause(state, obj, options);
return obj;
}
-#define DEFINE_ERROR_CTOR(errorName, lowerCaseErrorName) \
- static Value builtin##errorName##ErrorConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget) \
- { \
- if (!newTarget.hasValue()) { \
- newTarget = state.resolveCallee(); \
- } \
- Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* { \
- return constructorRealm->globalObject()->lowerCaseErrorName##ErrorPrototype(); \
- }); \
- ErrorObject* obj = new errorName##ErrorObject(state, proto, String::emptyString); \
- Value message = argv[0]; \
- if (!message.isUndefined()) { \
- obj->defineOwnPropertyThrowsExceptionWhenStrictMode(state, state.context()->staticStrings().message, \
- ObjectPropertyDescriptor(message.toString(state), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectStructurePropertyDescriptor::ConfigurablePresent))); \
- } \
- return obj; \
+#define DEFINE_ERROR_CTOR(errorName, lowerCaseErrorName) \
+ static Value builtin##errorName##ErrorConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget) \
+ { \
+ if (!newTarget.hasValue()) { \
+ newTarget = state.resolveCallee(); \
+ } \
+ Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* { \
+ return constructorRealm->globalObject()->lowerCaseErrorName##ErrorPrototype(); \
+ }); \
+ ErrorObject* obj = new errorName##ErrorObject(state, proto, String::emptyString); \
+ Value message = argv[0]; \
+ if (!message.isUndefined()) { \
+ obj->defineOwnPropertyThrowsException(state, state.context()->staticStrings().message, \
+ ObjectPropertyDescriptor(message.toString(state), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectStructurePropertyDescriptor::ConfigurablePresent))); \
+ } \
+ Value options = argc > 1 ? argv[1] : Value(); \
+ installErrorCause(state, obj, options); \
+ return obj; \
}
DEFINE_ERROR_CTOR(Reference, reference);
// Let msg be ? ToString(message).
// Let msgDesc be the PropertyDescriptor { [[Value]]: msg, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }.
// Perform ! DefinePropertyOrThrow(O, "message", msgDesc).
- O->defineOwnPropertyThrowsExceptionWhenStrictMode(state, state.context()->staticStrings().message,
- ObjectPropertyDescriptor(message.toString(state), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectStructurePropertyDescriptor::ConfigurablePresent)));
+ O->defineOwnPropertyThrowsException(state, state.context()->staticStrings().message,
+ ObjectPropertyDescriptor(message.toString(state), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectStructurePropertyDescriptor::ConfigurablePresent)));
}
+ // Perform ? InstallErrorCause(O, options).
+ Value options = argc > 2 ? argv[2] : Value();
+ installErrorCause(state, O, options);
+
// Let errorsList be ? IterableToList(errors).
auto errorsList = IteratorObject::iterableToList(state, argv[0]);
// Perform ! DefinePropertyOrThrow(O, "errors", PropertyDescriptor { [[Configurable]]: true, [[Enumerable]]: false, [[Writable]]: true, [[Value]]: ! CreateArrayFromList(errorsList) }).
- O->defineOwnPropertyThrowsExceptionWhenStrictMode(state, ObjectPropertyName(state, String::fromASCII("errors")),
- ObjectPropertyDescriptor(Value(Object::createArrayFromList(state, errorsList.size(), errorsList.data())), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectStructurePropertyDescriptor::ConfigurablePresent)));
+ O->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, String::fromASCII("errors")),
+ ObjectPropertyDescriptor(Value(Object::createArrayFromList(state, errorsList.size(), errorsList.data())), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectStructurePropertyDescriptor::ConfigurablePresent)));
// Return O.
return O;
}
return builder.finalize(&state);
}
+void GlobalObject::initializeError(ExecutionState& state)
+{
+#define DEFINE_ERROR_INIT(errorname, bname) \
+ { \
+ ObjectPropertyNativeGetterSetterData* nativeData = new ObjectPropertyNativeGetterSetterData(true, false, true, \
+ [](ExecutionState& state, Object* self, const Value& receiver, const EncodedValue& privateDataFromObjectPrivateArea) -> Value { \
+ ASSERT(self->isGlobalObject()); \
+ return self->asGlobalObject()->errorname##Error(); \
+ }, \
+ nullptr); \
+ defineNativeDataAccessorProperty(state, ObjectPropertyName(state.context()->staticStrings().bname##Error), nativeData, Value(Value::EmptyValue)); \
+ }
+
+ DEFINE_ERROR_INIT(reference, Reference);
+ DEFINE_ERROR_INIT(type, Type);
+ DEFINE_ERROR_INIT(syntax, Syntax);
+ DEFINE_ERROR_INIT(range, Range);
+ DEFINE_ERROR_INIT(uri, URI);
+ DEFINE_ERROR_INIT(eval, Eval);
+ DEFINE_ERROR_INIT(aggregate, Aggregate);
+
+ {
+ ObjectPropertyNativeGetterSetterData* nativeData = new ObjectPropertyNativeGetterSetterData(true, false, true,
+ [](ExecutionState& state, Object* self, const Value& receiver, const EncodedValue& privateDataFromObjectPrivateArea) -> Value {
+ ASSERT(self->isGlobalObject());
+ return self->asGlobalObject()->error();
+ },
+ nullptr);
+ defineNativeDataAccessorProperty(state, ObjectPropertyName(state.context()->staticStrings().Error), nativeData, Value(Value::EmptyValue));
+ }
+}
+
void GlobalObject::installError(ExecutionState& state)
{
m_error = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().Error, builtinErrorConstructor, 1), NativeFunctionObject::__ForBuiltinConstructor__);
m_##errorname##ErrorPrototype->defineOwnProperty(state, state.context()->staticStrings().message, ObjectPropertyDescriptor(String::emptyString, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectStructurePropertyDescriptor::ConfigurablePresent))); \
m_##errorname##ErrorPrototype->defineOwnProperty(state, state.context()->staticStrings().name, ObjectPropertyDescriptor(state.context()->staticStrings().bname##Error.string(), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectStructurePropertyDescriptor::ConfigurablePresent))); \
m_##errorname##Error->setFunctionPrototype(state, m_##errorname##ErrorPrototype); \
- defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().bname##Error), \
- ObjectPropertyDescriptor(m_##errorname##Error, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectStructurePropertyDescriptor::ConfigurablePresent)));
+ redefineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().bname##Error), \
+ ObjectPropertyDescriptor(m_##errorname##Error, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectStructurePropertyDescriptor::ConfigurablePresent)));
DEFINE_ERROR(reference, Reference, 1);
DEFINE_ERROR(type, Type, 1);
DEFINE_ERROR(eval, Eval, 1);
DEFINE_ERROR(aggregate, Aggregate, 2);
- defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().Error),
- ObjectPropertyDescriptor(m_error, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+ redefineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().Error),
+ ObjectPropertyDescriptor(m_error, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
}
} // namespace Escargot
return Value();
}
+void GlobalObject::initializeFinalizationRegistry(ExecutionState& state)
+{
+ ObjectPropertyNativeGetterSetterData* nativeData = new ObjectPropertyNativeGetterSetterData(true, false, true,
+ [](ExecutionState& state, Object* self, const Value& receiver, const EncodedValue& privateDataFromObjectPrivateArea) -> Value {
+ ASSERT(self->isGlobalObject());
+ return self->asGlobalObject()->finalizationRegistry();
+ },
+ nullptr);
+
+ defineNativeDataAccessorProperty(state, ObjectPropertyName(state.context()->staticStrings().FinalizationRegistry), nativeData, Value(Value::EmptyValue));
+}
+
void GlobalObject::installFinalizationRegistry(ExecutionState& state)
{
m_finalizationRegistry = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().FinalizationRegistry, builtinFinalizationRegistryConstructor, 1), NativeFunctionObject::__ForBuiltinConstructor__);
ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().cleanupSome, builtinfinalizationRegistryCleanupSome, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
m_finalizationRegistry->setFunctionPrototype(state, m_finalizationRegistryPrototype);
- defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().FinalizationRegistry),
- ObjectPropertyDescriptor(m_finalizationRegistry, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::NonEnumerablePresent)));
+ redefineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().FinalizationRegistry),
+ ObjectPropertyDescriptor(m_finalizationRegistry, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::NonEnumerablePresent)));
}
} // namespace Escargot
return Value(thisValue.asObject()->hasInstance(state, argv[0]));
}
+static Value builtinCallerAndArgumentsGetterSetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+ FunctionObject* targetFunction = nullptr;
+ bool needThrow = false;
+ if (thisValue.isCallable()) {
+ if (thisValue.isFunction()) {
+ targetFunction = thisValue.asFunction();
+ if (targetFunction->isScriptFunctionObject()) {
+ InterpretedCodeBlock* codeBlock = targetFunction->asScriptFunctionObject()->interpretedCodeBlock();
+ if (codeBlock->isStrict() || codeBlock->isArrowFunctionExpression() || codeBlock->isGenerator()) {
+ needThrow = true;
+ }
+ } else {
+ ASSERT(targetFunction->isNativeFunctionObject());
+ if (targetFunction->asNativeFunctionObject()->nativeCodeBlock()->isStrict()) {
+ needThrow = true;
+ }
+ }
+ } else if (thisValue.isObject()) {
+ auto object = thisValue.asObject();
+ if (object->isBoundFunctionObject()) {
+ needThrow = true;
+ }
+ }
+ } else if (!thisValue.isPrimitive() && !thisValue.isObject()) {
+ needThrow = true;
+ }
+
+ if (needThrow) {
+ ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "'caller' and 'arguments' restrict properties may not be accessed on strict mode functions or the arguments objects for calls to them");
+ }
+
+ bool inStrict = false;
+
+ ExecutionState* p = state.parent();
+ while (p) {
+ if (p->inStrictMode()) {
+ inStrict = true;
+ break;
+ }
+ p = p->parent();
+ }
+
+ if (targetFunction && !inStrict) {
+ bool foundTargetFunction = false;
+ ExecutionState* p = &state;
+ while (p) {
+ if (foundTargetFunction) {
+ auto callee = p->resolveCallee();
+ if (callee != targetFunction) {
+ if (callee) {
+ return Value(callee);
+ } else {
+ return Value(Value::Null);
+ }
+ }
+ } else {
+ if (p->resolveCallee() == targetFunction) {
+ foundTargetFunction = true;
+ }
+ }
+ p = p->parent();
+ }
+ }
+
+ return Value(Value::Null);
+}
+
+void GlobalObject::initializeFunction(ExecutionState& state)
+{
+ // Function should be installed at the start time
+ installFunction(state);
+}
+
void GlobalObject::installFunction(ExecutionState& state)
{
m_functionPrototype = new NativeFunctionObject(state, NativeFunctionInfo(AtomicString(), builtinFunctionEmptyFunction, 0, NativeFunctionInfo::Strict),
m_functionPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(state.context()->vmInstance()->globalSymbols().hasInstance)),
ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(AtomicString(state, String::fromASCII("[Symbol.hasInstance]")), builtinFunctionHasInstanceOf, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::NonWritablePresent | ObjectPropertyDescriptor::NonConfigurablePresent)));
+ // 8.2.2 - 12
+ // AddRestrictedFunctionProperties(funcProto, realmRec).
+ m_callerAndArgumentsGetterSetter = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().caller, builtinCallerAndArgumentsGetterSetter, 0, NativeFunctionInfo::Strict));
+
+ {
+ JSGetterSetter gs(m_callerAndArgumentsGetterSetter, m_callerAndArgumentsGetterSetter);
+ ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
+
+ m_functionPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().caller), desc);
+ m_functionPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().arguments), desc);
+ }
+
defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().Function),
ObjectPropertyDescriptor(m_function, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
}
return GeneratorObject::generatorResumeAbrupt(state, thisValue, argc > 0 ? argv[0] : Value(), GeneratorObject::GeneratorAbruptType::Throw);
}
+void GlobalObject::initializeGenerator(ExecutionState& state)
+{
+ // do nothing
+}
+
void GlobalObject::installGenerator(ExecutionState& state)
{
+ ASSERT(!!m_iteratorPrototype);
+
// %GeneratorFunction% : The constructor of generator objects
m_generatorFunction = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().GeneratorFunction, builtinGeneratorFunction, 1), NativeFunctionObject::__ForBuiltinConstructor__);
m_generatorFunction->setGlobalIntrinsicObject(state);
m_generator->setGlobalIntrinsicObject(state, true);
m_generatorFunction->setFunctionPrototype(state, m_generator);
-
// 25.2.3.1 The initial value of GeneratorFunction.prototype.constructor is the intrinsic object %GeneratorFunction%.
m_generator->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().constructor), ObjectPropertyDescriptor(m_generatorFunction, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::NonWritablePresent | ObjectPropertyDescriptor::NonEnumerablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+ {
+ ASSERT(!!m_callerAndArgumentsGetterSetter);
+ JSGetterSetter gs(m_callerAndArgumentsGetterSetter, m_callerAndArgumentsGetterSetter);
+ ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
+
+ m_generator->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().caller), desc);
+ m_generator->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().arguments), desc);
+ }
+
// %GeneratorPrototype% : The initial value of the prototype property of %Generator%
m_generatorPrototype = new Object(state, m_iteratorPrototype);
m_generatorPrototype->setGlobalIntrinsicObject(state, true);
-#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
/*
* Copyright (C) 2015 Andy VanWagoner (thetalecrafter@gmail.com)
* Copyright (C) 2015 Sukolsak Sakshuwong (sukolsak@gmail.com)
namespace Escargot {
+#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
+
static Value builtinIntlCollatorConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
{
// https://www.ecma-international.org/ecma-402/6.0/index.html#sec-intl.collator
Object* proto = Object::getPrototypeFromConstructor(state, newTargetVariable, [](ExecutionState& state, Context* realm) -> Object* {
return realm->globalObject()->intlDateTimeFormatPrototype();
});
- Object* dateTimeFormat = new Object(state, proto);
- IntlDateTimeFormat::initialize(state, dateTimeFormat, locales, options);
+ Object* dateTimeFormat = new IntlDateTimeFormatObject(state, proto, locales, options);
return dateTimeFormat;
}
static Value builtinIntlDateTimeFormatFormat(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
{
FunctionObject* callee = state.resolveCallee();
- if (!callee->hasInternalSlot() || !callee->internalSlot()->hasOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().lazyInitializedDateTimeFormat()))) {
+ if (!callee->internalSlot() || !callee->internalSlot()->isIntlDateTimeFormatObject()) {
ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
}
- Object* dateTimeFormat = callee->asObject();
+ IntlDateTimeFormatObject* dateTimeFormat = callee->internalSlot()->asIntlDateTimeFormatObject();
double value;
if (argc == 0 || argv[0].isUndefined()) {
value = DateObject::currentTime();
} else {
value = argv[0].toNumber(state);
}
- auto result = IntlDateTimeFormat::format(state, dateTimeFormat, value);
+ auto result = dateTimeFormat->format(state, value);
return Value(new UTF16String(result.data(), result.length()));
}
static Value builtinIntlDateTimeFormatFormatGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
{
- if (!thisValue.isObject() || !thisValue.asObject()->hasInternalSlot() || !thisValue.asObject()->internalSlot()->hasOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().lazyInitializedDateTimeFormat()))) {
+ if (!thisValue.isObject() || !thisValue.asObject()->isIntlDateTimeFormatObject()) {
ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
}
- Object* internalSlot = thisValue.asObject()->internalSlot();
- FunctionObject* fn;
- auto g = internalSlot->get(state, ObjectPropertyName(state.context()->staticStrings().format));
- if (g.hasValue()) {
- fn = g.value(state, internalSlot).asFunction();
- } else {
- fn = new NativeFunctionObject(state, NativeFunctionInfo(AtomicString(), builtinIntlDateTimeFormatFormat, 1, NativeFunctionInfo::Strict));
- internalSlot->set(state, ObjectPropertyName(state.context()->staticStrings().format), Value(fn), internalSlot);
- fn->setInternalSlot(internalSlot);
+ IntlDateTimeFormatObject* dtf = thisValue.asObject()->asIntlDateTimeFormatObject();
+
+ if (!dtf->internalSlot()) {
+ FunctionObject* formatFunction = new NativeFunctionObject(state, NativeFunctionInfo(AtomicString(), builtinIntlDateTimeFormatFormat, 1, NativeFunctionInfo::Strict));
+ formatFunction->setInternalSlot(dtf);
+ dtf->setInternalSlot(formatFunction);
}
- return fn;
+ return dtf->internalSlot();
}
static Value builtinIntlDateTimeFormatFormatToParts(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
// Let dtf be this value.
// If Type(dtf) is not Object, throw a TypeError exception.
// If dtf does not have an [[InitializedDateTimeFormat]] internal slot, throw a TypeError exception.
- if (!thisValue.isObject() || !thisValue.asObject()->hasInternalSlot() || !thisValue.asObject()->internalSlot()->hasOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().lazyInitializedDateTimeFormat()))) {
+ if (!thisValue.isObject() || !thisValue.asObject()->isIntlDateTimeFormatObject()) {
ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
}
+ IntlDateTimeFormatObject* dtf = thisValue.asObject()->asIntlDateTimeFormatObject();
Value date = argv[0];
double x;
// If date is undefined, then
x = date.toNumber(state);
}
// Return ? FormatDateTimeToParts(dtf, x).
- return IntlDateTimeFormat::formatToParts(state, thisValue.asObject(), x);
+ return dtf->formatToParts(state, x);
}
static void setFormatOpt(ExecutionState& state, Object* internalSlot, Object* result, const char* pName)
static Value builtinIntlDateTimeFormatResolvedOptions(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
{
- if (!thisValue.isObject() || !thisValue.asObject()->hasInternalSlot() || !thisValue.asObject()->internalSlot()->hasOwnProperty(state, ObjectPropertyName(state, state.context()->staticStrings().lazyInitializedDateTimeFormat()))) {
+ if (!thisValue.isObject() || !thisValue.asObject()->isIntlDateTimeFormatObject()) {
ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Method called on incompatible receiver");
}
- Object* internalSlot = thisValue.asObject()->internalSlot();
-
+ IntlDateTimeFormatObject* intlDateTimeFormatObject = thisValue.asObject()->asIntlDateTimeFormatObject();
Object* result = new Object(state);
- setFormatOpt(state, internalSlot, result, "locale");
- setFormatOpt(state, internalSlot, result, "calendar");
- setFormatOpt(state, internalSlot, result, "numberingSystem");
- setFormatOpt(state, internalSlot, result, "timeZone");
- setFormatOpt(state, internalSlot, result, "hourCycle");
- setFormatOpt(state, internalSlot, result, "hour12");
- setFormatOpt(state, internalSlot, result, "weekday");
- setFormatOpt(state, internalSlot, result, "era");
- setFormatOpt(state, internalSlot, result, "year");
- setFormatOpt(state, internalSlot, result, "month");
- setFormatOpt(state, internalSlot, result, "day");
- setFormatOpt(state, internalSlot, result, "hour");
- setFormatOpt(state, internalSlot, result, "minute");
- setFormatOpt(state, internalSlot, result, "second");
- setFormatOpt(state, internalSlot, result, "timeZoneName");
+#define SET_RESULT(name) \
+ { \
+ Value v(intlDateTimeFormatObject->name()); \
+ if (!v.isUndefined()) { \
+ const char s[] = #name; \
+ result->defineOwnProperty(state, ObjectPropertyName(state, String::fromASCII(s, sizeof(s) - 1)), ObjectPropertyDescriptor(v, ObjectPropertyDescriptor::AllPresent)); \
+ } \
+ }
+
+ SET_RESULT(locale);
+ SET_RESULT(calendar);
+ SET_RESULT(numberingSystem);
+ SET_RESULT(timeZone);
+ SET_RESULT(hourCycle);
+ SET_RESULT(hour12);
+ SET_RESULT(weekday);
+ SET_RESULT(era);
+ SET_RESULT(year);
+ SET_RESULT(month);
+ SET_RESULT(day);
+ SET_RESULT(dayPeriod);
+ SET_RESULT(hour);
+ SET_RESULT(minute);
+ SET_RESULT(second);
+ SET_RESULT(fractionalSecondDigits);
+ SET_RESULT(timeZoneName);
+ SET_RESULT(dateStyle);
+ SET_RESULT(timeStyle);
+#undef SET_RESULT
return Value(result);
}
return Object::createArrayFromList(state, ll);
}
+void GlobalObject::initializeIntl(ExecutionState& state)
+{
+ ObjectPropertyNativeGetterSetterData* nativeData = new ObjectPropertyNativeGetterSetterData(true, false, true,
+ [](ExecutionState& state, Object* self, const Value& receiver, const EncodedValue& privateDataFromObjectPrivateArea) -> Value {
+ ASSERT(self->isGlobalObject());
+ return self->asGlobalObject()->intl();
+ },
+ nullptr);
+
+ defineNativeDataAccessorProperty(state, ObjectPropertyName(state.context()->staticStrings().Intl), nativeData, Value(Value::EmptyValue));
+}
+
void GlobalObject::installIntl(ExecutionState& state)
{
m_intl = new Object(state);
m_intl->setGlobalIntrinsicObject(state);
const StaticStrings* strings = &state.context()->staticStrings();
- defineOwnProperty(state, ObjectPropertyName(strings->Intl),
- ObjectPropertyDescriptor(m_intl, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+ redefineOwnProperty(state, ObjectPropertyName(strings->Intl),
+ ObjectPropertyDescriptor(m_intl, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
m_intlCollator = new NativeFunctionObject(state, NativeFunctionInfo(strings->Collator, builtinIntlCollatorConstructor, 0), NativeFunctionObject::__ForBuiltinConstructor__);
m_intlCollator->setGlobalIntrinsicObject(state);
m_intlNumberFormatPrototype = m_intlNumberFormat->getFunctionPrototype(state).asObject();
m_intlNumberFormatPrototype->setGlobalIntrinsicObject(state, true);
- formatFunction = new NativeFunctionObject(state, NativeFunctionInfo(strings->getFormat, builtinIntlNumberFormatFormatGetter, 0, NativeFunctionInfo::Strict));
- m_intlNumberFormatPrototype->defineOwnProperty(state, state.context()->staticStrings().format,
- ObjectPropertyDescriptor(JSGetterSetter(formatFunction, Value(Value::EmptyValue)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
+ {
+ formatFunction = new NativeFunctionObject(state, NativeFunctionInfo(strings->getFormat, builtinIntlNumberFormatFormatGetter, 0, NativeFunctionInfo::Strict));
+ JSGetterSetter gs(formatFunction, Value());
+ ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
+ m_intlNumberFormatPrototype->defineOwnProperty(state, ObjectPropertyName(state, strings->format), desc);
+ }
m_intlNumberFormatPrototype->defineOwnProperty(state, state.context()->staticStrings().formatToParts,
ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->formatToParts, builtinIntlNumberFormatFormatToParts, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::WritablePresent)));
m_intl->defineOwnProperty(state, ObjectPropertyName(strings->getCanonicalLocales),
ObjectPropertyDescriptor(getCanonicalLocales, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
}
-} // namespace Escargot
+
+#else
+
+void GlobalObject::initializeIntl(ExecutionState& state)
+{
+ // dummy initialize function
+}
#endif // ENABLE_ICU
+} // namespace Escargot
+++ /dev/null
-/*
- * Copyright (c) 2018-present Samsung Electronics Co., Ltd
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
- * USA
- */
-
-#include "Escargot.h"
-#include "runtime/GlobalObject.h"
-#include "runtime/Context.h"
-#include "runtime/VMInstance.h"
-#include "runtime/NativeFunctionObject.h"
-#include "runtime/ToStringRecursionPreventer.h"
-
-namespace Escargot {
-
-static Value builtinIteratorIterator(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
- return thisValue;
-}
-
-void GlobalObject::installIterator(ExecutionState& state)
-{
- m_iteratorPrototype = new Object(state);
- m_iteratorPrototype->setGlobalIntrinsicObject(state, true);
-
- // https://www.ecma-international.org/ecma-262/10.0/index.html#sec-%iteratorprototype%-@@iterator
- FunctionObject* fn = new NativeFunctionObject(state, NativeFunctionInfo(AtomicString(state, String::fromASCII("[Symbol.iterator]")), builtinIteratorIterator, 0, NativeFunctionInfo::Strict));
- m_iteratorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().iterator),
- ObjectPropertyDescriptor(fn,
- (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-}
-} // namespace Escargot
return Value();
}
+void GlobalObject::initializeJSON(ExecutionState& state)
+{
+ ObjectPropertyNativeGetterSetterData* nativeData = new ObjectPropertyNativeGetterSetterData(true, false, true,
+ [](ExecutionState& state, Object* self, const Value& receiver, const EncodedValue& privateDataFromObjectPrivateArea) -> Value {
+ ASSERT(self->isGlobalObject());
+ return self->asGlobalObject()->json();
+ },
+ nullptr);
+
+ defineNativeDataAccessorProperty(state, ObjectPropertyName(state.context()->staticStrings().JSON), nativeData, Value(Value::EmptyValue));
+}
+
void GlobalObject::installJSON(ExecutionState& state)
{
m_json = new Object(state);
ObjectPropertyDescriptor(Value(state.context()->staticStrings().JSON.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
- defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().JSON),
- ObjectPropertyDescriptor(m_json, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+ redefineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().JSON),
+ ObjectPropertyDescriptor(m_json, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
m_jsonParse = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().parse, builtinJSONParse, 2, NativeFunctionInfo::Strict));
m_json->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().parse),
return iter->next(state);
}
+void GlobalObject::initializeMap(ExecutionState& state)
+{
+ ObjectPropertyNativeGetterSetterData* nativeData = new ObjectPropertyNativeGetterSetterData(true, false, true,
+ [](ExecutionState& state, Object* self, const Value& receiver, const EncodedValue& privateDataFromObjectPrivateArea) -> Value {
+ ASSERT(self->isGlobalObject());
+ return self->asGlobalObject()->map();
+ },
+ nullptr);
+
+ defineNativeDataAccessorProperty(state, ObjectPropertyName(state.context()->staticStrings().Map), nativeData, Value(Value::EmptyValue));
+}
+
void GlobalObject::installMap(ExecutionState& state)
{
+ ASSERT(!!m_iteratorPrototype);
+
m_map = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().Map, builtinMapConstructor, 0), NativeFunctionObject::__ForBuiltinConstructor__);
m_map->setGlobalIntrinsicObject(state);
m_map->setFunctionPrototype(state, m_mapPrototype);
- defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().Map),
- ObjectPropertyDescriptor(m_map, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+ redefineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().Map),
+ ObjectPropertyDescriptor(m_map, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
}
} // namespace Escargot
return Value(ieee754::expm1(x));
}
+void GlobalObject::initializeMath(ExecutionState& state)
+{
+ ObjectPropertyNativeGetterSetterData* nativeData = new ObjectPropertyNativeGetterSetterData(true, false, true,
+ [](ExecutionState& state, Object* self, const Value& receiver, const EncodedValue& privateDataFromObjectPrivateArea) -> Value {
+ ASSERT(self->isGlobalObject());
+ return self->asGlobalObject()->math();
+ },
+ nullptr);
+
+ defineNativeDataAccessorProperty(state, ObjectPropertyName(state.context()->staticStrings().Math), nativeData, Value(Value::EmptyValue));
+}
+
void GlobalObject::installMath(ExecutionState& state)
{
m_math = new Object(state);
m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().trunc),
ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().trunc, builtinMathTrunc, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
- defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().Math),
- ObjectPropertyDescriptor(m_math, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+ redefineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().Math),
+ ObjectPropertyDescriptor(m_math, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
}
} // namespace Escargot
return Value(Value::False);
}
+void GlobalObject::initializeNumber(ExecutionState& state)
+{
+ ObjectPropertyNativeGetterSetterData* nativeData = new ObjectPropertyNativeGetterSetterData(true, false, true,
+ [](ExecutionState& state, Object* self, const Value& receiver, const EncodedValue& privateDataFromObjectPrivateArea) -> Value {
+ ASSERT(self->isGlobalObject());
+ return self->asGlobalObject()->number();
+ },
+ nullptr);
+
+ defineNativeDataAccessorProperty(state, ObjectPropertyName(state.context()->staticStrings().Number), nativeData, Value(Value::EmptyValue));
+}
+
void GlobalObject::installNumber(ExecutionState& state)
{
+ ASSERT(!!m_parseInt && !!m_parseFloat);
+
const StaticStrings* strings = &state.context()->staticStrings();
m_number = new NativeFunctionObject(state, NativeFunctionInfo(strings->Number, builtinNumberConstructor, 1), NativeFunctionObject::__ForBuiltinConstructor__);
m_number->setGlobalIntrinsicObject(state);
// $20.1.2.3 Number.isNaN
m_number->defineOwnPropertyThrowsException(state, strings->isNaN,
ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->isNaN, builtinNumberIsNaN, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+ m_number->defineOwnPropertyThrowsException(state, strings->parseInt,
+ ObjectPropertyDescriptor(m_parseInt,
+ (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+ m_number->defineOwnProperty(state, ObjectPropertyName(strings->parseFloat),
+ ObjectPropertyDescriptor(m_parseFloat,
+ (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
// $20.1.2.5 Number.isSafeInteger
m_number->defineOwnPropertyThrowsException(state, strings->isSafeInteger,
ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->isSafeInteger, builtinNumberIsSafeInteger, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
// $20.1.2.14 Number.POSITIVE_INFINITY
m_number->defineOwnPropertyThrowsException(state, strings->POSITIVE_INFINITY, ObjectPropertyDescriptor(Value(std::numeric_limits<double>::infinity()), allFalsePresent));
- defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().Number),
- ObjectPropertyDescriptor(m_number, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+ m_numberProxyObject = new NumberObject(state);
+
+ redefineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().Number),
+ ObjectPropertyDescriptor(m_number, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
}
} // namespace Escargot
return strings->lazyObjectObjectToString().string();
}
+static Value builtinObjectHasOwn(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+ Object* obj = argv[0].toObject(state);
+ Value key = argv[1].toPropertyKey(state);
+ return Value(obj->hasOwnProperty(state, ObjectPropertyName(state, key)));
+}
+
static Value builtinObjectHasOwnProperty(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
{
Value key = argv[0].toPrimitive(state, Value::PrimitiveTypeHint::PreferString);
return Object::createArrayFromList(state, nameList.size(), nameList.data());
}
+// Object.prototype.__defineGetter__ ( P, getter )
+static Value builtinDefineGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+ // Let O be ? ToObject(this value).
+ Object* O = thisValue.toObject(state);
+ // If IsCallable(getter) is false, throw a TypeError exception.
+ if (!argv[1].isCallable()) {
+ ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, String::emptyString, true, state.context()->staticStrings().__defineGetter__.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
+ }
+ // Let desc be PropertyDescriptor{[[Get]]: getter, [[Enumerable]]: true, [[Configurable]]: true}.
+ ObjectPropertyDescriptor desc(JSGetterSetter(argv[1].asObject(), Value(Value::EmptyValue)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::EnumerablePresent | ObjectPropertyDescriptor::ConfigurablePresent));
+
+ // Let key be ? ToPropertyKey(P).
+ ObjectPropertyName key(state, argv[0]);
+
+// Perform ? DefinePropertyOrThrow(O, key, desc).
+#if defined(ENABLE_V8_LIKE_DEFINE_LOOKUP_GETTER_SETTER)
+ O->defineOwnProperty(state, key, desc);
+#else
+ O->defineOwnPropertyThrowsException(state, key, desc);
+#endif
+
+ // Return undefined.
+ return Value();
+}
+
+// Object.prototype.__defineSetter__ ( P, getter )
+static Value builtinDefineSetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+ // Let O be ? ToObject(this value).
+ Object* O = thisValue.toObject(state);
+ // If IsCallable(getter) is false, throw a TypeError exception.
+ if (!argv[1].isCallable()) {
+ ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, String::emptyString, true, state.context()->staticStrings().__defineSetter__.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
+ }
+ // Let desc be PropertyDescriptor{[[Get]]: getter, [[Enumerable]]: true, [[Configurable]]: true}.
+ ObjectPropertyDescriptor desc(JSGetterSetter(Value(Value::EmptyValue), argv[1].asObject()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::EnumerablePresent | ObjectPropertyDescriptor::ConfigurablePresent));
+
+ // Let key be ? ToPropertyKey(P).
+ ObjectPropertyName key(state, argv[0]);
+
+// Perform ? DefinePropertyOrThrow(O, key, desc).
+#if defined(ENABLE_V8_LIKE_DEFINE_LOOKUP_GETTER_SETTER)
+ O->defineOwnProperty(state, key, desc);
+#else
+ O->defineOwnPropertyThrowsException(state, key, desc);
+#endif
+
+ // Return undefined.
+ return Value();
+}
+
+// Object.prototype.__lookupGetter__ ( P, getter )
+static Value builtinLookupGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+ // Let O be ? ToObject(this value).
+ Object* O = thisValue.toObject(state);
+ // Let key be ? ToPropertyKey(P).
+ ObjectPropertyName key(state, argv[0]);
+
+ // Repeat,
+ while (O) {
+ // Let desc be ? O.[[GetOwnProperty]](key).
+ auto desc = O->getOwnProperty(state, key);
+
+ // If desc is not undefined, then
+ if (desc.hasValue()) {
+ // If IsAccessorDescriptor(desc) is true, return desc.[[Get]].
+ if (!desc.isDataProperty() && desc.jsGetterSetter()->hasGetter()) {
+ return desc.jsGetterSetter()->getter();
+ }
+ // Return undefined.
+ return Value();
+ }
+ // Set O to ? O.[[GetPrototypeOf]]().
+ O = O->getPrototypeObject(state);
+ // If O is null, return undefined.
+ }
+ return Value();
+}
+
+// Object.prototype.__lookupSetter__ ( P, getter )
+static Value builtinLookupSetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+ // Let O be ? ToObject(this value).
+ Object* O = thisValue.toObject(state);
+ // Let key be ? ToPropertyKey(P).
+ ObjectPropertyName key(state, argv[0]);
+
+ // Repeat,
+ while (O) {
+ // Let desc be ? O.[[GetOwnProperty]](key).
+ auto desc = O->getOwnProperty(state, key);
+
+ // If desc is not undefined, then
+ if (desc.hasValue()) {
+ // If IsAccessorDescriptor(desc) is true, return desc.[[Set]].
+ if (!desc.isDataProperty() && desc.jsGetterSetter()->hasSetter()) {
+ return desc.jsGetterSetter()->setter();
+ }
+ // Return undefined.
+ return Value();
+ }
+ // Set O to ? O.[[GetPrototypeOf]]().
+ O = O->getPrototypeObject(state);
+ // If O is null, return undefined.
+ }
+ return Value();
+}
+
+void GlobalObject::initializeObject(ExecutionState& state)
+{
+ // Object should be installed at the start time
+ installObject(state);
+}
+
void GlobalObject::installObject(ExecutionState& state)
{
const StaticStrings& strings = state.context()->staticStrings();
ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.entries, builtinObjectEntries, 1, NativeFunctionInfo::Strict)),
(ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+ // Object.hasOwn
+ m_object->defineOwnProperty(state, ObjectPropertyName(strings.hasOwn),
+ ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.hasOwn, builtinObjectHasOwn, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
// $19.1.3.2 Object.prototype.hasOwnProperty(V)
m_objectPrototype->defineOwnProperty(state, ObjectPropertyName(strings.hasOwnProperty),
ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings.hasOwnProperty, builtinObjectHasOwnProperty, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
m_objectPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().propertyIsEnumerable),
ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().propertyIsEnumerable, builtinObjectPropertyIsEnumerable, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+ auto defineLookupGetterSetterNativeFunctionFlag =
+#if defined(ENABLE_V8_LIKE_DEFINE_LOOKUP_GETTER_SETTER)
+ 0;
+#else
+ NativeFunctionInfo::Strict;
+#endif
+ m_objectPrototype->defineOwnProperty(state, ObjectPropertyName(strings.__defineGetter__),
+ ObjectPropertyDescriptor(new NativeFunctionObject(state,
+ NativeFunctionInfo(strings.__defineGetter__, builtinDefineGetter, 2, defineLookupGetterSetterNativeFunctionFlag)),
+ (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+ m_objectPrototype->defineOwnProperty(state, ObjectPropertyName(strings.__defineSetter__),
+ ObjectPropertyDescriptor(new NativeFunctionObject(state,
+ NativeFunctionInfo(strings.__defineSetter__, builtinDefineSetter, 2, defineLookupGetterSetterNativeFunctionFlag)),
+ (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+ m_objectPrototype->defineOwnProperty(state, ObjectPropertyName(strings.__lookupGetter__),
+ ObjectPropertyDescriptor(new NativeFunctionObject(state,
+ NativeFunctionInfo(strings.__lookupGetter__, builtinLookupGetter, 1, defineLookupGetterSetterNativeFunctionFlag)),
+ (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+ m_objectPrototype->defineOwnProperty(state, ObjectPropertyName(strings.__lookupSetter__),
+ ObjectPropertyDescriptor(new NativeFunctionObject(state,
+ NativeFunctionInfo(strings.__lookupSetter__, builtinLookupSetter, 1, defineLookupGetterSetterNativeFunctionFlag)),
+ (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
JSGetterSetter gs(
new NativeFunctionObject(state, NativeFunctionInfo(strings.get__proto__, builtinObject__proto__Getter, 0, NativeFunctionInfo::Strict)),
new NativeFunctionObject(state, NativeFunctionInfo(strings.set__proto__, builtinObject__proto__Setter, 1, NativeFunctionInfo::Strict)));
ObjectPropertyDescriptor __proto__desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
m_objectPrototype->defineOwnProperty(state, ObjectPropertyName(strings.__proto__), __proto__desc);
+
defineOwnProperty(state, ObjectPropertyName(strings.Object),
ObjectPropertyDescriptor(m_object, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
return result;
}
+void GlobalObject::initializePromise(ExecutionState& state)
+{
+ ObjectPropertyNativeGetterSetterData* nativeData = new ObjectPropertyNativeGetterSetterData(true, false, true,
+ [](ExecutionState& state, Object* self, const Value& receiver, const EncodedValue& privateDataFromObjectPrivateArea) -> Value {
+ ASSERT(self->isGlobalObject());
+ return self->asGlobalObject()->promise();
+ },
+ nullptr);
+
+ defineNativeDataAccessorProperty(state, ObjectPropertyName(state.context()->staticStrings().Promise), nativeData, Value(Value::EmptyValue));
+}
+
void GlobalObject::installPromise(ExecutionState& state)
{
const StaticStrings* strings = &state.context()->staticStrings();
(ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
- defineOwnProperty(state, ObjectPropertyName(strings->Promise),
- ObjectPropertyDescriptor(m_promise, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+ redefineOwnProperty(state, ObjectPropertyName(strings->Promise),
+ ObjectPropertyDescriptor(m_promise, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
}
} // namespace Escargot
return result;
}
+void GlobalObject::initializeProxy(ExecutionState& state)
+{
+ ObjectPropertyNativeGetterSetterData* nativeData = new ObjectPropertyNativeGetterSetterData(true, false, true,
+ [](ExecutionState& state, Object* self, const Value& receiver, const EncodedValue& privateDataFromObjectPrivateArea) -> Value {
+ ASSERT(self->isGlobalObject());
+ return self->asGlobalObject()->proxy();
+ },
+ nullptr);
+
+ defineNativeDataAccessorProperty(state, ObjectPropertyName(state.context()->staticStrings().Proxy), nativeData, Value(Value::EmptyValue));
+}
+
void GlobalObject::installProxy(ExecutionState& state)
{
const StaticStrings* strings = &state.context()->staticStrings();
m_proxy->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->revocable), ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->revocable, builtinProxyRevocable, 2, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
- defineOwnProperty(state, ObjectPropertyName(strings->Proxy),
- ObjectPropertyDescriptor(m_proxy, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+ redefineOwnProperty(state, ObjectPropertyName(strings->Proxy),
+ ObjectPropertyDescriptor(m_proxy, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
}
} // namespace Escargot
return Value(target.asObject()->setPrototype(state, proto));
}
+void GlobalObject::initializeReflect(ExecutionState& state)
+{
+ ObjectPropertyNativeGetterSetterData* nativeData = new ObjectPropertyNativeGetterSetterData(true, false, true,
+ [](ExecutionState& state, Object* self, const Value& receiver, const EncodedValue& privateDataFromObjectPrivateArea) -> Value {
+ ASSERT(self->isGlobalObject());
+ return self->asGlobalObject()->reflect();
+ },
+ nullptr);
+
+ defineNativeDataAccessorProperty(state, ObjectPropertyName(state.context()->staticStrings().Reflect), nativeData, Value(Value::EmptyValue));
+}
+
void GlobalObject::installReflect(ExecutionState& state)
{
const StaticStrings* strings = &state.context()->staticStrings();
m_reflect->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(state.context()->vmInstance()->globalSymbols().toStringTag)),
ObjectPropertyDescriptor(state.context()->staticStrings().Reflect.string(), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
- defineOwnProperty(state, ObjectPropertyName(strings->Reflect),
- ObjectPropertyDescriptor(m_reflect, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+ redefineOwnProperty(state, ObjectPropertyName(strings->Reflect),
+ ObjectPropertyDescriptor(m_reflect, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
}
} // namespace Escargot
return std::make_pair(match, false);
}
+void GlobalObject::initializeRegExp(ExecutionState& state)
+{
+ ObjectPropertyNativeGetterSetterData* nativeData = new ObjectPropertyNativeGetterSetterData(true, false, true,
+ [](ExecutionState& state, Object* self, const Value& receiver, const EncodedValue& privateDataFromObjectPrivateArea) -> Value {
+ ASSERT(self->isGlobalObject());
+ return self->asGlobalObject()->regexp();
+ },
+ nullptr);
+
+ defineNativeDataAccessorProperty(state, ObjectPropertyName(state.context()->staticStrings().RegExp), nativeData, Value(Value::EmptyValue));
+}
+
void GlobalObject::installRegExp(ExecutionState& state)
{
+ ASSERT(!!m_iteratorPrototype);
+
const StaticStrings* strings = &state.context()->staticStrings();
m_regexp = new NativeFunctionObject(state, NativeFunctionInfo(strings->RegExp, builtinRegExpConstructor, 2), NativeFunctionObject::__ForBuiltinConstructor__);
m_regexpStringIteratorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag),
ObjectPropertyDescriptor(Value(String::fromASCII("RegExp String Iterator")), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
- defineOwnProperty(state, ObjectPropertyName(strings->RegExp),
- ObjectPropertyDescriptor(m_regexp, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+ redefineOwnProperty(state, ObjectPropertyName(strings->RegExp),
+ ObjectPropertyDescriptor(m_regexp, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
}
} // namespace Escargot
return iter->next(state);
}
+void GlobalObject::initializeSet(ExecutionState& state)
+{
+ ObjectPropertyNativeGetterSetterData* nativeData = new ObjectPropertyNativeGetterSetterData(true, false, true,
+ [](ExecutionState& state, Object* self, const Value& receiver, const EncodedValue& privateDataFromObjectPrivateArea) -> Value {
+ ASSERT(self->isGlobalObject());
+ return self->asGlobalObject()->set();
+ },
+ nullptr);
+
+ defineNativeDataAccessorProperty(state, ObjectPropertyName(state.context()->staticStrings().Set), nativeData, Value(Value::EmptyValue));
+}
+
void GlobalObject::installSet(ExecutionState& state)
{
+ ASSERT(!!m_iteratorPrototype);
+
m_set = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().Set, builtinSetConstructor, 0), NativeFunctionObject::__ForBuiltinConstructor__);
m_set->setGlobalIntrinsicObject(state);
ObjectPropertyDescriptor(Value(String::fromASCII("Set Iterator")), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
m_set->setFunctionPrototype(state, m_setPrototype);
- defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().Set),
- ObjectPropertyDescriptor(m_set, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+ redefineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().Set),
+ ObjectPropertyDescriptor(m_set, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
}
} // namespace Escargot
* USA
*/
-#if defined(ENABLE_THREADING)
-
#include "Escargot.h"
#include "runtime/GlobalObject.h"
#include "runtime/Context.h"
namespace Escargot {
+#if defined(ENABLE_THREADING)
+
// https://262.ecma-international.org/#sec-sharedarraybuffer-constructor
static Value builtinSharedArrayBufferConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
{
return newBuffer;
}
+void GlobalObject::initializeSharedArrayBuffer(ExecutionState& state)
+{
+ ObjectPropertyNativeGetterSetterData* nativeData = new ObjectPropertyNativeGetterSetterData(true, false, true,
+ [](ExecutionState& state, Object* self, const Value& receiver, const EncodedValue& privateDataFromObjectPrivateArea) -> Value {
+ ASSERT(self->isGlobalObject());
+ return self->asGlobalObject()->sharedArrayBuffer();
+ },
+ nullptr);
+
+ defineNativeDataAccessorProperty(state, ObjectPropertyName(state.context()->staticStrings().SharedArrayBuffer), nativeData, Value(Value::EmptyValue));
+}
+
void GlobalObject::installSharedArrayBuffer(ExecutionState& state)
{
const StaticStrings* strings = &state.context()->staticStrings();
m_sharedArrayBuffer->setFunctionPrototype(state, m_sharedArrayBufferPrototype);
- defineOwnProperty(state, ObjectPropertyName(strings->SharedArrayBuffer),
- ObjectPropertyDescriptor(m_sharedArrayBuffer, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+ redefineOwnProperty(state, ObjectPropertyName(strings->SharedArrayBuffer),
+ ObjectPropertyDescriptor(m_sharedArrayBuffer, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+}
+
+#else
+
+void GlobalObject::initializeSharedArrayBuffer(ExecutionState& state)
+{
+ // dummy initialize function
}
-} // namespace Escargot
#endif
+} // namespace Escargot
return new StringIteratorObject(state, S);
}
+void GlobalObject::initializeString(ExecutionState& state)
+{
+ ObjectPropertyNativeGetterSetterData* nativeData = new ObjectPropertyNativeGetterSetterData(true, false, true,
+ [](ExecutionState& state, Object* self, const Value& receiver, const EncodedValue& privateDataFromObjectPrivateArea) -> Value {
+ ASSERT(self->isGlobalObject());
+ return self->asGlobalObject()->string();
+ },
+ nullptr);
+
+ defineNativeDataAccessorProperty(state, ObjectPropertyName(state.context()->staticStrings().String), nativeData, Value(Value::EmptyValue));
+}
+
void GlobalObject::installString(ExecutionState& state)
{
+ ASSERT(!!m_iteratorPrototype);
+
const StaticStrings* strings = &state.context()->staticStrings();
m_string = new NativeFunctionObject(state, NativeFunctionInfo(strings->String, builtinStringConstructor, 1), NativeFunctionObject::__ForBuiltinConstructor__);
m_string->setGlobalIntrinsicObject(state);
m_stringIteratorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag),
ObjectPropertyDescriptor(Value(String::fromASCII("String Iterator")), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
- defineOwnProperty(state, ObjectPropertyName(strings->String),
- ObjectPropertyDescriptor(m_string, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+ m_stringProxyObject = new StringObject(state);
+
+ redefineOwnProperty(state, ObjectPropertyName(strings->String),
+ ObjectPropertyDescriptor(m_string, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
}
} // namespace Escargot
return Value();
}
+void GlobalObject::initializeSymbol(ExecutionState& state)
+{
+ ObjectPropertyNativeGetterSetterData* nativeData = new ObjectPropertyNativeGetterSetterData(true, false, true,
+ [](ExecutionState& state, Object* self, const Value& receiver, const EncodedValue& privateDataFromObjectPrivateArea) -> Value {
+ ASSERT(self->isGlobalObject());
+ return self->asGlobalObject()->symbol();
+ },
+ nullptr);
+
+ defineNativeDataAccessorProperty(state, ObjectPropertyName(state.context()->staticStrings().Symbol), nativeData, Value(Value::EmptyValue));
+}
+
void GlobalObject::installSymbol(ExecutionState& state)
{
m_symbol = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().Symbol, builtinSymbolConstructor, 0), NativeFunctionObject::__ForBuiltinConstructor__);
DEFINE_GLOBAL_SYMBOLS(DECLARE_GLOBAL_SYMBOLS);
m_symbol->setFunctionPrototype(state, m_symbolPrototype);
- defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().Symbol),
- ObjectPropertyDescriptor(m_symbol, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+ m_symbolProxyObject = new SymbolObject(state, state.context()->vmInstance()->globalSymbols().iterator);
+
+ redefineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().Symbol),
+ ObjectPropertyDescriptor(m_symbol, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
}
} // namespace Escargot
static Value builtinTypedArrayFind(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
{
+ Value predicate = argv[0];
+ Value thisArg = argc > 1 ? argv[1] : Value();
// Let O be ToObject(this value).
RESOLVE_THIS_BINDING_TO_OBJECT(O, TypedArray, find);
// validateTypedArray is applied to the this value prior to evaluating the algorithm.
// Array.prototype.find as defined in 22.1.3.8 except
// that the this object’s [[ArrayLength]] internal slot is accessed
// in place of performing a [[Get]] of "length"
- double len = O->asTypedArrayObject()->arrayLength();
+ size_t len = O->asTypedArrayObject()->arrayLength();
// If IsCallable(predicate) is false, throw a TypeError exception.
- Value predicate = argv[0];
if (!predicate.isCallable()) {
ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), true, state.context()->staticStrings().find.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
}
- // If thisArg was supplied, let T be thisArg; else let T be undefined.
- Value T;
- if (argc > 1) {
- T = argv[1];
- }
-
// Let k be 0.
size_t k = 0;
- Value kValue;
// Repeat, while k < len
while (k < len) {
// Let kValue be Get(O, Pk).
- kValue = O->getIndexedProperty(state, Value(k)).value(state, O);
- // Let testResult be ToBoolean(Call(predicate, T, «kValue, k, O»)).
+ Value kValue = O->getIndexedProperty(state, Value(k)).value(state, O);
+ // Let testResult be ToBoolean(Call(predicate, thisArg, «kValue, k, O»)).
Value args[] = { kValue, Value(k), O };
- bool testResult = Object::call(state, predicate, T, 3, args).toBoolean(state);
+ bool testResult = Object::call(state, predicate, thisArg, 3, args).toBoolean(state);
// If testResult is true, return kValue.
if (testResult) {
return kValue;
static Value builtinTypedArrayFindIndex(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
{
+ Value predicate = argv[0];
+ Value thisArg = argc > 1 ? argv[1] : Value();
// Let O be ToObject(this value).
RESOLVE_THIS_BINDING_TO_OBJECT(O, TypedArray, findIndex);
// validateTypedArray is applied to the this value prior to evaluating the algorithm.
// Array.prototype.findIndex as defined in 22.1.3.9 except
// that the this object’s [[ArrayLength]] internal slot is accessed
// in place of performing a [[Get]] of "length"
- double len = O->asTypedArrayObject()->arrayLength();
+ size_t len = O->asTypedArrayObject()->arrayLength();
// If IsCallable(predicate) is false, throw a TypeError exception.
- Value predicate = argv[0];
if (!predicate.isCallable()) {
ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), true, state.context()->staticStrings().findIndex.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
}
- // If thisArg was supplied, let T be thisArg; else let T be undefined.
- Value T;
- if (argc > 1) {
- T = argv[1];
- }
-
// Let k be 0.
size_t k = 0;
- Value kValue;
// Repeat, while k < len
while (k < len) {
// Let kValue be ? Get(O, Pk).
Value kValue = O->getIndexedProperty(state, Value(k)).value(state, O);
- // Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).
+ // Let testResult be ToBoolean(? Call(predicate, thisArg, « kValue, k, O »)).
Value args[] = { kValue, Value(k), O };
- bool testResult = Object::call(state, predicate, T, 3, args).toBoolean(state);
+ bool testResult = Object::call(state, predicate, thisArg, 3, args).toBoolean(state);
// If testResult is true, return k.
if (testResult) {
return Value(k);
return Value(-1);
}
+static Value builtinTypedArrayFindLast(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+ Value predicate = argv[0];
+ Value thisArg = argc > 1 ? argv[1] : Value();
+ // Let O be ToObject(this value).
+ RESOLVE_THIS_BINDING_TO_OBJECT(O, TypedArray, find);
+ // validateTypedArray is applied to the this value prior to evaluating the algorithm.
+ TypedArrayObject::validateTypedArray(state, O);
+
+ // Let len be O.[[ArrayLength]].
+ int64_t len = static_cast<int64_t>(O->asTypedArrayObject()->arrayLength());
+
+ // If IsCallable(predicate) is false, throw a TypeError exception.
+ if (!predicate.isCallable()) {
+ ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), true, state.context()->staticStrings().findLast.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
+ }
+
+ // Let k be len - 1.
+ int64_t k = len - 1;
+ Value kValue;
+ // Repeat, while k >= 0
+ while (k >= 0) {
+ // Let kValue be Get(O, Pk).
+ kValue = O->getIndexedProperty(state, Value(k)).value(state, O);
+ // Let testResult be ToBoolean(Call(predicate, thisArg, «kValue, k, O»)).
+ Value args[] = { kValue, Value(k), O };
+ bool testResult = Object::call(state, predicate, thisArg, 3, args).toBoolean(state);
+ // If testResult is true, return kValue.
+ if (testResult) {
+ return kValue;
+ }
+ // Set k to k - 1.
+ k--;
+ }
+ // Return undefined.
+ return Value();
+}
+
+static Value builtinTypedArrayFindLastIndex(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+{
+ Value predicate = argv[0];
+ Value thisArg = argc > 1 ? argv[1] : Value();
+ // Let O be ToObject(this value).
+ RESOLVE_THIS_BINDING_TO_OBJECT(O, TypedArray, findIndex);
+ // validateTypedArray is applied to the this value prior to evaluating the algorithm.
+ TypedArrayObject::validateTypedArray(state, O);
+
+ // Let len be O.[[ArrayLength]].
+ int64_t len = static_cast<int64_t>(O->asTypedArrayObject()->arrayLength());
+
+ // If IsCallable(predicate) is false, throw a TypeError exception.
+ if (!predicate.isCallable()) {
+ ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, state.context()->staticStrings().TypedArray.string(), true, state.context()->staticStrings().findIndex.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
+ }
+
+ // Let k be len - 1.
+ int64_t k = len - 1;
+ Value kValue;
+ // Repeat, while k >= 0
+ while (k >= 0) {
+ // Let kValue be ? Get(O, Pk).
+ Value kValue = O->getIndexedProperty(state, Value(k)).value(state, O);
+ // Let testResult be ToBoolean(? Call(predicate, thisArg, « kValue, k, O »)).
+ Value args[] = { kValue, Value(k), O };
+ bool testResult = Object::call(state, predicate, thisArg, 3, args).toBoolean(state);
+ // If testResult is true, return k.
+ if (testResult) {
+ return Value(k);
+ }
+ // Set k to k - 1.
+ k--;
+ }
+ // Return -1
+ return Value(-1);
+}
+
static Value builtinTypedArrayForEach(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
{
// Let O be ToObject(this value).
// 22.2.6.2 /TypedArray/.prototype.constructor
taPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->constructor), ObjectPropertyDescriptor(taConstructor, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
- defineOwnProperty(state, ObjectPropertyName(taName),
- ObjectPropertyDescriptor(taConstructor, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+ redefineOwnProperty(state, ObjectPropertyName(taName),
+ ObjectPropertyDescriptor(taConstructor, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
return taConstructor;
}
+void GlobalObject::initializeTypedArray(ExecutionState& state)
+{
+ const StaticStrings* strings = &state.context()->staticStrings();
+
+#define INITIALIZE_TYPEDARRAY(TYPE, type, siz, nativeType) \
+ { \
+ ObjectPropertyNativeGetterSetterData* nativeData = new ObjectPropertyNativeGetterSetterData(true, false, true, \
+ [](ExecutionState& state, Object* self, const Value& receiver, const EncodedValue& privateDataFromObjectPrivateArea) -> Value { \
+ ASSERT(self->isGlobalObject()); \
+ return self->asGlobalObject()->type##Array(); \
+ }, \
+ nullptr); \
+ defineNativeDataAccessorProperty(state, ObjectPropertyName(strings->TYPE##Array), nativeData, Value(Value::EmptyValue)); \
+ }
+
+ FOR_EACH_TYPEDARRAY_TYPES(INITIALIZE_TYPEDARRAY)
+#undef INITIALIZE_TYPEDARRAY
+}
+
void GlobalObject::installTypedArray(ExecutionState& state)
{
+ ASSERT(!!m_arrayToString);
+
const StaticStrings* strings = &state.context()->staticStrings();
// %TypedArray%
ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->find, builtinTypedArrayFind, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->findIndex),
ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->findIndex, builtinTypedArrayFindIndex, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+ typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->findLast),
+ ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->findLast, builtinTypedArrayFindLast, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+ typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->findLastIndex),
+ ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->findLastIndex, builtinTypedArrayFindLastIndex, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->forEach),
ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->forEach, builtinTypedArrayForEach, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->join),
// https://www.ecma-international.org/ecma-262/10.0/#sec-%typedarray%.prototype.tostring
// The initial value of the %TypedArray%.prototype.toString data property is the same built-in function object as the Array.prototype.toString method
- ASSERT(!!m_arrayPrototype && m_arrayPrototype->hasOwnProperty(state, ObjectPropertyName(strings->toString)));
- Value arrayToString = m_arrayPrototype->getOwnProperty(state, ObjectPropertyName(strings->toString)).value(state, m_arrayPrototype);
typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->toString),
- ObjectPropertyDescriptor(arrayToString, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+ ObjectPropertyDescriptor(m_arrayToString, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->indexOf),
ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->indexOf, builtinTypedArrayIndexOf, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
typedArrayPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(strings->lastIndexOf),
return M;
}
+void GlobalObject::initializeWeakMap(ExecutionState& state)
+{
+ ObjectPropertyNativeGetterSetterData* nativeData = new ObjectPropertyNativeGetterSetterData(true, false, true,
+ [](ExecutionState& state, Object* self, const Value& receiver, const EncodedValue& privateDataFromObjectPrivateArea) -> Value {
+ ASSERT(self->isGlobalObject());
+ return self->asGlobalObject()->weakMap();
+ },
+ nullptr);
+
+ defineNativeDataAccessorProperty(state, ObjectPropertyName(state.context()->staticStrings().WeakMap), nativeData, Value(Value::EmptyValue));
+}
+
void GlobalObject::installWeakMap(ExecutionState& state)
{
m_weakMap = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().WeakMap, builtinWeakMapConstructor, 0), NativeFunctionObject::__ForBuiltinConstructor__);
ObjectPropertyDescriptor(Value(state.context()->staticStrings().WeakMap.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
m_weakMap->setFunctionPrototype(state, m_weakMapPrototype);
- defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().WeakMap),
- ObjectPropertyDescriptor(m_weakMap, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+ redefineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().WeakMap),
+ ObjectPropertyDescriptor(m_weakMap, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
}
} // namespace Escargot
return weakRef->targetAsValue();
}
+void GlobalObject::initializeWeakRef(ExecutionState& state)
+{
+ ObjectPropertyNativeGetterSetterData* nativeData = new ObjectPropertyNativeGetterSetterData(true, false, true,
+ [](ExecutionState& state, Object* self, const Value& receiver, const EncodedValue& privateDataFromObjectPrivateArea) -> Value {
+ ASSERT(self->isGlobalObject());
+ return self->asGlobalObject()->weakRef();
+ },
+ nullptr);
+
+ defineNativeDataAccessorProperty(state, ObjectPropertyName(state.context()->staticStrings().WeakRef), nativeData, Value(Value::EmptyValue));
+}
void GlobalObject::installWeakRef(ExecutionState& state)
{
ObjectPropertyDescriptor(Value(state.context()->staticStrings().WeakRef.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
m_weakRef->setFunctionPrototype(state, m_weakRefPrototype);
- defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().WeakRef),
- ObjectPropertyDescriptor(m_weakRef, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+ redefineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().WeakRef),
+ ObjectPropertyDescriptor(m_weakRef, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
}
} // namespace Escargot
return Value(S->has(state, argv[0].asObject()));
}
+void GlobalObject::initializeWeakSet(ExecutionState& state)
+{
+ ObjectPropertyNativeGetterSetterData* nativeData = new ObjectPropertyNativeGetterSetterData(true, false, true,
+ [](ExecutionState& state, Object* self, const Value& receiver, const EncodedValue& privateDataFromObjectPrivateArea) -> Value {
+ ASSERT(self->isGlobalObject());
+ return self->asGlobalObject()->weakSet();
+ },
+ nullptr);
+
+ defineNativeDataAccessorProperty(state, ObjectPropertyName(state.context()->staticStrings().WeakSet), nativeData, Value(Value::EmptyValue));
+}
+
void GlobalObject::installWeakSet(ExecutionState& state)
{
m_weakSet = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().WeakSet, builtinWeakSetConstructor, 0), NativeFunctionObject::__ForBuiltinConstructor__);
ObjectPropertyDescriptor(Value(state.context()->staticStrings().WeakSet.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
m_weakSet->setFunctionPrototype(state, m_weakSetPrototype);
- defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().WeakSet),
- ObjectPropertyDescriptor(m_weakSet, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+ redefineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().WeakSet),
+ ObjectPropertyDescriptor(m_weakSet, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
}
} // namespace Escargot
namespace Escargot {
OpcodeTable g_opcodeTable;
+#ifndef NDEBUG
+// Represent start code position which is used for bytecode dump
+static MAY_THREAD_LOCAL size_t g_dumpCodeStartPosition;
+#endif
OpcodeTable::OpcodeTable()
{
}
#ifndef NDEBUG
-void ByteCode::dumpCode(size_t pos, const char* byteCodeStart)
+void ByteCode::dumpCode(const char* byteCodeStart, const size_t endPos)
{
- printf("%d\t\t", (int)pos);
+ // set the start code position
+ g_dumpCodeStartPosition = (size_t)byteCodeStart;
+
+ size_t curPos = 0;
+ while (curPos < endPos) {
+ ByteCode* curCode = (ByteCode*)(byteCodeStart + curPos);
- const char* opcodeName = NULL;
- switch (m_orgOpcode) {
+ printf("%zu\t\t", curPos);
+
+ const char* opcodeName = nullptr;
+ switch (curCode->m_orgOpcode) {
#define RETURN_BYTECODE_NAME(name, pushCount, popCount) \
case name##Opcode: \
- ((name*)this)->dump(byteCodeStart); \
+ static_cast<name*>(curCode)->dump(); \
opcodeName = #name; \
break;
- FOR_EACH_BYTECODE_OP(RETURN_BYTECODE_NAME)
+ FOR_EACH_BYTECODE_OP(RETURN_BYTECODE_NAME)
#undef RETURN_BYTECODE_NAME
- default:
- RELEASE_ASSERT_NOT_REACHED();
- }
+ default:
+ RELEASE_ASSERT_NOT_REACHED();
+ }
- printf(" | %s ", opcodeName);
- printf("(line: %d:%d)\n", (int)m_loc.line, (int)m_loc.column);
+ printf(" | %s ", opcodeName);
+ printf("(line: %zu:%zu)\n", curCode->m_loc.line, curCode->m_loc.column);
+
+ if (curCode->m_orgOpcode == ExecutionPauseOpcode) {
+ if (static_cast<ExecutionPause*>(curCode)->m_reason == ExecutionPause::Yield) {
+ curPos += static_cast<ExecutionPause*>(curCode)->m_yieldData.m_tailDataLength;
+ } else if (static_cast<ExecutionPause*>(curCode)->m_reason == ExecutionPause::Await) {
+ curPos += static_cast<ExecutionPause*>(curCode)->m_awaitData.m_tailDataLength;
+ } else if (static_cast<ExecutionPause*>(curCode)->m_reason == ExecutionPause::GeneratorsInitialize) {
+ curPos += static_cast<ExecutionPause*>(curCode)->m_asyncGeneratorInitializeData.m_tailDataLength;
+ } else {
+ ASSERT_NOT_REACHED();
+ }
+ }
+
+ curPos += byteCodeLengths[curCode->m_orgOpcode];
+ }
}
-int ByteCode::dumpJumpPosition(size_t pos, const char* byteCodeStart)
+size_t ByteCode::dumpJumpPosition(size_t pos)
{
- return (int)(pos - (size_t)byteCodeStart);
+ ASSERT(!!g_dumpCodeStartPosition && pos > g_dumpCodeStartPosition);
+ return (pos - g_dumpCodeStartPosition);
}
-void GetGlobalVariable::dump(const char* byteCodeStart)
+void GetGlobalVariable::dump()
{
- printf("get global variable r%d <- global.%s", (int)m_registerIndex, m_slot->m_propertyName.string()->toUTF8StringData().data());
+ printf("get global variable r%u <- global.%s", m_registerIndex, m_slot->m_propertyName.string()->toUTF8StringData().data());
}
-void SetGlobalVariable::dump(const char* byteCodeStart)
+void SetGlobalVariable::dump()
{
- printf("set global variable global.%s <- r%d", m_slot->m_propertyName.string()->toUTF8StringData().data(), (int)m_registerIndex);
+ printf("set global variable global.%s <- r%u", m_slot->m_propertyName.string()->toUTF8StringData().data(), m_registerIndex);
}
#endif
ByteCodeLOC m_loc;
Opcode m_orgOpcode;
- void dumpCode(size_t pos, const char* byteCodeStart);
- int dumpJumpPosition(size_t pos, const char* byteCodeStart);
+ static void dumpCode(const char* byteCodeStart, const size_t endPos);
+ static size_t dumpJumpPosition(size_t pos);
#endif
};
Value m_value;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("load r%d <- ", (int)m_registerIndex);
+ printf("load r%u <- ", m_registerIndex);
Value v = m_value;
if (v.isNumber()) {
printf("%lf", v.asNumber());
ByteCodeRegisterIndex m_registerIndex;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("r%d <- new.target", (int)m_registerIndex);
+ printf("r%u <- new.target", m_registerIndex);
}
#endif
};
AtomicString m_name;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("load r%d <- %s", (int)m_registerIndex, m_name.string()->toUTF8StringData().data());
+ printf("load r%u <- %s", m_registerIndex, m_name.string()->toUTF8StringData().data());
}
#endif
};
AtomicString m_name;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("store %s <- r%d", m_name.string()->toUTF8StringData().data(), (int)m_registerIndex);
+ printf("store %s <- r%u", m_name.string()->toUTF8StringData().data(), m_registerIndex);
}
#endif
};
AtomicString m_name;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("initialize %s <- r%d", m_name.string()->toUTF8StringData().data(), (int)m_registerIndex);
+ printf("initialize %s <- r%u", m_name.string()->toUTF8StringData().data(), m_registerIndex);
}
#endif
};
ByteCodeRegisterIndex m_index;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("load r%d <- heap[%d][%d]", (int)m_registerIndex, (int)m_upperIndex, (int)m_index);
+ printf("load r%u <- heap[%u][%u]", m_registerIndex, m_upperIndex, m_index);
}
#endif
};
ByteCodeRegisterIndex m_index;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("store heap[%d][%d] <- r%d", (int)m_upperIndex, (int)m_index, (int)m_registerIndex);
+ printf("store heap[%u][%u] <- r%u", m_upperIndex, m_index, m_registerIndex);
}
#endif
};
ByteCodeRegisterIndex m_index;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("initialize heap[0][%d] <- r%d", (int)m_index, (int)m_registerIndex);
+ printf("initialize heap[0][%u] <- r%u", m_index, m_registerIndex);
}
#endif
};
ByteCodeRegisterIndex m_homeObjectRegisterIndex;
InterpretedCodeBlock* m_codeBlock;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
printf("create ");
if (m_codeBlock->isArrowFunctionExpression()) {
printf("arrow");
}
- printf("function %s -> r%d", m_codeBlock->functionName().string()->toUTF8StringData().data(), (int)m_registerIndex);
+ printf("function %s -> r%u", m_codeBlock->functionName().string()->toUTF8StringData().data(), m_registerIndex);
}
#endif
};
}; // SetStaticPrivateFieldData
};
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
if (m_stage == Stage::CreateClass) {
if (m_superClassRegisterIndex == REGISTER_LIMIT) {
- printf("create class r%d { r%d }", (int)m_classConstructorRegisterIndex, (int)m_classPrototypeRegisterIndex);
+ printf("create class r%u { r%u }", m_classConstructorRegisterIndex, m_classPrototypeRegisterIndex);
} else {
- printf("create class r%d : r%d { r%d }", (int)m_classConstructorRegisterIndex, (int)m_superClassRegisterIndex, (int)m_classPrototypeRegisterIndex);
+ printf("create class r%u : r%u { r%u }", m_classConstructorRegisterIndex, m_superClassRegisterIndex, m_classPrototypeRegisterIndex);
}
} else if (m_stage == Stage::SetFieldSize) {
- printf("set field size r%d -> %d,%d", (int)m_classConstructorRegisterIndex, (int)m_fieldSize, (int)m_staticFieldSize);
+ printf("set field size r%u -> %u,%u", m_classConstructorRegisterIndex, m_fieldSize, m_staticFieldSize);
} else if (m_stage == Stage::InitField) {
- printf("init field r%d[%d, r%d]", (int)m_classConstructorRegisterIndex, (int)m_initFieldIndex, (int)m_propertyInitRegisterIndex);
+ printf("init field r%u[%u, r%u]", m_classConstructorRegisterIndex, m_initFieldIndex, m_propertyInitRegisterIndex);
} else if (m_stage == Stage::InitPrivateField) {
- printf("init private field r%d[%d, r%d] type %d", (int)m_classConstructorRegisterIndex, (int)m_initPrivateFieldIndex, (int)m_privatePropertyInitRegisterIndex, (int)m_initPrivateFieldType);
+ printf("init private field r%u[%u, r%u] type %u", m_classConstructorRegisterIndex, m_initPrivateFieldIndex, m_privatePropertyInitRegisterIndex, m_initPrivateFieldType);
} else if (m_stage == Stage::SetFieldData) {
- printf("set field data r%d[%d] = r%d", (int)m_classConstructorRegisterIndex, (int)m_setFieldIndex, (int)m_propertySetRegisterIndex);
+ printf("set field data r%u[%u] = r%u", m_classConstructorRegisterIndex, m_setFieldIndex, m_propertySetRegisterIndex);
} else if (m_stage == Stage::SetPrivateFieldData) {
- printf("set private field data r%d[%d] = r%d type %d", (int)m_classConstructorRegisterIndex, (int)m_setPrivateFieldIndex, (int)m_privatePropertySetRegisterIndex, (int)m_setPrivateFieldType);
+ printf("set private field data r%u[%u] = r%u type %u", m_classConstructorRegisterIndex, m_setPrivateFieldIndex, m_privatePropertySetRegisterIndex, m_setPrivateFieldType);
} else if (m_stage == Stage::InitStaticField) {
- printf("init static field r%d.r%d", (int)m_classConstructorRegisterIndex, (int)m_staticPropertyInitRegisterIndex);
+ printf("init static field r%u.r%u", m_classConstructorRegisterIndex, m_staticPropertyInitRegisterIndex);
} else if (m_stage == Stage::InitStaticPrivateField) {
- printf("init private static field r%d.r%d", (int)m_classConstructorRegisterIndex, (int)m_staticPrivatePropertyInitRegisterIndex);
+ printf("init private static field r%u.r%u", m_classConstructorRegisterIndex, m_staticPrivatePropertyInitRegisterIndex);
} else if (m_stage == Stage::SetStaticFieldData) {
- printf("set static field r%d.? = r%d", (int)m_classConstructorRegisterIndex, (int)m_staticPropertySetRegisterIndex);
+ printf("set static field r%u.? = r%u", m_classConstructorRegisterIndex, m_staticPropertySetRegisterIndex);
} else if (m_stage == Stage::SetStaticPrivateFieldData) {
- printf("set static private field r%d.? = r%d(%d)", (int)m_classConstructorRegisterIndex, (int)m_staticPrivatePropertySetRegisterIndex, (int)m_setStaticPrivateFieldType);
+ printf("set static private field r%u.? = r%u(%u)", m_classConstructorRegisterIndex, m_staticPrivatePropertySetRegisterIndex, m_setStaticPrivateFieldType);
} else {
ASSERT(m_stage == Stage::CleanupStaticData);
- printf("cleanup static field data r%d", (int)m_classConstructorRegisterIndex);
+ printf("cleanup static field data r%u", m_classConstructorRegisterIndex);
}
}
#endif
ByteCodeRegisterIndex m_registerIndex;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("Create RestElement -> r%d", (int)m_registerIndex);
+ printf("Create RestElement -> r%u", m_registerIndex);
}
#endif
};
ByteCodeRegisterIndex m_dstIndex : REGISTER_INDEX_IN_BIT;
bool m_isCall : 1;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
if (m_isCall) {
- printf("super constructor -> r%d", (int)m_dstIndex);
+ printf("super constructor -> r%u", m_dstIndex);
} else {
- printf("super property -> r%d", (int)m_dstIndex);
+ printf("super property -> r%u", m_dstIndex);
}
}
#endif
};
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
if (m_type == Super) {
- printf("set object complex(r%d).r%d <- r%d", (int)m_objectRegisterIndex, (int)m_propertyNameIndex, (int)m_loadRegisterIndex);
+ printf("set object complex(r%u).r%u <- r%u", m_objectRegisterIndex, m_propertyNameIndex, m_loadRegisterIndex);
} else {
ASSERT(m_type == Private || m_type == PrivateWithoutOuterClass);
- printf("set object complex(r%d).#%s <- r%d %s", (int)m_objectRegisterIndex,
- m_propertyName.string()->toNonGCUTF8StringData().data(), (int)m_loadRegisterIndex,
+ printf("set object complex(r%u).#%s <- r%u %s", m_objectRegisterIndex,
+ m_propertyName.string()->toNonGCUTF8StringData().data(), m_loadRegisterIndex,
m_type == Private ? "refer outer class" : "");
}
}
};
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
if (m_type == Super) {
- printf("get object r%d <- complex(r%d).r%d", (int)m_storeRegisterIndex, (int)m_objectRegisterIndex, (int)m_propertyNameIndex);
+ printf("get object r%u <- complex(r%u).r%u", m_storeRegisterIndex, m_objectRegisterIndex, m_propertyNameIndex);
} else {
ASSERT(m_type == Private || m_type == PrivateWithoutOuterClass);
- printf("get object r%d <- complex(r%d).#%s %s", (int)m_storeRegisterIndex, (int)m_objectRegisterIndex,
+ printf("get object r%u <- complex(r%u).#%s %s", m_storeRegisterIndex, m_objectRegisterIndex,
m_propertyName.string()->toNonGCUTF8StringData().data(), m_type == Private ? "refer outer class" : "");
}
}
ByteCodeRegisterIndex m_dstIndex;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("load this binding -> r%d", (int)m_dstIndex);
+ printf("load this binding -> r%u", m_dstIndex);
}
#endif
};
#ifdef NDEBUG
#define DEFINE_BINARY_OPERATION_DUMP(name)
#else
-#define DEFINE_BINARY_OPERATION_DUMP(name) \
- void dump(const char* byteCodeStart) \
- { \
- printf(name " r%d <- r%d , r%d", (int)m_dstIndex, (int)m_srcIndex0, (int)m_srcIndex1); \
+#define DEFINE_BINARY_OPERATION_DUMP(name) \
+ void dump() \
+ { \
+ printf(name " r%u <- r%u , r%u", m_dstIndex, m_srcIndex0, m_srcIndex1); \
}
#endif
}
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
printf("breakpointDisabled");
}
}
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
printf("breakpointEnabled");
}
ByteCodeRegisterIndex m_registerIndex;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("createobject -> r%d", (int)m_registerIndex);
+ printf("createobject -> r%u", m_registerIndex);
}
#endif
};
size_t m_length;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("createarray -> r%d", (int)m_registerIndex);
+ printf("createarray -> r%u", m_registerIndex);
}
#endif
};
ByteCodeRegisterIndex m_argumentIndex;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("create spread array object(r%d) -> r%d", (int)m_argumentIndex, (int)m_registerIndex);
+ printf("create spread array object(r%u) -> r%u", m_argumentIndex, m_registerIndex);
}
#endif
};
ByteCodeRegisterIndex m_storeRegisterIndex;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("get object r%d <- r%d[r%d]", (int)m_storeRegisterIndex, (int)m_objectRegisterIndex, (int)m_propertyRegisterIndex);
+ printf("get object r%u <- r%u[r%u]", m_storeRegisterIndex, m_objectRegisterIndex, m_propertyRegisterIndex);
}
#endif
};
ByteCodeRegisterIndex m_loadRegisterIndex;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("set object r%d[r%d] <- r%d", (int)m_objectRegisterIndex, (int)m_propertyRegisterIndex, (int)m_loadRegisterIndex);
+ printf("set object r%u[r%u] <- r%u", m_objectRegisterIndex, m_propertyRegisterIndex, m_loadRegisterIndex);
}
#endif
};
bool m_redefineFunctionOrClassName : 1;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("object define own property r%d[r%d] <- r%d", (int)m_objectRegisterIndex, (int)m_propertyRegisterIndex, (int)m_loadRegisterIndex);
+ printf("object define own property r%u[r%u] <- r%u", m_objectRegisterIndex, m_propertyRegisterIndex, m_loadRegisterIndex);
}
#endif
};
ObjectPropertyDescriptor::PresentAttribute m_presentAttribute : 8;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("object define own property with name r%d.%s <- r%d", (int)m_objectRegisterIndex, m_propertyName.string()->toUTF8StringData().data(), (int)m_loadRegisterIndex);
+ printf("object define own property with name r%u.%s <- r%u", m_objectRegisterIndex, m_propertyName.string()->toUTF8StringData().data(), m_loadRegisterIndex);
}
#endif
};
ByteCodeRegisterIndex m_loadRegisterIndexs[ARRAY_DEFINE_OPERATION_MERGE_COUNT];
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("array define own property r%d[%d - %d] <- ", (int)m_objectRegisterIndex, (int)m_baseIndex, (int)(m_baseIndex + m_count));
+ printf("array define own property r%u[%u - %u] <- ", m_objectRegisterIndex, m_baseIndex, (m_baseIndex + m_count));
for (int i = 0; i < m_count; i++) {
if (m_loadRegisterIndexs[i] == REGISTER_LIMIT) {
printf(", ");
} else {
- printf("r%d, ", m_loadRegisterIndexs[i]);
+ printf("r%u, ", m_loadRegisterIndexs[i]);
}
}
}
ByteCodeRegisterIndex m_loadRegisterIndexs[ARRAY_DEFINE_OPERATION_MERGE_COUNT];
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("array define own property by spread element r%d[ - ] <- ", (int)m_objectRegisterIndex);
+ printf("array define own property by spread element r%u[ - ] <- ", m_objectRegisterIndex);
for (int i = 0; i < m_count; i++) {
if (m_loadRegisterIndexs[i] == REGISTER_LIMIT) {
printf(", ");
} else {
- printf("r%d, ", m_loadRegisterIndexs[i]);
+ printf("r%u, ", m_loadRegisterIndexs[i]);
}
}
}
ByteCodeRegisterIndex m_storeRegisterIndex;
ObjectStructurePropertyName m_propertyName;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("get object r%d <- r%d.%s", (int)m_storeRegisterIndex, (int)m_objectRegisterIndex, m_propertyName.plainString()->toUTF8StringData().data());
+ printf("get object r%u <- r%u.%s", m_storeRegisterIndex, m_objectRegisterIndex, m_propertyName.plainString()->toUTF8StringData().data());
}
#endif
};
bool m_isLength : 1;
uint16_t m_missCount : 16;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("set object r%d.%s <- r%d", (int)m_objectRegisterIndex, m_propertyName.plainString()->toUTF8StringData().data(), (int)m_loadRegisterIndex);
+ printf("set object r%u.%s <- r%u", m_objectRegisterIndex, m_propertyName.plainString()->toUTF8StringData().data(), m_loadRegisterIndex);
}
#endif
};
GlobalVariableAccessCacheItem* m_slot;
#ifndef NDEBUG
- void dump(const char* byteCodeStart);
+ void dump();
#endif
};
GlobalVariableAccessCacheItem* m_slot;
#ifndef NDEBUG
- void dump(const char* byteCodeStart);
+ void dump();
#endif
};
AtomicString m_variableName;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("initialize global variable %s <- r%d", m_variableName.string()->toUTF8StringData().data(), (int)m_registerIndex);
+ printf("initialize global variable %s <- r%u", m_variableName.string()->toUTF8StringData().data(), m_registerIndex);
}
#endif
};
ByteCodeRegisterIndex m_registerIndex1;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("mov r%d <- r%d", (int)m_registerIndex1, (int)m_registerIndex0);
+ printf("mov r%u <- r%u", m_registerIndex1, m_registerIndex0);
}
#endif
};
ByteCodeRegisterIndex m_dstIndex;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("to number r%d <- r%d", (int)m_dstIndex, (int)m_srcIndex);
+ printf("to number r%u <- r%u", m_dstIndex, m_srcIndex);
}
#endif
};
ByteCodeRegisterIndex m_dstIndex;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("increment r%d <- r%d", (int)m_dstIndex, (int)m_srcIndex);
+ printf("increment r%u <- r%u", m_dstIndex, m_srcIndex);
}
#endif
};
ByteCodeRegisterIndex m_dstIndex;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("to numeric increment(r%d) -> r%d, r%d", (int)m_srcIndex, (int)m_storeIndex, (int)m_dstIndex);
+ printf("to numeric increment(r%u) -> r%u, r%u", m_srcIndex, m_storeIndex, m_dstIndex);
}
#endif
};
ByteCodeRegisterIndex m_dstIndex;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("decrement r%d <- r%d", (int)m_dstIndex, (int)m_srcIndex);
+ printf("decrement r%u <- r%u", m_dstIndex, m_srcIndex);
}
#endif
};
ByteCodeRegisterIndex m_dstIndex;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("to numeric decrement(r%d) -> r%d, r%d", (int)m_srcIndex, (int)m_storeIndex, (int)m_dstIndex);
+ printf("to numeric decrement(r%u) -> r%u, r%u", m_srcIndex, m_storeIndex, m_dstIndex);
}
#endif
};
ByteCodeRegisterIndex m_dstIndex;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("unary minus r%d <- r%d", (int)m_dstIndex, (int)m_srcIndex);
+ printf("unary minus r%u <- r%u", m_dstIndex, m_srcIndex);
}
#endif
};
ByteCodeRegisterIndex m_dstIndex;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("unary not r%d <- r%d", (int)m_dstIndex, (int)m_srcIndex);
+ printf("unary not r%u <- r%u", m_dstIndex, m_srcIndex);
}
#endif
};
ByteCodeRegisterIndex m_dstIndex;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("unary bitwise not r%d <- r%d", (int)m_dstIndex, (int)m_srcIndex);
+ printf("unary bitwise not r%u <- r%u", m_dstIndex, m_srcIndex);
}
#endif
};
AtomicString m_id;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("unary typeof r%d <- r%d", (int)m_dstIndex, (int)m_srcIndex);
+ printf("unary typeof r%u <- r%u", m_dstIndex, m_srcIndex);
}
#endif
};
AtomicString m_id;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("unary delete r%d <- r%d r%d %s", (int)m_dstIndex, (int)m_srcIndex0, (int)m_srcIndex1, m_id.string()->toUTF8StringData().data());
+ printf("unary delete r%u <- r%u r%u %s", m_dstIndex, m_srcIndex0, m_srcIndex1, m_id.string()->toUTF8StringData().data());
}
#endif
};
ByteCodeRegisterIndex m_dstIndex;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("template operation(+) r%d <- r%d + r%d", (int)m_dstIndex, (int)m_src0Index, (int)m_src1Index);
+ printf("template operation(+) r%u <- r%u + r%u", m_dstIndex, m_src0Index, m_src1Index);
}
#endif
};
size_t m_jumpPosition;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("jump %d", dumpJumpPosition(m_jumpPosition, byteCodeStart));
+ printf("jump %zu", dumpJumpPosition(m_jumpPosition));
}
#endif
};
size_t m_recordIndex;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
printf("jump complex");
}
ByteCodeRegisterIndex m_registerIndex;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("jump if r%d is true -> %d", (int)m_registerIndex, dumpJumpPosition(m_jumpPosition, byteCodeStart));
+ printf("jump if r%u is true -> %zu", m_registerIndex, dumpJumpPosition(m_jumpPosition));
}
#endif
};
ByteCodeRegisterIndex m_registerIndex;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
if (m_shouldNegate) {
- printf("jump if r%d is not undefined nor null -> %d", (int)m_registerIndex, dumpJumpPosition(m_jumpPosition, byteCodeStart));
+ printf("jump if r%u is not undefined nor null -> %zu", m_registerIndex, dumpJumpPosition(m_jumpPosition));
} else {
- printf("jump if r%d is undefined or null -> %d", (int)m_registerIndex, dumpJumpPosition(m_jumpPosition, byteCodeStart));
+ printf("jump if r%u is undefined or null -> %zu", m_registerIndex, dumpJumpPosition(m_jumpPosition));
}
}
#endif
ByteCodeRegisterIndex m_registerIndex;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("jump if r%d is false -> %d", (int)m_registerIndex, dumpJumpPosition(m_jumpPosition, byteCodeStart));
+ printf("jump if r%u is false -> %zu", m_registerIndex, dumpJumpPosition(m_jumpPosition));
}
#endif
};
bool m_switched; // left and right operands are switched
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
char* op;
if (m_switched) {
op = (char*)"less than";
}
}
- printf("jump if r%d is not %s r%d -> %d", (int)m_leftIndex, op, (int)m_rightIndex, dumpJumpPosition(m_jumpPosition, byteCodeStart));
+ printf("jump if r%u is not %s r%u -> %zu", m_leftIndex, op, m_rightIndex, dumpJumpPosition(m_jumpPosition));
}
#endif
};
bool m_shouldNegate; // condition should meet NOT EQUAL
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
char* op;
if (m_isStrict) {
op = (char*)"equal";
}
}
- printf("jump if r%d is %s to r%d -> %d", (int)m_registerIndex0, op, (int)m_registerIndex1, dumpJumpPosition(m_jumpPosition, byteCodeStart));
+ printf("jump if r%u is %s to r%u -> %zu", m_registerIndex0, op, m_registerIndex1, dumpJumpPosition(m_jumpPosition));
}
#endif
};
uint16_t m_argumentCount;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("call r%d <- r%d(r%d-r%d)", (int)m_resultIndex, (int)m_calleeIndex, (int)m_argumentsStartIndex, (int)m_argumentsStartIndex + (int)m_argumentCount);
+ printf("call r%u <- r%u(r%u-r%u)", m_resultIndex, m_calleeIndex, m_argumentsStartIndex, m_argumentsStartIndex + m_argumentCount);
}
#endif
};
uint16_t m_argumentCount;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("call r%d <- r%d,r%d(r%d-r%d)", (int)m_resultIndex, (int)m_receiverIndex, (int)m_calleeIndex, (int)m_argumentsStartIndex, (int)m_argumentsStartIndex + (int)m_argumentCount);
+ printf("call r%u <- r%u,r%u(r%u-r%u)", m_resultIndex, m_receiverIndex, m_calleeIndex, m_argumentsStartIndex, m_argumentsStartIndex + m_argumentCount);
}
#endif
};
ByteCodeRegisterIndex m_resultIndex;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
if (m_kind == Kind::InWithScope) {
- printf("call(complex inWith) r%d <- %s(r%d-r%d)", (int)m_resultIndex, m_calleeName.string()->toNonGCUTF8StringData().data(), (int)m_argumentsStartIndex, (int)m_argumentsStartIndex + (int)m_argumentCount);
+ printf("call(complex inWith) r%u <- %s(r%u-r%u)", m_resultIndex, m_calleeName.string()->toNonGCUTF8StringData().data(), m_argumentsStartIndex, m_argumentsStartIndex + m_argumentCount);
} else {
if (m_receiverOrThisIndex != REGISTER_LIMIT) {
- printf("call(complex %d) r%d <- r%d,r%d(r%d-r%d)", (int)m_kind, (int)m_resultIndex, (int)m_receiverOrThisIndex, (int)m_calleeIndex, (int)m_argumentsStartIndex, (int)m_argumentsStartIndex + (int)m_argumentCount);
+ printf("call(complex %u) r%u <- r%u,r%u(r%u-r%u)", m_kind, m_resultIndex, m_receiverOrThisIndex, m_calleeIndex, m_argumentsStartIndex, m_argumentsStartIndex + m_argumentCount);
} else {
- printf("call(complex %d) r%d <- r%d(r%d-r%d)", (int)m_kind, (int)m_resultIndex, (int)m_calleeIndex, (int)m_argumentsStartIndex, (int)m_argumentsStartIndex + (int)m_argumentCount);
+ printf("call(complex %u) r%u <- r%u(r%u-r%u)", m_kind, m_resultIndex, m_calleeIndex, m_argumentsStartIndex, m_argumentsStartIndex + m_argumentCount);
}
}
}
ExecutionPauser* m_pauser;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
printf("execution resume");
}
};
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
printf("execution pause ");
if (m_reason == Reason::Yield) {
- printf("yield r%d r%d r%d", (int)m_yieldData.m_yieldIndex, (int)m_yieldData.m_dstIndex, (int)m_yieldData.m_dstStateIndex);
+ printf("yield r%u r%u r%u", m_yieldData.m_yieldIndex, m_yieldData.m_dstIndex, m_yieldData.m_dstStateIndex);
} else if (m_reason == Reason::Await) {
- printf("await r%d r%d r%d", (int)m_awaitData.m_awaitIndex, (int)m_awaitData.m_dstIndex, (int)m_awaitData.m_dstStateIndex);
+ printf("await r%u r%u r%u", m_awaitData.m_awaitIndex, m_awaitData.m_dstIndex, m_awaitData.m_dstStateIndex);
} else if (m_reason == Reason::GeneratorsInitialize) {
printf("generators initialize ");
}
uint16_t m_argumentCount;
ByteCodeRegisterIndex m_resultIndex;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("new r%d <- r%d(r%d-r%d)", (int)m_resultIndex, (int)m_calleeIndex, (int)m_argumentsStartIndex, (int)m_argumentsStartIndex + (int)m_argumentCount);
+ printf("new r%u <- r%u(r%u-r%u)", m_resultIndex, m_calleeIndex, m_argumentsStartIndex, m_argumentsStartIndex + m_argumentCount);
}
#endif
};
uint16_t m_argumentCount;
ByteCodeRegisterIndex m_resultIndex;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("new(spread) r%d <- r%d(r%d-r%d)", (int)m_resultIndex, (int)m_calleeIndex, (int)m_argumentsStartIndex, (int)m_argumentsStartIndex + (int)m_argumentCount);
+ printf("new(spread) r%u <- r%u(r%u-r%u)", m_resultIndex, m_calleeIndex, m_argumentsStartIndex, m_argumentsStartIndex + m_argumentCount);
}
#endif
};
ByteCodeRegisterIndex m_registerIndex;
uint16_t m_paramIndex;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("get parameter r%d <- argv[%d]", (int)m_registerIndex, (int)m_paramIndex);
+ printf("get parameter r%u <- argv[%u]", m_registerIndex, m_paramIndex);
}
#endif
};
ByteCodeRegisterIndex m_registerIndex;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("return r%d", (int)m_registerIndex);
+ printf("return r%u", m_registerIndex);
}
#endif
};
size_t m_tryCatchEndPosition;
size_t m_finallyEndPosition;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("try (hasCatch:%d, save catched value to:r%d, hasFinalizer:%d)", (int)m_hasCatch, (int)m_catchedValueRegisterIndex, (int)m_hasFinalizer);
+ printf("try (hasCatch:%u, save catched value to:r%u, hasFinalizer:%u)", m_hasCatch, m_catchedValueRegisterIndex, m_hasFinalizer);
}
#endif
};
}
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
printf("close lexical environment");
}
ByteCodeRegisterIndex m_registerIndex;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("throw r%d", (int)m_registerIndex);
+ printf("throw r%u", m_registerIndex);
}
#endif
};
AtomicString m_templateDataString;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
printf("throw static error %s", m_errorMessage);
}
bool m_isDestruction : 1;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("create enumerate object r%d <- r%d", (int)m_dataRegisterIndex, (int)m_objectRegisterIndex);
+ printf("create enumerate object r%u <- r%u", m_dataRegisterIndex, m_objectRegisterIndex);
}
#endif
};
ByteCodeRegisterIndex m_dataRegisterIndex;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("get enumerate key r%d r%d", (int)m_registerIndex, (int)m_dataRegisterIndex);
+ printf("get enumerate key r%u r%u", m_registerIndex, m_dataRegisterIndex);
}
#endif
};
ByteCodeRegisterIndex m_registerIndex;
size_t m_exitPosition;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("check if key is last r%d", (int)m_registerIndex);
+ printf("check if key is last r%u", m_registerIndex);
}
#endif
};
ByteCodeRegisterIndex m_dataRegisterIndex;
ByteCodeRegisterIndex m_keyRegisterIndex;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("mark enumerate key r%d to enumerate object r%d", (int)m_keyRegisterIndex, (int)m_dataRegisterIndex);
+ printf("mark enumerate key r%u to enumerate object r%u", m_keyRegisterIndex, m_dataRegisterIndex);
}
#endif
};
}
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
if (m_operation == Operation::GetIterator) {
- printf("get iterator(r%d) -> r%d", (int)m_getIteratorData.m_srcObjectRegisterIndex, (int)m_getIteratorData.m_dstIteratorRecordIndex);
+ printf("get iterator(r%u) -> r%u", m_getIteratorData.m_srcObjectRegisterIndex, m_getIteratorData.m_dstIteratorRecordIndex);
} else if (m_operation == Operation::IteratorClose) {
- printf("iterator close(r%d, r%d)", (int)m_iteratorCloseData.m_iterRegisterIndex, (int)m_iteratorCloseData.m_execeptionRegisterIndexIfExists);
+ printf("iterator close(r%u, r%u)", m_iteratorCloseData.m_iterRegisterIndex, m_iteratorCloseData.m_execeptionRegisterIndexIfExists);
} else if (m_operation == Operation::IteratorBind) {
- printf("iterator bind(r%d) -> r%d", (int)m_iteratorBindData.m_iterRegisterIndex, (int)m_iteratorBindData.m_registerIndex);
+ printf("iterator bind(r%u) -> r%u", m_iteratorBindData.m_iterRegisterIndex, m_iteratorBindData.m_registerIndex);
} else if (m_operation == Operation::IteratorTestDone) {
- printf("iterator test done iteratorRecord(%d)->m_done -> r%d", (int)m_iteratorTestDoneData.m_iteratorRecordOrObjectRegisterIndex,
- (int)m_iteratorTestDoneData.m_dstRegisterIndex);
+ printf("iterator test done iteratorRecord(%u)->m_done -> r%u", m_iteratorTestDoneData.m_iteratorRecordOrObjectRegisterIndex,
+ m_iteratorTestDoneData.m_dstRegisterIndex);
} else if (m_operation == Operation::IteratorNext) {
- printf("iterator next r%d.[[next]](r%d) -> r%d", (int)m_iteratorNextData.m_iteratorRecordRegisterIndex,
- (int)m_iteratorNextData.m_valueRegisterIndex, (int)m_iteratorNextData.m_returnRegisterIndex);
+ printf("iterator next r%u.[[next]](r%u) -> r%u", m_iteratorNextData.m_iteratorRecordRegisterIndex,
+ m_iteratorNextData.m_valueRegisterIndex, m_iteratorNextData.m_returnRegisterIndex);
} else if (m_operation == Operation::IteratorTestResultIsObject) {
- printf("iterator test result is object r%d", (int)m_iteratorTestResultIsObjectData.m_valueRegisterIndex);
+ printf("iterator test result is object r%u", m_iteratorTestResultIsObjectData.m_valueRegisterIndex);
} else if (m_operation == Operation::IteratorValue) {
- printf("iterator value r%d -> r%d", (int)m_iteratorValueData.m_srcRegisterIndex, (int)m_iteratorValueData.m_dstRegisterIndex);
+ printf("iterator value r%u -> r%u", m_iteratorValueData.m_srcRegisterIndex, m_iteratorValueData.m_dstRegisterIndex);
} else if (m_operation == Operation::IteratorCheckOngoingExceptionOnAsyncIteratorClose) {
printf("iterator check ongoing exception");
} else {
AtomicString m_propertyName;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("get method r%d.%s -> r%d", (int)m_objectRegisterIndex, m_propertyName.string()->toNonGCUTF8StringData().data(), (int)m_resultRegisterIndex);
+ printf("get method r%u.%s -> r%u", m_objectRegisterIndex, m_propertyName.string()->toNonGCUTF8StringData().data(), m_resultRegisterIndex);
}
#endif
};
String* m_body;
String* m_option;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("load regexp %s -> r%d", m_body->toUTF8StringData().data(), (int)m_registerIndex);
+ printf("load regexp %s -> r%u", m_body->toUTF8StringData().data(), m_registerIndex);
}
#endif
};
ByteCodeRegisterIndex m_withOrThisRegisterIndex : 16;
size_t m_endPostion;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("open lexical env r%d(%d)", (int)m_withOrThisRegisterIndex, (int)m_kind);
+ printf("open lexical env r%u(%u)", m_withOrThisRegisterIndex, m_kind);
}
#endif
};
bool m_isGetter : 1; // other case, this is setter
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
if (m_isGetter) {
- printf("object define getter r%d[r%d] = r%d", (int)m_objectRegisterIndex, (int)m_objectPropertyNameRegisterIndex, (int)m_objectPropertyValueRegisterIndex);
+ printf("object define getter r%u[r%u] = r%u", m_objectRegisterIndex, m_objectPropertyNameRegisterIndex, m_objectPropertyValueRegisterIndex);
} else {
- printf("object define setter r%d[r%d] = r%d", (int)m_objectRegisterIndex, (int)m_objectPropertyNameRegisterIndex, (int)m_objectPropertyValueRegisterIndex);
+ printf("object define setter r%u[r%u] = r%u", m_objectRegisterIndex, m_objectPropertyNameRegisterIndex, m_objectPropertyValueRegisterIndex);
}
}
#endif
ByteCodeRegisterIndex m_iterOrEnumIndex;
ByteCodeRegisterIndex m_dstIndex;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("binding rest element(r%d) -> r%d", (int)m_iterOrEnumIndex, (int)m_dstIndex);
+ printf("binding rest element(r%u) -> r%u", m_iterOrEnumIndex, m_dstIndex);
}
#endif
};
size_t m_blockEndPosition;
InterpretedCodeBlock::BlockInfo* m_blockInfo;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("block operation (%p) -> end %d", m_blockInfo, (int)m_blockEndPosition);
+ printf("block operation (%p) -> end %zu", m_blockInfo, m_blockEndPosition);
}
#endif
};
InterpretedCodeBlock::BlockInfo* m_blockInfo;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
printf("replace block lexical env operation (%p)", m_blockInfo);
}
};
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
if (m_operaton == TestCacheOperation) {
- printf("tagged template operation operation (test cache %d)", (int)m_testCacheOperationData.m_cacheIndex);
+ printf("tagged template operation operation (test cache %zu)", m_testCacheOperationData.m_cacheIndex);
} else {
- printf("tagged template operation operation (fill cache %d)", (int)m_testCacheOperationData.m_cacheIndex);
+ printf("tagged template operation operation (fill cache %zu)", m_testCacheOperationData.m_cacheIndex);
}
}
#endif
}
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
printf("ensure arguments object");
}
}
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("r%d <- resolve name address (%s)", (int)m_registerIndex, m_name.string()->toNonGCUTF8StringData().data());
+ printf("r%u <- resolve name address (%s)", m_registerIndex, m_name.string()->toNonGCUTF8StringData().data());
}
#endif
AtomicString m_name;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("store with address r%d, %s <- r%d", (int)m_addressRegisterIndex, m_name.string()->toUTF8StringData().data(), (int)m_valueRegisterIndex);
+ printf("store with address r%u, %s <- r%u", m_addressRegisterIndex, m_name.string()->toUTF8StringData().data(), m_valueRegisterIndex);
}
#endif
};
ByteCodeRegisterIndex m_registerIndex;
#ifndef NDEBUG
- void dump(const char* byteCodeStart)
+ void dump()
{
- printf("end(return with r[%d])", (int)m_registerIndex);
+ printf("end(return with r[%u])", m_registerIndex);
}
#endif
};
}
printf("]\n");
-
- char* code = block->m_code.data();
- size_t idx = 0;
- size_t end = block->m_code.size();
-
- while (idx < end) {
- ByteCode* currentCode = (ByteCode*)(code + idx);
-
- currentCode->dumpCode(idx, (const char*)code);
-
- if (currentCode->m_orgOpcode == ExecutionPauseOpcode) {
- if (((ExecutionPause*)currentCode)->m_reason == ExecutionPause::Yield) {
- idx += ((ExecutionPause*)currentCode)->m_yieldData.m_tailDataLength;
- } else if (((ExecutionPause*)currentCode)->m_reason == ExecutionPause::Await) {
- idx += ((ExecutionPause*)currentCode)->m_awaitData.m_tailDataLength;
- } else if (((ExecutionPause*)currentCode)->m_reason == ExecutionPause::GeneratorsInitialize) {
- idx += ((ExecutionPause*)currentCode)->m_asyncGeneratorInitializeData.m_tailDataLength;
- } else {
- ASSERT_NOT_REACHED();
- }
- }
-
- idx += byteCodeLengths[currentCode->m_orgOpcode];
- }
-
+ ByteCode::dumpCode(block->m_code.data(), block->m_code.size());
printf("dumpBytecode...<<<<<<<<<<<<<<<<<<<<<<\n");
}
}
}
ObjectPropertyDescriptor desc(*gs, code->m_presentAttribute);
Object* object = registerFile[code->m_objectRegisterIndex].toObject(state);
- object->defineOwnPropertyThrowsExceptionWhenStrictMode(state, ObjectPropertyName(state, pName), desc);
+ object->defineOwnPropertyThrowsException(state, ObjectPropertyName(state, pName), desc);
}
ALWAYS_INLINE Value ByteCodeInterpreter::incrementOperation(ExecutionState& state, const Value& value)
static std::string intlPreferredLanguageTag(const std::string& tag)
{
- // 78 possible replacements
+ // languageAlias element in
+ // https://www.unicode.org/repos/cldr/trunk/common/supplemental/supplementalMetadata.xml
+ if (tag == "cmn")
+ return "zh";
+ if (tag == "ces")
+ return "cs";
+ if (tag == "heb")
+ return "he";
+ if (tag == "xsj")
+ return "suj";
if (tag == "aar")
return "aa";
+
+ // legacy
+ if (tag == "tl")
+ return "fil";
+
+ // 92 possible replacements
if (tag == "aam")
return "aas";
if (tag == "adp")
return "dz";
+ if (tag == "asd")
+ return "snz";
if (tag == "aue")
return "ktz";
if (tag == "ayx")
return "nun";
if (tag == "bgm")
return "bcg";
+ if (tag == "bic")
+ return "bir";
if (tag == "bjd")
return "drl";
+ if (tag == "blg")
+ return "iba";
if (tag == "ccq")
return "rki";
- if (tag == "ces")
- return "cs";
if (tag == "cjr")
return "mom";
if (tag == "cka")
return "cmr";
if (tag == "cmk")
return "xch";
- if (tag == "cmn")
- return "zh";
if (tag == "coy")
return "pij";
if (tag == "cqu")
return "quh";
+ if (tag == "dit")
+ return "dif";
if (tag == "drh")
return "khk";
+ if (tag == "drr")
+ return "kzk";
if (tag == "drw")
return "prs";
if (tag == "gav")
return "vaj";
if (tag == "ggn")
return "gvr";
+ if (tag == "gli")
+ return "kzk";
if (tag == "gti")
return "nyc";
if (tag == "guv")
return "duz";
- if (tag == "heb")
- return "he";
if (tag == "hrr")
return "jal";
if (tag == "ibi")
return "yam";
if (tag == "kxe")
return "tvd";
+ if (tag == "kxl")
+ return "kru";
if (tag == "kzj")
return "dtp";
if (tag == "kzt")
return "dtp";
if (tag == "lii")
return "raq";
+ if (tag == "llo")
+ return "ngt";
if (tag == "lmm")
return "rmx";
if (tag == "meg")
return "mry";
if (tag == "mwj")
return "vaj";
+ if (tag == "myd")
+ return "aog";
if (tag == "myt")
return "mry";
if (tag == "nad")
return "xny";
if (tag == "ncp")
return "kdz";
+ if (tag == "nns")
+ return "nbr";
if (tag == "nnx")
return "ngv";
if (tag == "nts")
return "pij";
+ if (tag == "nxu")
+ return "bpp";
if (tag == "oun")
return "vaj";
+ if (tag == "pat")
+ return "kxr";
if (tag == "pcr")
return "adx";
if (tag == "pmc")
return "dtp";
if (tag == "thc")
return "tpo";
+ if (tag == "thw")
+ return "ola";
if (tag == "thx")
return "oyb";
if (tag == "tie")
return "acn";
if (tag == "xkh")
return "waw";
- if (tag == "xsj")
- return "suj";
+ if (tag == "xrq")
+ return "dmw";
if (tag == "ybd")
return "rki";
if (tag == "yma")
return "zom";
if (tag == "yuu")
return "yug";
+ if (tag == "zir")
+ return "scv";
return "";
}
static std::string intlRedundantLanguageTag(const std::string& tag)
{
- // 24 possible replacements
+ // non-iana
if (tag == "hy-arevela")
return "hy";
if (tag == "hy-arevmda")
return "hyw";
+
+ // 24 possible replacements
if (tag == "ja-Latn-hepburn-heploc")
return "ja-Latn-alalc97";
if (tag == "sgn-BR")
return "fsl";
if (tag == "sgn-GB")
return "bfi";
- if (tag == "gss")
- return "sgn-GR";
+ if (tag == "sgn-GR")
+ return "gss";
if (tag == "sgn-IE")
return "isg";
if (tag == "sgn-IT")
static std::string intlPreferredExtlangTag(const std::string& tag)
{
- // 235 possible replacements
+ // 245 possible replacements
if (tag == "aao")
return "ar";
if (tag == "abh")
return "zh";
if (tag == "cmn")
return "zh";
+ if (tag == "cnp")
+ return "zh";
if (tag == "coa")
return "ms";
if (tag == "cpx")
return "sgn";
if (tag == "csn")
return "sgn";
+ if (tag == "csp")
+ return "zh";
if (tag == "csq")
return "sgn";
if (tag == "csr")
return "sgn";
+ if (tag == "csx")
+ return "sgn";
if (tag == "czh")
return "zh";
if (tag == "czo")
return "ms";
if (tag == "ecs")
return "sgn";
+ if (tag == "ehs")
+ return "sgn";
if (tag == "esl")
return "sgn";
if (tag == "esn")
return "sgn";
if (tag == "jhs")
return "sgn";
+ if (tag == "jks")
+ return "sgn";
if (tag == "jls")
return "sgn";
if (tag == "jos")
return "ms";
if (tag == "lls")
return "sgn";
+ if (tag == "lsb")
+ return "sgn";
if (tag == "lsg")
return "sgn";
if (tag == "lsl")
return "sgn";
+ if (tag == "lsn")
+ return "sgn";
if (tag == "lso")
return "sgn";
if (tag == "lsp")
return "sgn";
if (tag == "lst")
return "sgn";
+ if (tag == "lsv")
+ return "sgn";
if (tag == "lsy")
return "sgn";
if (tag == "ltg")
return "sgn";
if (tag == "sqs")
return "sgn";
+ if (tag == "sqx")
+ return "sgn";
if (tag == "ssh")
return "ar";
if (tag == "ssp")
return "sgn";
if (tag == "ysl")
return "sgn";
+ if (tag == "ysm")
+ return "sgn";
if (tag == "yue")
return "zh";
if (tag == "zib")
std::transform(language.begin(), language.end(), language.begin(), tolower);
result.language = language;
language = Intl::preferredLanguage(language);
+
+ // test legacy cases
+ // https://github.com/unicode-org/cldr/blob/master/common/supplemental/supplementalMetadata.xml
+ if (result.language == "sh") {
+ language = result.language = "sr";
+ if (!result.script.length()) {
+ result.script = "Latn";
+ }
+ } else if (result.language == "cnr") {
+ language = result.language = "sr";
+ if (!result.region.length()) {
+ result.region = "ME";
+ }
+ }
+
canonical.appendString(String::fromUTF8(language.data(), language.length()));
// Check for extlang.
// Check for script.
// script = 4ALPHA
+ bool isScriptAddToCanonical = false;
if (currentIndex < numParts) {
std::string script = parts[currentIndex];
unsigned scriptLength = script.length();
script = script.substr(1, 3);
result.script += script;
canonical.appendString(String::fromUTF8(script.data(), script.length()));
+ isScriptAddToCanonical = true;
}
}
+ if (!isScriptAddToCanonical && result.script.length()) {
+ canonical.appendString("-");
+ canonical.appendString(String::fromUTF8(result.script.data(), result.script.length()));
+ }
+
// Check for region.
// region = 2ALPHA / 3DIGIT
+ bool isRegionAddToCanonical = false;
if (currentIndex < numParts) {
std::string region = parts[currentIndex];
unsigned regionLength = region.length();
result.region = region;
auto preffered = preferredRegion(region);
canonical.appendString(String::fromUTF8(preffered.data(), preffered.length()));
+ isRegionAddToCanonical = true;
}
}
+ if (!isRegionAddToCanonical && result.region.length()) {
+ canonical.appendString("-");
+ canonical.appendString(String::fromUTF8(result.region.data(), result.region.length()));
+ }
+
// Check for variant.
// variant = 5*8alphanum / (DIGIT 3alphanum)
std::unordered_set<std::string> subtags;
}
}
+template <typename T>
+T Intl::getNumberOption(ExecutionState& state, Object* options, String* property, double minimum, double maximum, const T& fallback)
+{
+ // http://www.ecma-international.org/ecma-402/1.0/index.html#sec-9.2.10
+
+ // Let value be the result of calling the [[Get]] internal method of options with argument property.
+ Value value = options->get(state, ObjectPropertyName(state, property)).value(state, options);
+ // If value is not undefined, then
+ if (!value.isUndefined()) {
+ // Let value be ToNumber(value).
+ double doubleValue = value.toNumber(state);
+ // If value is NaN or less than minimum or greater than maximum, throw a RangeError exception.
+ if (std::isnan(doubleValue) || doubleValue < minimum || maximum < doubleValue) {
+ ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "Got invalid number option value");
+ }
+ // Return floor(value).
+ return T(floor(doubleValue));
+ } else {
+ // Else return fallback.
+ return fallback;
+ }
+}
+
+template Value Intl::getNumberOption(ExecutionState& state, Object* options, String* property, double minimum, double maximum, const Value& fallback);
+template double Intl::getNumberOption(ExecutionState& state, Object* options, String* property, double minimum, double maximum, const double& fallback);
+template int Intl::getNumberOption(ExecutionState& state, Object* options, String* property, double minimum, double maximum, const int& fallback);
+
static std::vector<std::string> initAvailableNumberingSystems()
{
std::vector<std::string> availableNumberingSystems;
BooleanValue
};
static Value getOption(ExecutionState& state, Object* options, Value property, OptionValueType type, Value* values, size_t valuesLength, const Value& fallback);
+ template <typename T>
+ static T getNumberOption(ExecutionState& state, Object* options, String* property, double minimum, double maximum, const T& fallback);
static std::string preferredLanguage(const std::string& language);
static String* icuLocaleToBCP47Tag(String* string);
static std::vector<std::string> calendarsForLocale(String* locale);
static const size_t indexOfExtensionKeyNu = 1;
static const size_t indexOfExtensionKeyHc = 2;
static const double minECMAScriptTime = -8.64E15;
+static const size_t defaultStringBufferSize = 32;
std::vector<std::string> Intl::calendarsForLocale(String* locale)
{
return String::fromUTF8(state.context()->vmInstance()->timezoneID().data(), state.context()->vmInstance()->timezoneID().length());
}
-Object* IntlDateTimeFormat::create(ExecutionState& state, Context* realm, Value locales, Value options)
-{
- Object* dateTimeFormat = new Object(state, realm->globalObject()->intlDateTimeFormatPrototype());
- initialize(state, dateTimeFormat, locales, options);
- return dateTimeFormat;
-}
-
static std::string readHourCycleFromPattern(const UTF16StringDataNonGCStd& patternString)
{
bool inQuote = false;
}
-void IntlDateTimeFormat::initialize(ExecutionState& state, Object* dateTimeFormat, Value locales, Value options)
+static String* icuFieldTypeToPartName(ExecutionState& state, int32_t fieldName)
{
- // If dateTimeFormat has an [[initializedIntlObject]] internal property with value true, throw a TypeError exception.
- AtomicString initializedIntlObject = state.context()->staticStrings().lazyInitializedIntlObject();
- if (dateTimeFormat->hasInternalSlot() && dateTimeFormat->internalSlot()->hasOwnProperty(state, ObjectPropertyName(state, ObjectStructurePropertyName(initializedIntlObject)))) {
- ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Cannot initialize Intl Object twice");
+ if (fieldName == -1) {
+ return state.context()->staticStrings().lazyLiteral().string();
}
- // Set the [[initializedIntlObject]] internal property of dateTimeFormat to true.
- dateTimeFormat->ensureInternalSlot(state)->defineOwnProperty(state, ObjectPropertyName(initializedIntlObject), ObjectPropertyDescriptor(Value(true)));
+ switch (static_cast<UDateFormatField>(fieldName)) {
+ case UDAT_ERA_FIELD:
+ return state.context()->staticStrings().lazyEra().string();
+ case UDAT_YEAR_FIELD:
+ case UDAT_YEAR_WOY_FIELD:
+ case UDAT_EXTENDED_YEAR_FIELD:
+ case UDAT_YEAR_NAME_FIELD:
+ return state.context()->staticStrings().lazyYear().string();
+ case UDAT_MONTH_FIELD:
+ case UDAT_STANDALONE_MONTH_FIELD:
+ return state.context()->staticStrings().lazyMonth().string();
+ case UDAT_DATE_FIELD:
+ case UDAT_JULIAN_DAY_FIELD:
+ return state.context()->staticStrings().lazyDay().string();
+ case UDAT_HOUR_OF_DAY1_FIELD:
+ case UDAT_HOUR_OF_DAY0_FIELD:
+ case UDAT_HOUR1_FIELD:
+ case UDAT_HOUR0_FIELD:
+ return state.context()->staticStrings().lazyHour().string();
+ case UDAT_MINUTE_FIELD:
+ return state.context()->staticStrings().lazyMinute().string();
+ case UDAT_SECOND_FIELD:
+ return state.context()->staticStrings().lazySecond().string();
+ case UDAT_DAY_OF_WEEK_FIELD:
+ case UDAT_STANDALONE_DAY_FIELD:
+ case UDAT_DOW_LOCAL_FIELD:
+ case UDAT_DAY_OF_WEEK_IN_MONTH_FIELD:
+ return state.context()->staticStrings().lazyWeekday().string();
+ case UDAT_AM_PM_FIELD:
+ case UDAT_AM_PM_MIDNIGHT_NOON_FIELD:
+ case UDAT_FLEXIBLE_DAY_PERIOD_FIELD:
+ return state.context()->staticStrings().lazyDayPeriod().string();
+ case UDAT_TIMEZONE_FIELD:
+ return state.context()->staticStrings().lazyTimeZoneName().string();
+ case UDAT_FRACTIONAL_SECOND_FIELD:
+ return state.context()->staticStrings().lazyFractionalSecond().string();
+ default:
+ ASSERT_NOT_REACHED();
+ return String::emptyString;
+ }
+}
- // Let requestedLocales be the result of calling the
- // CanonicalizeLocaleList abstract operation (defined in 9.2.1) with argument locales.
- ValueVector requestedLocales = Intl::canonicalizeLocaleList(state, locales);
+IntlDateTimeFormatObject::IntlDateTimeFormatObject(ExecutionState& state, Value locales, Value options)
+ : IntlDateTimeFormatObject(state, state.context()->globalObject()->intlDateTimeFormatPrototype(), locales, options)
+{
+}
- // Let options be the result of calling the ToDateTimeOptions abstract operation (defined below) with arguments options, "any", and "date".
+IntlDateTimeFormatObject::IntlDateTimeFormatObject(ExecutionState& state, Object* proto, Value locales, Value options)
+ : Object(state, proto)
+ , m_locale(String::emptyString)
+ , m_calendar(String::emptyString)
+ , m_numberingSystem(String::emptyString)
+ , m_timeZone(String::emptyString)
+{
+ // Let requestedLocales be ? CanonicalizeLocaleList(locales).
+ ValueVector requestedLocales = Intl::canonicalizeLocaleList(state, locales);
+ // Let options be ? ToDateTimeOptions(options, "any", "date").
options = toDateTimeOptions(state, options, state.context()->staticStrings().lazyAny().string(), state.context()->staticStrings().lazyDate().string());
-
// Let opt be a new Record.
StringMap opt;
- // Let matcher be the result of calling the GetOption abstract operation (defined in 9.2.9) with arguments options,
- // "localeMatcher", "string", a List containing the two String values "lookup" and "best fit", and "best fit".
+ // Let matcher be ? GetOption(options, "localeMatcher", "string", « "lookup", "best fit" », "best fit").
+ // Set opt.[[localeMatcher]] to matcher.
Value matcherValues[2] = { state.context()->staticStrings().lazyLookup().string(), state.context()->staticStrings().lazyBestFit().string() };
Value matcher = Intl::getOption(state, options.asObject(), state.context()->staticStrings().lazyLocaleMatcher().string(), Intl::StringValue, matcherValues, 2, matcherValues[1]);
- // Set opt.[[localeMatcher]] to matcher.
- opt.insert(std::make_pair("localeMatcher", matcher.toString(state)));
-
// Let calendar be ? GetOption(options, "calendar", "string", undefined, undefined).
Value calendar = Intl::getOption(state, options.asObject(), state.context()->staticStrings().calendar.string(), Intl::StringValue, nullptr, 0, Value());
// If calendar is not undefined, then
ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "The calendar value you gave is not valid");
}
}
+
// Set opt.[[ca]] to calendar.
if (!calendar.isUndefined()) {
opt.insert(std::make_pair("ca", calendar.toString(state)));
}
+
// Let numberingSystem be ? GetOption(options, "numberingSystem", "string", undefined, undefined).
Value numberingSystem = Intl::getOption(state, options.asObject(), state.context()->staticStrings().numberingSystem.string(), Intl::StringValue, nullptr, 0, Value());
// If numberingSystem is not undefined, then
opt.insert(std::make_pair("hc", hourCycle.toString(state)));
}
- // Let DateTimeFormat be the standard built-in object that is the initial value of Intl.DateTimeFormat.
- // Let localeData be the value of the [[localeData]] internal property of DateTimeFormat.
+ // Let localeData be %DateTimeFormat%.[[LocaleData]].
const auto& availableLocales = state.context()->vmInstance()->intlDateTimeFormatAvailableLocales();
-
- // Let r be the result of calling the ResolveLocale abstract operation (defined in 9.2.5) with the
- // [[availableLocales]] internal property of DateTimeFormat, requestedLocales, opt, the [[relevantExtensionKeys]] internal property of DateTimeFormat, and localeData.
+ // Let r be ResolveLocale(%DateTimeFormat%.[[AvailableLocales]], requestedLocales, opt, %DateTimeFormat%.[[RelevantExtensionKeys]], localeData).
StringMap r = Intl::resolveLocale(state, availableLocales, requestedLocales, opt, intlDateTimeFormatRelevantExtensionKeys, intlDateTimeFormatRelevantExtensionKeysLength, localeDataDateTimeFormat);
// The resolved locale doesn't include a hc Unicode extension value if the hour12 or hourCycle option is also present.
iter->second = Intl::canonicalizeLanguageTag(locale->toNonGCUTF8StringData(), "hc").canonicalizedTag.value();
}
- // Set the [[locale]] internal property of dateTimeFormat to the value of r.[[locale]].
- dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazySmallLetterLocale()), r.at("locale"), dateTimeFormat->internalSlot());
- // Set the [[calendar]] internal property of dateTimeFormat to the value of r.[[ca]].
- dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().calendar), r.at("ca"), dateTimeFormat->internalSlot());
- // Set dateTimeFormat.[[hourCycle]] to r.[[hc]].
- dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().hourCycle), r.at("hc"), dateTimeFormat->internalSlot());
- // Set the [[numberingSystem]] internal property of dateTimeFormat to the value of r.[[nu]].
- dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().numberingSystem), r.at("nu"), dateTimeFormat->internalSlot());
-
- // Let dataLocale be the value of r.[[dataLocale]].
+ // Set dateTimeFormat.[f[Locale]] to r.[[locale]].
+ m_locale = r.at("locale");
+ // Let calendar be r.[[ca]].
+ calendar = r.at("ca");
+ // Set dateTimeFormat.[[Calendar]] to calendar.
+ m_calendar = calendar.asString();
+ // Set dateTimeFormat.[[HourCycle]] to r.[[hc]].
+ m_hourCycle = r.at("hc");
+ // Set dateTimeFormat.[[NumberingSystem]] to r.[[nu]].
+ m_numberingSystem = r.at("nu");
+
+ // Let dataLocale be r.[[dataLocale]].
Value dataLocale = r.at("dataLocale");
-
- // Always use ICU date format generator, rather than our own pattern list and matcher.
- UErrorCode status = U_ZERO_ERROR;
- LocalResourcePointer<UDateTimePatternGenerator> generator(udatpg_open(dataLocale.toString(state)->toUTF8StringData().data(), &status),
- [](UDateTimePatternGenerator* d) { udatpg_close(d); });
- if (U_FAILURE(status)) {
- ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "failed to initialize DateTimeFormat");
- return;
- }
-
- // Let tz be the result of calling the [[Get]] internal method of options with argument "timeZone".
- Value tz = options.asObject()->get(state, ObjectPropertyName(state.context()->staticStrings().lazyTimeZone())).value(state, options.asObject());
-
- // If tz is not undefined, then
- if (!tz.isUndefined()) {
- // Let tz be ToString(tz).
- String* tzString = tz.toString(state);
- // Convert tz to upper case as described in 6.1.
- // NOTE: If an implementation accepts additional time zone values, as permitted under certain conditions by the Conformance clause,
- // different casing rules apply., If tz is not "UTC", then throw a RangeError exception.
- tz = canonicalizeTimeZoneName(state, tzString);
- tzString = tz.toString(state);
+ std::string dataLocaleWithExtensions = dataLocale.toString(state)->toNonGCUTF8StringData() + "-u-ca-" + m_calendar->toNonGCUTF8StringData() + "-nu-" + m_numberingSystem->toNonGCUTF8StringData();
+
+ // Let timeZone be ? Get(options, "timeZone").
+ Value timeZone = options.asObject()->get(state, state.context()->staticStrings().lazyTimeZone()).value(state, options.asObject());
+ // If timeZone is undefined, then
+ if (timeZone.isUndefined()) {
+ // Let timeZone be DefaultTimeZone().
+ timeZone = defaultTimeZone(state);
+ } else {
+ // Else,
+ // Let timeZone be ? ToString(timeZone).
+ // If the result of IsValidTimeZoneName(timeZone) is false, then Throw a RangeError exception.
+ // Let timeZone be CanonicalizeTimeZoneName(timeZone).
+ String* tzString = timeZone.toString(state);
+ timeZone = canonicalizeTimeZoneName(state, tzString);
+ tzString = timeZone.toString(state);
if (tzString->length() == 0) {
ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "got invalid timezone value");
}
- } else {
- tz = defaultTimeZone(state);
}
- // Set the [[timeZone]] internal property of dateTimeFormat to tz.
- dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyTimeZone()), tz, dateTimeFormat->internalSlot());
+
+ // Set dateTimeFormat.[[TimeZone]] to timeZone.
+ if (!timeZone.isUndefined()) {
+ m_timeZone = timeZone.asString();
+ }
// Let opt be a new Record.
opt.clear();
- // Table 3 – Components of date and time formats
- // Property Values
- // weekday "narrow", "short", "long"
- // era "narrow", "short", "long"
- // year "2-digit", "numeric"
- // month "2-digit", "numeric", "narrow", "short", "long"
- // day "2-digit", "numeric"
- // hour "2-digit", "numeric"
- // minute "2-digit", "numeric"
- // second "2-digit", "numeric"
- // timeZoneName "short", "long"
-
- // For each row of Table 3, except the header row, do:
- std::function<void(String * prop, Value * values, size_t valuesSize)> doTable3 = [&](String* prop, Value* values, size_t valuesSize) {
- // Let prop be the name given in the Property column of the row.
- // Let value be the result of calling the GetOption abstract operation, passing as argument options, the name given in the Property column of the row,
- // "string", a List containing the strings given in the Values column of the row, and undefined.
+ // Table 4: Components of date and time formats
+ // [[Weekday]] "weekday" "narrow", "short", "long"
+ // [[Era]] "era" "narrow", "short", "long"
+ // [[Year]] "year" "2-digit", "numeric"
+ // [[Month]] "month" "2-digit", "numeric", "narrow", "short", "long"
+ // [[Day]] "day" "2-digit", "numeric"
+ // [[DayPeriod]] "dayPeriod" "narrow", "short", "long"
+ // [[Hour]] "hour" "2-digit", "numeric"
+ // [[Minute]] "minute" "2-digit", "numeric"
+ // [[Second]] "second" "2-digit", "numeric"
+ // [[FractionalSecondDigits]] "fractionalSecondDigits" 1𝔽, 2𝔽, 3𝔽
+ // [[TimeZoneName]] "timeZoneName" "short", "long"
+
+ std::function<void(String * prop, Value * values, size_t valuesSize)> doTable4 = [&](String* prop, Value* values, size_t valuesSize) {
Value value = Intl::getOption(state, options.asObject(), prop, Intl::StringValue, values, valuesSize, Value());
// Set opt.[[<prop>]] to value.
if (!value.isUndefined()) {
opt.insert(std::make_pair(prop->toNonGCUTF8StringData(), value.toString(state)));
}
};
-
StringBuilder skeletonBuilder;
+ // For each row of Table 4, except the header row, in table order, do
+ // Let prop be the name given in the Property column of the row.
+ // If prop is "fractionalSecondDigits", then
+ // Let value be ? GetNumberOption(options, "fractionalSecondDigits", 1, 3, undefined).
+ // Else,
+ // Let value be ? GetOption(options, prop, "string", « the strings given in the Values column of the row », undefined).
+ // Set opt.[[<prop>]] to value.
+
Value narrowShortLongValues[3] = { state.context()->staticStrings().lazyNarrow().string(), state.context()->staticStrings().lazyShort().string(), state.context()->staticStrings().lazyLong().string() };
- doTable3(state.context()->staticStrings().lazyWeekday().string(), narrowShortLongValues, 3);
+ doTable4(state.context()->staticStrings().lazyWeekday().string(), narrowShortLongValues, 3);
String* ret = opt.at("weekday");
skeletonBuilder.appendString("EEEE");
}
- doTable3(state.context()->staticStrings().lazyEra().string(), narrowShortLongValues, 3);
+ doTable4(state.context()->staticStrings().lazyEra().string(), narrowShortLongValues, 3);
ret = opt.at("era");
if (ret->equals("narrow")) {
}
Value twoDightNumericValues[2] = { state.context()->staticStrings().lazyTwoDigit().string(), state.context()->staticStrings().numeric.string() };
- doTable3(state.context()->staticStrings().lazyYear().string(), twoDightNumericValues, 2);
+ doTable4(state.context()->staticStrings().lazyYear().string(), twoDightNumericValues, 2);
ret = opt.at("year");
if (ret->equals("2-digit")) {
}
Value allValues[5] = { state.context()->staticStrings().lazyTwoDigit().string(), state.context()->staticStrings().numeric.string(), state.context()->staticStrings().lazyNarrow().string(), state.context()->staticStrings().lazyShort().string(), state.context()->staticStrings().lazyLong().string() };
- doTable3(state.context()->staticStrings().lazyMonth().string(), allValues, 5);
+ doTable4(state.context()->staticStrings().lazyMonth().string(), allValues, 5);
ret = opt.at("month");
if (ret->equals("2-digit")) {
skeletonBuilder.appendString("MMMM");
}
- doTable3(state.context()->staticStrings().lazyDay().string(), twoDightNumericValues, 2);
+ doTable4(state.context()->staticStrings().lazyDay().string(), twoDightNumericValues, 2);
ret = opt.at("day");
if (ret->equals("2-digit")) {
skeletonBuilder.appendString("d");
}
- doTable3(state.context()->staticStrings().lazyHour().string(), twoDightNumericValues, 2);
+ doTable4(state.context()->staticStrings().lazyDayPeriod().string(), narrowShortLongValues, 3);
+ String* dayPeriodString = opt.at("dayPeriod");
+
+ doTable4(state.context()->staticStrings().lazyHour().string(), twoDightNumericValues, 2);
String* hour = ret = opt.at("hour");
Value hr12Value = hour12;
skeletonBuilder.appendChar('H');
}
- doTable3(state.context()->staticStrings().lazyMinute().string(), twoDightNumericValues, 2);
+ // dayPeriod must be set after setting hour.
+ // https://unicode-org.atlassian.net/browse/ICU-20731
+ if (dayPeriodString->equals("narrow")) {
+ skeletonBuilder.appendString("BBBBB");
+ } else if (dayPeriodString->equals("short")) {
+ skeletonBuilder.appendString("B");
+ } else if (dayPeriodString->equals("long")) {
+ skeletonBuilder.appendString("BBBB");
+ }
+
+ doTable4(state.context()->staticStrings().lazyMinute().string(), twoDightNumericValues, 2);
ret = opt.at("minute");
if (ret->equals("2-digit")) {
skeletonBuilder.appendString("m");
}
- doTable3(state.context()->staticStrings().lazySecond().string(), twoDightNumericValues, 2);
+ doTable4(state.context()->staticStrings().lazySecond().string(), twoDightNumericValues, 2);
ret = opt.at("second");
if (ret->equals("2-digit")) {
skeletonBuilder.appendString("s");
}
+ Value fractionalSecondDigits = Intl::getNumberOption(state, options.asObject(), state.context()->staticStrings().lazyFractionalSecondDigits().string(), 1, 3, Value());
+ if (!fractionalSecondDigits.isUndefined()) {
+ for (double i = 0; i < fractionalSecondDigits.asNumber(); i++) {
+ skeletonBuilder.appendString("S");
+ }
+ opt.insert(std::make_pair("fractionalSecondDigits", fractionalSecondDigits.toString(state)));
+ }
+
Value shortLongValues[2] = { state.context()->staticStrings().lazyShort().string(), state.context()->staticStrings().lazyLong().string() };
- doTable3(state.context()->staticStrings().lazyTimeZoneName().string(), shortLongValues, 2);
+ doTable4(state.context()->staticStrings().lazyTimeZoneName().string(), shortLongValues, 2);
ret = opt.at("timeZoneName");
if (ret->equals("short")) {
skeletonBuilder.appendString("zzzz");
}
- // Let dataLocaleData be the result of calling the [[Get]] internal method of localeData with argument dataLocale.
- // Let formats be the result of calling the [[Get]] internal method of dataLocaleData with argument "formats".
- // Let matcher be the result of calling the GetOption abstract operation with arguments options,
- // "formatMatcher", "string", a List containing the two String values "basic" and "best fit", and "best fit".
- Value formatMatcherValues[2] = { state.context()->staticStrings().lazyBasic().string(), state.context()->staticStrings().lazyBestFit().string() };
- matcher = Intl::getOption(state, options.asObject(), state.context()->staticStrings().lazyFormatMatcher().string(), Intl::StringValue, formatMatcherValues, 2, formatMatcherValues[1]);
+ // Let dataLocaleData be localeData.[[<dataLocale>]].
+
+ matcherValues[0] = state.context()->staticStrings().lazyBasic().string();
+ matcher = Intl::getOption(state, options.asObject(), state.context()->staticStrings().lazyFormatMatcher().string(), Intl::StringValue, matcherValues, 2, matcherValues[1]);
+
+ // Let dateStyle be ? GetOption(options, "dateStyle", "string", « "full", "long", "medium", "short" », undefined).
+ // Set dateTimeFormat.[[DateStyle]] to dateStyle.
+ Value dateTimeStyleValues[4] = { state.context()->staticStrings().lazyFull().string(), state.context()->staticStrings().lazyLong().string(),
+ state.context()->staticStrings().lazyMedium().string(), state.context()->staticStrings().lazyShort().string() };
+ Value dateStyle = Intl::getOption(state, options.asObject(), state.context()->staticStrings().lazyDateStyle().string(), Intl::StringValue, dateTimeStyleValues, 4, Value());
+ m_dateStyle = dateStyle;
+ // Let timeStyle be ? GetOption(options, "timeStyle", "string", « "full", "long", "medium", "short" », undefined).
+ Value timeStyle = Intl::getOption(state, options.asObject(), state.context()->staticStrings().lazyTimeStyle().string(), Intl::StringValue, dateTimeStyleValues, 4, Value());
+ // Set dateTimeFormat.[[TimeStyle]] to timeStyle.
+ m_timeStyle = timeStyle;
+
+ UErrorCode status = U_ZERO_ERROR;
+ UTF16StringData skeleton;
+ UTF16StringDataNonGCStd patternBuffer;
+
+ LocalResourcePointer<UDateTimePatternGenerator> generator(udatpg_open(dataLocale.toString(state)->toUTF8StringData().data(), &status),
+ [](UDateTimePatternGenerator* d) { udatpg_close(d); });
+ if (U_FAILURE(status)) {
+ ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "failed to initialize DateTimeFormat");
+ return;
+ }
+
+ // If dateStyle is not undefined or timeStyle is not undefined, then
+ if (!dateStyle.isUndefined() || !timeStyle.isUndefined()) {
+ // For each row in Table 4, except the header row, do
+ // Let prop be the name given in the Property column of the row.
+ // Let p be opt.[[<prop>]].
+ // If p is not undefined, then Throw a TypeError exception.
+ auto iter = opt.begin();
+ while (iter != opt.end()) {
+ if (iter->second->length()) {
+ ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "dateStyle and timeStyle may not be used with other DateTimeFormat options");
+ }
+ iter++;
+ }
+ // Let styles be dataLocaleData.[[styles]].[[<calendar>]].
+ // Let bestFormat be DateTimeStyleFormat(dateStyle, timeStyle, styles).
+
+ auto convertFormatStyle = [](Value s) -> UDateFormatStyle {
+ if (s.isString()) {
+ String* style = s.asString();
+ if (style->equals("full")) {
+ return UDAT_FULL;
+ } else if (style->equals("long")) {
+ return UDAT_LONG;
+ } else if (style->equals("medium")) {
+ return UDAT_MEDIUM;
+ } else if (style->equals("short")) {
+ return UDAT_SHORT;
+ }
+ }
+ return UDAT_NONE;
+ };
+
+ UErrorCode status = U_ZERO_ERROR;
+ LocalResourcePointer<UDateFormat> dateFormatFromStyle(
+ udat_open(convertFormatStyle(m_timeStyle), convertFormatStyle(m_dateStyle), dataLocaleWithExtensions.data(), m_timeZone->toUTF16StringData().data(), m_timeZone->length(), nullptr, -1, &status),
+ [](UDateFormat* fmt) { udat_close(fmt); });
+
+ if (U_FAILURE(status)) {
+ ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "failed to initialize DateTimeFormat");
+ return;
+ }
+
+ patternBuffer.resize(defaultStringBufferSize);
+ status = U_ZERO_ERROR;
+ auto patternLength = udat_toPattern(dateFormatFromStyle.get(), false, (UChar*)patternBuffer.data(), patternBuffer.size(), &status);
+ patternBuffer.resize(patternLength);
+ if (status == U_BUFFER_OVERFLOW_ERROR) {
+ status = U_ZERO_ERROR;
+ patternBuffer.resize(patternLength);
+ udat_toPattern(dateFormatFromStyle.get(), false, (UChar*)patternBuffer.data(), patternBuffer.size(), &status);
+ }
+ if (U_FAILURE(status)) {
+ ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "failed to initialize DateTimeFormat");
+ return;
+ }
+
+ // It is possible that timeStyle includes dayPeriod, which is sensitive to hour-cycle.
+ // If dayPeriod is included, just replacing hour based on hourCycle / hour12 produces strange results.
+ // Let's consider about the example. The formatted result looks like "02:12:47 PM Coordinated Universal Time"
+ // If we simply replace 02 to 14, this becomes "14:12:47 PM Coordinated Universal Time", this looks strange since "PM" is unnecessary!
+ //
+ // If the generated pattern's hour12 does not match against the option's one, we retrieve skeleton from the pattern, enforcing hour-cycle,
+ // and re-generating the best pattern from the modified skeleton. ICU will look into the generated skeleton, and pick the best format for the request.
+ // We do not care about h11 vs. h12 and h23 vs. h24 difference here since this will be later adjusted by replaceHourCycleInPattern.
+ //
+ // test262/test/intl402/DateTimeFormat/prototype/format/timedatestyle-en.js includes the test for this behavior.
+ if (!Value(m_timeStyle).isUndefined() && (!hourCycle.isUndefinedOrNull() || !hour12.isUndefined())) {
+ bool isHour12 = hourCycle.isString() && (hourCycle.asString()->equals("h11") || hourCycle.asString()->equals("h12"));
+ bool specifiedHour12 = false;
+ // If hour12 is specified, we prefer it and ignore hourCycle.
+ if (!hour12.isUndefined()) {
+ specifiedHour12 = hour12.asBoolean();
+ } else {
+ specifiedHour12 = isHour12;
+ }
+ std::string extractedHourCycle = readHourCycleFromPattern(patternBuffer);
+ if (extractedHourCycle.size() && (extractedHourCycle == "h11" || extractedHourCycle == "h12") != specifiedHour12) {
+ UTF16StringDataNonGCStd skeleton;
+ skeleton.resize(defaultStringBufferSize);
+ status = U_ZERO_ERROR;
+ auto resultLength = udatpg_getSkeleton(nullptr, (UChar*)patternBuffer.data(), patternBuffer.size(), (UChar*)skeleton.data(), skeleton.size(), &status);
+ skeleton.resize(resultLength);
+ if (status == U_BUFFER_OVERFLOW_ERROR) {
+ status = U_ZERO_ERROR;
+ skeleton.resize(resultLength);
+ udatpg_getSkeleton(nullptr, (UChar*)patternBuffer.data(), patternBuffer.size(), (UChar*)skeleton.data(), skeleton.size(), &status);
+ }
+ if (U_FAILURE(status)) {
+ ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "failed to initialize DateTimeFormat");
+ return;
+ }
+
+ for (size_t i = 0; i < skeleton.size(); i++) {
+ auto ch = skeleton[i];
+ if (ch == 'h' || ch == 'H' || ch == 'j') {
+ if (specifiedHour12) {
+ skeleton[i] = 'H';
+ } else {
+ skeleton[i] = 'h';
+ }
+ }
+ }
- // Always use ICU date format generator, rather than our own pattern list and matcher.
- // Covers steps 28-36.
- String* skeleton = skeletonBuilder.finalize();
- UTF16StringData skeletonUTF16String = skeleton->toUTF16StringData();
+ patternBuffer.resize(defaultStringBufferSize);
+ status = U_ZERO_ERROR;
+ auto patternLength = udatpg_getBestPatternWithOptions(generator.get(), (UChar*)skeleton.data(), skeleton.length(), UDATPG_MATCH_HOUR_FIELD_LENGTH, (UChar*)patternBuffer.data(), patternBuffer.size(), &status);
+ patternBuffer.resize(patternLength);
+ if (status == U_BUFFER_OVERFLOW_ERROR) {
+ status = U_ZERO_ERROR;
+ patternBuffer.resize(patternLength);
+ udatpg_getBestPatternWithOptions(generator.get(), (UChar*)skeleton.data(), skeleton.length(), UDATPG_MATCH_HOUR_FIELD_LENGTH, (UChar*)patternBuffer.data(), patternBuffer.size(), &status);
+ }
+ if (U_FAILURE(status)) {
+ ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "failed to initialize DateTimeFormat");
+ return;
+ }
+ }
+ }
+
+ } else {
+ // Else,
+ // Let formats be dataLocaleData.[[formats]].[[<calendar>]].
+ // If matcher is "basic", then
+ // Let bestFormat be BasicFormatMatcher(opt, formats).
+ // Else,
+ // Let bestFormat be BestFitFormatMatcher(opt, formats).
+ skeleton = skeletonBuilder.finalize()->toUTF16StringData();
+ patternBuffer.resize(defaultStringBufferSize);
+ status = U_ZERO_ERROR;
+ auto patternLength = udatpg_getBestPatternWithOptions(generator.get(), (UChar*)skeleton.data(), skeleton.length(), UDATPG_MATCH_HOUR_FIELD_LENGTH, (UChar*)patternBuffer.data(), patternBuffer.size(), &status);
+ patternBuffer.resize(patternLength);
+ if (status == U_BUFFER_OVERFLOW_ERROR) {
+ status = U_ZERO_ERROR;
+ patternBuffer.resize(patternLength);
+ udatpg_getBestPatternWithOptions(generator.get(), (UChar*)skeleton.data(), skeleton.length(), UDATPG_MATCH_HOUR_FIELD_LENGTH, (UChar*)patternBuffer.data(), patternBuffer.size(), &status);
+ }
+ if (U_FAILURE(status)) {
+ ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "failed to initialize DateTimeFormat");
+ return;
+ }
+ }
// If dateTimeFormat.[[Hour]] is not undefined, then
bool hasHourOption = hour->length();
if (hasHourOption) {
// Let hcDefault be dataLocaleData.[[hourCycle]].
UTF16StringDataNonGCStd patternBuffer;
- patternBuffer.resize(32);
+ patternBuffer.resize(defaultStringBufferSize);
status = U_ZERO_ERROR;
auto patternLength = udatpg_getBestPattern(generator.get(), u"jjmm", 4, (UChar*)patternBuffer.data(), patternBuffer.length(), &status);
patternBuffer.resize(patternLength);
ASSERT(U_SUCCESS(status));
auto hcDefault = readHourCycleFromPattern(patternBuffer);
// Let hc be dateTimeFormat.[[HourCycle]].
- auto hc = dateTimeFormat->internalSlot()->get(state, ObjectPropertyName(state.context()->staticStrings().hourCycle)).value(state, dateTimeFormat->internalSlot()).asString();
+ auto hc = m_hourCycle;
// If hc is null, then
- if (!hc->length()) {
+ if (Value(hc).isUndefined()) {
// Set hc to hcDefault.
hc = String::fromUTF8(hcDefault.data(), hcDefault.size());
}
}
// Let dateTimeFormat.[[HourCycle]] to hc.
- dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().hourCycle), Value(hc), dateTimeFormat->internalSlot());
+ // If dateTimeformat.[[HourCycle]] is "h11" or "h12", then
+ // Let pattern be bestFormat.[[pattern12]].
+ // Let rangePatterns be bestFormat.[[rangePatterns12]].
+ // Else,
+ // Let pattern be bestFormat.[[pattern]].
+ // Let rangePatterns be bestFormat.[[rangePatterns]].
+ m_hourCycle = hc;
} else {
// Set dateTimeFormat.[[HourCycle]] to undefined.
- dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().hourCycle), Value(), dateTimeFormat->internalSlot());
// Let pattern be bestFormat.[[pattern]].
+ // Let rangePatterns be bestFormat.[[rangePatterns]].
+ m_hourCycle = Value();
}
- UTF16StringDataNonGCStd patternBuffer;
- patternBuffer.resize(32);
- status = U_ZERO_ERROR;
- auto patternLength = udatpg_getBestPatternWithOptions(generator.get(), (UChar*)skeletonUTF16String.data(), skeletonUTF16String.length(), UDATPG_MATCH_HOUR_FIELD_LENGTH, (UChar*)patternBuffer.data(), patternBuffer.size(), &status);
- patternBuffer.resize(patternLength);
- if (status == U_BUFFER_OVERFLOW_ERROR) {
- status = U_ZERO_ERROR;
- patternBuffer.resize(patternLength);
- udatpg_getBestPatternWithOptions(generator.get(), (UChar*)skeletonUTF16String.data(), skeletonUTF16String.length(), UDATPG_MATCH_HOUR_FIELD_LENGTH, (UChar*)patternBuffer.data(), patternLength, &status);
- }
- if (U_FAILURE(status)) {
- ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "failed to initialize DateTimeFormat");
- return;
- }
+ // Set dateTimeFormat.[[Pattern]] to pattern.
+ // Set dateTimeFormat.[[RangePatterns]] to rangePatterns.
+ // Return dateTimeFormat.
- Value hc = dateTimeFormat->internalSlot()->get(state, ObjectPropertyName(state.context()->staticStrings().hourCycle)).value(state, dateTimeFormat->internalSlot());
- if (!hc.isUndefined() && hc.asString()->length()) {
- patternBuffer = updateHourCycleInPatternDueToHourCycle(patternBuffer, hc.asString());
+ // After generating pattern from skeleton, we need to change h11 vs. h12 and h23 vs. h24 if hourCycle is specified.
+ if (!Value(m_hourCycle).isUndefined()) {
+ patternBuffer = updateHourCycleInPatternDueToHourCycle(patternBuffer, Value(m_hourCycle).asString());
}
+ // For each row in Table 4, except the header row, in table order, do
+ // Let prop be the name given in the Property column of the row.
+ // If bestFormat has a field [[<prop>]], then
+ // Let p be bestFormat.[[<prop>]].
+ // Set dateTimeFormat's internal slot whose name is the Internal Slot column of the row to p.
bool inQuote = false;
unsigned length = patternBuffer.length();
for (unsigned i = 0; i < length; ++i) {
if (hasHourOption && !inQuote) {
if (currentCharacter == 'h' || currentCharacter == 'K') {
- dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyHour12()), Value(true), dateTimeFormat->internalSlot());
+ m_hour12 = Value(true);
} else if (currentCharacter == 'H' || currentCharacter == 'k') {
- dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyHour12()), Value(false), dateTimeFormat->internalSlot());
+ m_hour12 = Value(false);
}
}
switch (currentCharacter) {
case 'G':
- if (count <= 3)
- dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyEra()), Value(state.context()->staticStrings().lazyShort().string()), dateTimeFormat->internalSlot());
- else if (count == 4)
- dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyEra()), Value(state.context()->staticStrings().lazyLong().string()), dateTimeFormat->internalSlot());
- else if (count == 5)
- dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyEra()), Value(state.context()->staticStrings().lazyNarrow().string()), dateTimeFormat->internalSlot());
+ if (count <= 3) {
+ m_era = state.context()->staticStrings().lazyShort().string();
+ } else if (count == 4) {
+ m_era = state.context()->staticStrings().lazyLong().string();
+ } else if (count == 5) {
+ m_era = state.context()->staticStrings().lazyNarrow().string();
+ }
break;
case 'y':
- if (count == 1)
- dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyYear()), Value(state.context()->staticStrings().numeric.string()), dateTimeFormat->internalSlot());
- else if (count == 2)
- dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyYear()), Value(state.context()->staticStrings().lazyTwoDigit().string()), dateTimeFormat->internalSlot());
+ if (count == 1) {
+ m_year = state.context()->staticStrings().numeric.string();
+ } else if (count == 2) {
+ m_year = state.context()->staticStrings().lazyTwoDigit().string();
+ }
break;
case 'M':
case 'L':
- if (count == 1)
- dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyMonth()), Value(state.context()->staticStrings().numeric.string()), dateTimeFormat->internalSlot());
- else if (count == 2)
- dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyMonth()), Value(state.context()->staticStrings().lazyTwoDigit().string()), dateTimeFormat->internalSlot());
- else if (count == 3)
- dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyMonth()), Value(state.context()->staticStrings().lazyShort().string()), dateTimeFormat->internalSlot());
- else if (count == 4)
- dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyMonth()), Value(state.context()->staticStrings().lazyLong().string()), dateTimeFormat->internalSlot());
- else if (count == 5)
- dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyMonth()), Value(state.context()->staticStrings().lazyNarrow().string()), dateTimeFormat->internalSlot());
+ if (count == 1) {
+ m_month = state.context()->staticStrings().numeric.string();
+ } else if (count == 2) {
+ m_month = state.context()->staticStrings().lazyTwoDigit().string();
+ } else if (count == 3) {
+ m_month = state.context()->staticStrings().lazyShort().string();
+ } else if (count == 4) {
+ m_month = state.context()->staticStrings().lazyLong().string();
+ } else if (count == 5) {
+ m_month = state.context()->staticStrings().lazyNarrow().string();
+ }
break;
case 'E':
case 'e':
case 'c':
- if (count <= 3)
- dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyWeekday()), Value(state.context()->staticStrings().lazyShort().string()), dateTimeFormat->internalSlot());
- else if (count == 4)
- dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyWeekday()), Value(state.context()->staticStrings().lazyLong().string()), dateTimeFormat->internalSlot());
- else if (count == 5)
- dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyWeekday()), Value(state.context()->staticStrings().lazyNarrow().string()), dateTimeFormat->internalSlot());
+ if (count <= 3) {
+ m_weekday = state.context()->staticStrings().lazyShort().string();
+ } else if (count == 4) {
+ m_weekday = state.context()->staticStrings().lazyLong().string();
+ } else if (count == 5) {
+ m_weekday = state.context()->staticStrings().lazyNarrow().string();
+ }
break;
case 'd':
- if (count == 1)
- dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyDay()), Value(state.context()->staticStrings().numeric.string()), dateTimeFormat->internalSlot());
- else if (count == 2)
- dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyDay()), Value(state.context()->staticStrings().lazyTwoDigit().string()), dateTimeFormat->internalSlot());
+ if (count == 1) {
+ m_day = state.context()->staticStrings().numeric.string();
+ } else if (count == 2) {
+ m_day = state.context()->staticStrings().lazyTwoDigit().string();
+ }
+ break;
+ case 'a':
+ case 'b':
+ case 'B':
+ if (count <= 3) {
+ m_dayPeriod = state.context()->staticStrings().lazyShort().string();
+ } else if (count == 4) {
+ m_dayPeriod = state.context()->staticStrings().lazyLong().string();
+ } else if (count == 5) {
+ m_dayPeriod = state.context()->staticStrings().lazyNarrow().string();
+ }
break;
case 'h':
case 'H':
case 'k':
case 'K':
- if (count == 1)
- dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyHour()), Value(state.context()->staticStrings().numeric.string()), dateTimeFormat->internalSlot());
- else if (count == 2)
- dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyHour()), Value(state.context()->staticStrings().lazyTwoDigit().string()), dateTimeFormat->internalSlot());
+ if (count == 1) {
+ m_hour = state.context()->staticStrings().numeric.string();
+ } else if (count == 2) {
+ m_hour = state.context()->staticStrings().lazyTwoDigit().string();
+ }
break;
case 'm':
- if (count == 1)
- dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyMinute()), Value(state.context()->staticStrings().numeric.string()), dateTimeFormat->internalSlot());
- else if (count == 2)
- dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyMinute()), Value(state.context()->staticStrings().lazyTwoDigit().string()), dateTimeFormat->internalSlot());
+ if (count == 1) {
+ m_minute = state.context()->staticStrings().numeric.string();
+ } else if (count == 2) {
+ m_minute = state.context()->staticStrings().lazyTwoDigit().string();
+ }
break;
case 's':
- if (count == 1)
- dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazySecond()), Value(state.context()->staticStrings().numeric.string()), dateTimeFormat->internalSlot());
- else if (count == 2)
- dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazySecond()), Value(state.context()->staticStrings().lazyTwoDigit().string()), dateTimeFormat->internalSlot());
+ if (count == 1) {
+ m_second = state.context()->staticStrings().numeric.string();
+ } else if (count == 2) {
+ m_second = state.context()->staticStrings().lazyTwoDigit().string();
+ }
break;
case 'z':
case 'v':
case 'V':
- if (count == 1)
- dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyTimeZoneName()), Value(state.context()->staticStrings().lazyShort().string()), dateTimeFormat->internalSlot());
- else if (count == 4)
- dateTimeFormat->internalSlot()->set(state, ObjectPropertyName(state.context()->staticStrings().lazyTimeZoneName()), Value(state.context()->staticStrings().lazyLong().string()), dateTimeFormat->internalSlot());
+ if (count == 1) {
+ m_timeZoneName = state.context()->staticStrings().lazyShort().string();
+ } else if (count == 4) {
+ m_timeZoneName = state.context()->staticStrings().lazyLong().string();
+ }
+ break;
+ case 'S':
+ m_fractionalSecondDigits = Value(count);
break;
}
}
status = U_ZERO_ERROR;
- UTF16StringData timeZoneView = dateTimeFormat->internalSlot()->get(state, ObjectPropertyName(state.context()->staticStrings().lazyTimeZone())).value(state, dateTimeFormat->internalSlot()).toString(state)->toUTF16StringData();
- UTF8StringData localeStringView = r.at("locale")->toUTF8StringData();
- UDateFormat* icuDateFormat = udat_open(UDAT_PATTERN, UDAT_PATTERN, localeStringView.data(), (UChar*)timeZoneView.data(), timeZoneView.length(), (UChar*)patternBuffer.data(), patternBuffer.length(), &status);
+ UTF16StringData timeZoneView = m_timeZone->toUTF16StringData();
+ m_icuDateFormat = udat_open(UDAT_PATTERN, UDAT_PATTERN, dataLocaleWithExtensions.data(), (UChar*)timeZoneView.data(), timeZoneView.length(), (UChar*)patternBuffer.data(), patternBuffer.length(), &status);
if (U_FAILURE(status)) {
ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "failed to initialize DateTimeFormat");
return;
}
- dateTimeFormat->internalSlot()->setExtraData(icuDateFormat);
-
- dateTimeFormat->internalSlot()->addFinalizer([](Object* obj, void* data) {
- Object* self = (Object*)obj;
- udat_close((UDateFormat*)self->extraData());
+ addFinalizer([](Object* obj, void* data) {
+ IntlDateTimeFormatObject* self = (IntlDateTimeFormatObject*)obj;
+ udat_close(self->m_icuDateFormat);
},
- nullptr);
-
- // Set dateTimeFormat.[[boundFormat]] to undefined.
- // Set dateTimeFormat.[[initializedDateTimeFormat]] to true.
- dateTimeFormat->internalSlot()->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().lazyInitializedDateTimeFormat()), ObjectPropertyDescriptor(Value(true)));
+ nullptr);
status = U_ZERO_ERROR;
- UCalendar* cal = const_cast<UCalendar*>(udat_getCalendar(icuDateFormat));
+ UCalendar* cal = const_cast<UCalendar*>(udat_getCalendar(m_icuDateFormat));
std::string type(ucal_getType(cal, &status));
if (status == U_ZERO_ERROR && std::string("gregorian") == type) {
ucal_setGregorianChange(cal, minECMAScriptTime, &status);
}
- // Return dateTimeFormat.
- return;
}
-UTF16StringDataNonGCStd IntlDateTimeFormat::format(ExecutionState& state, Object* dateTimeFormat, double x)
+UTF16StringDataNonGCStd IntlDateTimeFormatObject::format(ExecutionState& state, double x)
{
// If x is not a finite Number, then throw a RangeError exception.
// If x is NaN, throw a RangeError exception
x = Value(x).toInteger(state);
- UDateFormat* udat = (UDateFormat*)dateTimeFormat->internalSlot()->extraData();
+ UDateFormat* udat = (UDateFormat*)m_icuDateFormat;
// Delegate remaining steps to ICU.
UErrorCode status = U_ZERO_ERROR;
UTF16StringDataNonGCStd result;
- result.resize(32);
+ result.resize(defaultStringBufferSize);
auto resultLength = udat_format(udat, x, (UChar*)result.data(), result.size(), nullptr, &status);
result.resize(resultLength);
return result;
}
-
-static String* icuFieldTypeToPartName(ExecutionState& state, int32_t fieldName)
-{
- if (fieldName == -1) {
- return state.context()->staticStrings().lazyLiteral().string();
- }
-
- switch ((UDateFormatField)fieldName) {
- case UDAT_ERA_FIELD:
- return state.context()->staticStrings().lazyEra().string();
- case UDAT_YEAR_FIELD:
- case UDAT_YEAR_WOY_FIELD:
- case UDAT_EXTENDED_YEAR_FIELD:
- case UDAT_YEAR_NAME_FIELD:
- return state.context()->staticStrings().lazyYear().string();
- case UDAT_MONTH_FIELD:
- case UDAT_STANDALONE_MONTH_FIELD:
- return state.context()->staticStrings().lazyMonth().string();
- case UDAT_DATE_FIELD:
- case UDAT_JULIAN_DAY_FIELD:
- return state.context()->staticStrings().lazyDay().string();
- case UDAT_HOUR_OF_DAY1_FIELD:
- case UDAT_HOUR_OF_DAY0_FIELD:
- case UDAT_HOUR1_FIELD:
- case UDAT_HOUR0_FIELD:
- return state.context()->staticStrings().lazyHour().string();
- case UDAT_MINUTE_FIELD:
- return state.context()->staticStrings().lazyMinute().string();
- case UDAT_SECOND_FIELD:
- return state.context()->staticStrings().lazySecond().string();
- case UDAT_DAY_OF_WEEK_FIELD:
- case UDAT_STANDALONE_DAY_FIELD:
- case UDAT_DOW_LOCAL_FIELD:
- case UDAT_DAY_OF_WEEK_IN_MONTH_FIELD:
- return state.context()->staticStrings().lazyWeekday().string();
- case UDAT_AM_PM_FIELD:
- return state.context()->staticStrings().lazyDayPeriod().string();
- case UDAT_TIMEZONE_FIELD:
- return state.context()->staticStrings().lazyTimeZoneName().string();
- default:
- ASSERT_NOT_REACHED();
- return String::emptyString;
- }
-}
-
-
-ArrayObject* IntlDateTimeFormat::formatToParts(ExecutionState& state, Object* dateTimeFormat, double x)
+ArrayObject* IntlDateTimeFormatObject::formatToParts(ExecutionState& state, double x)
{
// If x is not a finite Number, then throw a RangeError exception.
// If x is NaN, throw a RangeError exception
ArrayObject* result = new ArrayObject(state);
- UDateFormat* udat = (UDateFormat*)dateTimeFormat->internalSlot()->extraData();
+ UDateFormat* udat = (UDateFormat*)m_icuDateFormat;
UErrorCode status = U_ZERO_ERROR;
ASSERT(U_SUCCESS(status));
UTF16StringDataNonGCStd resultString;
- resultString.resize(32);
+ resultString.resize(defaultStringBufferSize);
auto resultLength = udat_formatForFields(udat, x, (UChar*)resultString.data(), resultString.size(), fpositer, &status);
resultString.resize(resultLength);
return result;
}
-Value IntlDateTimeFormat::toDateTimeOptions(ExecutionState& state, Value options, Value required, Value defaults)
+Value IntlDateTimeFormatObject::toDateTimeOptions(ExecutionState& state, Value options, Value required, Value defaults)
{
// If options is undefined, then let options be null, else let options be ToObject(options).
if (options.isUndefined()) {
} else {
options = options.toObject(state);
}
- // Let create be the standard built-in function object defined in ES5, 15.2.3.5.
- // Let options be the result of calling the [[Call]] internal method of create with undefined as the this value
- // and an argument list containing the single item options.
- options = Object::call(state, state.context()->globalObject()->objectCreate(), Value(), 1, &options);
+ // Let options be OrdinaryObjectCreate(options).
+ if (options.isObject()) {
+ Value proto = options;
+ options = new Object(state);
+ options.asObject()->setPrototype(state, proto);
+ } else {
+ options = new Object(state, Object::PrototypeIsNull);
+ }
// Let needDefaults be true.
bool needDefaults = true;
}
// If required is "time" or "any", then
if (required.equalsTo(state, state.context()->staticStrings().lazyTime().string()) || required.equalsTo(state, state.context()->staticStrings().lazyAny().string())) {
- // For each of the property names "hour", "minute", "second":
+ // For each of the property names "dayPeriod", "hour", "minute", "second", "fractionalSecondDigits"
// If the result of calling the [[Get]] internal method of options with the property name is not undefined, then let needDefaults be false.
+ toDateTimeOptionsTest(state, options, state.context()->staticStrings().lazyDayPeriod(), needDefaults);
toDateTimeOptionsTest(state, options, state.context()->staticStrings().lazyHour(), needDefaults);
toDateTimeOptionsTest(state, options, state.context()->staticStrings().lazyMinute(), needDefaults);
toDateTimeOptionsTest(state, options, state.context()->staticStrings().lazySecond(), needDefaults);
+ toDateTimeOptionsTest(state, options, state.context()->staticStrings().lazyFractionalSecondDigits(), needDefaults);
+ }
+
+ // Let dateStyle be ? Get(options, "dateStyle").
+ Value dateStyle = options.asObject()->get(state, state.context()->staticStrings().lazyDateStyle()).value(state, options);
+ // Let timeStyle be ? Get(options, "timeStyle").
+ Value timeStyle = options.asObject()->get(state, state.context()->staticStrings().lazyTimeStyle()).value(state, options);
+ // If dateStyle is not undefined or timeStyle is not undefined, let needDefaults be false.
+ if (!dateStyle.isUndefined() || !timeStyle.isUndefined()) {
+ needDefaults = false;
+ }
+ // If required is "date" and timeStyle is not undefined, then
+ if (required.equalsTo(state, state.context()->staticStrings().lazyDate().string())) {
+ if (!timeStyle.isUndefined()) {
+ // Throw a TypeError exception.
+ ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "The given option value is invalid");
+ }
+ }
+ // If required is "time" and dateStyle is not undefined, then
+ if (required.equalsTo(state, state.context()->staticStrings().lazyTime().string())) {
+ if (!dateStyle.isUndefined()) {
+ // Throw a TypeError exception.
+ ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "The given option value is invalid");
+ }
}
// If needDefaults is true and defaults is either "date" or "all", then
namespace Escargot {
-class IntlDateTimeFormat {
+class IntlDateTimeFormatObject : public Object {
public:
- static Object* create(ExecutionState& state, Context* realm, Value locales, Value options);
- static void initialize(ExecutionState& state, Object* dateTimeFormat, Value locales, Value options);
- static UTF16StringDataNonGCStd format(ExecutionState& state, Object* dateTimeFormat, double x);
- static ArrayObject* formatToParts(ExecutionState& state, Object* dateTimeFormat, double x);
+ IntlDateTimeFormatObject(ExecutionState& state, Value locales, Value options);
+ IntlDateTimeFormatObject(ExecutionState& state, Object* proto, Value locales, Value options);
+
+ virtual bool isIntlDateTimeFormatObject() const override
+ {
+ return true;
+ }
+
+ UTF16StringDataNonGCStd format(ExecutionState& state, double x);
+ ArrayObject* formatToParts(ExecutionState& state, double x);
static Value toDateTimeOptions(ExecutionState& state, Value options, Value required, Value defaults);
+
+ String* locale() const
+ {
+ return m_locale;
+ }
+
+ String* calendar() const
+ {
+ return m_calendar;
+ }
+
+ String* numberingSystem() const
+ {
+ return m_numberingSystem;
+ }
+
+ String* timeZone() const
+ {
+ return m_timeZone;
+ }
+
+ Value hour12() const
+ {
+ return m_hour12;
+ }
+
+ Value era() const
+ {
+ return m_era;
+ }
+
+ Value year() const
+ {
+ return m_year;
+ }
+
+ Value month() const
+ {
+ return m_month;
+ }
+
+ Value weekday() const
+ {
+ return m_weekday;
+ }
+
+ Value day() const
+ {
+ return m_day;
+ }
+
+ Value dayPeriod() const
+ {
+ return m_dayPeriod;
+ }
+
+ Value hour() const
+ {
+ return m_hour;
+ }
+
+ Value hourCycle() const
+ {
+ return m_hourCycle;
+ }
+
+ Value minute() const
+ {
+ return m_minute;
+ }
+
+ Value second() const
+ {
+ return m_second;
+ }
+
+ Value timeZoneName() const
+ {
+ return m_timeZoneName;
+ }
+
+ Value fractionalSecondDigits() const
+ {
+ return m_fractionalSecondDigits;
+ }
+
+ Value dateStyle() const
+ {
+ return m_dateStyle;
+ }
+
+ Value timeStyle() const
+ {
+ return m_timeStyle;
+ }
+
+protected:
+ String* m_locale;
+ String* m_calendar;
+ String* m_numberingSystem;
+ String* m_timeZone;
+
+ EncodedValue m_hour12;
+ EncodedValue m_era;
+ EncodedValue m_year;
+ EncodedValue m_month;
+ EncodedValue m_weekday;
+ EncodedValue m_day;
+ EncodedValue m_dayPeriod;
+ EncodedValue m_hour;
+ EncodedValue m_hourCycle;
+ EncodedValue m_minute;
+ EncodedValue m_second;
+ EncodedValue m_timeZoneName;
+ EncodedValue m_fractionalSecondDigits;
+ EncodedValue m_dateStyle;
+ EncodedValue m_timeStyle;
+
+ UDateFormat* m_icuDateFormat;
};
} // namespace Escargot
}
}
-static double getNumberOption(ExecutionState& state, Object* options, String* property, double minimum, double maximum, double fallback)
-{
- // http://www.ecma-international.org/ecma-402/1.0/index.html#sec-9.2.10
-
- // Let value be the result of calling the [[Get]] internal method of options with argument property.
- Value value = options->get(state, ObjectPropertyName(state, property)).value(state, options);
- // If value is not undefined, then
- if (!value.isUndefined()) {
- // Let value be ToNumber(value).
- double doubleValue = value.toNumber(state);
- // If value is NaN or less than minimum or greater than maximum, throw a RangeError exception.
- if (std::isnan(doubleValue) || doubleValue < minimum || maximum < doubleValue) {
- ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "Got invalid number option value");
- }
- // Return floor(value).
- return floor(doubleValue);
- } else {
- // Else return fallback.
- return fallback;
- }
-}
-
-
Object* IntlNumberFormat::create(ExecutionState& state, Context* realm, Value locales, Value options)
{
Object* numberFormat = new Object(state, realm->globalObject()->intlNumberFormatPrototype());
// Perform ? SetNumberFormatDigitOptions(numberFormat, options, mnfdDefault, mxfdDefault, notation).
// Let mnid be ? GetNumberOption(options, "minimumIntegerDigits,", 1, 21, 1).
- double mnid = getNumberOption(state, options.asObject(), state.context()->staticStrings().lazyMinimumIntegerDigits().string(), 1, 21, 1);
+ double mnid = Intl::getNumberOption(state, options.asObject(), state.context()->staticStrings().lazyMinimumIntegerDigits().string(), 1, 21, 1);
// Let mnfd be ? Get(options, "minimumFractionDigits").
Value mnfd;
auto g = options.asObject()->get(state, ObjectPropertyName(state.context()->staticStrings().lazyMinimumFractionDigits()));
FunctionContextVarMap* m_identifierInfoMap;
TightVector<Optional<ArrayObject*>, GCUtil::gc_malloc_allocator<Optional<ArrayObject*>>> m_taggedTemplateLiteralCache;
AtomicStringTightVector* m_classPrivateNames;
+#ifdef ESCARGOT_DEBUGGER
+ size_t m_debuggerLineStart;
+#endif /* ESCARGOT_DEBUGGER */
InterpretedCodeBlockRareData()
: m_identifierInfoMap(nullptr)
, m_classPrivateNames(nullptr)
+#ifdef ESCARGOT_DEBUGGER
+ , m_debuggerLineStart(SIZE_MAX)
+#endif /* ESCARGOT_DEBUGGER */
{
}
InterpretedCodeBlockRareData(FunctionContextVarMap* map, AtomicStringTightVector* classPrivateNames)
: m_identifierInfoMap(map)
, m_classPrivateNames(classPrivateNames)
+#ifdef ESCARGOT_DEBUGGER
+ , m_debuggerLineStart(SIZE_MAX)
+#endif /* ESCARGOT_DEBUGGER */
{
}
};
, m_rareData(new InterpretedCodeBlockRareData(scopeCtx->m_varNamesMap, scopeCtx->m_classPrivateNames))
{
ASSERT(scopeCtx->m_needRareData);
+#ifdef ESCARGOT_DEBUGGER
+ m_rareData->m_debuggerLineStart = scopeCtx->m_debuggerLineStart;
+#endif /* ESCARGOT_DEBUGGER */
}
InterpretedCodeBlockWithRareData(Context* ctx, Script* script, StringView src, ASTScopeContext* scopeCtx, InterpretedCodeBlock* parentBlock, bool isEvalCode, bool isEvalCodeInFunction)
, m_rareData(new InterpretedCodeBlockRareData(scopeCtx->m_varNamesMap, scopeCtx->m_classPrivateNames))
{
ASSERT(scopeCtx->m_needRareData);
+#ifdef ESCARGOT_DEBUGGER
+ m_rareData->m_debuggerLineStart = scopeCtx->m_debuggerLineStart;
+#endif /* ESCARGOT_DEBUGGER */
}
InterpretedCodeBlockWithRareData(Context* ctx, Script* script)
NodeLOC m_bodyEndLOC;
#endif
+#ifdef ESCARGOT_DEBUGGER
+ // This field is storing line info data for class field initializers
+ size_t m_debuggerLineStart;
+#endif /* ESCARGOT_DEBUGGER */
+
// ASTScopeContext is allocated by ASTAllocator
inline void *operator new(size_t size, ASTAllocator &allocator)
{
#else
, m_bodyEndLOC(SIZE_MAX)
#endif
+#ifdef ESCARGOT_DEBUGGER
+ , m_debuggerLineStart(SIZE_MAX)
+#endif /* ESCARGOT_DEBUGGER */
{
}
};
size_t returnUndefinedTestRegister = newContext.getRegister();
codeBlock->pushCode(LoadLiteral(ByteCodeLOC(m_loc.index), returnUndefinedTestRegister, Value()), &newContext, this);
size_t returnUndefinedCompareJump = codeBlock->currentCodeSize();
- codeBlock->pushCode(JumpIfEqual(ByteCodeLOC(m_loc.index), returnUndefinedTestRegister, returnOrInnerResultRegister, false, true), &newContext, this);
+ codeBlock->pushCode(JumpIfEqual(ByteCodeLOC(m_loc.index), returnUndefinedTestRegister, returnOrInnerResultRegister, false, false), &newContext, this);
newContext.giveUpRegister(); // drop returnUndefinedTestRegister
// Let innerResult be Call(return, iterator, « »).
if (context->m_breakpointContext->m_breakpointLocations.size() == 0) {
ASSERT(context->m_breakpointContext->m_lastBreakpointLineOffset == 0);
ASSERT(context->m_breakpointContext->m_breakpointLocations.size() == 0);
- ExtendedNodeLOC sourceElementStart = context->m_codeBlock->functionStart();
- size_t lastLineOffset = context->calculateBreakpointLineOffset(m_loc.index, sourceElementStart);
- context->insertBreakpointAt(lastLineOffset + sourceElementStart.line, this);
+
+ InterpretedCodeBlock* interpretedCodeBlock = context->m_codeBlock;
+
+ if (interpretedCodeBlock->hasRareData() && interpretedCodeBlock->rareData()->m_debuggerLineStart != SIZE_MAX) {
+ ASSERT(interpretedCodeBlock->isOneExpressionOnlyVirtualArrowFunctionExpression());
+ context->insertBreakpointAt(interpretedCodeBlock->rareData()->m_debuggerLineStart, this);
+ } else {
+ ExtendedNodeLOC sourceElementStart = context->m_codeBlock->functionStart();
+ size_t lastLineOffset = context->calculateBreakpointLineOffset(m_loc.index, sourceElementStart);
+ context->insertBreakpointAt(lastLineOffset + sourceElementStart.line, this);
+ }
} else {
insertBreakpoint(context);
}
StatementNode()
: Node()
, m_nextSibling(nullptr)
-#ifdef ESCARGOT_DEBUGGER
- , m_line(0)
-#endif /* ESCARGOT_DEBUGGER */
{
}
private:
StatementNode* m_nextSibling;
-#ifdef ESCARGOT_DEBUGGER
- size_t m_line;
-#endif /* ESCARGOT_DEBUGGER */
};
class StatementContainer {
}
template <class ASTBuilder>
- ASTNode parseClassStaticFieldInitializer(ASTBuilder& builder, const AtomicString& className)
+ ASTNode parseClassStaticFieldInitializer(ASTBuilder& builder, const AtomicString& className, size_t debuggerLineStart)
{
ASSERT(this->match(Substitution));
this->context->allowSuperProperty = true;
MetaNode node = this->createNode();
- ASTNode expr = this->parseAssignmentExpressionAndWrapIntoArrowFunction(builder, className);
+ ASTNode expr = this->parseAssignmentExpressionAndWrapIntoArrowFunction(builder, className, debuggerLineStart);
this->consumeSemicolon();
this->context->allowArguments = previousAllowArguments;
}
template <class ASTBuilder>
- ASTNode parseClassFieldInitializer(ASTBuilder& builder)
+ ASTNode parseClassFieldInitializer(ASTBuilder& builder, size_t debuggerLineStart)
{
ASSERT(this->match(Substitution));
this->context->allowArguments = false;
this->context->allowSuperProperty = true;
- ASTNode expr = this->parseAssignmentExpressionAndWrapIntoArrowFunction(builder, AtomicString());
+ ASTNode expr = this->parseAssignmentExpressionAndWrapIntoArrowFunction(builder, AtomicString(), debuggerLineStart);
this->consumeSemicolon();
this->context->allowArguments = previousAllowArguments;
}
template <class ASTBuilder>
- ASTNode parseAssignmentExpressionAndWrapIntoArrowFunction(ASTBuilder& builder, const AtomicString& paramName)
+ ASTNode parseAssignmentExpressionAndWrapIntoArrowFunction(ASTBuilder& builder, const AtomicString& paramName, size_t debuggerLineStart)
{
+ UNUSED_VARIABLE(debuggerLineStart);
+
ASTNode result;
if (!this->isParsingSingleFunction) {
BEGIN_FUNCTION_SCANNING(AtomicString());
this->currentScopeContext->m_allowSuperCall = this->context->allowSuperCall;
this->currentScopeContext->m_allowSuperProperty = this->context->allowSuperProperty;
this->currentScopeContext->m_allowArguments = this->context->allowArguments;
+#ifdef ESCARGOT_DEBUGGER
+ this->currentScopeContext->m_needRareData = true;
+ this->currentScopeContext->m_debuggerLineStart = debuggerLineStart;
+#endif /* ESCARGOT_DEBUGGER */
this->isolateCoverGrammar(builder, &Parser::parseAssignmentExpression<ASTBuilder, false>);
auto lastContext = this->lastPoppedScopeContext;
bool isAsync = false;
bool isPrivate = false;
+#ifdef ESCARGOT_DEBUGGER
+ size_t debuggerLineStart = token->lineNumber;
+#else /* !ESCARGOT_DEBUGGER */
+ size_t debuggerLineStart = 0;
+#endif /* ESCARGOT_DEBUGGER */
+
if (this->match(Multiply)) {
this->nextToken();
} else {
if (token->type == Token::KeywordToken && (this->qualifiedPropertyName(&this->lookahead) || this->match(Multiply) || this->match(Hash)) && token->relatedSource(this->scanner->source) == "static") {
*token = this->lookahead;
isStatic = true;
+#ifdef ESCARGOT_DEBUGGER
+ debuggerLineStart = token->lineNumber;
+#endif /* ESCARGOT_DEBUGGER */
mayMethodStartNode = this->createNode();
computed = this->match(LeftSquareBracket);
if (this->match(Multiply)) {
} else if (this->match(Substitution)) {
if (isStatic) {
kind = ClassElementNode::Kind::Field;
- value = this->parseClassStaticFieldInitializer(builder, className);
+ value = this->parseClassStaticFieldInitializer(builder, className, debuggerLineStart);
} else {
kind = ClassElementNode::Kind::Field;
- value = this->parseClassFieldInitializer(builder);
+ value = this->parseClassFieldInitializer(builder, debuggerLineStart);
}
-
} else if (this->match(SemiColon)) {
auto metaNode = this->createNode();
this->nextToken();
auto length = arrayLength(state);
for (size_t i = 0; i < length; i++) {
if (!m_fastModeData[i].isEmpty()) {
- defineOwnPropertyThrowsExceptionWhenStrictMode(state, ObjectPropertyName(state, Value(i)), ObjectPropertyDescriptor(m_fastModeData[i], ObjectPropertyDescriptor::AllPresent));
+ defineOwnPropertyThrowsException(state, ObjectPropertyName(state, Value(i)), ObjectPropertyDescriptor(m_fastModeData[i], ObjectPropertyDescriptor::AllPresent));
}
}
{
ExecutionState stateForInit(this);
m_globalObjectProxy = m_globalObject = new GlobalObject(stateForInit);
- m_globalObject->installBuiltins(stateForInit);
+ m_globalObject->initializeBuiltins(stateForInit);
}
void Context::throwException(ExecutionState& state, const Value& exception)
ObjectPropertyDescriptor::PresentAttribute attribute = (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectStructurePropertyDescriptor::EnumerablePresent);
if (canDelete)
attribute = (ObjectPropertyDescriptor::PresentAttribute)(attribute | ObjectPropertyDescriptor::ConfigurablePresent);
- m_bindingObject->defineOwnPropertyThrowsExceptionWhenStrictMode(state, name, ObjectPropertyDescriptor(Value(), attribute));
+ m_bindingObject->defineOwnPropertyThrowsException(state, name, ObjectPropertyDescriptor(Value(), attribute));
}
}
virtual void initializeBinding(ExecutionState& state, const AtomicString& name, const Value& V) override
{
- m_bindingObject->defineOwnPropertyThrowsExceptionWhenStrictMode(state, name, ObjectPropertyDescriptor(V, ObjectPropertyDescriptor::AllPresent));
+ m_bindingObject->defineOwnPropertyThrowsException(state, name, ObjectPropertyDescriptor(V, ObjectPropertyDescriptor::AllPresent));
}
virtual GetBindingValueResult getBindingValue(ExecutionState& state, const AtomicString& name) override
, m_stackTraceData(nullptr)
{
if (errorMessage->length()) {
- defineOwnPropertyThrowsExceptionWhenStrictMode(state, state.context()->staticStrings().message,
- ObjectPropertyDescriptor(errorMessage, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectStructurePropertyDescriptor::ConfigurablePresent)));
+ defineOwnPropertyThrowsException(state, state.context()->staticStrings().message,
+ ObjectPropertyDescriptor(errorMessage, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectStructurePropertyDescriptor::ConfigurablePresent)));
}
}
#if defined(ENABLE_ATOMICS_GLOBAL_LOCK)
SpinLock Global::g_atomicsLock;
#endif
+#if defined(ENABLE_THREADING)
+std::mutex Global::g_waiterMutex;
+std::vector<Global::Waiter*> Global::g_waiter;
+#endif
void Global::initialize(Platform* platform)
{
static bool called_once = true;
RELEASE_ASSERT(called_once && inited);
+
+#if defined(ENABLE_THREADING)
+ for (size_t i = 0; i < g_waiter.size(); i++) {
+ delete g_waiter[i];
+ }
+ std::vector<Waiter*>().swap(g_waiter);
+#endif
+
delete g_platform;
g_platform = nullptr;
return g_platform;
}
+#if defined(ENABLE_THREADING)
+Global::Waiter* Global::waiter(void* blockAddress)
+{
+ std::lock_guard<std::mutex> guard(g_waiterMutex);
+ for (size_t i = 0; i < g_waiter.size(); i++) {
+ if (g_waiter[i]->m_blockAddress == blockAddress) {
+ return g_waiter[i];
+ }
+ }
+
+ Waiter* w = new Waiter();
+ w->m_blockAddress = blockAddress;
+ g_waiter.push_back(w);
+
+ return w;
+}
+#endif
+
} // namespace Escargot
#ifndef __EscargotGlobal__
#define __EscargotGlobal__
+#if defined(ENABLE_THREADING)
+#include <mutex>
+#endif
+
#if defined(ENABLE_THREADING) && !defined(HAVE_BUILTIN_ATOMIC_FUNCTIONS)
#define ENABLE_ATOMICS_GLOBAL_LOCK
#endif
return g_atomicsLock;
}
#endif
+
+#if defined(ENABLE_THREADING)
+ struct Waiter {
+ void* m_blockAddress;
+ std::mutex m_mutex;
+ std::condition_variable m_waiter;
+ std::mutex m_conditionVariableMutex;
+ std::atomic_uint m_waiterCount;
+ };
+
+ static std::mutex g_waiterMutex;
+ static std::vector<Waiter*> g_waiter;
+ static Waiter* waiter(void* blockAddress);
+#endif
};
} // namespace Escargot
GlobalObject::GlobalObject(ExecutionState& state)
: Object(state, ESCARGOT_OBJECT_BUILTIN_PROPERTY_NUMBER, Object::__ForGlobalBuiltin__)
, m_context(state.context())
-#define INIT_BUILTIN_VALUE(builtin, TYPE, NAME) \
+#define INIT_BUILTIN_VALUE(builtin, TYPE, objName) \
, m_##builtin(nullptr)
- GLOBALOBJECT_BUILTIN_LIST(INIT_BUILTIN_VALUE)
+ GLOBALOBJECT_BUILTIN_ALL_LIST(INIT_BUILTIN_VALUE)
#undef INIT_BUILTIN_VALUE
{
// m_objectPrototype should be initialized ahead of any other builtins
Object::setGlobalIntrinsicObject(state);
}
-void GlobalObject::installBuiltins(ExecutionState& state)
+void GlobalObject::initializeBuiltins(ExecutionState& state)
{
// m_objectPrototype has been initialized ahead of any other builtins
ASSERT(!!m_objectPrototype);
- installFunction(state);
- installObject(state);
- installIterator(state);
- installError(state);
- installSymbol(state);
- installBigInt(state);
- installString(state);
- installNumber(state);
- installBoolean(state);
- installArray(state);
- installMath(state);
- installDate(state);
- installRegExp(state);
- installJSON(state);
-#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
- installIntl(state);
-#endif
- installPromise(state);
- installProxy(state);
- installReflect(state);
- installArrayBuffer(state);
- installDataView(state);
- installTypedArray(state);
- installMap(state);
- installSet(state);
- installWeakMap(state);
- installWeakRef(state);
- installWeakSet(state);
- installFinalizationRegistry(state);
- installGenerator(state);
- installAsyncFunction(state);
- installAsyncIterator(state);
- installAsyncFromSyncIterator(state);
- installAsyncGeneratorFunction(state);
-#if defined(ENABLE_THREADING)
- installAtomics(state);
- installSharedArrayBuffer(state);
-#endif
-#if defined(ENABLE_WASM)
- installWASM(state);
-#endif
- installOthers(state);
+ /*
+ initialize all global builtin properties by calling initialize##objName method
+ Object, Function and other prerequisite builtins are installed ahead
+ */
+#define DECLARE_BUILTIN_INIT_FUNC(OBJNAME, objName, ARG) \
+ initialize##objName(state);
+
+ GLOBALOBJECT_BUILTIN_OBJECT_LIST(DECLARE_BUILTIN_INIT_FUNC, )
+#undef DECLARE_BUILTIN_INIT_FUNC
}
Value builtinSpeciesGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
}
}
-
size_t newLen = escaped.size();
auto ptr = escaped.takeBuffer();
return new ASCIIString(ptr, newLen, ASCIIString::FromGCBufferTag);
return encode(state, argv[0].toString(state), false, state.context()->staticStrings().encodeURIComponent.string());
}
-
void char2hex(char dec, URIBuilderString& result)
{
unsigned char dig1 = (dec & 0xF0) >> 4;
}
}
-
static Value builtinEscape(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
{
String* str = argv[0].toString(state);
}
}
-// Object.prototype.__defineGetter__ ( P, getter )
-static Value builtinDefineGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
- // Let O be ? ToObject(this value).
- Object* O = thisValue.toObject(state);
- // If IsCallable(getter) is false, throw a TypeError exception.
- if (!argv[1].isCallable()) {
- ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, String::emptyString, true, state.context()->staticStrings().__defineGetter__.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
- }
- // Let desc be PropertyDescriptor{[[Get]]: getter, [[Enumerable]]: true, [[Configurable]]: true}.
- ObjectPropertyDescriptor desc(JSGetterSetter(argv[1].asObject(), Value(Value::EmptyValue)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::EnumerablePresent | ObjectPropertyDescriptor::ConfigurablePresent));
-
- // Let key be ? ToPropertyKey(P).
- ObjectPropertyName key(state, argv[0]);
-
-// Perform ? DefinePropertyOrThrow(O, key, desc).
-#if defined(ENABLE_V8_LIKE_DEFINE_LOOKUP_GETTER_SETTER)
- O->defineOwnProperty(state, key, desc);
-#else
- O->defineOwnPropertyThrowsException(state, key, desc);
-#endif
-
- // Return undefined.
- return Value();
-}
-
-// Object.prototype.__defineSetter__ ( P, getter )
-static Value builtinDefineSetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
- // Let O be ? ToObject(this value).
- Object* O = thisValue.toObject(state);
- // If IsCallable(getter) is false, throw a TypeError exception.
- if (!argv[1].isCallable()) {
- ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, String::emptyString, true, state.context()->staticStrings().__defineSetter__.string(), ErrorObject::Messages::GlobalObject_CallbackNotCallable);
- }
- // Let desc be PropertyDescriptor{[[Get]]: getter, [[Enumerable]]: true, [[Configurable]]: true}.
- ObjectPropertyDescriptor desc(JSGetterSetter(Value(Value::EmptyValue), argv[1].asObject()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::EnumerablePresent | ObjectPropertyDescriptor::ConfigurablePresent));
-
- // Let key be ? ToPropertyKey(P).
- ObjectPropertyName key(state, argv[0]);
-
-// Perform ? DefinePropertyOrThrow(O, key, desc).
-#if defined(ENABLE_V8_LIKE_DEFINE_LOOKUP_GETTER_SETTER)
- O->defineOwnProperty(state, key, desc);
-#else
- O->defineOwnPropertyThrowsException(state, key, desc);
-#endif
-
- // Return undefined.
- return Value();
-}
-
-// Object.prototype.__lookupGetter__ ( P, getter )
-static Value builtinLookupGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
-{
- // Let O be ? ToObject(this value).
- Object* O = thisValue.toObject(state);
- // Let key be ? ToPropertyKey(P).
- ObjectPropertyName key(state, argv[0]);
-
- // Repeat,
- while (O) {
- // Let desc be ? O.[[GetOwnProperty]](key).
- auto desc = O->getOwnProperty(state, key);
-
- // If desc is not undefined, then
- if (desc.hasValue()) {
- // If IsAccessorDescriptor(desc) is true, return desc.[[Get]].
- if (!desc.isDataProperty() && desc.jsGetterSetter()->hasGetter()) {
- return desc.jsGetterSetter()->getter();
- }
- // Return undefined.
- return Value();
- }
- // Set O to ? O.[[GetPrototypeOf]]().
- O = O->getPrototypeObject(state);
- // If O is null, return undefined.
- }
- return Value();
-}
-
-// Object.prototype.__lookupSetter__ ( P, getter )
-static Value builtinLookupSetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+static Value builtinArrayToString(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
{
- // Let O be ? ToObject(this value).
- Object* O = thisValue.toObject(state);
- // Let key be ? ToPropertyKey(P).
- ObjectPropertyName key(state, argv[0]);
-
- // Repeat,
- while (O) {
- // Let desc be ? O.[[GetOwnProperty]](key).
- auto desc = O->getOwnProperty(state, key);
-
- // If desc is not undefined, then
- if (desc.hasValue()) {
- // If IsAccessorDescriptor(desc) is true, return desc.[[Set]].
- if (!desc.isDataProperty() && desc.jsGetterSetter()->hasSetter()) {
- return desc.jsGetterSetter()->setter();
- }
- // Return undefined.
- return Value();
- }
- // Set O to ? O.[[GetPrototypeOf]]().
- O = O->getPrototypeObject(state);
- // If O is null, return undefined.
+ // this builtin function is shared both for Array and TypedArray (prototype.toString property)
+ RESOLVE_THIS_BINDING_TO_OBJECT(thisObject, Array, toString);
+ Value toString = thisObject->get(state, state.context()->staticStrings().join).value(state, thisObject);
+ if (!toString.isCallable()) {
+ toString = state.context()->globalObject()->objectPrototypeToString();
}
- return Value();
+ return Object::call(state, toString, thisObject, 0, nullptr);
}
-static Value builtinCallerAndArgumentsGetterSetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
+void GlobalObject::initializeOthers(ExecutionState& state)
{
- FunctionObject* targetFunction = nullptr;
- bool needThrow = false;
- if (thisValue.isCallable()) {
- if (thisValue.isFunction()) {
- targetFunction = thisValue.asFunction();
- if (targetFunction->isScriptFunctionObject()) {
- InterpretedCodeBlock* codeBlock = targetFunction->asScriptFunctionObject()->interpretedCodeBlock();
- if (codeBlock->isStrict() || codeBlock->isArrowFunctionExpression() || codeBlock->isGenerator()) {
- needThrow = true;
- }
- } else {
- ASSERT(targetFunction->isNativeFunctionObject());
- if (targetFunction->asNativeFunctionObject()->nativeCodeBlock()->isStrict()) {
- needThrow = true;
- }
- }
- } else if (thisValue.isObject()) {
- auto object = thisValue.asObject();
- if (object->isBoundFunctionObject()) {
- needThrow = true;
- }
- }
- } else if (!thisValue.isPrimitive() && !thisValue.isObject()) {
- needThrow = true;
- }
-
- if (needThrow) {
- ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "'caller' and 'arguments' restrict properties may not be accessed on strict mode functions or the arguments objects for calls to them");
- }
-
- bool inStrict = false;
-
- ExecutionState* p = state.parent();
- while (p) {
- if (p->inStrictMode()) {
- inStrict = true;
- break;
- }
- p = p->parent();
- }
-
- if (targetFunction && !inStrict) {
- bool foundTargetFunction = false;
- ExecutionState* p = &state;
- while (p) {
- if (foundTargetFunction) {
- auto callee = p->resolveCallee();
- if (callee != targetFunction) {
- if (callee) {
- return Value(callee);
- } else {
- return Value(Value::Null);
- }
- }
- } else {
- if (p->resolveCallee() == targetFunction) {
- foundTargetFunction = true;
- }
- }
- p = p->parent();
- }
- }
-
- return Value(Value::Null);
+ // Other prerequisite builtins should be installed at the start time
+ installOthers(state);
}
void GlobalObject::installOthers(ExecutionState& state)
// $18.2.1 eval (x)
m_eval = new NativeFunctionObject(state,
NativeFunctionInfo(strings->eval, builtinEval, 1, NativeFunctionInfo::Strict));
+
defineOwnProperty(state, ObjectPropertyName(strings->eval),
ObjectPropertyDescriptor(m_eval, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
// $18.2.2 isFinite(number)
defineOwnProperty(state, ObjectPropertyName(strings->isFinite),
ObjectPropertyDescriptor(new NativeFunctionObject(state,
ObjectPropertyDescriptor(new NativeFunctionObject(state,
NativeFunctionInfo(strings->isNaN, builtinIsNaN, 1, NativeFunctionInfo::Strict)),
(ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
- FunctionObject* parseInt = new NativeFunctionObject(state, NativeFunctionInfo(strings->parseInt, builtinParseInt, 2, NativeFunctionInfo::Strict));
- defineOwnProperty(state, ObjectPropertyName(strings->parseInt),
- ObjectPropertyDescriptor(parseInt,
- (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
- m_number->defineOwnProperty(state, ObjectPropertyName(strings->parseInt),
- ObjectPropertyDescriptor(parseInt,
- (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
- FunctionObject* parseFloat = new NativeFunctionObject(state, NativeFunctionInfo(strings->parseFloat, builtinParseFloat, 1, NativeFunctionInfo::Strict));
- defineOwnProperty(state, ObjectPropertyName(strings->parseFloat),
- ObjectPropertyDescriptor(parseFloat,
- (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
- m_number->defineOwnProperty(state, ObjectPropertyName(strings->parseFloat),
- ObjectPropertyDescriptor(parseFloat,
- (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
defineOwnProperty(state, ObjectPropertyName(strings->encodeURI),
ObjectPropertyDescriptor(new NativeFunctionObject(state,
NativeFunctionInfo(strings->encodeURI, builtinEncodeURI, 1, NativeFunctionInfo::Strict)),
NativeFunctionInfo(strings->unescape, builtinUnescape, 1, NativeFunctionInfo::Strict)),
(ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
- auto defineLookupGetterSetterNativeFunctionFlag =
-#if defined(ENABLE_V8_LIKE_DEFINE_LOOKUP_GETTER_SETTER)
- 0;
-#else
- NativeFunctionInfo::Strict;
-#endif
- m_objectPrototype->defineOwnProperty(state, ObjectPropertyName(strings->__defineGetter__),
- ObjectPropertyDescriptor(new NativeFunctionObject(state,
- NativeFunctionInfo(strings->__defineGetter__, builtinDefineGetter, 2, defineLookupGetterSetterNativeFunctionFlag)),
- (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
- m_objectPrototype->defineOwnProperty(state, ObjectPropertyName(strings->__defineSetter__),
- ObjectPropertyDescriptor(new NativeFunctionObject(state,
- NativeFunctionInfo(strings->__defineSetter__, builtinDefineSetter, 2, defineLookupGetterSetterNativeFunctionFlag)),
- (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
- m_objectPrototype->defineOwnProperty(state, ObjectPropertyName(strings->__lookupGetter__),
- ObjectPropertyDescriptor(new NativeFunctionObject(state,
- NativeFunctionInfo(strings->__lookupGetter__, builtinLookupGetter, 1, defineLookupGetterSetterNativeFunctionFlag)),
- (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
-
- m_objectPrototype->defineOwnProperty(state, ObjectPropertyName(strings->__lookupSetter__),
- ObjectPropertyDescriptor(new NativeFunctionObject(state,
- NativeFunctionInfo(strings->__lookupSetter__, builtinLookupSetter, 1, defineLookupGetterSetterNativeFunctionFlag)),
- (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+ // shared builtin methods
+ m_parseInt = new NativeFunctionObject(state, NativeFunctionInfo(strings->parseInt, builtinParseInt, 2, NativeFunctionInfo::Strict));
+ defineOwnProperty(state, ObjectPropertyName(strings->parseInt),
+ ObjectPropertyDescriptor(m_parseInt,
+ (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+ m_parseFloat = new NativeFunctionObject(state, NativeFunctionInfo(strings->parseFloat, builtinParseFloat, 1, NativeFunctionInfo::Strict));
+ defineOwnProperty(state, ObjectPropertyName(strings->parseFloat),
+ ObjectPropertyDescriptor(m_parseFloat,
+ (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+ m_arrayToString = new NativeFunctionObject(state, NativeFunctionInfo(strings->toString, builtinArrayToString, 0, NativeFunctionInfo::Strict));
+
+ // shared builtin objects
+ m_asyncIteratorPrototype = new Object(state);
+ m_asyncIteratorPrototype->setGlobalIntrinsicObject(state, true);
+ // https://www.ecma-international.org/ecma-262/10.0/index.html#sec-asynciteratorprototype-asynciterator
+ m_asyncIteratorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().asyncIterator),
+ ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(AtomicString(state, String::fromASCII("[Symbol.asyncIterator]")), builtinSpeciesGetter, 0, NativeFunctionInfo::Strict)),
+ (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+
+ m_iteratorPrototype = new Object(state);
+ m_iteratorPrototype->setGlobalIntrinsicObject(state, true);
+ // https://www.ecma-international.org/ecma-262/10.0/index.html#sec-%iteratorprototype%-@@iterator
+ m_iteratorPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().iterator),
+ ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(AtomicString(state, String::fromASCII("[Symbol.iterator]")), builtinSpeciesGetter, 0, NativeFunctionInfo::Strict)),
+ (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
#if defined(ESCARGOT_ENABLE_TEST)
AtomicString isFunctionAllocatedOnStackFunctionName(state, "isFunctionAllocatedOnStack");
(ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::AllPresent)));
#endif
- m_stringProxyObject = new StringObject(state);
- m_numberProxyObject = new NumberObject(state);
- m_booleanProxyObject = new BooleanObject(state);
- m_symbolProxyObject = new SymbolObject(state, state.context()->vmInstance()->globalSymbols().iterator);
- m_bigIntProxyObject = new BigIntObject(state, new BigInt(UINT64_C(0)));
-
- // 8.2.2 - 12
- // AddRestrictedFunctionProperties(funcProto, realmRec).
- auto fn = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().caller, builtinCallerAndArgumentsGetterSetter, 0, NativeFunctionInfo::Strict));
- JSGetterSetter gs(fn, fn);
- ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
- m_functionPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().caller), desc);
- m_functionPrototype->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().arguments), desc);
-
- m_generator->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().caller), desc);
- m_generator->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().arguments), desc);
-
// https://tc39.es/ecma262/#sec-globalthis
// The initial value of globalThis is the well-known intrinsic object %GlobalThisValue%.
// This property has the attributes { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }.
String* NAME = thisValue.toString(state);
-#define GLOBALOBJECT_BUILTIN_ARRAYBUFFER(F, NAME) \
- F(arrayBuffer, FunctionObject, NAME) \
- F(arrayBufferPrototype, Object, NAME)
-#define GLOBALOBJECT_BUILTIN_ARRAY(F, NAME) \
- F(array, FunctionObject, NAME) \
- F(arrayPrototype, Object, NAME) \
- F(arrayIteratorPrototype, Object, NAME) \
- F(arrayPrototypeValues, FunctionObject, NAME)
-#define GLOBALOBJECT_BUILTIN_ASYNCFROMSYNCITERATOR(F, NAME) \
- F(asyncFromSyncIteratorPrototype, Object, NAME)
-#define GLOBALOBJECT_BUILTIN_ASYNCFUNCTION(F, NAME) \
- F(asyncFunction, FunctionObject, NAME) \
- F(asyncFunctionPrototype, Object, NAME)
-#define GLOBALOBJECT_BUILTIN_ASYNCGENERATOR(F, NAME) \
- F(asyncGenerator, Object, NAME) \
- F(asyncGeneratorPrototype, Object, NAME) \
- F(asyncGeneratorFunction, FunctionObject, NAME)
-#define GLOBALOBJECT_BUILTIN_ASYNCITERATOR(F, NAME) \
- F(asyncIteratorPrototype, Object, NAME)
-#define GLOBALOBJECT_BUILTIN_BOOLEAN(F, NAME) \
- F(boolean, FunctionObject, NAME) \
- F(booleanPrototype, Object, NAME)
-#define GLOBALOBJECT_BUILTIN_DATAVIEW(F, NAME) \
- F(dataView, FunctionObject, NAME) \
- F(dataViewPrototype, Object, NAME)
-#define GLOBALOBJECT_BUILTIN_DATE(F, NAME) \
- F(date, FunctionObject, NAME) \
- F(datePrototype, Object, NAME)
-#define GLOBALOBJECT_BUILTIN_ERROR(F, NAME) \
- F(error, FunctionObject, NAME) \
- F(errorPrototype, Object, NAME) \
- F(referenceError, FunctionObject, NAME) \
- F(referenceErrorPrototype, Object, NAME) \
- F(typeError, FunctionObject, NAME) \
- F(typeErrorPrototype, Object, NAME) \
- F(rangeError, FunctionObject, NAME) \
- F(rangeErrorPrototype, Object, NAME) \
- F(syntaxError, FunctionObject, NAME) \
- F(syntaxErrorPrototype, Object, NAME) \
- F(uriError, FunctionObject, NAME) \
- F(uriErrorPrototype, Object, NAME) \
- F(evalError, FunctionObject, NAME) \
- F(evalErrorPrototype, Object, NAME) \
- F(aggregateError, FunctionObject, NAME) \
- F(aggregateErrorPrototype, Object, NAME) \
- F(throwTypeError, FunctionObject, NAME) \
- F(throwerGetterSetterData, JSGetterSetter, NAME)
-#define GLOBALOBJECT_BUILTIN_EVAL(F, NAME) \
- F(eval, FunctionObject, NAME)
-#define GLOBALOBJECT_BUILTIN_FUNCTION(F, NAME) \
- F(function, FunctionObject, NAME) \
- F(functionPrototype, FunctionObject, NAME) \
- F(functionApply, FunctionObject, NAME)
-#define GLOBALOBJECT_BUILTIN_GENERATOR(F, NAME) \
- F(generatorFunction, FunctionObject, NAME) \
- F(generator, FunctionObject, NAME) \
- F(generatorPrototype, Object, NAME)
+#define GLOBALOBJECT_BUILTIN_ARRAYBUFFER(F, objName) \
+ F(arrayBuffer, FunctionObject, objName) \
+ F(arrayBufferPrototype, Object, objName)
+#define GLOBALOBJECT_BUILTIN_ARRAY(F, objName) \
+ F(array, FunctionObject, objName) \
+ F(arrayPrototype, Object, objName) \
+ F(arrayIteratorPrototype, Object, objName) \
+ F(arrayPrototypeValues, FunctionObject, objName)
+#define GLOBALOBJECT_BUILTIN_ASYNCFROMSYNCITERATOR(F, objName) \
+ F(asyncFromSyncIteratorPrototype, Object, objName)
+#define GLOBALOBJECT_BUILTIN_ASYNCFUNCTION(F, objName) \
+ F(asyncFunction, FunctionObject, objName) \
+ F(asyncFunctionPrototype, Object, objName)
+#define GLOBALOBJECT_BUILTIN_ASYNCGENERATOR(F, objName) \
+ F(asyncGenerator, Object, objName) \
+ F(asyncGeneratorPrototype, Object, objName) \
+ F(asyncGeneratorFunction, FunctionObject, objName)
+#define GLOBALOBJECT_BUILTIN_BOOLEAN(F, objName) \
+ F(boolean, FunctionObject, objName) \
+ F(booleanPrototype, Object, objName) \
+ F(booleanProxyObject, BooleanObject, objName)
+#define GLOBALOBJECT_BUILTIN_DATAVIEW(F, objName) \
+ F(dataView, FunctionObject, objName) \
+ F(dataViewPrototype, Object, objName)
+#define GLOBALOBJECT_BUILTIN_DATE(F, objName) \
+ F(date, FunctionObject, objName) \
+ F(datePrototype, Object, objName)
+#define GLOBALOBJECT_BUILTIN_ERROR(F, objName) \
+ F(error, FunctionObject, objName) \
+ F(errorPrototype, Object, objName) \
+ F(referenceError, FunctionObject, objName) \
+ F(referenceErrorPrototype, Object, objName) \
+ F(typeError, FunctionObject, objName) \
+ F(typeErrorPrototype, Object, objName) \
+ F(rangeError, FunctionObject, objName) \
+ F(rangeErrorPrototype, Object, objName) \
+ F(syntaxError, FunctionObject, objName) \
+ F(syntaxErrorPrototype, Object, objName) \
+ F(uriError, FunctionObject, objName) \
+ F(uriErrorPrototype, Object, objName) \
+ F(evalError, FunctionObject, objName) \
+ F(evalErrorPrototype, Object, objName) \
+ F(aggregateError, FunctionObject, objName) \
+ F(aggregateErrorPrototype, Object, objName) \
+ F(throwTypeError, FunctionObject, objName) \
+ F(throwerGetterSetterData, JSGetterSetter, objName)
+#define GLOBALOBJECT_BUILTIN_FUNCTION(F, objName) \
+ F(function, FunctionObject, objName) \
+ F(functionPrototype, FunctionObject, objName) \
+ F(functionApply, FunctionObject, objName) \
+ F(callerAndArgumentsGetterSetter, FunctionObject, objName)
+#define GLOBALOBJECT_BUILTIN_GENERATOR(F, objName) \
+ F(generatorFunction, FunctionObject, objName) \
+ F(generator, FunctionObject, objName) \
+ F(generatorPrototype, Object, objName)
//INTL
#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
-#define GLOBALOBJECT_BUILTIN_INTL(F, NAME) \
- F(intl, Object, NAME) \
- F(intlCollator, FunctionObject, NAME) \
- F(intlDateTimeFormat, FunctionObject, NAME) \
- F(intlDateTimeFormatPrototype, Object, NAME) \
- F(intlNumberFormat, FunctionObject, NAME) \
- F(intlNumberFormatPrototype, Object, NAME) \
- F(intlRelativeTimeFormat, FunctionObject, NAME) \
- F(intlRelativeTimeFormatPrototype, Object, NAME) \
- F(intlLocale, FunctionObject, NAME) \
- F(intlLocalePrototype, Object, NAME) \
- F(intlPluralRules, FunctionObject, NAME) \
- F(intlPluralRulesPrototype, Object, NAME)
+#define GLOBALOBJECT_BUILTIN_INTL(F, objName) \
+ F(intl, Object, objName) \
+ F(intlCollator, FunctionObject, objName) \
+ F(intlDateTimeFormat, FunctionObject, objName) \
+ F(intlDateTimeFormatPrototype, Object, objName) \
+ F(intlNumberFormat, FunctionObject, objName) \
+ F(intlNumberFormatPrototype, Object, objName) \
+ F(intlRelativeTimeFormat, FunctionObject, objName) \
+ F(intlRelativeTimeFormatPrototype, Object, objName) \
+ F(intlLocale, FunctionObject, objName) \
+ F(intlLocalePrototype, Object, objName) \
+ F(intlPluralRules, FunctionObject, objName) \
+ F(intlPluralRulesPrototype, Object, objName)
#else
-#define GLOBALOBJECT_BUILTIN_INTL(F, NAME)
+#define GLOBALOBJECT_BUILTIN_INTL(F, objName)
#endif
-#define GLOBALOBJECT_BUILTIN_ITERATOR(F, NAME) \
- F(iteratorPrototype, Object, NAME)
-#define GLOBALOBJECT_BUILTIN_JSON(F, NAME) \
- F(json, Object, NAME) \
- F(jsonStringify, FunctionObject, NAME) \
- F(jsonParse, FunctionObject, NAME)
-#define GLOBALOBJECT_BUILTIN_MAP(F, NAME) \
- F(map, FunctionObject, NAME) \
- F(mapPrototype, Object, NAME) \
- F(mapIteratorPrototype, Object, NAME)
-#define GLOBALOBJECT_BUILTIN_MATH(F, NAME) \
- F(math, Object, NAME)
-#define GLOBALOBJECT_BUILTIN_NUMBER(F, NAME) \
- F(number, FunctionObject, NAME) \
- F(numberPrototype, Object, NAME)
-#define GLOBALOBJECT_BUILTIN_OBJECT(F, NAME) \
- F(object, FunctionObject, NAME) \
- F(objectCreate, FunctionObject, NAME) \
- F(objectFreeze, FunctionObject, NAME) \
- F(objectPrototype, Object, NAME) \
- F(objectPrototypeToString, FunctionObject, NAME)
-#define GLOBALOBJECT_BUILTIN_OTHERS(F, NAME) \
- F(stringProxyObject, StringObject, NAME) \
- F(numberProxyObject, NumberObject, NAME) \
- F(booleanProxyObject, BooleanObject, NAME) \
- F(symbolProxyObject, SymbolObject, NAME) \
- F(bigIntProxyObject, BigIntObject, NAME)
-#define GLOBALOBJECT_BUILTIN_PROMISE(F, NAME) \
- F(promise, FunctionObject, NAME) \
- F(promisePrototype, Object, NAME)
-#define GLOBALOBJECT_BUILTIN_PROXY(F, NAME) \
- F(proxy, FunctionObject, NAME)
-#define GLOBALOBJECT_BUILTIN_REFLECT(F, NAME) \
- F(reflect, Object, NAME)
-#define GLOBALOBJECT_BUILTIN_REGEXP(F, NAME) \
- F(regexp, FunctionObject, NAME) \
- F(regexpExecMethod, FunctionObject, NAME) \
- F(regexpPrototype, Object, NAME) \
- F(regexpReplaceMethod, FunctionObject, NAME) \
- F(regexpStringIteratorPrototype, Object, NAME) \
- F(regexpSplitMethod, FunctionObject, NAME)
-#define GLOBALOBJECT_BUILTIN_SET(F, NAME) \
- F(set, FunctionObject, NAME) \
- F(setPrototype, Object, NAME) \
- F(setIteratorPrototype, Object, NAME)
-#define GLOBALOBJECT_BUILTIN_STRING(F, NAME) \
- F(string, FunctionObject, NAME) \
- F(stringPrototype, Object, NAME) \
- F(stringIteratorPrototype, Object, NAME)
-#define GLOBALOBJECT_BUILTIN_SYMBOL(F, NAME) \
- F(symbol, FunctionObject, NAME) \
- F(symbolPrototype, Object, NAME)
-#define GLOBALOBJECT_BUILTIN_BIGINT(F, NAME) \
- F(bigInt, FunctionObject, NAME) \
- F(bigIntPrototype, Object, NAME)
-#define GLOBALOBJECT_BUILTIN_TYPEDARRAY(F, NAME) \
- F(typedArray, FunctionObject, NAME) \
- F(typedArrayPrototype, Object, NAME) \
- F(int8Array, FunctionObject, NAME) \
- F(int8ArrayPrototype, Object, NAME) \
- F(uint8Array, FunctionObject, NAME) \
- F(uint8ArrayPrototype, Object, NAME) \
- F(uint8ClampedArray, FunctionObject, NAME) \
- F(uint8ClampedArrayPrototype, Object, NAME) \
- F(int16Array, FunctionObject, NAME) \
- F(int16ArrayPrototype, Object, NAME) \
- F(uint16Array, FunctionObject, NAME) \
- F(uint16ArrayPrototype, Object, NAME) \
- F(int32Array, FunctionObject, NAME) \
- F(int32ArrayPrototype, Object, NAME) \
- F(uint32Array, FunctionObject, NAME) \
- F(uint32ArrayPrototype, Object, NAME) \
- F(float32Array, FunctionObject, NAME) \
- F(float32ArrayPrototype, Object, NAME) \
- F(float64Array, FunctionObject, NAME) \
- F(float64ArrayPrototype, Object, NAME) \
- F(bigInt64Array, FunctionObject, NAME) \
- F(bigInt64ArrayPrototype, Object, NAME) \
- F(bigUint64Array, FunctionObject, NAME) \
- F(bigUint64ArrayPrototype, Object, NAME)
-#define GLOBALOBJECT_BUILTIN_WEAKMAP(F, NAME) \
- F(weakMap, FunctionObject, NAME) \
- F(weakMapPrototype, Object, NAME)
-#define GLOBALOBJECT_BUILTIN_WEAKSET(F, NAME) \
- F(weakSet, FunctionObject, NAME) \
- F(weakSetPrototype, Object, NAME)
-#define GLOBALOBJECT_BUILTIN_WEAKREF(F, NAME) \
- F(weakRef, FunctionObject, NAME) \
- F(weakRefPrototype, Object, NAME)
-#define GLOBALOBJECT_BUILTIN_FINALIZATIONREGISTRY(F, NAME) \
- F(finalizationRegistry, FunctionObject, NAME) \
- F(finalizationRegistryPrototype, Object, NAME)
+#define GLOBALOBJECT_BUILTIN_JSON(F, objName) \
+ F(json, Object, objName) \
+ F(jsonStringify, FunctionObject, objName) \
+ F(jsonParse, FunctionObject, objName)
+#define GLOBALOBJECT_BUILTIN_MAP(F, objName) \
+ F(map, FunctionObject, objName) \
+ F(mapPrototype, Object, objName) \
+ F(mapIteratorPrototype, Object, objName)
+#define GLOBALOBJECT_BUILTIN_MATH(F, objName) \
+ F(math, Object, objName)
+#define GLOBALOBJECT_BUILTIN_NUMBER(F, objName) \
+ F(number, FunctionObject, objName) \
+ F(numberPrototype, Object, objName) \
+ F(numberProxyObject, NumberObject, objName)
+#define GLOBALOBJECT_BUILTIN_OBJECT(F, objName) \
+ F(object, FunctionObject, objName) \
+ F(objectCreate, FunctionObject, objName) \
+ F(objectFreeze, FunctionObject, objName) \
+ F(objectPrototype, Object, objName) \
+ F(objectPrototypeToString, FunctionObject, objName)
+#define GLOBALOBJECT_BUILTIN_OTHERS(F, objName) \
+ F(eval, FunctionObject, objName) \
+ F(parseInt, FunctionObject, objName) \
+ F(parseFloat, FunctionObject, objName) \
+ F(arrayToString, FunctionObject, objName) \
+ F(asyncIteratorPrototype, Object, objName) \
+ F(iteratorPrototype, Object, objName)
+#define GLOBALOBJECT_BUILTIN_PROMISE(F, objName) \
+ F(promise, FunctionObject, objName) \
+ F(promisePrototype, Object, objName)
+#define GLOBALOBJECT_BUILTIN_PROXY(F, objName) \
+ F(proxy, FunctionObject, objName)
+#define GLOBALOBJECT_BUILTIN_REFLECT(F, objName) \
+ F(reflect, Object, objName)
+#define GLOBALOBJECT_BUILTIN_REGEXP(F, objName) \
+ F(regexp, FunctionObject, objName) \
+ F(regexpExecMethod, FunctionObject, objName) \
+ F(regexpPrototype, Object, objName) \
+ F(regexpReplaceMethod, FunctionObject, objName) \
+ F(regexpStringIteratorPrototype, Object, objName) \
+ F(regexpSplitMethod, FunctionObject, objName)
+#define GLOBALOBJECT_BUILTIN_SET(F, objName) \
+ F(set, FunctionObject, objName) \
+ F(setPrototype, Object, objName) \
+ F(setIteratorPrototype, Object, objName)
+#define GLOBALOBJECT_BUILTIN_STRING(F, objName) \
+ F(string, FunctionObject, objName) \
+ F(stringPrototype, Object, objName) \
+ F(stringIteratorPrototype, Object, objName) \
+ F(stringProxyObject, StringObject, objName)
+#define GLOBALOBJECT_BUILTIN_SYMBOL(F, objName) \
+ F(symbol, FunctionObject, objName) \
+ F(symbolPrototype, Object, objName) \
+ F(symbolProxyObject, SymbolObject, objName)
+#define GLOBALOBJECT_BUILTIN_BIGINT(F, objName) \
+ F(bigInt, FunctionObject, objName) \
+ F(bigIntPrototype, Object, objName) \
+ F(bigIntProxyObject, BigIntObject, objName)
+#define GLOBALOBJECT_BUILTIN_TYPEDARRAY(F, objName) \
+ F(typedArray, FunctionObject, objName) \
+ F(typedArrayPrototype, Object, objName) \
+ F(int8Array, FunctionObject, objName) \
+ F(int8ArrayPrototype, Object, objName) \
+ F(uint8Array, FunctionObject, objName) \
+ F(uint8ArrayPrototype, Object, objName) \
+ F(uint8ClampedArray, FunctionObject, objName) \
+ F(uint8ClampedArrayPrototype, Object, objName) \
+ F(int16Array, FunctionObject, objName) \
+ F(int16ArrayPrototype, Object, objName) \
+ F(uint16Array, FunctionObject, objName) \
+ F(uint16ArrayPrototype, Object, objName) \
+ F(int32Array, FunctionObject, objName) \
+ F(int32ArrayPrototype, Object, objName) \
+ F(uint32Array, FunctionObject, objName) \
+ F(uint32ArrayPrototype, Object, objName) \
+ F(float32Array, FunctionObject, objName) \
+ F(float32ArrayPrototype, Object, objName) \
+ F(float64Array, FunctionObject, objName) \
+ F(float64ArrayPrototype, Object, objName) \
+ F(bigInt64Array, FunctionObject, objName) \
+ F(bigInt64ArrayPrototype, Object, objName) \
+ F(bigUint64Array, FunctionObject, objName) \
+ F(bigUint64ArrayPrototype, Object, objName)
+#define GLOBALOBJECT_BUILTIN_WEAKMAP(F, objName) \
+ F(weakMap, FunctionObject, objName) \
+ F(weakMapPrototype, Object, objName)
+#define GLOBALOBJECT_BUILTIN_WEAKSET(F, objName) \
+ F(weakSet, FunctionObject, objName) \
+ F(weakSetPrototype, Object, objName)
+#define GLOBALOBJECT_BUILTIN_WEAKREF(F, objName) \
+ F(weakRef, FunctionObject, objName) \
+ F(weakRefPrototype, Object, objName)
+#define GLOBALOBJECT_BUILTIN_FINALIZATIONREGISTRY(F, objName) \
+ F(finalizationRegistry, FunctionObject, objName) \
+ F(finalizationRegistryPrototype, Object, objName)
#if defined(ENABLE_THREADING)
-#define GLOBALOBJECT_BUILTIN_ATOMICS(F, NAME) \
- F(atomics, Object, Name)
-#define GLOBALOBJECT_BUILTIN_SHAREDARRAYBUFFER(F, NAME) \
- F(sharedArrayBuffer, FunctionObject, Name) \
- F(sharedArrayBufferPrototype, Object, Name)
+#define GLOBALOBJECT_BUILTIN_ATOMICS(F, objName) \
+ F(atomics, Object, objName)
+#define GLOBALOBJECT_BUILTIN_SHAREDARRAYBUFFER(F, objName) \
+ F(sharedArrayBuffer, FunctionObject, objName) \
+ F(sharedArrayBufferPrototype, Object, objName)
#else
-#define GLOBALOBJECT_BUILTIN_ATOMICS(F, NAME)
-#define GLOBALOBJECT_BUILTIN_SHAREDARRAYBUFFER(F, NAME)
+#define GLOBALOBJECT_BUILTIN_ATOMICS(F, objName)
+#define GLOBALOBJECT_BUILTIN_SHAREDARRAYBUFFER(F, objName)
#endif
//WebAssembly
#if defined(ENABLE_WASM)
-#define GLOBALOBJECT_BUILTIN_WASM(F, NAME) \
- F(wasmModulePrototype, Object, Name) \
- F(wasmInstancePrototype, Object, Name) \
- F(wasmMemoryPrototype, Object, Name) \
- F(wasmTablePrototype, Object, Name) \
- F(wasmGlobalPrototype, Object, Name) \
- F(wasmCompileErrorPrototype, Object, NAME) \
- F(wasmLinkErrorPrototype, Object, NAME) \
- F(wasmRuntimeErrorPrototype, Object, NAME)
+#define GLOBALOBJECT_BUILTIN_WASM(F, objName) \
+ F(wasm, Object, objName) \
+ F(wasmModulePrototype, Object, objName) \
+ F(wasmInstancePrototype, Object, objName) \
+ F(wasmMemoryPrototype, Object, objName) \
+ F(wasmTablePrototype, Object, objName) \
+ F(wasmGlobalPrototype, Object, objName) \
+ F(wasmCompileErrorPrototype, Object, objName) \
+ F(wasmLinkErrorPrototype, Object, objName) \
+ F(wasmRuntimeErrorPrototype, Object, objName)
#else
-#define GLOBALOBJECT_BUILTIN_WASM(F, NAME)
+#define GLOBALOBJECT_BUILTIN_WASM(F, objName)
#endif
-#define GLOBALOBJECT_BUILTIN_LIST(F) \
- GLOBALOBJECT_BUILTIN_ARRAYBUFFER(F, ArrayBuffer) \
- GLOBALOBJECT_BUILTIN_ARRAY(F, Array) \
- GLOBALOBJECT_BUILTIN_ASYNCFROMSYNCITERATOR(F, AsyncFromSyncIterator) \
- GLOBALOBJECT_BUILTIN_ASYNCFUNCTION(F, AsyncFunction) \
- GLOBALOBJECT_BUILTIN_ASYNCGENERATOR(F, AsyncGenerator) \
- GLOBALOBJECT_BUILTIN_ASYNCITERATOR(F, AsyncIterator) \
- GLOBALOBJECT_BUILTIN_ATOMICS(F, Atomics) \
- GLOBALOBJECT_BUILTIN_BOOLEAN(F, Boolean) \
- GLOBALOBJECT_BUILTIN_DATAVIEW(F, DataView) \
- GLOBALOBJECT_BUILTIN_DATE(F, Date) \
- GLOBALOBJECT_BUILTIN_ERROR(F, Error) \
- GLOBALOBJECT_BUILTIN_EVAL(F, Eval) \
- GLOBALOBJECT_BUILTIN_FUNCTION(F, Function) \
- GLOBALOBJECT_BUILTIN_GENERATOR(F, Generator) \
- GLOBALOBJECT_BUILTIN_INTL(F, Intl) \
- GLOBALOBJECT_BUILTIN_ITERATOR(F, Iterator) \
- GLOBALOBJECT_BUILTIN_JSON(F, JSON) \
- GLOBALOBJECT_BUILTIN_MAP(F, Map) \
- GLOBALOBJECT_BUILTIN_MATH(F, Math) \
- GLOBALOBJECT_BUILTIN_NUMBER(F, Number) \
- GLOBALOBJECT_BUILTIN_OBJECT(F, Object) \
- GLOBALOBJECT_BUILTIN_OTHERS(F, Others) \
- GLOBALOBJECT_BUILTIN_PROMISE(F, Promise) \
- GLOBALOBJECT_BUILTIN_PROXY(F, Proxy) \
- GLOBALOBJECT_BUILTIN_REFLECT(F, Reflect) \
- GLOBALOBJECT_BUILTIN_REGEXP(F, RegExp) \
- GLOBALOBJECT_BUILTIN_SET(F, Set) \
- GLOBALOBJECT_BUILTIN_SHAREDARRAYBUFFER(F, SharedArrayBuffer) \
- GLOBALOBJECT_BUILTIN_STRING(F, String) \
- GLOBALOBJECT_BUILTIN_SYMBOL(F, Symbol) \
- GLOBALOBJECT_BUILTIN_BIGINT(F, BigInt) \
- GLOBALOBJECT_BUILTIN_TYPEDARRAY(F, TypedArray) \
- GLOBALOBJECT_BUILTIN_WEAKMAP(F, WeakMap) \
- GLOBALOBJECT_BUILTIN_WEAKSET(F, WeakSet) \
- GLOBALOBJECT_BUILTIN_WEAKREF(F, WeakRef) \
- GLOBALOBJECT_BUILTIN_FINALIZATIONREGISTRY(F, FinalizationRegistry) \
- GLOBALOBJECT_BUILTIN_WASM(F, WebAssembly)
+#define GLOBALOBJECT_BUILTIN_OBJECT_LIST(F, ARG) \
+ F(ARRAYBUFFER, ArrayBuffer, ARG) \
+ F(ARRAY, Array, ARG) \
+ F(ASYNCFROMSYNCITERATOR, AsyncFromSyncIterator, ARG) \
+ F(ASYNCFUNCTION, AsyncFunction, ARG) \
+ F(ASYNCGENERATOR, AsyncGenerator, ARG) \
+ F(ATOMICS, Atomics, ARG) \
+ F(BOOLEAN, Boolean, ARG) \
+ F(DATAVIEW, DataView, ARG) \
+ F(DATE, Date, ARG) \
+ F(ERROR, Error, ARG) \
+ F(FUNCTION, Function, ARG) \
+ F(GENERATOR, Generator, ARG) \
+ F(INTL, Intl, ARG) \
+ F(JSON, JSON, ARG) \
+ F(MAP, Map, ARG) \
+ F(MATH, Math, ARG) \
+ F(NUMBER, Number, ARG) \
+ F(OBJECT, Object, ARG) \
+ F(OTHERS, Others, ARG) \
+ F(PROMISE, Promise, ARG) \
+ F(PROXY, Proxy, ARG) \
+ F(REFLECT, Reflect, ARG) \
+ F(REGEXP, RegExp, ARG) \
+ F(SET, Set, ARG) \
+ F(SHAREDARRAYBUFFER, SharedArrayBuffer, ARG) \
+ F(STRING, String, ARG) \
+ F(SYMBOL, Symbol, ARG) \
+ F(BIGINT, BigInt, ARG) \
+ F(TYPEDARRAY, TypedArray, ARG) \
+ F(WEAKMAP, WeakMap, ARG) \
+ F(WEAKSET, WeakSet, ARG) \
+ F(WEAKREF, WeakRef, ARG) \
+ F(FINALIZATIONREGISTRY, FinalizationRegistry, ARG) \
+ F(WASM, WebAssembly, ARG)
+
+
+#define DECLARE_BUILTIN_ALL_LIST(OBJNAME, objName, ARG) \
+ GLOBALOBJECT_BUILTIN_##OBJNAME(ARG, objName)
+
+#define GLOBALOBJECT_BUILTIN_ALL_LIST(F) \
+ GLOBALOBJECT_BUILTIN_OBJECT_LIST(DECLARE_BUILTIN_ALL_LIST, F)
Value builtinSpeciesGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget);
class GlobalObject : public Object {
public:
- friend class ByteCodeInterpreter;
friend class GlobalEnvironmentRecord;
- friend class IdentifierNode;
explicit GlobalObject(ExecutionState& state);
return true;
}
- void installBuiltins(ExecutionState& state);
-
- Value eval(ExecutionState& state, const Value& arg);
- // we get isInWithOperation as parameter because this affects bytecode
- Value evalLocal(ExecutionState& state, const Value& arg, Value thisValue, InterpretedCodeBlock* parentCodeBlock, bool inWithOperation);
-
-#define DECLARE_BUILTIN_FUNC(builtin, TYPE, NAME) \
- TYPE* builtin() \
- { \
- ASSERT(!!m_##builtin); \
- return m_##builtin; \
- }
-
- GLOBALOBJECT_BUILTIN_LIST(DECLARE_BUILTIN_FUNC)
-#undef DECLARE_BUILTIN_FUNC
-
virtual bool isInlineCacheable() override
{
return false;
virtual ObjectHasPropertyResult hasProperty(ExecutionState& state, const ObjectPropertyName& P) override;
virtual ObjectGetResult getOwnProperty(ExecutionState& state, const ObjectPropertyName& P) override;
+ /*
+ Global builtin property getter method
+ If builtin property is not yet installed (m_##builtin is null), call install#objName method to install it
+ Installation is executed only once for each builtin object
+ */
+#define DECLARE_BUILTIN_GETTER_FUNC(builtin, TYPE, objName) \
+ TYPE* builtin() \
+ { \
+ if (UNLIKELY(!m_##builtin)) { \
+ ExecutionState tempState(m_context); \
+ install##objName(tempState); \
+ } \
+ ASSERT(!!m_##builtin); \
+ return m_##builtin; \
+ }
+
+ GLOBALOBJECT_BUILTIN_ALL_LIST(DECLARE_BUILTIN_GETTER_FUNC)
+#undef DECLARE_BUILTIN_GETTER_FUNC
+
+ void initializeBuiltins(ExecutionState& state);
+
+ Value eval(ExecutionState& state, const Value& arg);
+ // we get isInWithOperation as parameter because this affects bytecode
+ Value evalLocal(ExecutionState& state, const Value& arg, Value thisValue, InterpretedCodeBlock* parentCodeBlock, bool inWithOperation);
+
void* operator new(size_t size)
{
return GC_MALLOC(size);
private:
Context* m_context;
-#define DECLARE_BUILTIN_VALUE(builtin, TYPE, NAME) \
+#define DECLARE_BUILTIN_MEMBER_VALUE(builtin, TYPE, objName) \
TYPE* m_##builtin;
- GLOBALOBJECT_BUILTIN_LIST(DECLARE_BUILTIN_VALUE)
-#undef DECLARE_BUILTIN_VALUE
-
- void installFunction(ExecutionState& state);
- void installObject(ExecutionState& state);
- void installError(ExecutionState& state);
- void installSymbol(ExecutionState& state);
- void installBigInt(ExecutionState& state);
- void installString(ExecutionState& state);
- void installNumber(ExecutionState& state);
- void installBoolean(ExecutionState& state);
- void installArray(ExecutionState& state);
- void installMath(ExecutionState& state);
- void installDate(ExecutionState& state);
- void installRegExp(ExecutionState& state);
- void installJSON(ExecutionState& state);
-#if defined(ENABLE_ICU) && defined(ENABLE_INTL)
- void installIntl(ExecutionState& state);
-#endif
- void installPromise(ExecutionState& state);
- void installProxy(ExecutionState& state);
- void installReflect(ExecutionState& state);
- void installArrayBuffer(ExecutionState& state);
- void installDataView(ExecutionState& state);
- void installTypedArray(ExecutionState& state);
+ GLOBALOBJECT_BUILTIN_ALL_LIST(DECLARE_BUILTIN_MEMBER_VALUE)
+#undef DECLARE_BUILTIN_MEMBER_VALUE
+
+#define DECLARE_BUILTIN_MEMBER_FUNC(OBJNAME, objName, ARG) \
+ void initialize##objName(ExecutionState& state); \
+ void install##objName(ExecutionState& state);
+
+ GLOBALOBJECT_BUILTIN_OBJECT_LIST(DECLARE_BUILTIN_MEMBER_FUNC, )
+#undef DECLARE_BUILTIN_MEMBER_FUNC
+
template <typename TA, int elementSize>
FunctionObject* installTypedArray(ExecutionState& state, AtomicString taName, Object** proto, FunctionObject* typedArrayFunction);
- void installIterator(ExecutionState& state);
- void installMap(ExecutionState& state);
- void installSet(ExecutionState& state);
- void installWeakMap(ExecutionState& state);
- void installWeakRef(ExecutionState& state);
- void installWeakSet(ExecutionState& state);
- void installFinalizationRegistry(ExecutionState& state);
- void installGenerator(ExecutionState& state);
- void installAsyncFunction(ExecutionState& state);
- void installAsyncIterator(ExecutionState& state);
- void installAsyncFromSyncIterator(ExecutionState& state);
- void installAsyncGeneratorFunction(ExecutionState& state);
-#if defined(ENABLE_THREADING)
- void installAtomics(ExecutionState& state);
- void installSharedArrayBuffer(ExecutionState& state);
-#endif
-#if defined(ENABLE_WASM)
- void installWASM(ExecutionState& state);
-#endif
- void installOthers(ExecutionState& state);
};
} // namespace Escargot
// examine the remainder to determine whether we should be considering rounding
// up or down. If remainder is precisely 0.5 rounding is to even.
int dComparePoint5 = fraction.comparePoint5();
- if (dComparePoint5 > 0 || (!dComparePoint5 && (radix & 1 ? isOddInOddRadix : digit & 1))) {
+ if (dComparePoint5 > 0 || (!dComparePoint5 && ((radix & 1) ? isOddInOddRadix : (digit & 1)))) {
// Check for rounding up; are we closer to the value we'd round off to than
// the next IEEE value would be?
if (fraction.sumGreaterThanOne(halfDeltaNext)) {
while (true) {
int dComparePoint5 = fraction.comparePoint5();
- if (dComparePoint5 > 0 || (!dComparePoint5 && (radix & 1 ? isOddInOddRadix : digit & 1))) {
+ if (dComparePoint5 > 0 || (!dComparePoint5 && ((radix & 1) ? isOddInOddRadix : (digit & 1)))) {
if (fraction.sumGreaterThanOne(halfDelta)) {
needsRoundingUp = true;
break;
ValueVector Object::createListFromArrayLike(ExecutionState& state, Value obj, uint8_t elementTypes)
{
- // https://www.ecma-international.org/ecma-262/6.0/#sec-createlistfromarraylike
+ // https://tc39.es/ecma262/#sec-createlistfromarraylike
auto strings = &state.context()->staticStrings();
- // 1. ReturnIfAbrupt(obj).
- // 2. If elementTypes was not passed, let elementTypes be (Undefined, Null, Boolean, String, Symbol, Number, Object).
-
- // 3. If Type(obj) is not Object, throw a TypeError exception.
+ // If elementTypes is not present, set elementTypes to « Undefined, Null, Boolean, String, Symbol, Number, BigInt, Object ».
+ // If Type(obj) is not Object, throw a TypeError exception.
if (!obj.isObject()) {
- ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->object.string(), false, String::emptyString, "%s: obj is not Object");
+ ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, ErrorObject::Messages::GlobalObject_FirstArgumentNotObject);
}
- // 4. Let len be ToLength(Get(obj, "length")).
- // 5. ReturnIfAbrupt(len).
+ // Let len be ? LengthOfArrayLike(obj).
Object* o = obj.asObject();
auto len = o->length(state);
- // Honorate "length" property: If length>2^32-1, throw a RangeError exception.
- if (len > ((1LL << 32LL) - 1LL)) {
- ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, ErrorObject::Messages::GlobalObject_InvalidArrayLength);
- }
-
- // 6. Let list be an empty List.
+ // Let list be an empty List.
+ // Let index be 0.
ValueVector list;
- // 7. Let index be 0.
uint64_t index = 0;
- //8. Repeat while index < len
+ bool allTypes = (elementTypes == static_cast<uint8_t>(ElementTypes::ALL));
+
+ // Repeat while index < len
while (index < len) {
- // b. Let next be Get(obj, indexName).
- // c. ReturnIfAbrupt(next).
+ // Let next be Get(obj, indexName).
Value next = o->getIndexedProperty(state, Value(index)).value(state, o);
- // d. If Type(next) is not an element of elementTypes, throw a TypeError exception.
- if (!(((elementTypes & (uint8_t)ElementTypes::Undefined) && next.isUndefined()) || ((elementTypes & (uint8_t)ElementTypes::Null) && next.isNull()) || ((elementTypes & (uint8_t)ElementTypes::Boolean) && next.isBoolean()) || ((elementTypes & (uint8_t)ElementTypes::String) && next.isString()) || ((elementTypes & (uint8_t)ElementTypes::Symbol) && next.isSymbol()) || ((elementTypes & (uint8_t)ElementTypes::Number) && next.isNumber()) || ((elementTypes & (uint8_t)ElementTypes::Object) && next.isObject()))) {
+ // If Type(next) is not an element of elementTypes, throw a TypeError exception.
+ bool validType = false;
+ if (next.isUndefined()) {
+ validType = allTypes || (elementTypes & static_cast<uint8_t>(ElementTypes::Undefined));
+ } else if (next.isNull()) {
+ validType = allTypes || (elementTypes & static_cast<uint8_t>(ElementTypes::Null));
+ } else if (next.isBoolean()) {
+ validType = allTypes || (elementTypes & static_cast<uint8_t>(ElementTypes::Boolean));
+ } else if (next.isString()) {
+ validType = allTypes || (elementTypes & static_cast<uint8_t>(ElementTypes::String));
+ } else if (next.isSymbol()) {
+ validType = allTypes || (elementTypes & static_cast<uint8_t>(ElementTypes::Symbol));
+ } else if (next.isNumber()) {
+ validType = allTypes || (elementTypes & static_cast<uint8_t>(ElementTypes::Number));
+ } else if (next.isBigInt()) {
+ validType = allTypes || (elementTypes & static_cast<uint8_t>(ElementTypes::BigInt));
+ } else if (next.isObject()) {
+ validType = allTypes || (elementTypes & static_cast<uint8_t>(ElementTypes::Object));
+ }
+
+ if (UNLIKELY(!validType)) {
ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, strings->object.string(), false, String::emptyString, "%s: Type(next) is not an element of elementTypes");
}
- // e. Append next as the last element of list.
+
+ // Append next as the last element of list.
list.pushBack(next);
- // f. Set index to index + 1.
+ // Set index to index + 1.
index++;
}
- // 9. Return list.
+ // Return list.
return list;
}
ensureRareData()->m_isInlineCacheable = false;
}
+void Object::redefineOwnProperty(ExecutionState& state, const ObjectPropertyName& P, const ObjectPropertyDescriptor& desc)
+{
+ ASSERT(!P.isIndexString());
+ ASSERT(desc.isDataProperty());
+ ASSERT(desc.isWritable());
+ ASSERT(desc.isConfigurable());
+
+ ObjectStructurePropertyName propertyName = P.toObjectStructurePropertyName(state);
+ auto findResult = m_structure->findProperty(propertyName);
+ ASSERT(findResult.first != SIZE_MAX);
+
+ size_t idx = findResult.first;
+ const ObjectStructureItem* item = findResult.second.value();
+ auto current = item->m_descriptor;
+ ASSERT(current.isDataProperty());
+ ASSERT(current.isWritable());
+ ASSERT(current.isConfigurable());
+
+ m_structure = m_structure->replacePropertyDescriptor(idx, desc.toObjectStructurePropertyDescriptor());
+ m_values[idx] = desc.value();
+}
+
uint64_t Object::length(ExecutionState& state)
{
// ToLength(Get(obj, "length"))
String = 1 << 3,
Symbol = 1 << 4,
Number = 1 << 5,
- Object = 1 << 6,
- ALL = Undefined | Null | Boolean | String | Symbol | Number | Object
+ BigInt = 1 << 6,
+ Object = 1 << 7,
+ ALL = Undefined | Null | Boolean | String | Symbol | Number | BigInt | Object
};
class Object : public PointerValue {
}
}
- void defineOwnPropertyThrowsExceptionWhenStrictMode(ExecutionState& state, const ObjectPropertyName& P, const ObjectPropertyDescriptor& desc)
- {
- if (!defineOwnProperty(state, P, desc) && state.inStrictMode()) {
- throwCannotDefineError(state, P.toObjectStructurePropertyName(state));
- }
- }
-
void deleteOwnPropertyThrowsException(ExecutionState& state, const ObjectPropertyName& P)
{
if (!deleteOwnProperty(state, P)) {
static void throwCannotDeleteError(ExecutionState& state, const ObjectStructurePropertyName& P);
static ArrayObject* createArrayFromList(ExecutionState& state, const uint64_t& size, const Value* buffer);
static ArrayObject* createArrayFromList(ExecutionState& state, const ValueVector& elements);
- static ValueVector createListFromArrayLike(ExecutionState& state, Value obj, uint8_t types = (uint8_t)ElementTypes::ALL);
+ static ValueVector createListFromArrayLike(ExecutionState& state, Value obj, uint8_t types = static_cast<uint8_t>(ElementTypes::ALL));
static ValueVectorWithInlineStorage enumerableOwnProperties(ExecutionState& state, Object* object, EnumerableOwnPropertiesType kind);
// this function differ with defineOwnProperty.
void deleteOwnProperty(ExecutionState& state, size_t idx);
void markAsNonInlineCachable();
+
+ // redefine function used only for builtin installation
+ void redefineOwnProperty(ExecutionState& state, const ObjectPropertyName& P, const ObjectPropertyDescriptor& desc);
};
} // namespace Escargot
virtual void didLoadModule(Context* relatedContext, Optional<Script*> whereRequestFrom, Script* loadedModule) = 0;
virtual void hostImportModuleDynamically(Context* relatedContext, Script* referrer, String* src, PromiseObject* promise) = 0;
+ virtual bool canBlockExecution(Context* relatedContext) = 0;
+
// ThreadLocal custom data (g_customData)
virtual void* allocateThreadLocalCustomData() = 0;
virtual void deallocateThreadLocalCustomData() = 0;
#if defined(ENABLE_INTL)
class IntlLocaleObject;
class IntlPluralRulesObject;
+class IntlDateTimeFormatObject;
class IntlRelativeTimeFormatObject;
#endif
#if defined(ENABLE_WASM)
return false;
}
+ virtual bool isIntlDateTimeFormatObject() const
+ {
+ return false;
+ }
+
virtual bool isIntlRelativeTimeFormatObject() const
{
return false;
return (IntlPluralRulesObject*)this;
}
+ IntlDateTimeFormatObject* asIntlDateTimeFormatObject()
+ {
+ ASSERT(isIntlDateTimeFormatObject());
+ return (IntlDateTimeFormatObject*)this;
+ }
+
IntlRelativeTimeFormatObject* asIntlRelativeTimeFormatObject()
{
ASSERT(isIntlRelativeTimeFormatObject());
Value trapResultArray;
Value arguments[] = { target };
trapResultArray = Object::call(state, trap, handler, 1, arguments);
- auto trapResult = Object::createListFromArrayLike(state, trapResultArray, ((uint8_t)ElementTypes::String | (uint8_t)ElementTypes::Symbol));
+ auto trapResult = Object::createListFromArrayLike(state, trapResultArray, (static_cast<uint8_t>(ElementTypes::String) | static_cast<uint8_t>(ElementTypes::Symbol)));
// If trapResult contains any duplicate entries, throw a TypeError exception
for (size_t i = 0; i < trapResult.size(); i++) {
Value ScriptArrowFunctionObject::construct(ExecutionState& state, const size_t argc, Value* argv, Object* newTarget)
{
- ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Arrow function cannot be invoked with 'new'");
+ ExecutionState newState(m_codeBlock->context(), &state,
+ static_cast<LexicalEnvironment*>(nullptr), argc, argv, m_codeBlock->asInterpretedCodeBlock()->isStrict());
+ ErrorObject::throwBuiltinError(newState, ErrorObject::TypeError, "Arrow function cannot be invoked with 'new'");
ASSERT_NOT_REACHED();
return Value();
}
Value ScriptAsyncFunctionObject::construct(ExecutionState& state, const size_t argc, Value* argv, Object* newTarget)
{
- ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Async function cannot be invoked with 'new'");
+ ExecutionState newState(m_codeBlock->context(), &state,
+ static_cast<LexicalEnvironment*>(nullptr), argc, argv, m_codeBlock->asInterpretedCodeBlock()->isStrict());
+ ErrorObject::throwBuiltinError(newState, ErrorObject::TypeError, "Async function cannot be invoked with 'new'");
ASSERT_NOT_REACHED();
return Value();
}
Value ScriptAsyncGeneratorFunctionObject::construct(ExecutionState& state, const size_t argc, Value* argv, Object* newTarget)
{
- ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "AsyncGenerator cannot be invoked with 'new'");
+ ExecutionState newState(m_codeBlock->context(), &state,
+ static_cast<LexicalEnvironment*>(nullptr), argc, argv, m_codeBlock->asInterpretedCodeBlock()->isStrict());
+ ErrorObject::throwBuiltinError(newState, ErrorObject::TypeError, "AsyncGenerator cannot be invoked with 'new'");
ASSERT_NOT_REACHED();
return Value();
}
Value ScriptClassConstructorFunctionObject::call(ExecutionState& state, const Value& thisValue, const size_t argc, Value* argv)
{
- ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Class constructor cannot be invoked without 'new'");
+ ExecutionState newState(m_codeBlock->context(), &state, static_cast<LexicalEnvironment*>(nullptr), argc, argv, m_codeBlock->asInterpretedCodeBlock()->isStrict());
+ ErrorObject::throwBuiltinError(newState, ErrorObject::TypeError, "Class constructor cannot be invoked without 'new'");
return Value();
}
Value ScriptGeneratorFunctionObject::construct(ExecutionState& state, const size_t argc, Value* argv, Object* newTarget)
{
- ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "Generator cannot be invoked with 'new'");
+ ExecutionState newState(m_codeBlock->context(), &state,
+ static_cast<LexicalEnvironment*>(nullptr), argc, argv, m_codeBlock->asInterpretedCodeBlock()->isStrict());
+ ErrorObject::throwBuiltinError(newState, ErrorObject::TypeError, "Generator cannot be invoked with 'new'");
ASSERT_NOT_REACHED();
return Value();
}
Value ScriptVirtualArrowFunctionObject::call(ExecutionState& state, const Value& thisValue, const size_t argc, Value* argv)
{
- ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "This function cannot be invoked");
+ ExecutionState newState(m_codeBlock->context(), &state,
+ static_cast<LexicalEnvironment*>(nullptr), argc, argv, m_codeBlock->asInterpretedCodeBlock()->isStrict());
+ ErrorObject::throwBuiltinError(newState, ErrorObject::TypeError, "This function cannot be invoked");
ASSERT_NOT_REACHED();
return Value();
}
Value ScriptVirtualArrowFunctionObject::construct(ExecutionState& state, const size_t argc, Value* argv, Object* newTarget)
{
- ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, "This function cannot be invoked");
+ ExecutionState newState(m_codeBlock->context(), &state,
+ static_cast<LexicalEnvironment*>(nullptr), argc, argv, m_codeBlock->asInterpretedCodeBlock()->isStrict());
+ ErrorObject::throwBuiltinError(newState, ErrorObject::TypeError, "This function cannot be invoked");
ASSERT_NOT_REACHED();
return Value();
}
#define DECLARE_LAZY_STATIC_STRING(Name, unused) m_lazy##Name = AtomicString();
FOR_EACH_LAZY_STATIC_STRING(DECLARE_LAZY_STATIC_STRING);
FOR_EACH_LAZY_INTL_STATIC_STRING(DECLARE_LAZY_STATIC_STRING);
+ FOR_EACH_LAZY_THREADING_STATIC_STRING(DECLARE_LAZY_STATIC_STRING);
#undef DECLARE_LAZY_STATIC_STRING
}
}
FOR_EACH_LAZY_STATIC_STRING(DECLARE_LAZY_STATIC_STRING);
FOR_EACH_LAZY_INTL_STATIC_STRING(DECLARE_LAZY_STATIC_STRING);
+FOR_EACH_LAZY_THREADING_STATIC_STRING(DECLARE_LAZY_STATIC_STRING);
#undef DECLARE_LAZY_STATIC_STRING
::Escargot::String* StaticStrings::dtoa(double d) const
F(callee) \
F(caller) \
F(caseFirst) \
+ F(cause) \
F(cbrt) \
F(ceil) \
F(charAt) \
F(finally) \
F(find) \
F(findIndex) \
+ F(findLast) \
+ F(findLastIndex) \
F(fixed) \
F(flags) \
F(flat) \
F(groups) \
F(has) \
F(hasInstance) \
+ F(hasOwn) \
F(hasOwnProperty) \
F(hourCycle) \
F(hypot) \
F(URL, "url")
#if defined(ENABLE_INTL)
-#define FOR_EACH_LAZY_INTL_STATIC_STRING(F) \
- F(Accent, "accent") \
- F(Accounting, "accounting") \
- F(Always, "always") \
- F(Any, "any") \
- F(Auto, "auto") \
- F(Base, "base") \
- F(Basic, "basic") \
- F(BestFit, "best fit") \
- F(Cardinal, "cardinal") \
- F(Case, "case") \
- F(Code, "code") \
- F(Compact, "compact") \
- F(CompactDisplay, "compactDisplay") \
- F(CompareFunction, "compareFunction") \
- F(Currency, "currency") \
- F(CurrencyDisplay, "currencyDisplay") \
- F(CurrencySign, "currencySign") \
- F(DashU, "-u") \
- F(DataLocale, "dataLocale") \
- F(Date, "date") \
- F(Day, "day") \
- F(DayPeriod, "dayPeriod") \
- F(Decimal, "decimal") \
- F(Engineering, "engineering") \
- F(Era, "era") \
- F(ExceptZero, "exceptZero") \
- F(ExponentInteger, "exponentInteger") \
- F(ExponentMinusSign, "exponentMinusSign") \
- F(ExponentSeparator, "exponentSeparator") \
- F(FormatMatcher, "formatMatcher") \
- F(Fraction, "fraction") \
- F(Group, "group") \
- F(H11, "h11") \
- F(H12, "h12") \
- F(H23, "h23") \
- F(H24, "h24") \
- F(Hour, "hour") \
- F(Hour12, "hour12") \
- F(IgnorePunctuation, "ignorePunctuation") \
- F(InitializedCollator, "initializedCollator") \
- F(InitializedDateTimeFormat, "initializedDateTimeFormat") \
- F(InitializedIntlObject, "initializedIntlObject") \
- F(InitializedNumberFormat, "initializedNumberFormat") \
- F(Integer, "integer") \
- F(Kf, "kf") \
- F(Kn, "kn") \
- F(Literal, "literal") \
- F(LocaleMatcher, "localeMatcher") \
- F(Long, "long") \
- F(Lookup, "lookup") \
- F(Lower, "lower") \
- F(MaximumFractionDigits, "maximumFractionDigits") \
- F(MaximumSignificantDigits, "maximumSignificantDigits") \
- F(MinimumFractionDigits, "minimumFractionDigits") \
- F(MinimumIntegerDigits, "minimumIntegerDigits") \
- F(MinimumSignificantDigits, "minimumSignificantDigits") \
- F(MinusSign, "minusSign") \
- F(Minute, "minute") \
- F(Month, "month") \
- F(Narrow, "narrow") \
- F(NarrowSymbol, "narrowSymbol") \
- F(Never, "never") \
- F(Notation, "notation") \
- F(Ordinal, "ordinal") \
- F(Percent, "percent") \
- F(PercentSign, "percentSign") \
- F(PlusSign, "plusSign") \
- F(Quarter, "quarter") \
- F(Scientific, "scientific") \
- F(Second, "second") \
- F(Sensitivity, "sensitivity") \
- F(Short, "short") \
- F(SignDisplay, "signDisplay") \
- F(SmallLetterInfinity, "infinity") \
- F(SmallLetterLocale, "locale") \
- F(SmallLetterNaN, "nan") \
- F(Standard, "standard") \
- F(Style, "style") \
- F(Time, "time") \
- F(TimeZone, "timeZone") \
- F(TimeZoneName, "timeZoneName") \
- F(TwoDigit, "2-digit") \
- F(Type, "type") \
- F(Unit, "unit") \
- F(UnitDisplay, "unitDisplay") \
- F(Upper, "upper") \
- F(Usage, "usage") \
- F(UseGrouping, "useGrouping") \
- F(Variant, "variant") \
- F(Week, "week") \
- F(Weekday, "weekday") \
+#define FOR_EACH_LAZY_INTL_STATIC_STRING(F) \
+ F(Accent, "accent") \
+ F(Accounting, "accounting") \
+ F(Always, "always") \
+ F(Any, "any") \
+ F(Auto, "auto") \
+ F(Base, "base") \
+ F(Basic, "basic") \
+ F(BestFit, "best fit") \
+ F(Cardinal, "cardinal") \
+ F(Case, "case") \
+ F(Code, "code") \
+ F(Compact, "compact") \
+ F(CompactDisplay, "compactDisplay") \
+ F(CompareFunction, "compareFunction") \
+ F(Currency, "currency") \
+ F(CurrencyDisplay, "currencyDisplay") \
+ F(CurrencySign, "currencySign") \
+ F(DashU, "-u") \
+ F(DataLocale, "dataLocale") \
+ F(Date, "date") \
+ F(DateStyle, "dateStyle") \
+ F(Day, "day") \
+ F(DayPeriod, "dayPeriod") \
+ F(Decimal, "decimal") \
+ F(Engineering, "engineering") \
+ F(Era, "era") \
+ F(ExceptZero, "exceptZero") \
+ F(ExponentInteger, "exponentInteger") \
+ F(ExponentMinusSign, "exponentMinusSign") \
+ F(ExponentSeparator, "exponentSeparator") \
+ F(FormatMatcher, "formatMatcher") \
+ F(Fraction, "fraction") \
+ F(FractionalSecond, "fractionalSecond") \
+ F(FractionalSecondDigits, "fractionalSecondDigits") \
+ F(Full, "full") \
+ F(Group, "group") \
+ F(H11, "h11") \
+ F(H12, "h12") \
+ F(H23, "h23") \
+ F(H24, "h24") \
+ F(Hour, "hour") \
+ F(Hour12, "hour12") \
+ F(IgnorePunctuation, "ignorePunctuation") \
+ F(InitializedCollator, "initializedCollator") \
+ F(InitializedIntlObject, "initializedIntlObject") \
+ F(InitializedNumberFormat, "initializedNumberFormat") \
+ F(Integer, "integer") \
+ F(Kf, "kf") \
+ F(Kn, "kn") \
+ F(Literal, "literal") \
+ F(LocaleMatcher, "localeMatcher") \
+ F(Long, "long") \
+ F(Lookup, "lookup") \
+ F(Lower, "lower") \
+ F(MaximumFractionDigits, "maximumFractionDigits") \
+ F(MaximumSignificantDigits, "maximumSignificantDigits") \
+ F(Medium, "medium") \
+ F(MinimumFractionDigits, "minimumFractionDigits") \
+ F(MinimumIntegerDigits, "minimumIntegerDigits") \
+ F(MinimumSignificantDigits, "minimumSignificantDigits") \
+ F(MinusSign, "minusSign") \
+ F(Minute, "minute") \
+ F(Month, "month") \
+ F(Narrow, "narrow") \
+ F(NarrowSymbol, "narrowSymbol") \
+ F(Never, "never") \
+ F(Notation, "notation") \
+ F(Ordinal, "ordinal") \
+ F(Percent, "percent") \
+ F(PercentSign, "percentSign") \
+ F(PlusSign, "plusSign") \
+ F(Quarter, "quarter") \
+ F(Scientific, "scientific") \
+ F(Second, "second") \
+ F(Sensitivity, "sensitivity") \
+ F(Short, "short") \
+ F(SignDisplay, "signDisplay") \
+ F(SmallLetterInfinity, "infinity") \
+ F(SmallLetterLocale, "locale") \
+ F(SmallLetterNaN, "nan") \
+ F(Standard, "standard") \
+ F(Style, "style") \
+ F(Time, "time") \
+ F(TimeStyle, "timeStyle") \
+ F(TimeZone, "timeZone") \
+ F(TimeZoneName, "timeZoneName") \
+ F(TwoDigit, "2-digit") \
+ F(Type, "type") \
+ F(Unit, "unit") \
+ F(UnitDisplay, "unitDisplay") \
+ F(Upper, "upper") \
+ F(Usage, "usage") \
+ F(UseGrouping, "useGrouping") \
+ F(Variant, "variant") \
+ F(Week, "week") \
+ F(Weekday, "weekday") \
F(Year, "year")
#else
#define FOR_EACH_LAZY_INTL_STATIC_STRING(F)
#endif
+#if defined(ENABLE_THREADING)
+#define FOR_EACH_LAZY_THREADING_STATIC_STRING(F) \
+ F(NotEqual, "not-equal") \
+ F(Ok, "ok") \
+ F(TimedOut, "timed-out")
+#else
+#define FOR_EACH_LAZY_THREADING_STATIC_STRING(F)
+#endif
+
class StaticStrings {
public:
StaticStrings(AtomicStringMap* atomicStringMap)
#define DECLARE_LAZY_STATIC_STRING(Name, unused) AtomicString lazy##Name();
FOR_EACH_LAZY_STATIC_STRING(DECLARE_LAZY_STATIC_STRING);
FOR_EACH_LAZY_INTL_STATIC_STRING(DECLARE_LAZY_STATIC_STRING);
+ FOR_EACH_LAZY_THREADING_STATIC_STRING(DECLARE_LAZY_STATIC_STRING);
#undef DECLARE_LAZY_STATIC_STRING
void initStaticStrings();
#define DECLARE_LAZY_STATIC_STRING(Name, unused) AtomicString m_lazy##Name;
FOR_EACH_LAZY_STATIC_STRING(DECLARE_LAZY_STATIC_STRING);
FOR_EACH_LAZY_INTL_STATIC_STRING(DECLARE_LAZY_STATIC_STRING);
+ FOR_EACH_LAZY_THREADING_STATIC_STRING(DECLARE_LAZY_STATIC_STRING);
#undef DECLARE_LAZY_STATIC_STRING
};
} // namespace Escargot
class ShellPlatform : public PlatformRef {
public:
+ bool m_canBlock;
+
+ ShellPlatform()
+ : m_canBlock(true)
+ {
+ }
+
+ void setCanBlock(bool b)
+ {
+ m_canBlock = b;
+ }
+
virtual void markJSJobEnqueued(ContextRef* relatedContext) override
{
// ignore. we always check pending job after eval script
notifyHostImportModuleDynamicallyResult(relatedContext, referrer, src, promise, loadedModuleResult);
}
+ virtual bool canBlockExecution(ContextRef* relatedContext) override
+ {
+ return m_canBlock;
+ }
+
virtual void* allocateThreadLocalCustomData() override
{
return new std::vector<std::tuple<std::string /* abs path */, ContextRef*, PersistentRefHolder<ScriptRef>>>();
mallopt(M_MMAP_MAX, 1024 * 1024);
#endif
- Globals::initialize(new ShellPlatform());
+ ShellPlatform* platform = new ShellPlatform();
+ Globals::initialize(platform);
Memory::setGCFrequency(24);
seenModule = true;
continue;
}
+ if (strcmp(argv[i], "--canblock-is-false") == 0) {
+ platform->setCanBlock(false);
+ continue;
+ }
if (strstr(argv[i], "--filename-as=") == argv[i]) {
fileName = argv[i] + sizeof("--filename-as=") - 1;
continue;
}
// WebAssemblly.Error
-#define DEFINE_ERROR_CTOR(errorName, lowerCaseErrorName) \
- static Value builtin##errorName##ErrorConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget) \
- { \
- if (!newTarget.hasValue()) { \
- newTarget = state.resolveCallee(); \
- } \
- Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* { \
- return constructorRealm->globalObject()->lowerCaseErrorName##ErrorPrototype(); \
- }); \
- ErrorObject* obj = new errorName##ErrorObject(state, proto, String::emptyString); \
- Value message = argv[0]; \
- if (!message.isUndefined()) { \
- obj->defineOwnPropertyThrowsExceptionWhenStrictMode(state, state.context()->staticStrings().message, \
- ObjectPropertyDescriptor(message.toString(state), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectStructurePropertyDescriptor::ConfigurablePresent))); \
- } \
- return obj; \
+#define DEFINE_ERROR_CTOR(errorName, lowerCaseErrorName) \
+ static Value builtin##errorName##ErrorConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget) \
+ { \
+ if (!newTarget.hasValue()) { \
+ newTarget = state.resolveCallee(); \
+ } \
+ Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* { \
+ return constructorRealm->globalObject()->lowerCaseErrorName##ErrorPrototype(); \
+ }); \
+ ErrorObject* obj = new errorName##ErrorObject(state, proto, String::emptyString); \
+ Value message = argv[0]; \
+ if (!message.isUndefined()) { \
+ obj->defineOwnPropertyThrowsException(state, state.context()->staticStrings().message, \
+ ObjectPropertyDescriptor(message.toString(state), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectStructurePropertyDescriptor::ConfigurablePresent))); \
+ } \
+ return obj; \
}
DEFINE_ERROR_CTOR(WASMCompile, wasmCompile)
DEFINE_ERROR_CTOR(WASMLink, wasmLink)
DEFINE_ERROR_CTOR(WASMRuntime, wasmRuntime)
-void GlobalObject::installWASM(ExecutionState& state)
+void GlobalObject::initializeWebAssembly(ExecutionState& state)
+{
+ ObjectPropertyNativeGetterSetterData* nativeData = new ObjectPropertyNativeGetterSetterData(true, false, true,
+ [](ExecutionState& state, Object* self, const Value& receiver, const EncodedValue& privateDataFromObjectPrivateArea) -> Value {
+ ASSERT(self->isGlobalObject());
+ return self->asGlobalObject()->wasm();
+ },
+ nullptr);
+
+ defineNativeDataAccessorProperty(state, ObjectPropertyName(state.context()->staticStrings().WebAssembly), nativeData, Value(Value::EmptyValue));
+}
+
+void GlobalObject::installWebAssembly(ExecutionState& state)
{
// builtin Error should be installed ahead
- ASSERT(!!this->error());
+ if (!m_error) {
+ error();
+ }
+ ASSERT(!!m_error);
Object* wasm = new Object(state);
wasm->setGlobalIntrinsicObject(state);
+ m_wasm = wasm;
const StaticStrings* strings = &state.context()->staticStrings();
DEFINE_ERROR(wasmRuntime, WASMRuntime, Runtime)
- defineOwnProperty(state, ObjectPropertyName(strings->WebAssembly),
- ObjectPropertyDescriptor(wasm, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+ redefineOwnProperty(state, ObjectPropertyName(strings->WebAssembly),
+ ObjectPropertyDescriptor(wasm, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
+}
+} // namespace Escargot
+
+#else
+
+#include "Escargot.h"
+#include "runtime/GlobalObject.h"
+
+namespace Escargot {
+class ExecutionState;
+
+void GlobalObject::initializeWebAssembly(ExecutionState& state)
+{
+ // dummy initialize function
}
} // namespace Escargot
#define udat_formatForFields RuntimeICUBinder::ICU::instance().udat_formatForFields
#define udat_close RuntimeICUBinder::ICU::instance().udat_close
#define udat_getCalendar RuntimeICUBinder::ICU::instance().udat_getCalendar
+#define udat_toPattern RuntimeICUBinder::ICU::instance().udat_toPattern
#define uenum_count RuntimeICUBinder::ICU::instance().uenum_count
#define uenum_unext RuntimeICUBinder::ICU::instance().uenum_unext
#define udatpg_open RuntimeICUBinder::ICU::instance().udatpg_open
#define udatpg_getBestPattern RuntimeICUBinder::ICU::instance().udatpg_getBestPattern
#define udatpg_getBestPatternWithOptions RuntimeICUBinder::ICU::instance().udatpg_getBestPatternWithOptions
+#define udatpg_getSkeleton RuntimeICUBinder::ICU::instance().udatpg_getSkeleton
#define ubrk_open RuntimeICUBinder::ICU::instance().ubrk_open
#define ubrk_openRules RuntimeICUBinder::ICU::instance().ubrk_openRules
F(udat_format, int32_t (*)(const UDateFormat*, UDate, UChar*, int32_t, UFieldPosition*, UErrorCode*), int32_t) \
F(udat_formatForFields, int32_t (*)(const UDateFormat* format, UDate, UChar*, int32_t, UFieldPositionIterator*, UErrorCode*), int32_t) \
F(udat_getCalendar, const UCalendar* (*)(const UDateFormat* fmt), const UCalendar*) \
+ F(udat_toPattern, int32_t (*)(const UDateFormat *fmt, UBool localized, UChar *result, int32_t resultLength, UErrorCode *status), int32_t) \
F(uenum_count, int32_t (*)(UEnumeration * en, UErrorCode * status), int32_t) \
F(uenum_unext, const UChar* (*)(UEnumeration * en, int32_t * resultLength, UErrorCode * status), const UChar*) \
F(uenum_next, const char* (*)(UEnumeration * en, int32_t * resultLength, UErrorCode * status), const char*) \
F(udatpg_open, UDateTimePatternGenerator* (*)(const char* locale, UErrorCode* pErrorCode), UDateTimePatternGenerator*) \
F(udatpg_getBestPattern, int32_t (*)(UDateTimePatternGenerator * dtpg, const UChar* skeleton, int32_t length, UChar* bestPattern, int32_t capacity, UErrorCode* pErrorCode), int32_t) \
F(udatpg_getBestPatternWithOptions, int32_t (*)(UDateTimePatternGenerator*, const UChar*, int32_t, UDateTimePatternMatchOptions, UChar*, int32_t, UErrorCode*), int32_t) \
+ F(udatpg_getSkeleton, int32_t (*)(UDateTimePatternGenerator *unusedDtpg, const UChar *pattern, int32_t length, UChar *skeleton, int32_t capacity, UErrorCode *pErrorCode), int32_t) \
F(unum_countAvailable, int32_t (*)(), int32_t) \
F(unum_getAvailable, const char* (*)(int32_t), const char*) \
F(unum_open, UNumberFormat* (*)(UNumberFormatStyle style, const UChar* pattern, int32_t patternLength, const char* locale, UParseError* parseErr, UErrorCode* status), UNumberFormat*) \
--- /dev/null
+b do_break_class.js:37
+n
+b do_break_class.js:36
+c
+bt
+b do_break_class.js:66
+c
+c
+bt
+b do_break_class.js:69
+c
+b do_break_class.js:26
+b do_break_class.js:50
+b do_break_class.js:55
+c
+c
+bt
+c
+bt
+c
--- /dev/null
+Connecting to: localhost:6501
+Connection created!!!
+Stopped at tools/debugger/tests/do_break_class.js:20
+(escargot-debugger) b do_break_class.js:37
+No breakpoint found, do you want to add a pending breakpoint? (y or [n])
+(escargot-debugger) b do_break_class.js:36
+Breakpoint 1 at tools/debugger/tests/do_break_class.js:36 (in function() at line:37, col:7)
+(escargot-debugger) c
+Stopped at breakpoint:1 tools/debugger/tests/do_break_class.js:36 (in function() at line:37, col:7)
+(escargot-debugger) bt
+tools/debugger/tests/do_break_class.js:37:6 [depth:0]
+tools/debugger/tests/do_break_class.js:22:14 [depth:1]
+(escargot-debugger) b do_break_class.js:66
+Breakpoint 2 at tools/debugger/tests/do_break_class.js:66 (in function() at line:66, col:24)
+Breakpoint 3 at tools/debugger/tests/do_break_class.js:66 (in function() at line:66, col:48)
+(escargot-debugger) c
+Stopped at breakpoint:2 tools/debugger/tests/do_break_class.js:66 (in function() at line:66, col:24)
+(escargot-debugger) c
+Stopped at breakpoint:3 tools/debugger/tests/do_break_class.js:66 (in function() at line:66, col:48)
+(escargot-debugger) bt
+tools/debugger/tests/do_break_class.js:66:47 [depth:0]
+tools/debugger/tests/do_break_class.js:46:29 [depth:1]
+(escargot-debugger) b do_break_class.js:69
+Breakpoint 4 at tools/debugger/tests/do_break_class.js:69
+(escargot-debugger) c
+Stopped at breakpoint:4 tools/debugger/tests/do_break_class.js:69
+(escargot-debugger) b do_break_class.js:26
+Breakpoint 5 at tools/debugger/tests/do_break_class.js:26 (in function() at line:28, col:7)
+(escargot-debugger) b do_break_class.js:50
+Breakpoint 6 at tools/debugger/tests/do_break_class.js:50 (in function() at line:50, col:16)
+(escargot-debugger) b do_break_class.js:55
+Breakpoint 7 at tools/debugger/tests/do_break_class.js:55 (in constructor() at line:53, col:3)
+(escargot-debugger) c
+Stopped at breakpoint:7 tools/debugger/tests/do_break_class.js:55 (in constructor() at line:53, col:3)
+(escargot-debugger) c
+Stopped at breakpoint:5 tools/debugger/tests/do_break_class.js:26 (in function() at line:28, col:7)
+(escargot-debugger) bt
+tools/debugger/tests/do_break_class.js:28:6 [depth:0]
+tools/debugger/tests/do_break_class.js:55:5 [depth:2] (in constructor)
+tools/debugger/tests/do_break_class.js:69:9 [depth:3]
+(escargot-debugger) c
+Stopped at breakpoint:6 tools/debugger/tests/do_break_class.js:50 (in function() at line:50, col:16)
+(escargot-debugger) bt
+tools/debugger/tests/do_break_class.js:50:15 [depth:0]
+tools/debugger/tests/do_break_class.js:55:5 [depth:1] (in constructor)
+tools/debugger/tests/do_break_class.js:69:9 [depth:2]
+(escargot-debugger) c
+Connection closed.
--- /dev/null
+s
+bt
+s
+s
+s
+s
+bt
+s
+s
+s
+s
+s
+s
+s
+bt
+s
+s
+s
+s
+s
+s
+bt
+s
+s
+s
+s
+s
+s
--- /dev/null
+Connecting to: localhost:6501
+Connection created!!!
+Stopped at tools/debugger/tests/do_step_class.js:20
+(escargot-debugger) s
+Stopped at tools/debugger/tests/do_step_class.js:36 (in function() at line:37, col:7)
+(escargot-debugger) bt
+tools/debugger/tests/do_step_class.js:37:6 [depth:0]
+tools/debugger/tests/do_step_class.js:22:14 [depth:1]
+(escargot-debugger) s
+Stopped at tools/debugger/tests/do_step_class.js:40 (in function() at line:42, col:7)
+(escargot-debugger) s
+Stopped at tools/debugger/tests/do_step_class.js:43 (in function() at line:43, col:23)
+(escargot-debugger) s
+Stopped at tools/debugger/tests/do_step_class.js:43 (in function() at line:43, col:46)
+(escargot-debugger) s
+Stopped at tools/debugger/tests/do_step_class.js:60 (in function() at line:61, col:7)
+(escargot-debugger) bt
+tools/debugger/tests/do_step_class.js:61:6 [depth:0]
+tools/debugger/tests/do_step_class.js:46:29 [depth:1]
+(escargot-debugger) s
+Stopped at tools/debugger/tests/do_step_class.js:64 (in function() at line:65, col:7)
+(escargot-debugger) s
+Stopped at tools/debugger/tests/do_step_class.js:66 (in function() at line:66, col:24)
+(escargot-debugger) s
+Stopped at tools/debugger/tests/do_step_class.js:66 (in function() at line:66, col:48)
+(escargot-debugger) s
+Stopped at tools/debugger/tests/do_step_class.js:69
+(escargot-debugger) s
+Stopped at tools/debugger/tests/do_step_class.js:54 (in constructor() at line:53, col:3)
+(escargot-debugger) s
+Stopped at tools/debugger/tests/do_step_class.js:55 (in constructor() at line:53, col:3)
+(escargot-debugger) s
+Stopped at tools/debugger/tests/do_step_class.js:23 (in function() at line:24, col:7)
+(escargot-debugger) bt
+tools/debugger/tests/do_step_class.js:24:6 [depth:0]
+tools/debugger/tests/do_step_class.js:55:5 [depth:2] (in constructor)
+tools/debugger/tests/do_step_class.js:69:9 [depth:3]
+(escargot-debugger) s
+Stopped at tools/debugger/tests/do_step_class.js:26 (in function() at line:28, col:7)
+(escargot-debugger) s
+Stopped at tools/debugger/tests/do_step_class.js:29 (in function() at line:29, col:15)
+(escargot-debugger) s
+Stopped at tools/debugger/tests/do_step_class.js:29 (in function() at line:29, col:30)
+(escargot-debugger) s
+Stopped at tools/debugger/tests/do_step_class.js:32 (in constructor() at line:31, col:3)
+(escargot-debugger) s
+Stopped at tools/debugger/tests/do_step_class.js:33 (in constructor() at line:31, col:3)
+(escargot-debugger) s
+Stopped at tools/debugger/tests/do_step_class.js:47 (in function() at line:48, col:7)
+(escargot-debugger) bt
+tools/debugger/tests/do_step_class.js:48:6 [depth:0]
+tools/debugger/tests/do_step_class.js:55:5 [depth:1] (in constructor)
+tools/debugger/tests/do_step_class.js:69:9 [depth:2]
+(escargot-debugger) s
+Stopped at tools/debugger/tests/do_step_class.js:50 (in function() at line:50, col:16)
+(escargot-debugger) s
+Stopped at tools/debugger/tests/do_step_class.js:51 (in function() at line:51, col:16)
+(escargot-debugger) s
+Stopped at tools/debugger/tests/do_step_class.js:51 (in function() at line:51, col:31)
+(escargot-debugger) s
+Stopped at tools/debugger/tests/do_step_class.js:56 (in constructor() at line:53, col:3)
+(escargot-debugger) s
+Stopped at tools/debugger/tests/do_step_class.js:57 (in constructor() at line:53, col:3)
+(escargot-debugger) s
+Connection closed.
--- /dev/null
+/* crypt.h -- base code for crypt/uncrypt ZIPfile
+
+
+ Version 1.01e, February 12th, 2005
+
+ Copyright (C) 1998-2005 Gilles Vollant
+
+ This code is a modified version of crypting code in Infozip distribution
+
+ The encryption/decryption parts of this source code (as opposed to the
+ non-echoing password parts) were originally written in Europe. The
+ whole source package can be freely distributed, including from the USA.
+ (Prior to January 2000, re-export from the US was a violation of US law.)
+
+ This encryption code is a direct transcription of the algorithm from
+ Roger Schlafly, described by Phil Katz in the file appnote.txt. This
+ file (appnote.txt) is distributed with the PKZIP program (even in the
+ version without encryption capabilities).
+
+ If you don't need crypting in your application, just define symbols
+ NOCRYPT and NOUNCRYPT.
+
+ This code support the "Traditional PKWARE Encryption".
+
+ The new AES encryption added on Zip format by Winzip (see the page
+ http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong
+ Encryption is not supported.
+*/
+
+#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8))
+
+/***********************************************************************
+ * Return the next byte in the pseudo-random sequence
+ */
+static int decrypt_byte(unsigned long* pkeys, const z_crc_t* pcrc_32_tab)
+{
+ unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an
+ * unpredictable manner on 16-bit systems; not a problem
+ * with any known compiler so far, though */
+
+ temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2;
+ return (int)(((temp * (temp ^ 1)) >> 8) & 0xff);
+}
+
+/***********************************************************************
+ * Update the encryption keys with the next byte of plain text
+ */
+static int update_keys(unsigned long* pkeys,const z_crc_t* pcrc_32_tab,int c)
+{
+ (*(pkeys+0)) = CRC32((*(pkeys+0)), c);
+ (*(pkeys+1)) += (*(pkeys+0)) & 0xff;
+ (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1;
+ {
+ register int keyshift = (int)((*(pkeys+1)) >> 24);
+ (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift);
+ }
+ return c;
+}
+
+
+/***********************************************************************
+ * Initialize the encryption keys and the random header according to
+ * the given password.
+ */
+static void init_keys(const char* passwd,unsigned long* pkeys,const z_crc_t* pcrc_32_tab)
+{
+ *(pkeys+0) = 305419896L;
+ *(pkeys+1) = 591751049L;
+ *(pkeys+2) = 878082192L;
+ while (*passwd != '\0') {
+ update_keys(pkeys,pcrc_32_tab,(int)*passwd);
+ passwd++;
+ }
+}
+
+#define zdecode(pkeys,pcrc_32_tab,c) \
+ (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab)))
+
+#define zencode(pkeys,pcrc_32_tab,c,t) \
+ (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c))
+
+#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED
+
+#define RAND_HEAD_LEN 12
+ /* "last resort" source for second part of crypt seed pattern */
+# ifndef ZCR_SEED2
+# define ZCR_SEED2 3141592654UL /* use PI as default pattern */
+# endif
+
+static int crypthead(const char* passwd, /* password string */
+ unsigned char* buf, /* where to write header */
+ int bufSize,
+ unsigned long* pkeys,
+ const z_crc_t* pcrc_32_tab,
+ unsigned long crcForCrypting)
+{
+ int n; /* index in random header */
+ int t; /* temporary */
+ int c; /* random byte */
+ unsigned char header[RAND_HEAD_LEN-2]; /* random header */
+ static unsigned calls = 0; /* ensure different random header each time */
+
+ if (bufSize<RAND_HEAD_LEN)
+ return 0;
+
+ /* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the
+ * output of rand() to get less predictability, since rand() is
+ * often poorly implemented.
+ */
+ if (++calls == 1)
+ {
+ srand((unsigned)(time(NULL) ^ ZCR_SEED2));
+ }
+ init_keys(passwd, pkeys, pcrc_32_tab);
+ for (n = 0; n < RAND_HEAD_LEN-2; n++)
+ {
+ c = (rand() >> 7) & 0xff;
+ header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t);
+ }
+ /* Encrypt random header (last two bytes is high word of crc) */
+ init_keys(passwd, pkeys, pcrc_32_tab);
+ for (n = 0; n < RAND_HEAD_LEN-2; n++)
+ {
+ buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t);
+ }
+ buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t);
+ buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t);
+ return n;
+}
+
+#endif
--- /dev/null
+/* ioapi.h -- IO base function header for compress/uncompress .zip
+ part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
+
+ Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
+
+ Modifications for Zip64 support
+ Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
+
+ For more info read MiniZip_info.txt
+
+*/
+
+#if defined(_WIN32) && (!(defined(_CRT_SECURE_NO_WARNINGS)))
+ #define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#if defined(__APPLE__) || defined(__Fuchsia__) || defined(IOAPI_NO_64)
+// In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions
+#define FOPEN_FUNC(filename, mode) fopen(filename, mode)
+#define FTELLO_FUNC(stream) ftello(stream)
+#define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin)
+#else
+#define FOPEN_FUNC(filename, mode) fopen64(filename, mode)
+#define FTELLO_FUNC(stream) ftello64(stream)
+#define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin)
+#endif
+
+
+#include "ioapi.h"
+
+voidpf call_zopen64 (const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode)
+{
+ if (pfilefunc->zfile_func64.zopen64_file != NULL)
+ return (*(pfilefunc->zfile_func64.zopen64_file)) (pfilefunc->zfile_func64.opaque,filename,mode);
+ else
+ {
+ return (*(pfilefunc->zopen32_file))(pfilefunc->zfile_func64.opaque,(const char*)filename,mode);
+ }
+}
+
+long call_zseek64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin)
+{
+ if (pfilefunc->zfile_func64.zseek64_file != NULL)
+ return (*(pfilefunc->zfile_func64.zseek64_file)) (pfilefunc->zfile_func64.opaque,filestream,offset,origin);
+ else
+ {
+ uLong offsetTruncated = (uLong)offset;
+ if (offsetTruncated != offset)
+ return -1;
+ else
+ return (*(pfilefunc->zseek32_file))(pfilefunc->zfile_func64.opaque,filestream,offsetTruncated,origin);
+ }
+}
+
+ZPOS64_T call_ztell64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream)
+{
+ if (pfilefunc->zfile_func64.zseek64_file != NULL)
+ return (*(pfilefunc->zfile_func64.ztell64_file)) (pfilefunc->zfile_func64.opaque,filestream);
+ else
+ {
+ uLong tell_uLong = (*(pfilefunc->ztell32_file))(pfilefunc->zfile_func64.opaque,filestream);
+ if ((tell_uLong) == MAXU32)
+ return (ZPOS64_T)-1;
+ else
+ return tell_uLong;
+ }
+}
+
+void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32)
+{
+ p_filefunc64_32->zfile_func64.zopen64_file = NULL;
+ p_filefunc64_32->zopen32_file = p_filefunc32->zopen_file;
+ p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file;
+ p_filefunc64_32->zfile_func64.zread_file = p_filefunc32->zread_file;
+ p_filefunc64_32->zfile_func64.zwrite_file = p_filefunc32->zwrite_file;
+ p_filefunc64_32->zfile_func64.ztell64_file = NULL;
+ p_filefunc64_32->zfile_func64.zseek64_file = NULL;
+ p_filefunc64_32->zfile_func64.zclose_file = p_filefunc32->zclose_file;
+ p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file;
+ p_filefunc64_32->zfile_func64.opaque = p_filefunc32->opaque;
+ p_filefunc64_32->zseek32_file = p_filefunc32->zseek_file;
+ p_filefunc64_32->ztell32_file = p_filefunc32->ztell_file;
+}
+
+
+
+static voidpf ZCALLBACK fopen_file_func OF((voidpf opaque, const char* filename, int mode));
+static uLong ZCALLBACK fread_file_func OF((voidpf opaque, voidpf stream, void* buf, uLong size));
+static uLong ZCALLBACK fwrite_file_func OF((voidpf opaque, voidpf stream, const void* buf,uLong size));
+static ZPOS64_T ZCALLBACK ftell64_file_func OF((voidpf opaque, voidpf stream));
+static long ZCALLBACK fseek64_file_func OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin));
+static int ZCALLBACK fclose_file_func OF((voidpf opaque, voidpf stream));
+static int ZCALLBACK ferror_file_func OF((voidpf opaque, voidpf stream));
+
+static voidpf ZCALLBACK fopen_file_func (voidpf opaque, const char* filename, int mode)
+{
+ FILE* file = NULL;
+ const char* mode_fopen = NULL;
+ if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
+ mode_fopen = "rb";
+ else
+ if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
+ mode_fopen = "r+b";
+ else
+ if (mode & ZLIB_FILEFUNC_MODE_CREATE)
+ mode_fopen = "wb";
+
+ if ((filename!=NULL) && (mode_fopen != NULL))
+ file = fopen(filename, mode_fopen);
+ return file;
+}
+
+static voidpf ZCALLBACK fopen64_file_func (voidpf opaque, const void* filename, int mode)
+{
+ FILE* file = NULL;
+ const char* mode_fopen = NULL;
+ if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
+ mode_fopen = "rb";
+ else
+ if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
+ mode_fopen = "r+b";
+ else
+ if (mode & ZLIB_FILEFUNC_MODE_CREATE)
+ mode_fopen = "wb";
+
+ if ((filename!=NULL) && (mode_fopen != NULL))
+ file = FOPEN_FUNC((const char*)filename, mode_fopen);
+ return file;
+}
+
+
+static uLong ZCALLBACK fread_file_func (voidpf opaque, voidpf stream, void* buf, uLong size)
+{
+ uLong ret;
+ ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream);
+ return ret;
+}
+
+static uLong ZCALLBACK fwrite_file_func (voidpf opaque, voidpf stream, const void* buf, uLong size)
+{
+ uLong ret;
+ ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream);
+ return ret;
+}
+
+static long ZCALLBACK ftell_file_func (voidpf opaque, voidpf stream)
+{
+ long ret;
+ ret = ftell((FILE *)stream);
+ return ret;
+}
+
+
+static ZPOS64_T ZCALLBACK ftell64_file_func (voidpf opaque, voidpf stream)
+{
+ ZPOS64_T ret;
+ ret = FTELLO_FUNC((FILE *)stream);
+ return ret;
+}
+
+static long ZCALLBACK fseek_file_func (voidpf opaque, voidpf stream, uLong offset, int origin)
+{
+ int fseek_origin=0;
+ long ret;
+ switch (origin)
+ {
+ case ZLIB_FILEFUNC_SEEK_CUR :
+ fseek_origin = SEEK_CUR;
+ break;
+ case ZLIB_FILEFUNC_SEEK_END :
+ fseek_origin = SEEK_END;
+ break;
+ case ZLIB_FILEFUNC_SEEK_SET :
+ fseek_origin = SEEK_SET;
+ break;
+ default: return -1;
+ }
+ ret = 0;
+ if (fseek((FILE *)stream, offset, fseek_origin) != 0)
+ ret = -1;
+ return ret;
+}
+
+static long ZCALLBACK fseek64_file_func (voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)
+{
+ int fseek_origin=0;
+ long ret;
+ switch (origin)
+ {
+ case ZLIB_FILEFUNC_SEEK_CUR :
+ fseek_origin = SEEK_CUR;
+ break;
+ case ZLIB_FILEFUNC_SEEK_END :
+ fseek_origin = SEEK_END;
+ break;
+ case ZLIB_FILEFUNC_SEEK_SET :
+ fseek_origin = SEEK_SET;
+ break;
+ default: return -1;
+ }
+ ret = 0;
+
+ if(FSEEKO_FUNC((FILE *)stream, offset, fseek_origin) != 0)
+ ret = -1;
+
+ return ret;
+}
+
+
+static int ZCALLBACK fclose_file_func (voidpf opaque, voidpf stream)
+{
+ int ret;
+ ret = fclose((FILE *)stream);
+ return ret;
+}
+
+static int ZCALLBACK ferror_file_func (voidpf opaque, voidpf stream)
+{
+ int ret;
+ ret = ferror((FILE *)stream);
+ return ret;
+}
+
+void fill_fopen_filefunc (pzlib_filefunc_def)
+ zlib_filefunc_def* pzlib_filefunc_def;
+{
+ pzlib_filefunc_def->zopen_file = fopen_file_func;
+ pzlib_filefunc_def->zread_file = fread_file_func;
+ pzlib_filefunc_def->zwrite_file = fwrite_file_func;
+ pzlib_filefunc_def->ztell_file = ftell_file_func;
+ pzlib_filefunc_def->zseek_file = fseek_file_func;
+ pzlib_filefunc_def->zclose_file = fclose_file_func;
+ pzlib_filefunc_def->zerror_file = ferror_file_func;
+ pzlib_filefunc_def->opaque = NULL;
+}
+
+void fill_fopen64_filefunc (zlib_filefunc64_def* pzlib_filefunc_def)
+{
+ pzlib_filefunc_def->zopen64_file = fopen64_file_func;
+ pzlib_filefunc_def->zread_file = fread_file_func;
+ pzlib_filefunc_def->zwrite_file = fwrite_file_func;
+ pzlib_filefunc_def->ztell64_file = ftell64_file_func;
+ pzlib_filefunc_def->zseek64_file = fseek64_file_func;
+ pzlib_filefunc_def->zclose_file = fclose_file_func;
+ pzlib_filefunc_def->zerror_file = ferror_file_func;
+ pzlib_filefunc_def->opaque = NULL;
+}
--- /dev/null
+/* ioapi.h -- IO base function header for compress/uncompress .zip
+ part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
+
+ Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
+
+ Modifications for Zip64 support
+ Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
+
+ For more info read MiniZip_info.txt
+
+ Changes
+
+ Oct-2009 - Defined ZPOS64_T to fpos_t on windows and u_int64_t on linux. (might need to find a better why for this)
+ Oct-2009 - Change to fseeko64, ftello64 and fopen64 so large files would work on linux.
+ More if/def section may be needed to support other platforms
+ Oct-2009 - Defined fxxxx64 calls to normal fopen/ftell/fseek so they would compile on windows.
+ (but you should use iowin32.c for windows instead)
+
+*/
+
+#ifndef _ZLIBIOAPI64_H
+#define _ZLIBIOAPI64_H
+
+#if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__))
+
+ // Linux needs this to support file operation on files larger then 4+GB
+ // But might need better if/def to select just the platforms that needs them.
+
+ #ifndef __USE_FILE_OFFSET64
+ #define __USE_FILE_OFFSET64
+ #endif
+ #ifndef __USE_LARGEFILE64
+ #define __USE_LARGEFILE64
+ #endif
+ #ifndef _LARGEFILE64_SOURCE
+ #define _LARGEFILE64_SOURCE
+ #endif
+ #ifndef _FILE_OFFSET_BIT
+ #define _FILE_OFFSET_BIT 64
+ #endif
+
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "zlib.h"
+
+#if defined(USE_FILE32API)
+#define fopen64 fopen
+#define ftello64 ftell
+#define fseeko64 fseek
+#else
+#ifdef __FreeBSD__
+#define fopen64 fopen
+#define ftello64 ftello
+#define fseeko64 fseeko
+#endif
+#ifdef _MSC_VER
+ #define fopen64 fopen
+ #if (_MSC_VER >= 1400) && (!(defined(NO_MSCVER_FILE64_FUNC)))
+ #define ftello64 _ftelli64
+ #define fseeko64 _fseeki64
+ #else // old MSC
+ #define ftello64 ftell
+ #define fseeko64 fseek
+ #endif
+#endif
+#endif
+
+/*
+#ifndef ZPOS64_T
+ #ifdef _WIN32
+ #define ZPOS64_T fpos_t
+ #else
+ #include <stdint.h>
+ #define ZPOS64_T uint64_t
+ #endif
+#endif
+*/
+
+#ifdef HAVE_MINIZIP64_CONF_H
+#include "mz64conf.h"
+#endif
+
+/* a type choosen by DEFINE */
+#ifdef HAVE_64BIT_INT_CUSTOM
+typedef 64BIT_INT_CUSTOM_TYPE ZPOS64_T;
+#else
+#ifdef HAS_STDINT_H
+#include "stdint.h"
+typedef uint64_t ZPOS64_T;
+#else
+
+/* Maximum unsigned 32-bit value used as placeholder for zip64 */
+#define MAXU32 0xffffffff
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+typedef unsigned __int64 ZPOS64_T;
+#else
+typedef unsigned long long int ZPOS64_T;
+#endif
+#endif
+#endif
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define ZLIB_FILEFUNC_SEEK_CUR (1)
+#define ZLIB_FILEFUNC_SEEK_END (2)
+#define ZLIB_FILEFUNC_SEEK_SET (0)
+
+#define ZLIB_FILEFUNC_MODE_READ (1)
+#define ZLIB_FILEFUNC_MODE_WRITE (2)
+#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3)
+
+#define ZLIB_FILEFUNC_MODE_EXISTING (4)
+#define ZLIB_FILEFUNC_MODE_CREATE (8)
+
+
+#ifndef ZCALLBACK
+ #if (defined(WIN32) || defined(_WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK)
+ #define ZCALLBACK CALLBACK
+ #else
+ #define ZCALLBACK
+ #endif
+#endif
+
+
+
+
+typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode));
+typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size));
+typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size));
+typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream));
+typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream));
+
+typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream));
+typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin));
+
+
+/* here is the "old" 32 bits structure structure */
+typedef struct zlib_filefunc_def_s
+{
+ open_file_func zopen_file;
+ read_file_func zread_file;
+ write_file_func zwrite_file;
+ tell_file_func ztell_file;
+ seek_file_func zseek_file;
+ close_file_func zclose_file;
+ testerror_file_func zerror_file;
+ voidpf opaque;
+} zlib_filefunc_def;
+
+typedef ZPOS64_T (ZCALLBACK *tell64_file_func) OF((voidpf opaque, voidpf stream));
+typedef long (ZCALLBACK *seek64_file_func) OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin));
+typedef voidpf (ZCALLBACK *open64_file_func) OF((voidpf opaque, const void* filename, int mode));
+
+typedef struct zlib_filefunc64_def_s
+{
+ open64_file_func zopen64_file;
+ read_file_func zread_file;
+ write_file_func zwrite_file;
+ tell64_file_func ztell64_file;
+ seek64_file_func zseek64_file;
+ close_file_func zclose_file;
+ testerror_file_func zerror_file;
+ voidpf opaque;
+} zlib_filefunc64_def;
+
+void fill_fopen64_filefunc OF((zlib_filefunc64_def* pzlib_filefunc_def));
+void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def));
+
+/* now internal definition, only for zip.c and unzip.h */
+typedef struct zlib_filefunc64_32_def_s
+{
+ zlib_filefunc64_def zfile_func64;
+ open_file_func zopen32_file;
+ tell_file_func ztell32_file;
+ seek_file_func zseek32_file;
+} zlib_filefunc64_32_def;
+
+
+#define ZREAD64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zread_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size))
+#define ZWRITE64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zwrite_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size))
+//#define ZTELL64(filefunc,filestream) ((*((filefunc).ztell64_file)) ((filefunc).opaque,filestream))
+//#define ZSEEK64(filefunc,filestream,pos,mode) ((*((filefunc).zseek64_file)) ((filefunc).opaque,filestream,pos,mode))
+#define ZCLOSE64(filefunc,filestream) ((*((filefunc).zfile_func64.zclose_file)) ((filefunc).zfile_func64.opaque,filestream))
+#define ZERROR64(filefunc,filestream) ((*((filefunc).zfile_func64.zerror_file)) ((filefunc).zfile_func64.opaque,filestream))
+
+voidpf call_zopen64 OF((const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode));
+long call_zseek64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin));
+ZPOS64_T call_ztell64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream));
+
+void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32);
+
+#define ZOPEN64(filefunc,filename,mode) (call_zopen64((&(filefunc)),(filename),(mode)))
+#define ZTELL64(filefunc,filestream) (call_ztell64((&(filefunc)),(filestream)))
+#define ZSEEK64(filefunc,filestream,pos,mode) (call_zseek64((&(filefunc)),(filestream),(pos),(mode)))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+{
+ 'includes': ['../../common.gypi'],
+ 'targets': [
+ {
+ 'target_name': 'minizip',
+ 'type': 'static_library',
+ 'sources': [
+ 'unzip.c',
+ 'ioapi.c',
+ ],
+ 'defines': [
+ 'NOUNCRYPT',
+ ],
+ 'link_settings': {
+ 'libraries': ['-lz'],
+ },
+ 'direct_dependent_settings': {
+ 'defines': [
+ 'NOUNCRYPT',
+ ],
+ 'include_dirs': [
+ '.',
+ ],
+ },
+ },
+ ],
+}
--- /dev/null
+/* unzip.c -- IO for uncompress .zip files using zlib
+ Version 1.1, February 14h, 2010
+ part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
+
+ Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
+
+ Modifications of Unzip for Zip64
+ Copyright (C) 2007-2008 Even Rouault
+
+ Modifications for Zip64 support on both zip and unzip
+ Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
+
+ For more info read MiniZip_info.txt
+
+
+ ------------------------------------------------------------------------------------
+ Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of
+ compatibility with older software. The following is from the original crypt.c.
+ Code woven in by Terry Thorsen 1/2003.
+
+ Copyright (c) 1990-2000 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 2000-Apr-09 or later
+ (the contents of which are also included in zip.h) for terms of use.
+ If, for some reason, all these files are missing, the Info-ZIP license
+ also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
+
+ crypt.c (full version) by Info-ZIP. Last revised: [see crypt.h]
+
+ The encryption/decryption parts of this source code (as opposed to the
+ non-echoing password parts) were originally written in Europe. The
+ whole source package can be freely distributed, including from the USA.
+ (Prior to January 2000, re-export from the US was a violation of US law.)
+
+ This encryption code is a direct transcription of the algorithm from
+ Roger Schlafly, described by Phil Katz in the file appnote.txt. This
+ file (appnote.txt) is distributed with the PKZIP program (even in the
+ version without encryption capabilities).
+
+ ------------------------------------------------------------------------------------
+
+ Changes in unzip.c
+
+ 2007-2008 - Even Rouault - Addition of cpl_unzGetCurrentFileZStreamPos
+ 2007-2008 - Even Rouault - Decoration of symbol names unz* -> cpl_unz*
+ 2007-2008 - Even Rouault - Remove old C style function prototypes
+ 2007-2008 - Even Rouault - Add unzip support for ZIP64
+
+ Copyright (C) 2007-2008 Even Rouault
+
+
+ Oct-2009 - Mathias Svensson - Removed cpl_* from symbol names (Even Rouault added them but since this is now moved to a new project (minizip64) I renamed them again).
+ Oct-2009 - Mathias Svensson - Fixed problem if uncompressed size was > 4G and compressed size was <4G
+ should only read the compressed/uncompressed size from the Zip64 format if
+ the size from normal header was 0xFFFFFFFF
+ Oct-2009 - Mathias Svensson - Applied some bug fixes from paches recived from Gilles Vollant
+ Oct-2009 - Mathias Svensson - Applied support to unzip files with compression mathod BZIP2 (bzip2 lib is required)
+ Patch created by Daniel Borca
+
+ Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer
+
+ Copyright (C) 1998 - 2010 Gilles Vollant, Even Rouault, Mathias Svensson
+
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "zlib.h"
+#include "unzip.h"
+
+#ifdef STDC
+# include <stddef.h>
+# include <string.h>
+# include <stdlib.h>
+#endif
+#ifdef NO_ERRNO_H
+ extern int errno;
+#else
+# include <errno.h>
+#endif
+
+
+#ifndef local
+# define local static
+#endif
+/* compile with -Dlocal if your debugger can't find static symbols */
+
+
+#ifndef CASESENSITIVITYDEFAULT_NO
+# if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES)
+# define CASESENSITIVITYDEFAULT_NO
+# endif
+#endif
+
+
+#ifndef UNZ_BUFSIZE
+#define UNZ_BUFSIZE (16384)
+#endif
+
+#ifndef UNZ_MAXFILENAMEINZIP
+#define UNZ_MAXFILENAMEINZIP (256)
+#endif
+
+#ifndef ALLOC
+# define ALLOC(size) (malloc(size))
+#endif
+#ifndef TRYFREE
+# define TRYFREE(p) {if (p) free(p);}
+#endif
+
+#define SIZECENTRALDIRITEM (0x2e)
+#define SIZEZIPLOCALHEADER (0x1e)
+
+
+const char unz_copyright[] =
+ " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
+
+/* unz_file_info_interntal contain internal info about a file in zipfile*/
+typedef struct unz_file_info64_internal_s
+{
+ ZPOS64_T offset_curfile;/* relative offset of local header 8 bytes */
+} unz_file_info64_internal;
+
+
+/* file_in_zip_read_info_s contain internal information about a file in zipfile,
+ when reading and decompress it */
+typedef struct
+{
+ char *read_buffer; /* internal buffer for compressed data */
+ z_stream stream; /* zLib stream structure for inflate */
+
+#ifdef HAVE_BZIP2
+ bz_stream bstream; /* bzLib stream structure for bziped */
+#endif
+
+ ZPOS64_T pos_in_zipfile; /* position in byte on the zipfile, for fseek*/
+ uLong stream_initialised; /* flag set if stream structure is initialised*/
+
+ ZPOS64_T offset_local_extrafield;/* offset of the local extra field */
+ uInt size_local_extrafield;/* size of the local extra field */
+ ZPOS64_T pos_local_extrafield; /* position in the local extra field in read*/
+ ZPOS64_T total_out_64;
+
+ uLong crc32; /* crc32 of all data uncompressed */
+ uLong crc32_wait; /* crc32 we must obtain after decompress all */
+ ZPOS64_T rest_read_compressed; /* number of byte to be decompressed */
+ ZPOS64_T rest_read_uncompressed;/*number of byte to be obtained after decomp*/
+ zlib_filefunc64_32_def z_filefunc;
+ voidpf filestream; /* io structore of the zipfile */
+ uLong compression_method; /* compression method (0==store) */
+ ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
+ int raw;
+} file_in_zip64_read_info_s;
+
+
+/* unz64_s contain internal information about the zipfile
+*/
+typedef struct
+{
+ zlib_filefunc64_32_def z_filefunc;
+ int is64bitOpenFunction;
+ voidpf filestream; /* io structore of the zipfile */
+ unz_global_info64 gi; /* public global information */
+ ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
+ ZPOS64_T num_file; /* number of the current file in the zipfile*/
+ ZPOS64_T pos_in_central_dir; /* pos of the current file in the central dir*/
+ ZPOS64_T current_file_ok; /* flag about the usability of the current file*/
+ ZPOS64_T central_pos; /* position of the beginning of the central dir*/
+
+ ZPOS64_T size_central_dir; /* size of the central directory */
+ ZPOS64_T offset_central_dir; /* offset of start of central directory with
+ respect to the starting disk number */
+
+ unz_file_info64 cur_file_info; /* public info about the current file in zip*/
+ unz_file_info64_internal cur_file_info_internal; /* private info about it*/
+ file_in_zip64_read_info_s* pfile_in_zip_read; /* structure about the current
+ file if we are decompressing it */
+ int encrypted;
+
+ int isZip64;
+
+# ifndef NOUNCRYPT
+ unsigned long keys[3]; /* keys defining the pseudo-random sequence */
+ const z_crc_t* pcrc_32_tab;
+# endif
+} unz64_s;
+
+
+#ifndef NOUNCRYPT
+#include "crypt.h"
+#endif
+
+/* ===========================================================================
+ Read a byte from a gz_stream; update next_in and avail_in. Return EOF
+ for end of file.
+ IN assertion: the stream s has been successfully opened for reading.
+*/
+
+
+local int unz64local_getByte OF((
+ const zlib_filefunc64_32_def* pzlib_filefunc_def,
+ voidpf filestream,
+ int *pi));
+
+local int unz64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int *pi)
+{
+ unsigned char c;
+ int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,&c,1);
+ if (err==1)
+ {
+ *pi = (int)c;
+ return UNZ_OK;
+ }
+ else
+ {
+ if (ZERROR64(*pzlib_filefunc_def,filestream))
+ return UNZ_ERRNO;
+ else
+ return UNZ_EOF;
+ }
+}
+
+
+/* ===========================================================================
+ Reads a long in LSB order from the given gz_stream. Sets
+*/
+local int unz64local_getShort OF((
+ const zlib_filefunc64_32_def* pzlib_filefunc_def,
+ voidpf filestream,
+ uLong *pX));
+
+local int unz64local_getShort (const zlib_filefunc64_32_def* pzlib_filefunc_def,
+ voidpf filestream,
+ uLong *pX)
+{
+ uLong x ;
+ int i = 0;
+ int err;
+
+ err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+ x = (uLong)i;
+
+ if (err==UNZ_OK)
+ err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+ x |= ((uLong)i)<<8;
+
+ if (err==UNZ_OK)
+ *pX = x;
+ else
+ *pX = 0;
+ return err;
+}
+
+local int unz64local_getLong OF((
+ const zlib_filefunc64_32_def* pzlib_filefunc_def,
+ voidpf filestream,
+ uLong *pX));
+
+local int unz64local_getLong (const zlib_filefunc64_32_def* pzlib_filefunc_def,
+ voidpf filestream,
+ uLong *pX)
+{
+ uLong x ;
+ int i = 0;
+ int err;
+
+ err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+ x = (uLong)i;
+
+ if (err==UNZ_OK)
+ err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+ x |= ((uLong)i)<<8;
+
+ if (err==UNZ_OK)
+ err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+ x |= ((uLong)i)<<16;
+
+ if (err==UNZ_OK)
+ err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+ x += ((uLong)i)<<24;
+
+ if (err==UNZ_OK)
+ *pX = x;
+ else
+ *pX = 0;
+ return err;
+}
+
+local int unz64local_getLong64 OF((
+ const zlib_filefunc64_32_def* pzlib_filefunc_def,
+ voidpf filestream,
+ ZPOS64_T *pX));
+
+
+local int unz64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def,
+ voidpf filestream,
+ ZPOS64_T *pX)
+{
+ ZPOS64_T x ;
+ int i = 0;
+ int err;
+
+ err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+ x = (ZPOS64_T)i;
+
+ if (err==UNZ_OK)
+ err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+ x |= ((ZPOS64_T)i)<<8;
+
+ if (err==UNZ_OK)
+ err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+ x |= ((ZPOS64_T)i)<<16;
+
+ if (err==UNZ_OK)
+ err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+ x |= ((ZPOS64_T)i)<<24;
+
+ if (err==UNZ_OK)
+ err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+ x |= ((ZPOS64_T)i)<<32;
+
+ if (err==UNZ_OK)
+ err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+ x |= ((ZPOS64_T)i)<<40;
+
+ if (err==UNZ_OK)
+ err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+ x |= ((ZPOS64_T)i)<<48;
+
+ if (err==UNZ_OK)
+ err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
+ x |= ((ZPOS64_T)i)<<56;
+
+ if (err==UNZ_OK)
+ *pX = x;
+ else
+ *pX = 0;
+ return err;
+}
+
+/* My own strcmpi / strcasecmp */
+local int strcmpcasenosensitive_internal (const char* fileName1, const char* fileName2)
+{
+ for (;;)
+ {
+ char c1=*(fileName1++);
+ char c2=*(fileName2++);
+ if ((c1>='a') && (c1<='z'))
+ c1 -= 0x20;
+ if ((c2>='a') && (c2<='z'))
+ c2 -= 0x20;
+ if (c1=='\0')
+ return ((c2=='\0') ? 0 : -1);
+ if (c2=='\0')
+ return 1;
+ if (c1<c2)
+ return -1;
+ if (c1>c2)
+ return 1;
+ }
+}
+
+
+#ifdef CASESENSITIVITYDEFAULT_NO
+#define CASESENSITIVITYDEFAULTVALUE 2
+#else
+#define CASESENSITIVITYDEFAULTVALUE 1
+#endif
+
+#ifndef STRCMPCASENOSENTIVEFUNCTION
+#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal
+#endif
+
+/*
+ Compare two filename (fileName1,fileName2).
+ If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
+ If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
+ or strcasecmp)
+ If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
+ (like 1 on Unix, 2 on Windows)
+
+*/
+extern int ZEXPORT unzStringFileNameCompare (const char* fileName1,
+ const char* fileName2,
+ int iCaseSensitivity)
+
+{
+ if (iCaseSensitivity==0)
+ iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE;
+
+ if (iCaseSensitivity==1)
+ return strcmp(fileName1,fileName2);
+
+ return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2);
+}
+
+#ifndef BUFREADCOMMENT
+#define BUFREADCOMMENT (0x400)
+#endif
+
+/*
+ Locate the Central directory of a zipfile (at the end, just before
+ the global comment)
+*/
+local ZPOS64_T unz64local_SearchCentralDir OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream));
+local ZPOS64_T unz64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)
+{
+ unsigned char* buf;
+ ZPOS64_T uSizeFile;
+ ZPOS64_T uBackRead;
+ ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */
+ ZPOS64_T uPosFound=0;
+
+ if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
+ return 0;
+
+
+ uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);
+
+ if (uMaxBack>uSizeFile)
+ uMaxBack = uSizeFile;
+
+ buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
+ if (buf==NULL)
+ return 0;
+
+ uBackRead = 4;
+ while (uBackRead<uMaxBack)
+ {
+ uLong uReadSize;
+ ZPOS64_T uReadPos ;
+ int i;
+ if (uBackRead+BUFREADCOMMENT>uMaxBack)
+ uBackRead = uMaxBack;
+ else
+ uBackRead+=BUFREADCOMMENT;
+ uReadPos = uSizeFile-uBackRead ;
+
+ uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
+ (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos);
+ if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
+ break;
+
+ if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
+ break;
+
+ for (i=(int)uReadSize-3; (i--)>0;)
+ if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
+ ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
+ {
+ uPosFound = uReadPos+i;
+ break;
+ }
+
+ if (uPosFound!=0)
+ break;
+ }
+ TRYFREE(buf);
+ return uPosFound;
+}
+
+
+/*
+ Locate the Central directory 64 of a zipfile (at the end, just before
+ the global comment)
+*/
+local ZPOS64_T unz64local_SearchCentralDir64 OF((
+ const zlib_filefunc64_32_def* pzlib_filefunc_def,
+ voidpf filestream));
+
+local ZPOS64_T unz64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def,
+ voidpf filestream)
+{
+ unsigned char* buf;
+ ZPOS64_T uSizeFile;
+ ZPOS64_T uBackRead;
+ ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */
+ ZPOS64_T uPosFound=0;
+ uLong uL;
+ ZPOS64_T relativeOffset;
+
+ if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
+ return 0;
+
+
+ uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);
+
+ if (uMaxBack>uSizeFile)
+ uMaxBack = uSizeFile;
+
+ buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
+ if (buf==NULL)
+ return 0;
+
+ uBackRead = 4;
+ while (uBackRead<uMaxBack)
+ {
+ uLong uReadSize;
+ ZPOS64_T uReadPos;
+ int i;
+ if (uBackRead+BUFREADCOMMENT>uMaxBack)
+ uBackRead = uMaxBack;
+ else
+ uBackRead+=BUFREADCOMMENT;
+ uReadPos = uSizeFile-uBackRead ;
+
+ uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
+ (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos);
+ if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
+ break;
+
+ if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
+ break;
+
+ for (i=(int)uReadSize-3; (i--)>0;)
+ if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
+ ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07))
+ {
+ uPosFound = uReadPos+i;
+ break;
+ }
+
+ if (uPosFound!=0)
+ break;
+ }
+ TRYFREE(buf);
+ if (uPosFound == 0)
+ return 0;
+
+ /* Zip64 end of central directory locator */
+ if (ZSEEK64(*pzlib_filefunc_def,filestream, uPosFound,ZLIB_FILEFUNC_SEEK_SET)!=0)
+ return 0;
+
+ /* the signature, already checked */
+ if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
+ return 0;
+
+ /* number of the disk with the start of the zip64 end of central directory */
+ if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
+ return 0;
+ if (uL != 0)
+ return 0;
+
+ /* relative offset of the zip64 end of central directory record */
+ if (unz64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset)!=UNZ_OK)
+ return 0;
+
+ /* total number of disks */
+ if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
+ return 0;
+ if (uL != 1)
+ return 0;
+
+ /* Goto end of central directory record */
+ if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0)
+ return 0;
+
+ /* the signature */
+ if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
+ return 0;
+
+ if (uL != 0x06064b50)
+ return 0;
+
+ return relativeOffset;
+}
+
+/*
+ Open a Zip file. path contain the full pathname (by example,
+ on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer
+ "zlib/zlib114.zip".
+ If the zipfile cannot be opened (file doesn't exist or in not valid), the
+ return value is NULL.
+ Else, the return value is a unzFile Handle, usable with other function
+ of this unzip package.
+*/
+local unzFile unzOpenInternal (const void *path,
+ zlib_filefunc64_32_def* pzlib_filefunc64_32_def,
+ int is64bitOpenFunction)
+{
+ unz64_s us;
+ unz64_s *s;
+ ZPOS64_T central_pos;
+ uLong uL;
+
+ uLong number_disk; /* number of the current dist, used for
+ spaning ZIP, unsupported, always 0*/
+ uLong number_disk_with_CD; /* number the the disk with central dir, used
+ for spaning ZIP, unsupported, always 0*/
+ ZPOS64_T number_entry_CD; /* total number of entries in
+ the central dir
+ (same than number_entry on nospan) */
+
+ int err=UNZ_OK;
+
+ if (unz_copyright[0]!=' ')
+ return NULL;
+
+ us.z_filefunc.zseek32_file = NULL;
+ us.z_filefunc.ztell32_file = NULL;
+ if (pzlib_filefunc64_32_def==NULL)
+ fill_fopen64_filefunc(&us.z_filefunc.zfile_func64);
+ else
+ us.z_filefunc = *pzlib_filefunc64_32_def;
+ us.is64bitOpenFunction = is64bitOpenFunction;
+
+
+
+ us.filestream = ZOPEN64(us.z_filefunc,
+ path,
+ ZLIB_FILEFUNC_MODE_READ |
+ ZLIB_FILEFUNC_MODE_EXISTING);
+ if (us.filestream==NULL)
+ return NULL;
+
+ central_pos = unz64local_SearchCentralDir64(&us.z_filefunc,us.filestream);
+ if (central_pos)
+ {
+ uLong uS;
+ ZPOS64_T uL64;
+
+ us.isZip64 = 1;
+
+ if (ZSEEK64(us.z_filefunc, us.filestream,
+ central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
+ err=UNZ_ERRNO;
+
+ /* the signature, already checked */
+ if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* size of zip64 end of central directory record */
+ if (unz64local_getLong64(&us.z_filefunc, us.filestream,&uL64)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* version made by */
+ if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* version needed to extract */
+ if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* number of this disk */
+ if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* number of the disk with the start of the central directory */
+ if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* total number of entries in the central directory on this disk */
+ if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* total number of entries in the central directory */
+ if (unz64local_getLong64(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if ((number_entry_CD!=us.gi.number_entry) ||
+ (number_disk_with_CD!=0) ||
+ (number_disk!=0))
+ err=UNZ_BADZIPFILE;
+
+ /* size of the central directory */
+ if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* offset of start of central directory with respect to the
+ starting disk number */
+ if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ us.gi.size_comment = 0;
+ }
+ else
+ {
+ central_pos = unz64local_SearchCentralDir(&us.z_filefunc,us.filestream);
+ if (central_pos==0)
+ err=UNZ_ERRNO;
+
+ us.isZip64 = 0;
+
+ if (ZSEEK64(us.z_filefunc, us.filestream,
+ central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
+ err=UNZ_ERRNO;
+
+ /* the signature, already checked */
+ if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* number of this disk */
+ if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* number of the disk with the start of the central directory */
+ if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* total number of entries in the central dir on this disk */
+ if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
+ err=UNZ_ERRNO;
+ us.gi.number_entry = uL;
+
+ /* total number of entries in the central dir */
+ if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
+ err=UNZ_ERRNO;
+ number_entry_CD = uL;
+
+ if ((number_entry_CD!=us.gi.number_entry) ||
+ (number_disk_with_CD!=0) ||
+ (number_disk!=0))
+ err=UNZ_BADZIPFILE;
+
+ /* size of the central directory */
+ if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
+ err=UNZ_ERRNO;
+ us.size_central_dir = uL;
+
+ /* offset of start of central directory with respect to the
+ starting disk number */
+ if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
+ err=UNZ_ERRNO;
+ us.offset_central_dir = uL;
+
+ /* zipfile comment length */
+ if (unz64local_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK)
+ err=UNZ_ERRNO;
+ }
+
+ if ((central_pos<us.offset_central_dir+us.size_central_dir) &&
+ (err==UNZ_OK))
+ err=UNZ_BADZIPFILE;
+
+ if (err!=UNZ_OK)
+ {
+ ZCLOSE64(us.z_filefunc, us.filestream);
+ return NULL;
+ }
+
+ us.byte_before_the_zipfile = central_pos -
+ (us.offset_central_dir+us.size_central_dir);
+ us.central_pos = central_pos;
+ us.pfile_in_zip_read = NULL;
+ us.encrypted = 0;
+
+
+ s=(unz64_s*)ALLOC(sizeof(unz64_s));
+ if( s != NULL)
+ {
+ *s=us;
+ unzGoToFirstFile((unzFile)s);
+ }
+ return (unzFile)s;
+}
+
+
+extern unzFile ZEXPORT unzOpen2 (const char *path,
+ zlib_filefunc_def* pzlib_filefunc32_def)
+{
+ if (pzlib_filefunc32_def != NULL)
+ {
+ zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;
+ fill_zlib_filefunc64_32_def_from_filefunc32(&zlib_filefunc64_32_def_fill,pzlib_filefunc32_def);
+ return unzOpenInternal(path, &zlib_filefunc64_32_def_fill, 0);
+ }
+ else
+ return unzOpenInternal(path, NULL, 0);
+}
+
+extern unzFile ZEXPORT unzOpen2_64 (const void *path,
+ zlib_filefunc64_def* pzlib_filefunc_def)
+{
+ if (pzlib_filefunc_def != NULL)
+ {
+ zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;
+ zlib_filefunc64_32_def_fill.zfile_func64 = *pzlib_filefunc_def;
+ zlib_filefunc64_32_def_fill.ztell32_file = NULL;
+ zlib_filefunc64_32_def_fill.zseek32_file = NULL;
+ return unzOpenInternal(path, &zlib_filefunc64_32_def_fill, 1);
+ }
+ else
+ return unzOpenInternal(path, NULL, 1);
+}
+
+extern unzFile ZEXPORT unzOpen (const char *path)
+{
+ return unzOpenInternal(path, NULL, 0);
+}
+
+extern unzFile ZEXPORT unzOpen64 (const void *path)
+{
+ return unzOpenInternal(path, NULL, 1);
+}
+
+/*
+ Close a ZipFile opened with unzOpen.
+ If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
+ these files MUST be closed with unzCloseCurrentFile before call unzClose.
+ return UNZ_OK if there is no problem. */
+extern int ZEXPORT unzClose (unzFile file)
+{
+ unz64_s* s;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+
+ if (s->pfile_in_zip_read!=NULL)
+ unzCloseCurrentFile(file);
+
+ ZCLOSE64(s->z_filefunc, s->filestream);
+ TRYFREE(s);
+ return UNZ_OK;
+}
+
+
+/*
+ Write info about the ZipFile in the *pglobal_info structure.
+ No preparation of the structure is needed
+ return UNZ_OK if there is no problem. */
+extern int ZEXPORT unzGetGlobalInfo64 (unzFile file, unz_global_info64* pglobal_info)
+{
+ unz64_s* s;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+ *pglobal_info=s->gi;
+ return UNZ_OK;
+}
+
+extern int ZEXPORT unzGetGlobalInfo (unzFile file, unz_global_info* pglobal_info32)
+{
+ unz64_s* s;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+ /* to do : check if number_entry is not truncated */
+ pglobal_info32->number_entry = (uLong)s->gi.number_entry;
+ pglobal_info32->size_comment = s->gi.size_comment;
+ return UNZ_OK;
+}
+/*
+ Translate date/time from Dos format to tm_unz (readable more easilty)
+*/
+local void unz64local_DosDateToTmuDate (ZPOS64_T ulDosDate, tm_unz* ptm)
+{
+ ZPOS64_T uDate;
+ uDate = (ZPOS64_T)(ulDosDate>>16);
+ ptm->tm_mday = (uInt)(uDate&0x1f) ;
+ ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ;
+ ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;
+
+ ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);
+ ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ;
+ ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ;
+}
+
+/*
+ Get Info about the current file in the zipfile, with internal only info
+*/
+local int unz64local_GetCurrentFileInfoInternal OF((unzFile file,
+ unz_file_info64 *pfile_info,
+ unz_file_info64_internal
+ *pfile_info_internal,
+ char *szFileName,
+ uLong fileNameBufferSize,
+ void *extraField,
+ uLong extraFieldBufferSize,
+ char *szComment,
+ uLong commentBufferSize));
+
+local int unz64local_GetCurrentFileInfoInternal (unzFile file,
+ unz_file_info64 *pfile_info,
+ unz_file_info64_internal
+ *pfile_info_internal,
+ char *szFileName,
+ uLong fileNameBufferSize,
+ void *extraField,
+ uLong extraFieldBufferSize,
+ char *szComment,
+ uLong commentBufferSize)
+{
+ unz64_s* s;
+ unz_file_info64 file_info;
+ unz_file_info64_internal file_info_internal;
+ int err=UNZ_OK;
+ uLong uMagic;
+ long lSeek=0;
+ uLong uL;
+
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+ if (ZSEEK64(s->z_filefunc, s->filestream,
+ s->pos_in_central_dir+s->byte_before_the_zipfile,
+ ZLIB_FILEFUNC_SEEK_SET)!=0)
+ err=UNZ_ERRNO;
+
+
+ /* we check the magic */
+ if (err==UNZ_OK)
+ {
+ if (unz64local_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
+ err=UNZ_ERRNO;
+ else if (uMagic!=0x02014b50)
+ err=UNZ_BADZIPFILE;
+ }
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ unz64local_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
+
+ if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)
+ err=UNZ_ERRNO;
+ file_info.compressed_size = uL;
+
+ if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)
+ err=UNZ_ERRNO;
+ file_info.uncompressed_size = uL;
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ // relative offset of local header
+ if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)
+ err=UNZ_ERRNO;
+ file_info_internal.offset_curfile = uL;
+
+ lSeek+=file_info.size_filename;
+ if ((err==UNZ_OK) && (szFileName!=NULL))
+ {
+ uLong uSizeRead ;
+ if (file_info.size_filename<fileNameBufferSize)
+ {
+ *(szFileName+file_info.size_filename)='\0';
+ uSizeRead = file_info.size_filename;
+ }
+ else
+ uSizeRead = fileNameBufferSize;
+
+ if ((file_info.size_filename>0) && (fileNameBufferSize>0))
+ if (ZREAD64(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead)
+ err=UNZ_ERRNO;
+ lSeek -= uSizeRead;
+ }
+
+ // Read extrafield
+ if ((err==UNZ_OK) && (extraField!=NULL))
+ {
+ ZPOS64_T uSizeRead ;
+ if (file_info.size_file_extra<extraFieldBufferSize)
+ uSizeRead = file_info.size_file_extra;
+ else
+ uSizeRead = extraFieldBufferSize;
+
+ if (lSeek!=0)
+ {
+ if (ZSEEK64(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
+ lSeek=0;
+ else
+ err=UNZ_ERRNO;
+ }
+
+ if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
+ if (ZREAD64(s->z_filefunc, s->filestream,extraField,(uLong)uSizeRead)!=uSizeRead)
+ err=UNZ_ERRNO;
+
+ lSeek += file_info.size_file_extra - (uLong)uSizeRead;
+ }
+ else
+ lSeek += file_info.size_file_extra;
+
+
+ if ((err==UNZ_OK) && (file_info.size_file_extra != 0))
+ {
+ uLong acc = 0;
+
+ // since lSeek now points to after the extra field we need to move back
+ lSeek -= file_info.size_file_extra;
+
+ if (lSeek!=0)
+ {
+ if (ZSEEK64(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
+ lSeek=0;
+ else
+ err=UNZ_ERRNO;
+ }
+
+ while(acc < file_info.size_file_extra)
+ {
+ uLong headerId;
+ uLong dataSize;
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&headerId) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&dataSize) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* ZIP64 extra fields */
+ if (headerId == 0x0001)
+ {
+ uLong uL;
+
+ if(file_info.uncompressed_size == MAXU32)
+ {
+ if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK)
+ err=UNZ_ERRNO;
+ }
+
+ if(file_info.compressed_size == MAXU32)
+ {
+ if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK)
+ err=UNZ_ERRNO;
+ }
+
+ if(file_info_internal.offset_curfile == MAXU32)
+ {
+ /* Relative Header offset */
+ if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK)
+ err=UNZ_ERRNO;
+ }
+
+ if(file_info.disk_num_start == MAXU32)
+ {
+ /* Disk Start Number */
+ if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)
+ err=UNZ_ERRNO;
+ }
+
+ }
+ else
+ {
+ if (ZSEEK64(s->z_filefunc, s->filestream,dataSize,ZLIB_FILEFUNC_SEEK_CUR)!=0)
+ err=UNZ_ERRNO;
+ }
+
+ acc += 2 + 2 + dataSize;
+ }
+ }
+
+ if ((err==UNZ_OK) && (szComment!=NULL))
+ {
+ uLong uSizeRead ;
+ if (file_info.size_file_comment<commentBufferSize)
+ {
+ *(szComment+file_info.size_file_comment)='\0';
+ uSizeRead = file_info.size_file_comment;
+ }
+ else
+ uSizeRead = commentBufferSize;
+
+ if (lSeek!=0)
+ {
+ if (ZSEEK64(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
+ lSeek=0;
+ else
+ err=UNZ_ERRNO;
+ }
+
+ if ((file_info.size_file_comment>0) && (commentBufferSize>0))
+ if (ZREAD64(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead)
+ err=UNZ_ERRNO;
+ lSeek+=file_info.size_file_comment - uSizeRead;
+ }
+ else
+ lSeek+=file_info.size_file_comment;
+
+
+ if ((err==UNZ_OK) && (pfile_info!=NULL))
+ *pfile_info=file_info;
+
+ if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
+ *pfile_info_internal=file_info_internal;
+
+ return err;
+}
+
+
+
+/*
+ Write info about the ZipFile in the *pglobal_info structure.
+ No preparation of the structure is needed
+ return UNZ_OK if there is no problem.
+*/
+extern int ZEXPORT unzGetCurrentFileInfo64 (unzFile file,
+ unz_file_info64 * pfile_info,
+ char * szFileName, uLong fileNameBufferSize,
+ void *extraField, uLong extraFieldBufferSize,
+ char* szComment, uLong commentBufferSize)
+{
+ return unz64local_GetCurrentFileInfoInternal(file,pfile_info,NULL,
+ szFileName,fileNameBufferSize,
+ extraField,extraFieldBufferSize,
+ szComment,commentBufferSize);
+}
+
+extern int ZEXPORT unzGetCurrentFileInfo (unzFile file,
+ unz_file_info * pfile_info,
+ char * szFileName, uLong fileNameBufferSize,
+ void *extraField, uLong extraFieldBufferSize,
+ char* szComment, uLong commentBufferSize)
+{
+ int err;
+ unz_file_info64 file_info64;
+ err = unz64local_GetCurrentFileInfoInternal(file,&file_info64,NULL,
+ szFileName,fileNameBufferSize,
+ extraField,extraFieldBufferSize,
+ szComment,commentBufferSize);
+ if ((err==UNZ_OK) && (pfile_info != NULL))
+ {
+ pfile_info->version = file_info64.version;
+ pfile_info->version_needed = file_info64.version_needed;
+ pfile_info->flag = file_info64.flag;
+ pfile_info->compression_method = file_info64.compression_method;
+ pfile_info->dosDate = file_info64.dosDate;
+ pfile_info->crc = file_info64.crc;
+
+ pfile_info->size_filename = file_info64.size_filename;
+ pfile_info->size_file_extra = file_info64.size_file_extra;
+ pfile_info->size_file_comment = file_info64.size_file_comment;
+
+ pfile_info->disk_num_start = file_info64.disk_num_start;
+ pfile_info->internal_fa = file_info64.internal_fa;
+ pfile_info->external_fa = file_info64.external_fa;
+
+ pfile_info->tmu_date = file_info64.tmu_date,
+
+
+ pfile_info->compressed_size = (uLong)file_info64.compressed_size;
+ pfile_info->uncompressed_size = (uLong)file_info64.uncompressed_size;
+
+ }
+ return err;
+}
+/*
+ Set the current file of the zipfile to the first file.
+ return UNZ_OK if there is no problem
+*/
+extern int ZEXPORT unzGoToFirstFile (unzFile file)
+{
+ int err=UNZ_OK;
+ unz64_s* s;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+ s->pos_in_central_dir=s->offset_central_dir;
+ s->num_file=0;
+ err=unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,
+ &s->cur_file_info_internal,
+ NULL,0,NULL,0,NULL,0);
+ s->current_file_ok = (err == UNZ_OK);
+ return err;
+}
+
+/*
+ Set the current file of the zipfile to the next file.
+ return UNZ_OK if there is no problem
+ return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
+*/
+extern int ZEXPORT unzGoToNextFile (unzFile file)
+{
+ unz64_s* s;
+ int err;
+
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+ if (!s->current_file_ok)
+ return UNZ_END_OF_LIST_OF_FILE;
+ if (s->gi.number_entry != 0xffff) /* 2^16 files overflow hack */
+ if (s->num_file+1==s->gi.number_entry)
+ return UNZ_END_OF_LIST_OF_FILE;
+
+ s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
+ s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
+ s->num_file++;
+ err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,
+ &s->cur_file_info_internal,
+ NULL,0,NULL,0,NULL,0);
+ s->current_file_ok = (err == UNZ_OK);
+ return err;
+}
+
+
+/*
+ Try locate the file szFileName in the zipfile.
+ For the iCaseSensitivity signification, see unzStringFileNameCompare
+
+ return value :
+ UNZ_OK if the file is found. It becomes the current file.
+ UNZ_END_OF_LIST_OF_FILE if the file is not found
+*/
+extern int ZEXPORT unzLocateFile (unzFile file, const char *szFileName, int iCaseSensitivity)
+{
+ unz64_s* s;
+ int err;
+
+ /* We remember the 'current' position in the file so that we can jump
+ * back there if we fail.
+ */
+ unz_file_info64 cur_file_infoSaved;
+ unz_file_info64_internal cur_file_info_internalSaved;
+ ZPOS64_T num_fileSaved;
+ ZPOS64_T pos_in_central_dirSaved;
+
+
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+
+ if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
+ return UNZ_PARAMERROR;
+
+ s=(unz64_s*)file;
+ if (!s->current_file_ok)
+ return UNZ_END_OF_LIST_OF_FILE;
+
+ /* Save the current state */
+ num_fileSaved = s->num_file;
+ pos_in_central_dirSaved = s->pos_in_central_dir;
+ cur_file_infoSaved = s->cur_file_info;
+ cur_file_info_internalSaved = s->cur_file_info_internal;
+
+ err = unzGoToFirstFile(file);
+
+ while (err == UNZ_OK)
+ {
+ char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
+ err = unzGetCurrentFileInfo64(file,NULL,
+ szCurrentFileName,sizeof(szCurrentFileName)-1,
+ NULL,0,NULL,0);
+ if (err == UNZ_OK)
+ {
+ if (unzStringFileNameCompare(szCurrentFileName,
+ szFileName,iCaseSensitivity)==0)
+ return UNZ_OK;
+ err = unzGoToNextFile(file);
+ }
+ }
+
+ /* We failed, so restore the state of the 'current file' to where we
+ * were.
+ */
+ s->num_file = num_fileSaved ;
+ s->pos_in_central_dir = pos_in_central_dirSaved ;
+ s->cur_file_info = cur_file_infoSaved;
+ s->cur_file_info_internal = cur_file_info_internalSaved;
+ return err;
+}
+
+
+/*
+///////////////////////////////////////////
+// Contributed by Ryan Haksi (mailto://cryogen@infoserve.net)
+// I need random access
+//
+// Further optimization could be realized by adding an ability
+// to cache the directory in memory. The goal being a single
+// comprehensive file read to put the file I need in a memory.
+*/
+
+/*
+typedef struct unz_file_pos_s
+{
+ ZPOS64_T pos_in_zip_directory; // offset in file
+ ZPOS64_T num_of_file; // # of file
+} unz_file_pos;
+*/
+
+extern int ZEXPORT unzGetFilePos64(unzFile file, unz64_file_pos* file_pos)
+{
+ unz64_s* s;
+
+ if (file==NULL || file_pos==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+ if (!s->current_file_ok)
+ return UNZ_END_OF_LIST_OF_FILE;
+
+ file_pos->pos_in_zip_directory = s->pos_in_central_dir;
+ file_pos->num_of_file = s->num_file;
+
+ return UNZ_OK;
+}
+
+extern int ZEXPORT unzGetFilePos(
+ unzFile file,
+ unz_file_pos* file_pos)
+{
+ unz64_file_pos file_pos64;
+ int err = unzGetFilePos64(file,&file_pos64);
+ if (err==UNZ_OK)
+ {
+ file_pos->pos_in_zip_directory = (uLong)file_pos64.pos_in_zip_directory;
+ file_pos->num_of_file = (uLong)file_pos64.num_of_file;
+ }
+ return err;
+}
+
+extern int ZEXPORT unzGoToFilePos64(unzFile file, const unz64_file_pos* file_pos)
+{
+ unz64_s* s;
+ int err;
+
+ if (file==NULL || file_pos==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+
+ /* jump to the right spot */
+ s->pos_in_central_dir = file_pos->pos_in_zip_directory;
+ s->num_file = file_pos->num_of_file;
+
+ /* set the current file */
+ err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,
+ &s->cur_file_info_internal,
+ NULL,0,NULL,0,NULL,0);
+ /* return results */
+ s->current_file_ok = (err == UNZ_OK);
+ return err;
+}
+
+extern int ZEXPORT unzGoToFilePos(
+ unzFile file,
+ unz_file_pos* file_pos)
+{
+ unz64_file_pos file_pos64;
+ if (file_pos == NULL)
+ return UNZ_PARAMERROR;
+
+ file_pos64.pos_in_zip_directory = file_pos->pos_in_zip_directory;
+ file_pos64.num_of_file = file_pos->num_of_file;
+ return unzGoToFilePos64(file,&file_pos64);
+}
+
+/*
+// Unzip Helper Functions - should be here?
+///////////////////////////////////////////
+*/
+
+/*
+ Read the local header of the current zipfile
+ Check the coherency of the local header and info in the end of central
+ directory about this file
+ store in *piSizeVar the size of extra info in local header
+ (filename and size of extra field data)
+*/
+local int unz64local_CheckCurrentFileCoherencyHeader (unz64_s* s, uInt* piSizeVar,
+ ZPOS64_T * poffset_local_extrafield,
+ uInt * psize_local_extrafield)
+{
+ uLong uMagic,uData,uFlags;
+ uLong size_filename;
+ uLong size_extra_field;
+ int err=UNZ_OK;
+
+ *piSizeVar = 0;
+ *poffset_local_extrafield = 0;
+ *psize_local_extrafield = 0;
+
+ if (ZSEEK64(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile +
+ s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)
+ return UNZ_ERRNO;
+
+
+ if (err==UNZ_OK)
+ {
+ if (unz64local_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
+ err=UNZ_ERRNO;
+ else if (uMagic!=0x04034b50)
+ err=UNZ_BADZIPFILE;
+ }
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
+ err=UNZ_ERRNO;
+/*
+ else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
+ err=UNZ_BADZIPFILE;
+*/
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
+ err=UNZ_ERRNO;
+ else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
+ err=UNZ_BADZIPFILE;
+
+ if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
+/* #ifdef HAVE_BZIP2 */
+ (s->cur_file_info.compression_method!=Z_BZIP2ED) &&
+/* #endif */
+ (s->cur_file_info.compression_method!=Z_DEFLATED))
+ err=UNZ_BADZIPFILE;
+
+ if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */
+ err=UNZ_ERRNO;
+
+ if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */
+ err=UNZ_ERRNO;
+ else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) && ((uFlags & 8)==0))
+ err=UNZ_BADZIPFILE;
+
+ if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */
+ err=UNZ_ERRNO;
+ else if (uData != 0xFFFFFFFF && (err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) && ((uFlags & 8)==0))
+ err=UNZ_BADZIPFILE;
+
+ if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */
+ err=UNZ_ERRNO;
+ else if (uData != 0xFFFFFFFF && (err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && ((uFlags & 8)==0))
+ err=UNZ_BADZIPFILE;
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK)
+ err=UNZ_ERRNO;
+ else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
+ err=UNZ_BADZIPFILE;
+
+ *piSizeVar += (uInt)size_filename;
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK)
+ err=UNZ_ERRNO;
+ *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
+ SIZEZIPLOCALHEADER + size_filename;
+ *psize_local_extrafield = (uInt)size_extra_field;
+
+ *piSizeVar += (uInt)size_extra_field;
+
+ return err;
+}
+
+/*
+ Open for reading data the current file in the zipfile.
+ If there is no error and the file is opened, the return value is UNZ_OK.
+*/
+extern int ZEXPORT unzOpenCurrentFile3 (unzFile file, int* method,
+ int* level, int raw, const char* password)
+{
+ int err=UNZ_OK;
+ uInt iSizeVar;
+ unz64_s* s;
+ file_in_zip64_read_info_s* pfile_in_zip_read_info;
+ ZPOS64_T offset_local_extrafield; /* offset of the local extra field */
+ uInt size_local_extrafield; /* size of the local extra field */
+# ifndef NOUNCRYPT
+ char source[12];
+# else
+ if (password != NULL)
+ return UNZ_PARAMERROR;
+# endif
+
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+ if (!s->current_file_ok)
+ return UNZ_PARAMERROR;
+
+ if (s->pfile_in_zip_read != NULL)
+ unzCloseCurrentFile(file);
+
+ if (unz64local_CheckCurrentFileCoherencyHeader(s,&iSizeVar, &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
+ return UNZ_BADZIPFILE;
+
+ pfile_in_zip_read_info = (file_in_zip64_read_info_s*)ALLOC(sizeof(file_in_zip64_read_info_s));
+ if (pfile_in_zip_read_info==NULL)
+ return UNZ_INTERNALERROR;
+
+ pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);
+ pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
+ pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
+ pfile_in_zip_read_info->pos_local_extrafield=0;
+ pfile_in_zip_read_info->raw=raw;
+
+ if (pfile_in_zip_read_info->read_buffer==NULL)
+ {
+ TRYFREE(pfile_in_zip_read_info);
+ return UNZ_INTERNALERROR;
+ }
+
+ pfile_in_zip_read_info->stream_initialised=0;
+
+ if (method!=NULL)
+ *method = (int)s->cur_file_info.compression_method;
+
+ if (level!=NULL)
+ {
+ *level = 6;
+ switch (s->cur_file_info.flag & 0x06)
+ {
+ case 6 : *level = 1; break;
+ case 4 : *level = 2; break;
+ case 2 : *level = 9; break;
+ }
+ }
+
+ if ((s->cur_file_info.compression_method!=0) &&
+/* #ifdef HAVE_BZIP2 */
+ (s->cur_file_info.compression_method!=Z_BZIP2ED) &&
+/* #endif */
+ (s->cur_file_info.compression_method!=Z_DEFLATED))
+
+ err=UNZ_BADZIPFILE;
+
+ pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
+ pfile_in_zip_read_info->crc32=0;
+ pfile_in_zip_read_info->total_out_64=0;
+ pfile_in_zip_read_info->compression_method = s->cur_file_info.compression_method;
+ pfile_in_zip_read_info->filestream=s->filestream;
+ pfile_in_zip_read_info->z_filefunc=s->z_filefunc;
+ pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
+
+ pfile_in_zip_read_info->stream.total_out = 0;
+
+ if ((s->cur_file_info.compression_method==Z_BZIP2ED) && (!raw))
+ {
+#ifdef HAVE_BZIP2
+ pfile_in_zip_read_info->bstream.bzalloc = (void *(*) (void *, int, int))0;
+ pfile_in_zip_read_info->bstream.bzfree = (free_func)0;
+ pfile_in_zip_read_info->bstream.opaque = (voidpf)0;
+ pfile_in_zip_read_info->bstream.state = (voidpf)0;
+
+ pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
+ pfile_in_zip_read_info->stream.zfree = (free_func)0;
+ pfile_in_zip_read_info->stream.opaque = (voidpf)0;
+ pfile_in_zip_read_info->stream.next_in = (voidpf)0;
+ pfile_in_zip_read_info->stream.avail_in = 0;
+
+ err=BZ2_bzDecompressInit(&pfile_in_zip_read_info->bstream, 0, 0);
+ if (err == Z_OK)
+ pfile_in_zip_read_info->stream_initialised=Z_BZIP2ED;
+ else
+ {
+ TRYFREE(pfile_in_zip_read_info);
+ return err;
+ }
+#else
+ pfile_in_zip_read_info->raw=1;
+#endif
+ }
+ else if ((s->cur_file_info.compression_method==Z_DEFLATED) && (!raw))
+ {
+ pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
+ pfile_in_zip_read_info->stream.zfree = (free_func)0;
+ pfile_in_zip_read_info->stream.opaque = (voidpf)0;
+ pfile_in_zip_read_info->stream.next_in = 0;
+ pfile_in_zip_read_info->stream.avail_in = 0;
+
+ err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
+ if (err == Z_OK)
+ pfile_in_zip_read_info->stream_initialised=Z_DEFLATED;
+ else
+ {
+ TRYFREE(pfile_in_zip_read_info);
+ return err;
+ }
+ /* windowBits is passed < 0 to tell that there is no zlib header.
+ * Note that in this case inflate *requires* an extra "dummy" byte
+ * after the compressed stream in order to complete decompression and
+ * return Z_STREAM_END.
+ * In unzip, i don't wait absolutely Z_STREAM_END because I known the
+ * size of both compressed and uncompressed data
+ */
+ }
+ pfile_in_zip_read_info->rest_read_compressed =
+ s->cur_file_info.compressed_size ;
+ pfile_in_zip_read_info->rest_read_uncompressed =
+ s->cur_file_info.uncompressed_size ;
+
+
+ pfile_in_zip_read_info->pos_in_zipfile =
+ s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
+ iSizeVar;
+
+ pfile_in_zip_read_info->stream.avail_in = (uInt)0;
+
+ s->pfile_in_zip_read = pfile_in_zip_read_info;
+ s->encrypted = 0;
+
+# ifndef NOUNCRYPT
+ if (password != NULL)
+ {
+ int i;
+ s->pcrc_32_tab = get_crc_table();
+ init_keys(password,s->keys,s->pcrc_32_tab);
+ if (ZSEEK64(s->z_filefunc, s->filestream,
+ s->pfile_in_zip_read->pos_in_zipfile +
+ s->pfile_in_zip_read->byte_before_the_zipfile,
+ SEEK_SET)!=0)
+ return UNZ_INTERNALERROR;
+ if(ZREAD64(s->z_filefunc, s->filestream,source, 12)<12)
+ return UNZ_INTERNALERROR;
+
+ for (i = 0; i<12; i++)
+ zdecode(s->keys,s->pcrc_32_tab,source[i]);
+
+ s->pfile_in_zip_read->pos_in_zipfile+=12;
+ s->pfile_in_zip_read->rest_read_compressed-=12;
+ s->encrypted=1;
+ }
+# endif
+
+
+ return UNZ_OK;
+}
+
+extern int ZEXPORT unzOpenCurrentFile (unzFile file)
+{
+ return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL);
+}
+
+extern int ZEXPORT unzOpenCurrentFilePassword (unzFile file, const char* password)
+{
+ return unzOpenCurrentFile3(file, NULL, NULL, 0, password);
+}
+
+extern int ZEXPORT unzOpenCurrentFile2 (unzFile file, int* method, int* level, int raw)
+{
+ return unzOpenCurrentFile3(file, method, level, raw, NULL);
+}
+
+/** Addition for GDAL : START */
+
+extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64( unzFile file)
+{
+ unz64_s* s;
+ file_in_zip64_read_info_s* pfile_in_zip_read_info;
+ s=(unz64_s*)file;
+ if (file==NULL)
+ return 0; //UNZ_PARAMERROR;
+ pfile_in_zip_read_info=s->pfile_in_zip_read;
+ if (pfile_in_zip_read_info==NULL)
+ return 0; //UNZ_PARAMERROR;
+ return pfile_in_zip_read_info->pos_in_zipfile +
+ pfile_in_zip_read_info->byte_before_the_zipfile;
+}
+
+/** Addition for GDAL : END */
+
+/*
+ Read bytes from the current file.
+ buf contain buffer where data must be copied
+ len the size of buf.
+
+ return the number of byte copied if somes bytes are copied
+ return 0 if the end of file was reached
+ return <0 with error code if there is an error
+ (UNZ_ERRNO for IO error, or zLib error for uncompress error)
+*/
+extern int ZEXPORT unzReadCurrentFile (unzFile file, voidp buf, unsigned len)
+{
+ int err=UNZ_OK;
+ uInt iRead = 0;
+ unz64_s* s;
+ file_in_zip64_read_info_s* pfile_in_zip_read_info;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+ pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+ if (pfile_in_zip_read_info==NULL)
+ return UNZ_PARAMERROR;
+
+
+ if (pfile_in_zip_read_info->read_buffer == NULL)
+ return UNZ_END_OF_LIST_OF_FILE;
+ if (len==0)
+ return 0;
+
+ pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;
+
+ pfile_in_zip_read_info->stream.avail_out = (uInt)len;
+
+ if ((len>pfile_in_zip_read_info->rest_read_uncompressed) &&
+ (!(pfile_in_zip_read_info->raw)))
+ pfile_in_zip_read_info->stream.avail_out =
+ (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
+
+ if ((len>pfile_in_zip_read_info->rest_read_compressed+
+ pfile_in_zip_read_info->stream.avail_in) &&
+ (pfile_in_zip_read_info->raw))
+ pfile_in_zip_read_info->stream.avail_out =
+ (uInt)pfile_in_zip_read_info->rest_read_compressed+
+ pfile_in_zip_read_info->stream.avail_in;
+
+ while (pfile_in_zip_read_info->stream.avail_out>0)
+ {
+ if ((pfile_in_zip_read_info->stream.avail_in==0) &&
+ (pfile_in_zip_read_info->rest_read_compressed>0))
+ {
+ uInt uReadThis = UNZ_BUFSIZE;
+ if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
+ uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
+ if (uReadThis == 0)
+ return UNZ_EOF;
+ if (ZSEEK64(pfile_in_zip_read_info->z_filefunc,
+ pfile_in_zip_read_info->filestream,
+ pfile_in_zip_read_info->pos_in_zipfile +
+ pfile_in_zip_read_info->byte_before_the_zipfile,
+ ZLIB_FILEFUNC_SEEK_SET)!=0)
+ return UNZ_ERRNO;
+ if (ZREAD64(pfile_in_zip_read_info->z_filefunc,
+ pfile_in_zip_read_info->filestream,
+ pfile_in_zip_read_info->read_buffer,
+ uReadThis)!=uReadThis)
+ return UNZ_ERRNO;
+
+
+# ifndef NOUNCRYPT
+ if(s->encrypted)
+ {
+ uInt i;
+ for(i=0;i<uReadThis;i++)
+ pfile_in_zip_read_info->read_buffer[i] =
+ zdecode(s->keys,s->pcrc_32_tab,
+ pfile_in_zip_read_info->read_buffer[i]);
+ }
+# endif
+
+
+ pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
+
+ pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
+
+ pfile_in_zip_read_info->stream.next_in =
+ (Bytef*)pfile_in_zip_read_info->read_buffer;
+ pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
+ }
+
+ if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw))
+ {
+ uInt uDoCopy,i ;
+
+ if ((pfile_in_zip_read_info->stream.avail_in == 0) &&
+ (pfile_in_zip_read_info->rest_read_compressed == 0))
+ return (iRead==0) ? UNZ_EOF : iRead;
+
+ if (pfile_in_zip_read_info->stream.avail_out <
+ pfile_in_zip_read_info->stream.avail_in)
+ uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
+ else
+ uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
+
+ for (i=0;i<uDoCopy;i++)
+ *(pfile_in_zip_read_info->stream.next_out+i) =
+ *(pfile_in_zip_read_info->stream.next_in+i);
+
+ pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uDoCopy;
+
+ pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
+ pfile_in_zip_read_info->stream.next_out,
+ uDoCopy);
+ pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
+ pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
+ pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
+ pfile_in_zip_read_info->stream.next_out += uDoCopy;
+ pfile_in_zip_read_info->stream.next_in += uDoCopy;
+ pfile_in_zip_read_info->stream.total_out += uDoCopy;
+ iRead += uDoCopy;
+ }
+ else if (pfile_in_zip_read_info->compression_method==Z_BZIP2ED)
+ {
+#ifdef HAVE_BZIP2
+ uLong uTotalOutBefore,uTotalOutAfter;
+ const Bytef *bufBefore;
+ uLong uOutThis;
+
+ pfile_in_zip_read_info->bstream.next_in = (char*)pfile_in_zip_read_info->stream.next_in;
+ pfile_in_zip_read_info->bstream.avail_in = pfile_in_zip_read_info->stream.avail_in;
+ pfile_in_zip_read_info->bstream.total_in_lo32 = pfile_in_zip_read_info->stream.total_in;
+ pfile_in_zip_read_info->bstream.total_in_hi32 = 0;
+ pfile_in_zip_read_info->bstream.next_out = (char*)pfile_in_zip_read_info->stream.next_out;
+ pfile_in_zip_read_info->bstream.avail_out = pfile_in_zip_read_info->stream.avail_out;
+ pfile_in_zip_read_info->bstream.total_out_lo32 = pfile_in_zip_read_info->stream.total_out;
+ pfile_in_zip_read_info->bstream.total_out_hi32 = 0;
+
+ uTotalOutBefore = pfile_in_zip_read_info->bstream.total_out_lo32;
+ bufBefore = (const Bytef *)pfile_in_zip_read_info->bstream.next_out;
+
+ err=BZ2_bzDecompress(&pfile_in_zip_read_info->bstream);
+
+ uTotalOutAfter = pfile_in_zip_read_info->bstream.total_out_lo32;
+ uOutThis = uTotalOutAfter-uTotalOutBefore;
+
+ pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis;
+
+ pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,bufBefore, (uInt)(uOutThis));
+ pfile_in_zip_read_info->rest_read_uncompressed -= uOutThis;
+ iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
+
+ pfile_in_zip_read_info->stream.next_in = (Bytef*)pfile_in_zip_read_info->bstream.next_in;
+ pfile_in_zip_read_info->stream.avail_in = pfile_in_zip_read_info->bstream.avail_in;
+ pfile_in_zip_read_info->stream.total_in = pfile_in_zip_read_info->bstream.total_in_lo32;
+ pfile_in_zip_read_info->stream.next_out = (Bytef*)pfile_in_zip_read_info->bstream.next_out;
+ pfile_in_zip_read_info->stream.avail_out = pfile_in_zip_read_info->bstream.avail_out;
+ pfile_in_zip_read_info->stream.total_out = pfile_in_zip_read_info->bstream.total_out_lo32;
+
+ if (err==BZ_STREAM_END)
+ return (iRead==0) ? UNZ_EOF : iRead;
+ if (err!=BZ_OK)
+ break;
+#endif
+ } // end Z_BZIP2ED
+ else
+ {
+ ZPOS64_T uTotalOutBefore,uTotalOutAfter;
+ const Bytef *bufBefore;
+ ZPOS64_T uOutThis;
+ int flush=Z_SYNC_FLUSH;
+
+ uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
+ bufBefore = pfile_in_zip_read_info->stream.next_out;
+
+ /*
+ if ((pfile_in_zip_read_info->rest_read_uncompressed ==
+ pfile_in_zip_read_info->stream.avail_out) &&
+ (pfile_in_zip_read_info->rest_read_compressed == 0))
+ flush = Z_FINISH;
+ */
+ err=inflate(&pfile_in_zip_read_info->stream,flush);
+
+ if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL))
+ err = Z_DATA_ERROR;
+
+ uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
+ uOutThis = uTotalOutAfter-uTotalOutBefore;
+
+ pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis;
+
+ pfile_in_zip_read_info->crc32 =
+ crc32(pfile_in_zip_read_info->crc32,bufBefore,
+ (uInt)(uOutThis));
+
+ pfile_in_zip_read_info->rest_read_uncompressed -=
+ uOutThis;
+
+ iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
+
+ if (err==Z_STREAM_END)
+ return (iRead==0) ? UNZ_EOF : iRead;
+ if (err!=Z_OK)
+ break;
+ }
+ }
+
+ if (err==Z_OK)
+ return iRead;
+ return err;
+}
+
+
+/*
+ Give the current position in uncompressed data
+*/
+extern z_off_t ZEXPORT unztell (unzFile file)
+{
+ unz64_s* s;
+ file_in_zip64_read_info_s* pfile_in_zip_read_info;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+ pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+ if (pfile_in_zip_read_info==NULL)
+ return UNZ_PARAMERROR;
+
+ return (z_off_t)pfile_in_zip_read_info->stream.total_out;
+}
+
+extern ZPOS64_T ZEXPORT unztell64 (unzFile file)
+{
+
+ unz64_s* s;
+ file_in_zip64_read_info_s* pfile_in_zip_read_info;
+ if (file==NULL)
+ return (ZPOS64_T)-1;
+ s=(unz64_s*)file;
+ pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+ if (pfile_in_zip_read_info==NULL)
+ return (ZPOS64_T)-1;
+
+ return pfile_in_zip_read_info->total_out_64;
+}
+
+
+/*
+ return 1 if the end of file was reached, 0 elsewhere
+*/
+extern int ZEXPORT unzeof (unzFile file)
+{
+ unz64_s* s;
+ file_in_zip64_read_info_s* pfile_in_zip_read_info;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+ pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+ if (pfile_in_zip_read_info==NULL)
+ return UNZ_PARAMERROR;
+
+ if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
+ return 1;
+ else
+ return 0;
+}
+
+
+
+/*
+Read extra field from the current file (opened by unzOpenCurrentFile)
+This is the local-header version of the extra field (sometimes, there is
+more info in the local-header version than in the central-header)
+
+ if buf==NULL, it return the size of the local extra field that can be read
+
+ if buf!=NULL, len is the size of the buffer, the extra header is copied in
+ buf.
+ the return value is the number of bytes copied in buf, or (if <0)
+ the error code
+*/
+extern int ZEXPORT unzGetLocalExtrafield (unzFile file, voidp buf, unsigned len)
+{
+ unz64_s* s;
+ file_in_zip64_read_info_s* pfile_in_zip_read_info;
+ uInt read_now;
+ ZPOS64_T size_to_read;
+
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+ pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+ if (pfile_in_zip_read_info==NULL)
+ return UNZ_PARAMERROR;
+
+ size_to_read = (pfile_in_zip_read_info->size_local_extrafield -
+ pfile_in_zip_read_info->pos_local_extrafield);
+
+ if (buf==NULL)
+ return (int)size_to_read;
+
+ if (len>size_to_read)
+ read_now = (uInt)size_to_read;
+ else
+ read_now = (uInt)len ;
+
+ if (read_now==0)
+ return 0;
+
+ if (ZSEEK64(pfile_in_zip_read_info->z_filefunc,
+ pfile_in_zip_read_info->filestream,
+ pfile_in_zip_read_info->offset_local_extrafield +
+ pfile_in_zip_read_info->pos_local_extrafield,
+ ZLIB_FILEFUNC_SEEK_SET)!=0)
+ return UNZ_ERRNO;
+
+ if (ZREAD64(pfile_in_zip_read_info->z_filefunc,
+ pfile_in_zip_read_info->filestream,
+ buf,read_now)!=read_now)
+ return UNZ_ERRNO;
+
+ return (int)read_now;
+}
+
+/*
+ Close the file in zip opened with unzOpenCurrentFile
+ Return UNZ_CRCERROR if all the file was read but the CRC is not good
+*/
+extern int ZEXPORT unzCloseCurrentFile (unzFile file)
+{
+ int err=UNZ_OK;
+
+ unz64_s* s;
+ file_in_zip64_read_info_s* pfile_in_zip_read_info;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+ pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+ if (pfile_in_zip_read_info==NULL)
+ return UNZ_PARAMERROR;
+
+
+ if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) &&
+ (!pfile_in_zip_read_info->raw))
+ {
+ if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
+ err=UNZ_CRCERROR;
+ }
+
+
+ TRYFREE(pfile_in_zip_read_info->read_buffer);
+ pfile_in_zip_read_info->read_buffer = NULL;
+ if (pfile_in_zip_read_info->stream_initialised == Z_DEFLATED)
+ inflateEnd(&pfile_in_zip_read_info->stream);
+#ifdef HAVE_BZIP2
+ else if (pfile_in_zip_read_info->stream_initialised == Z_BZIP2ED)
+ BZ2_bzDecompressEnd(&pfile_in_zip_read_info->bstream);
+#endif
+
+
+ pfile_in_zip_read_info->stream_initialised = 0;
+ TRYFREE(pfile_in_zip_read_info);
+
+ s->pfile_in_zip_read=NULL;
+
+ return err;
+}
+
+
+/*
+ Get the global comment string of the ZipFile, in the szComment buffer.
+ uSizeBuf is the size of the szComment buffer.
+ return the number of byte copied or an error code <0
+*/
+extern int ZEXPORT unzGetGlobalComment (unzFile file, char * szComment, uLong uSizeBuf)
+{
+ unz64_s* s;
+ uLong uReadThis ;
+ if (file==NULL)
+ return (int)UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+
+ uReadThis = uSizeBuf;
+ if (uReadThis>s->gi.size_comment)
+ uReadThis = s->gi.size_comment;
+
+ if (ZSEEK64(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0)
+ return UNZ_ERRNO;
+
+ if (uReadThis>0)
+ {
+ *szComment='\0';
+ if (ZREAD64(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis)
+ return UNZ_ERRNO;
+ }
+
+ if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
+ *(szComment+s->gi.size_comment)='\0';
+ return (int)uReadThis;
+}
+
+/* Additions by RX '2004 */
+extern ZPOS64_T ZEXPORT unzGetOffset64(unzFile file)
+{
+ unz64_s* s;
+
+ if (file==NULL)
+ return 0; //UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+ if (!s->current_file_ok)
+ return 0;
+ if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff)
+ if (s->num_file==s->gi.number_entry)
+ return 0;
+ return s->pos_in_central_dir;
+}
+
+extern uLong ZEXPORT unzGetOffset (unzFile file)
+{
+ ZPOS64_T offset64;
+
+ if (file==NULL)
+ return 0; //UNZ_PARAMERROR;
+ offset64 = unzGetOffset64(file);
+ return (uLong)offset64;
+}
+
+extern int ZEXPORT unzSetOffset64(unzFile file, ZPOS64_T pos)
+{
+ unz64_s* s;
+ int err;
+
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+
+ s->pos_in_central_dir = pos;
+ s->num_file = s->gi.number_entry; /* hack */
+ err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,
+ &s->cur_file_info_internal,
+ NULL,0,NULL,0,NULL,0);
+ s->current_file_ok = (err == UNZ_OK);
+ return err;
+}
+
+extern int ZEXPORT unzSetOffset (unzFile file, uLong pos)
+{
+ return unzSetOffset64(file,pos);
+}
--- /dev/null
+/* unzip.h -- IO for uncompress .zip files using zlib
+ Version 1.1, February 14h, 2010
+ part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
+
+ Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
+
+ Modifications of Unzip for Zip64
+ Copyright (C) 2007-2008 Even Rouault
+
+ Modifications for Zip64 support on both zip and unzip
+ Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
+
+ For more info read MiniZip_info.txt
+
+ ---------------------------------------------------------------------------------
+
+ Condition of use and distribution are the same than zlib :
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ ---------------------------------------------------------------------------------
+
+ Changes
+
+ See header of unzip64.c
+
+*/
+
+#ifndef _unz64_H
+#define _unz64_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _ZLIB_H
+#include "zlib.h"
+#endif
+
+#ifndef _ZLIBIOAPI_H
+#include "ioapi.h"
+#endif
+
+#ifdef HAVE_BZIP2
+#include "bzlib.h"
+#endif
+
+#define Z_BZIP2ED 12
+
+#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP)
+/* like the STRICT of WIN32, we define a pointer that cannot be converted
+ from (void*) without cast */
+typedef struct TagunzFile__ { int unused; } unzFile__;
+typedef unzFile__ *unzFile;
+#else
+typedef voidp unzFile;
+#endif
+
+
+#define UNZ_OK (0)
+#define UNZ_END_OF_LIST_OF_FILE (-100)
+#define UNZ_ERRNO (Z_ERRNO)
+#define UNZ_EOF (0)
+#define UNZ_PARAMERROR (-102)
+#define UNZ_BADZIPFILE (-103)
+#define UNZ_INTERNALERROR (-104)
+#define UNZ_CRCERROR (-105)
+
+/* tm_unz contain date/time info */
+typedef struct tm_unz_s
+{
+ uInt tm_sec; /* seconds after the minute - [0,59] */
+ uInt tm_min; /* minutes after the hour - [0,59] */
+ uInt tm_hour; /* hours since midnight - [0,23] */
+ uInt tm_mday; /* day of the month - [1,31] */
+ uInt tm_mon; /* months since January - [0,11] */
+ uInt tm_year; /* years - [1980..2044] */
+} tm_unz;
+
+/* unz_global_info structure contain global data about the ZIPfile
+ These data comes from the end of central dir */
+typedef struct unz_global_info64_s
+{
+ ZPOS64_T number_entry; /* total number of entries in
+ the central dir on this disk */
+ uLong size_comment; /* size of the global comment of the zipfile */
+} unz_global_info64;
+
+typedef struct unz_global_info_s
+{
+ uLong number_entry; /* total number of entries in
+ the central dir on this disk */
+ uLong size_comment; /* size of the global comment of the zipfile */
+} unz_global_info;
+
+/* unz_file_info contain information about a file in the zipfile */
+typedef struct unz_file_info64_s
+{
+ uLong version; /* version made by 2 bytes */
+ uLong version_needed; /* version needed to extract 2 bytes */
+ uLong flag; /* general purpose bit flag 2 bytes */
+ uLong compression_method; /* compression method 2 bytes */
+ uLong dosDate; /* last mod file date in Dos fmt 4 bytes */
+ uLong crc; /* crc-32 4 bytes */
+ ZPOS64_T compressed_size; /* compressed size 8 bytes */
+ ZPOS64_T uncompressed_size; /* uncompressed size 8 bytes */
+ uLong size_filename; /* filename length 2 bytes */
+ uLong size_file_extra; /* extra field length 2 bytes */
+ uLong size_file_comment; /* file comment length 2 bytes */
+
+ uLong disk_num_start; /* disk number start 2 bytes */
+ uLong internal_fa; /* internal file attributes 2 bytes */
+ uLong external_fa; /* external file attributes 4 bytes */
+
+ tm_unz tmu_date;
+} unz_file_info64;
+
+typedef struct unz_file_info_s
+{
+ uLong version; /* version made by 2 bytes */
+ uLong version_needed; /* version needed to extract 2 bytes */
+ uLong flag; /* general purpose bit flag 2 bytes */
+ uLong compression_method; /* compression method 2 bytes */
+ uLong dosDate; /* last mod file date in Dos fmt 4 bytes */
+ uLong crc; /* crc-32 4 bytes */
+ uLong compressed_size; /* compressed size 4 bytes */
+ uLong uncompressed_size; /* uncompressed size 4 bytes */
+ uLong size_filename; /* filename length 2 bytes */
+ uLong size_file_extra; /* extra field length 2 bytes */
+ uLong size_file_comment; /* file comment length 2 bytes */
+
+ uLong disk_num_start; /* disk number start 2 bytes */
+ uLong internal_fa; /* internal file attributes 2 bytes */
+ uLong external_fa; /* external file attributes 4 bytes */
+
+ tm_unz tmu_date;
+} unz_file_info;
+
+extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1,
+ const char* fileName2,
+ int iCaseSensitivity));
+/*
+ Compare two filename (fileName1,fileName2).
+ If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
+ If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
+ or strcasecmp)
+ If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
+ (like 1 on Unix, 2 on Windows)
+*/
+
+
+extern unzFile ZEXPORT unzOpen OF((const char *path));
+extern unzFile ZEXPORT unzOpen64 OF((const void *path));
+/*
+ Open a Zip file. path contain the full pathname (by example,
+ on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer
+ "zlib/zlib113.zip".
+ If the zipfile cannot be opened (file don't exist or in not valid), the
+ return value is NULL.
+ Else, the return value is a unzFile Handle, usable with other function
+ of this unzip package.
+ the "64" function take a const void* pointer, because the path is just the
+ value passed to the open64_file_func callback.
+ Under Windows, if UNICODE is defined, using fill_fopen64_filefunc, the path
+ is a pointer to a wide unicode string (LPCTSTR is LPCWSTR), so const char*
+ does not describe the reality
+*/
+
+
+extern unzFile ZEXPORT unzOpen2 OF((const char *path,
+ zlib_filefunc_def* pzlib_filefunc_def));
+/*
+ Open a Zip file, like unzOpen, but provide a set of file low level API
+ for read/write the zip file (see ioapi.h)
+*/
+
+extern unzFile ZEXPORT unzOpen2_64 OF((const void *path,
+ zlib_filefunc64_def* pzlib_filefunc_def));
+/*
+ Open a Zip file, like unz64Open, but provide a set of file low level API
+ for read/write the zip file (see ioapi.h)
+*/
+
+extern int ZEXPORT unzClose OF((unzFile file));
+/*
+ Close a ZipFile opened with unzOpen.
+ If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
+ these files MUST be closed with unzCloseCurrentFile before call unzClose.
+ return UNZ_OK if there is no problem. */
+
+extern int ZEXPORT unzGetGlobalInfo OF((unzFile file,
+ unz_global_info *pglobal_info));
+
+extern int ZEXPORT unzGetGlobalInfo64 OF((unzFile file,
+ unz_global_info64 *pglobal_info));
+/*
+ Write info about the ZipFile in the *pglobal_info structure.
+ No preparation of the structure is needed
+ return UNZ_OK if there is no problem. */
+
+
+extern int ZEXPORT unzGetGlobalComment OF((unzFile file,
+ char *szComment,
+ uLong uSizeBuf));
+/*
+ Get the global comment string of the ZipFile, in the szComment buffer.
+ uSizeBuf is the size of the szComment buffer.
+ return the number of byte copied or an error code <0
+*/
+
+
+/***************************************************************************/
+/* Unzip package allow you browse the directory of the zipfile */
+
+extern int ZEXPORT unzGoToFirstFile OF((unzFile file));
+/*
+ Set the current file of the zipfile to the first file.
+ return UNZ_OK if there is no problem
+*/
+
+extern int ZEXPORT unzGoToNextFile OF((unzFile file));
+/*
+ Set the current file of the zipfile to the next file.
+ return UNZ_OK if there is no problem
+ return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
+*/
+
+extern int ZEXPORT unzLocateFile OF((unzFile file,
+ const char *szFileName,
+ int iCaseSensitivity));
+/*
+ Try locate the file szFileName in the zipfile.
+ For the iCaseSensitivity signification, see unzStringFileNameCompare
+
+ return value :
+ UNZ_OK if the file is found. It becomes the current file.
+ UNZ_END_OF_LIST_OF_FILE if the file is not found
+*/
+
+
+/* ****************************************** */
+/* Ryan supplied functions */
+/* unz_file_info contain information about a file in the zipfile */
+typedef struct unz_file_pos_s
+{
+ uLong pos_in_zip_directory; /* offset in zip file directory */
+ uLong num_of_file; /* # of file */
+} unz_file_pos;
+
+extern int ZEXPORT unzGetFilePos(
+ unzFile file,
+ unz_file_pos* file_pos);
+
+extern int ZEXPORT unzGoToFilePos(
+ unzFile file,
+ unz_file_pos* file_pos);
+
+typedef struct unz64_file_pos_s
+{
+ ZPOS64_T pos_in_zip_directory; /* offset in zip file directory */
+ ZPOS64_T num_of_file; /* # of file */
+} unz64_file_pos;
+
+extern int ZEXPORT unzGetFilePos64(
+ unzFile file,
+ unz64_file_pos* file_pos);
+
+extern int ZEXPORT unzGoToFilePos64(
+ unzFile file,
+ const unz64_file_pos* file_pos);
+
+/* ****************************************** */
+
+extern int ZEXPORT unzGetCurrentFileInfo64 OF((unzFile file,
+ unz_file_info64 *pfile_info,
+ char *szFileName,
+ uLong fileNameBufferSize,
+ void *extraField,
+ uLong extraFieldBufferSize,
+ char *szComment,
+ uLong commentBufferSize));
+
+extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file,
+ unz_file_info *pfile_info,
+ char *szFileName,
+ uLong fileNameBufferSize,
+ void *extraField,
+ uLong extraFieldBufferSize,
+ char *szComment,
+ uLong commentBufferSize));
+/*
+ Get Info about the current file
+ if pfile_info!=NULL, the *pfile_info structure will contain somes info about
+ the current file
+ if szFileName!=NULL, the filemane string will be copied in szFileName
+ (fileNameBufferSize is the size of the buffer)
+ if extraField!=NULL, the extra field information will be copied in extraField
+ (extraFieldBufferSize is the size of the buffer).
+ This is the Central-header version of the extra field
+ if szComment!=NULL, the comment string of the file will be copied in szComment
+ (commentBufferSize is the size of the buffer)
+*/
+
+
+/** Addition for GDAL : START */
+
+extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64 OF((unzFile file));
+
+/** Addition for GDAL : END */
+
+
+/***************************************************************************/
+/* for reading the content of the current zipfile, you can open it, read data
+ from it, and close it (you can close it before reading all the file)
+ */
+
+extern int ZEXPORT unzOpenCurrentFile OF((unzFile file));
+/*
+ Open for reading data the current file in the zipfile.
+ If there is no error, the return value is UNZ_OK.
+*/
+
+extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file,
+ const char* password));
+/*
+ Open for reading data the current file in the zipfile.
+ password is a crypting password
+ If there is no error, the return value is UNZ_OK.
+*/
+
+extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file,
+ int* method,
+ int* level,
+ int raw));
+/*
+ Same than unzOpenCurrentFile, but open for read raw the file (not uncompress)
+ if raw==1
+ *method will receive method of compression, *level will receive level of
+ compression
+ note : you can set level parameter as NULL (if you did not want known level,
+ but you CANNOT set method parameter as NULL
+*/
+
+extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file,
+ int* method,
+ int* level,
+ int raw,
+ const char* password));
+/*
+ Same than unzOpenCurrentFile, but open for read raw the file (not uncompress)
+ if raw==1
+ *method will receive method of compression, *level will receive level of
+ compression
+ note : you can set level parameter as NULL (if you did not want known level,
+ but you CANNOT set method parameter as NULL
+*/
+
+
+extern int ZEXPORT unzCloseCurrentFile OF((unzFile file));
+/*
+ Close the file in zip opened with unzOpenCurrentFile
+ Return UNZ_CRCERROR if all the file was read but the CRC is not good
+*/
+
+extern int ZEXPORT unzReadCurrentFile OF((unzFile file,
+ voidp buf,
+ unsigned len));
+/*
+ Read bytes from the current file (opened by unzOpenCurrentFile)
+ buf contain buffer where data must be copied
+ len the size of buf.
+
+ return the number of byte copied if somes bytes are copied
+ return 0 if the end of file was reached
+ return <0 with error code if there is an error
+ (UNZ_ERRNO for IO error, or zLib error for uncompress error)
+*/
+
+extern z_off_t ZEXPORT unztell OF((unzFile file));
+
+extern ZPOS64_T ZEXPORT unztell64 OF((unzFile file));
+/*
+ Give the current position in uncompressed data
+*/
+
+extern int ZEXPORT unzeof OF((unzFile file));
+/*
+ return 1 if the end of file was reached, 0 elsewhere
+*/
+
+extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file,
+ voidp buf,
+ unsigned len));
+/*
+ Read extra field from the current file (opened by unzOpenCurrentFile)
+ This is the local-header version of the extra field (sometimes, there is
+ more info in the local-header version than in the central-header)
+
+ if buf==NULL, it return the size of the local extra field
+
+ if buf!=NULL, len is the size of the buffer, the extra header is copied in
+ buf.
+ the return value is the number of bytes copied in buf, or (if <0)
+ the error code
+*/
+
+/***************************************************************************/
+
+/* Get the current file offset */
+extern ZPOS64_T ZEXPORT unzGetOffset64 (unzFile file);
+extern uLong ZEXPORT unzGetOffset (unzFile file);
+
+/* Set the current file offset */
+extern int ZEXPORT unzSetOffset64 (unzFile file, ZPOS64_T pos);
+extern int ZEXPORT unzSetOffset (unzFile file, uLong pos);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _unz64_H */
],
'include_dirs': [
'src/api/utils/logger',
+ 'src/api/utils',
'include/lwnode',
'include',
'.',
],
'cflags_cc!': ['-fno-exceptions'],
'cflags_cc': ['-fexceptions'],
+ 'conditions': [
+ ['enable_external_builtin_scripts == "true"', {
+ 'defines': ['LWNODE_USE_EXTERNAL_BUILTIN_SCRIPTS'],
+ }],
+ ],
},
'conditions': [
['OS == "linux"', {
bool dumpSelfMemorySnapshot();
+class MessageLoop {
+ public:
+ // this callback should be called right before polling I/O events
+ static void OnPrepare(v8::Isolate* isolate);
+};
+
class Utils {
public:
// should return string buffer
const char* path() { return path_; }
size_t preloadedDataLength() { return preloadedDataLength_; }
+ bool isOneByteString() { return isOneByteString_; }
static ReloadableSourceData* create(std::string sourcePath,
void* preloadedData,
- size_t preloadedDataLength);
+ size_t preloadedDataLength,
+ bool isOneByteString);
private:
char* path_{nullptr};
size_t preloadedDataLength_{0};
+ bool isOneByteString_{false};
ReloadableSourceData() = default;
};
- static v8::MaybeLocal<v8::String> NewReloadableStringFromOneByte(
+ static v8::MaybeLocal<v8::String> NewReloadableString(
v8::Isolate* isolate,
ReloadableSourceData* data,
LoadCallback loadCallback,
return Local<v8::Context>();
}
- auto globalObjectData =
- ObjectRefHelper::getExtraData(esVal.get()->globalObject())
- ->asGlobalObjectData();
-
- LWNODE_CHECK(globalObjectData->internalFieldCount() ==
- GlobalObjectData::kInternalFieldCount);
-
- auto lwCreationContext = reinterpret_cast<ContextWrap*>(
- globalObjectData->internalField(GlobalObjectData::kContextWrapSlot));
+ auto lwCreationContext = ContextWrap::fromEscargot(esVal.get());
return v8::Local<v8::Context>::New(
lwIsolate->toV8(),
esSource, esResourceName, source->GetResourceOptions().IsModule());
if (!result.isSuccessful()) {
+ Evaluator::EvaluatorResult r;
+ r.error = ExceptionHelper::createErrorObject(
+ esPureContext, result.parseErrorCode, result.parseErrorMessage);
+
+ lwIsolate->SetPendingExceptionAndMessage(r.error.get(), r.stackTraceData);
+ lwIsolate->ReportPendingMessages();
return MaybeLocal<UnboundScript>();
}
#include "api/module.h"
#include "api/object.h"
#include "api/serializer.h"
-#include "api/utils/string.h"
+#include "api/utils/string-util.h"
namespace i = v8::internal;
ScriptParserRef::InitializeScriptResult scriptResult =
context->scriptParser()->initializeScript(
StringRef::createExternalFromASCII(buffer, bufferSize),
- StringRef::createFromASCII(name,
- strnlen(name, v8::String::kMaxLength)));
+ StringRef::createFromUTF8(name,
+ strnlen(name, v8::String::kMaxLength)));
LWNODE_CHECK_MSG(scriptResult.isSuccessful(),
"Cannot parser %s: %s",
name,
return new ContextWrap(isolate);
}
+ContextWrap* ContextWrap::fromEscargot(Escargot::ContextRef* esContext) {
+ auto globalObjectData =
+ ObjectRefHelper::getExtraData(esContext->globalObject())
+ ->asGlobalObjectData();
+
+ LWNODE_CHECK(globalObjectData->internalFieldCount() ==
+ GlobalObjectData::kInternalFieldCount);
+
+ auto lwCreationContext = reinterpret_cast<ContextWrap*>(
+ globalObjectData->internalField(GlobalObjectData::kContextWrapSlot));
+ return lwCreationContext;
+}
+
void ContextWrap::Enter() {
isolate_->Enter();
isolate_->pushContext(this);
class ContextWrap : public ValueWrap {
public:
static ContextWrap* New(IsolateWrap* isolate);
+ static ContextWrap* fromEscargot(Escargot::ContextRef* context);
void Enter();
void Exit();
#include <sstream>
#include "handle.h"
#include "utils/misc.h"
-#include "utils/string.h"
+#include "utils/string-util.h"
using namespace Escargot;
#include "extra-data.h"
#include "isolate.h"
#include "utils/misc.h"
-#include "utils/string.h"
+#include "utils/string-util.h"
#include <sstream>
globalHandles_ = new GlobalHandles(toV8());
privateValuesSymbol_ = PersistentRefHolder<SymbolRef>(
- SymbolRef::create(StringRef::createFromASCII(PRIVATE_VALUES.data(),
- PRIVATE_VALUES.length())));
+ SymbolRef::create(StringRef::createFromUTF8(PRIVATE_VALUES.data(),
+ PRIVATE_VALUES.length())));
// NOTE: check lock_gc_release(); is needed (and where)
// lock_gc_release();
LWNODE_CHECK(r.isSuccessful());
otpl->set(
- StringRef::createFromASCII(name, length), r.result, false, false, true);
+ StringRef::createFromUTF8(name, length), r.result, false, false, true);
}
static void injectSitePrototype(ContextRef* context, ObjectTemplateRef* otpl) {
<< data->src()->toStdUTF8String() << ":" << data->loc().line
<< ":" << data->loc().column << ")";
auto string = stream.str();
- return StringRef::createFromASCII(string.data(), string.length());
+ return StringRef::createFromUTF8(string.data(), string.length());
});
}
#include "utils/conversions-inl.h"
#include "utils/gc.h"
#include "utils/misc.h"
-#include "utils/string.h"
+#include "utils/string-util.h"
#include "lwnode/lwnode.h"
#include <EscargotPublic.h>
+#include <malloc.h> // for malloc_trim
#include <chrono>
#include <fstream>
#include "api.h"
+#include "api/context.h"
+#include "api/es-helper.h"
#include "api/isolate.h"
#include "api/utils/misc.h"
#include "api/utils/smaps.h"
return ValueRef::createUndefined();
},
target,
- StringRef::createFromASCII(name.c_str(), name.length()),
+ StringRef::createFromUTF8(name.c_str(), name.length()),
nativeFunction);
}
auto outputPath = createDumpFilePath();
auto& smaps = getSelfSmaps();
if (dumpMemorySnapshot(outputPath, smaps)) {
- return StringRef::createFromASCII(outputPath.c_str(), outputPath.length());
+ return StringRef::createFromUTF8(outputPath.c_str(), outputPath.length());
}
return ValueRef::createUndefined();
};
}
Utils::ReloadableSourceData* Utils::ReloadableSourceData::create(
- std::string sourcePath, void* preloadedData, size_t preloadedDataLength) {
+ std::string sourcePath,
+ void* preloadedData,
+ size_t preloadedDataLength,
+ bool isOneByteString) {
auto data = new (Memory::gcMalloc(sizeof(ReloadableSourceData)))
ReloadableSourceData();
data->preloadedData = preloadedData;
data->preloadedDataLength_ = preloadedDataLength;
+ data->isOneByteString_ = isOneByteString;
return data;
}
-MaybeLocal<String> Utils::NewReloadableStringFromOneByte(
- Isolate* isolate,
- ReloadableSourceData* data,
- LoadCallback loadCallback,
- UnloadCallback unloadCallback) {
+MaybeLocal<String> Utils::NewReloadableString(Isolate* isolate,
+ ReloadableSourceData* data,
+ LoadCallback loadCallback,
+ UnloadCallback unloadCallback) {
MaybeLocal<String> result;
if (data->preloadedDataLength() == 0) {
Escargot::StringRef* reloadableString =
Escargot::StringRef::createReloadableString(
IsolateWrap::fromV8(isolate)->vmInstance(),
- true,
+ data->isOneByteString(),
data->preloadedDataLength(),
data, // data should be gc-managed.
loadCallback,
return result;
}
+static void IdleGC(v8::Isolate* isolate) {
+ LWNODE_LOG_INFO("IdleGC");
+ IsolateWrap::fromV8(isolate)->vmInstance()->enterIdleMode();
+ Escargot::Memory::gc();
+ malloc_trim(0);
+}
+
+void MessageLoop::OnPrepare(v8::Isolate* isolate) {
+ // @note escargot says:
+ // user can call 'enterIdleMode' many times without performance concern
+
+ // @todo consider delayed-entering Idle GC
+ IdleGC(isolate);
+}
+
} // namespace LWNode
'dependencies': [
'<(lwnode_jsengine_path)/escargotshim.gyp:escargotshim',
],
+ 'conditions': [
+ ['enable_external_builtin_scripts=="true"', {
+ 'variables': {
+ 'archive_filename%': '<(node_core_target_name).dat'
+ },
+ 'defines': [
+ 'LWNODE_EXTERNAL_BUILTINS_FILENAME="<(archive_filename)"',
+ ],
+ 'dependencies': [
+ '<(lwnode_jsengine_path)/deps/minizip/minizip.gyp:minizip',
+ ],
+ 'actions': [
+ {
+ 'action_name': 'generate_builtins_archive',
+ 'inputs': ['<@(library_files)'],
+ 'outputs': ['<(PRODUCT_DIR)/<(archive_filename)'],
+ 'process_outputs_as_sources': 1,
+ 'action': [
+ 'zip',
+ '-0', # no compression
+ '<(PRODUCT_DIR)/<(archive_filename)',
+ '<@(_inputs)',
+ ],
+ },
+ ],
+ }],
+ ],
}],
[ 'openssl_default_cipher_list!=""', {
'defines': [
'outputs': [
'<(SHARED_INTERMEDIATE_DIR)/node_javascript.cc',
],
- 'action': [
- 'python', '<@(_inputs)',
- '--target', '<@(_outputs)',
+ 'conditions': [
+ ['lwnode=="true" and enable_external_builtin_scripts=="true"', {
+ 'action': [
+ 'python', '<@(_inputs)',
+ '--reloadable',
+ '--target', '<@(_outputs)',
+ ]}, {
+ 'action': [
+ 'python', '<@(_inputs)',
+ '--target', '<@(_outputs)',
+ ],
+ }]
],
},
],
BuildRequires: make
BuildRequires: python
BuildRequires: ninja
+BuildRequires: zip
BuildRequires: pkgconfig(dlog)
BuildRequires: pkgconfig(aul)
BuildRequires: pkgconfig(capi-appfw-app-common)
BuildRequires: pkgconfig(icu-i18n)
BuildRequires: pkgconfig(icu-uc)
BuildRequires: pkgconfig(glib-2.0)
+BuildRequires: nghttp2-devel
+BuildRequires: pkgconfig(libcares)
%if (0%{?tizen_version_major} >= 6)
BuildRequires: pkgconfig(openssl1.1)
echo "Building:" %{target}
+CFLAGS+=' -Os '
+CXXFLAGS+=' -Os '
+
./configure --tizen --without-npm \
--without-inspector --without-node-code-cache --without-node-snapshot \
- --with-intl none --shared-openssl --shared-zlib --dest-os linux --dest-cpu '%{tizen_arch}' \
- --ninja %{?extra_config} %{?lib_type_config}
+ --with-intl none --shared-openssl --shared-zlib --shared-cares --shared-nghttp2 \
+ --dest-os linux --dest-cpu '%{tizen_arch}' \
+ --ninja %{?extra_config} %{?external_script_config} %{?lib_type_config}
+
%if "%{node_engine}" == "escargot" && "%{lib_type}" == "shared"
ninja -C %{target_src} %{target_lib}
%endif
# for devel files
strip -v -g %{target_src}/%{target}
cp %{target_src}/%{target} %{buildroot}%{_bindir}
+%if "%{external_script_config}" == "--enable-external-builtin-scripts"
+cp %{target_src}/%{target}.dat %{buildroot}%{_bindir}
+%endif
%clean
rm ./*.list
%files devel
%manifest packaging/%{name}.manifest
%{_bindir}/%{target}
+%if "%{external_script_config}" == "--enable-external-builtin-scripts"
+%{_bindir}/%{target}.dat
+%endif
#include "node_native_module.h"
#include "util-inl.h"
+#ifdef LWNODE_EXTERNAL_BUILTINS_FILENAME
+#include "node_native_module_lwnode-inl.h"
+#endif
+
namespace node {
namespace native_module {
MaybeLocal<String> NativeModuleLoader::LoadBuiltinModuleSource(Isolate* isolate,
const char* id) {
+#ifdef LWNODE_EXTERNAL_BUILTINS_FILENAME
+ return LoadExternalBuiltinSource(isolate, id);
+#endif
+
#ifdef NODE_BUILTIN_MODULES_PATH
std::string filename = OnDiskFileName(id);
friend class NativeModuleEnv;
friend class CodeCacheBuilder;
+ // @lwnode
+ inline bool IsOneByte(const char* id);
+ v8::MaybeLocal<v8::String> LoadExternalBuiltinSource(
+ v8::Isolate* isolate, const char* id);
+ // end of @lwnode
+
NativeModuleLoader();
static NativeModuleLoader* GetInstance();
--- /dev/null
+/*
+ * Copyright (c) 2021-present Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <unzip.h>
+#include "lwnode.h"
+#include "node_native_module.h"
+#include "trace.h"
+
+using namespace LWNode;
+
+namespace node {
+namespace native_module {
+using v8::Isolate;
+using v8::Local;
+using v8::MaybeLocal;
+using v8::String;
+
+std::string getSelfProcPath() {
+ char path[PATH_MAX];
+ ssize_t length = readlink("/proc/self/exe", path, PATH_MAX);
+ if (length < 0) {
+ ERROR_AND_ABORT("readlink fails");
+ }
+ path[length] = '\0';
+ return std::string(path);
+}
+
+class ArchiveFileScope {
+ public:
+ ArchiveFileScope(const char* path) { file_ = unzOpen(path); }
+ ~ArchiveFileScope() { unzClose(file_); }
+ unzFile file() { return file_; }
+
+ private:
+ unzFile file_{nullptr};
+};
+
+bool readFileFromArchive(std::string filename,
+ char** buffer,
+ size_t* fileSize) {
+ DCHECK_NOT_NULL(buffer);
+ DCHECK_NOT_NULL(fileSize);
+
+ static std::string s_externalBuiltinsPath;
+ if (s_externalBuiltinsPath.empty()) {
+ std::string executablePath = getSelfProcPath();
+ executablePath = executablePath.substr(0, executablePath.rfind('/') + 1);
+ s_externalBuiltinsPath = executablePath + LWNODE_EXTERNAL_BUILTINS_FILENAME;
+ }
+
+ ArchiveFileScope scope(s_externalBuiltinsPath.c_str());
+ const unzFile file = scope.file();
+ CHECK_NOT_NULL(file);
+
+ if (unzGoToFirstFile(file) < 0) {
+ return false;
+ }
+
+ bool isFileFound = false;
+ do {
+ unz_file_info fileInfo;
+ char currentFileName[PATH_MAX];
+
+ if (unzGetCurrentFileInfo(file,
+ &fileInfo,
+ currentFileName,
+ sizeof(currentFileName),
+ nullptr,
+ 0,
+ nullptr,
+ 0) < 0) {
+ return false;
+ }
+
+ if (filename.compare(currentFileName) == 0) {
+ isFileFound = true;
+
+ if (unzOpenCurrentFile(file) < 0) {
+ return false;
+ }
+
+ *fileSize = fileInfo.uncompressed_size;
+ *buffer = (char*)malloc(fileInfo.uncompressed_size);
+
+ if (unzReadCurrentFile(file, *buffer, *fileSize) < 0) {
+ free(buffer);
+ buffer = nullptr;
+ return false;
+ }
+ unzCloseCurrentFile(file);
+ break;
+ }
+
+ } while (unzGoToNextFile(file) != UNZ_END_OF_LIST_OF_FILE);
+
+ return isFileFound;
+}
+
+bool NativeModuleLoader::IsOneByte(const char* id) {
+ const auto& it = source_.find(id);
+ if (it == source_.end()) {
+ CHECK(false);
+ }
+ return it->second.is_one_byte();
+}
+
+static std::string OnArchiveFileName(const char* id) {
+ std::string filename;
+ if (strncmp(id, "internal/deps", strlen("internal/deps")) == 0) {
+ id += strlen("internal/");
+ } else {
+ filename += "lib/";
+ }
+ filename += id;
+ filename += ".js";
+ return filename;
+}
+
+MaybeLocal<String> NativeModuleLoader::LoadExternalBuiltinSource(
+ Isolate* isolate, const char* id) {
+ std::string filename = OnArchiveFileName(id);
+
+ size_t fileSize = 0;
+ char* buffer = nullptr;
+ if (readFileFromArchive(filename, &buffer, &fileSize) == false) {
+ ERROR_AND_ABORT("Failed to open builtins");
+ return MaybeLocal<String>();
+ }
+
+ struct Stat {
+ int loaded{0};
+ int reloaded{0};
+ };
+ static Stat s_stat;
+
+ bool is8BitString = true;
+ if (IsOneByte(id) == false) {
+ // FIXME: should be `is8BitString = false;` here
+ // "lib/internal/cli_table.js", "lib/internal/timers.js",
+ // "deps/node-inspect/lib/internal/inspect_repl.js",
+ // "deps/acorn/acorn/dist/acorn.js"
+ LWNODE_LOG_ERROR(
+ "FIXME: %s - createReloadableString fails to load uint16 string", id);
+ }
+
+ auto data = Utils::ReloadableSourceData::create(
+ filename, buffer, fileSize, is8BitString);
+
+ return Utils::NewReloadableString(
+ isolate,
+ data,
+ // Load-ReloadableSource
+ [](void* userData) -> void* {
+ auto data = reinterpret_cast<Utils::ReloadableSourceData*>(userData);
+
+ LWNODE_LOG_INFO(" Load: %d (%d) %p %s (+%.2f kB)",
+ ++s_stat.loaded,
+ s_stat.reloaded,
+ data->preloadedData,
+ data->path(),
+ (float)data->preloadedDataLength() / 1024);
+
+ if (data->preloadedData) {
+ auto buffer = data->preloadedData;
+ data->preloadedData = nullptr;
+ return buffer; // move memory ownership to js engine
+ }
+
+ s_stat.reloaded++;
+ size_t fileSize = 0;
+ char* buffer = nullptr;
+ bool result = readFileFromArchive(data->path(), &buffer, &fileSize);
+ CHECK(result);
+ return buffer;
+ },
+ // Unload-ReloadableSource
+ [](void* preloadedData, void* userData) -> void {
+ auto data = reinterpret_cast<Utils::ReloadableSourceData*>(userData);
+
+ LWNODE_LOG_INFO("Unload: %d (%d) %p %s (-%.2f kB)",
+ --s_stat.loaded,
+ s_stat.reloaded,
+ preloadedData,
+ data->path(),
+ (float)data->preloadedDataLength() / 1024);
+
+ if (data->preloadedData) {
+ free(data->preloadedData);
+ data->preloadedData = nullptr;
+ }
+ free(preloadedData);
+ });
+}
+
+} // namespace native_module
+} // namespace node
return threads_.size();
}
+#ifdef LWNODE
+void PerIsolatePlatformData::PrepareTask(uv_prepare_t *handle) {
+ auto data = reinterpret_cast<PerIsolatePlatformData*>(handle->data);
+ LWNode::MessageLoop::OnPrepare(data->isolate_);
+}
+#endif
+
PerIsolatePlatformData::PerIsolatePlatformData(
Isolate* isolate, uv_loop_t* loop)
: isolate_(isolate), loop_(loop) {
CHECK_EQ(0, uv_async_init(loop, flush_tasks_, FlushTasks));
flush_tasks_->data = static_cast<void*>(this);
uv_unref(reinterpret_cast<uv_handle_t*>(flush_tasks_));
+
+#if defined(LWNODE) && defined(LWNODE_EXTERNAL_BUILTINS_FILENAME)
+ prepare_task_ = new uv_prepare_t();
+ uv_prepare_init(loop_, prepare_task_);
+ uv_prepare_start(prepare_task_, PrepareTask);
+ prepare_task_->data = static_cast<void*>(this);
+ uv_unref(reinterpret_cast<uv_handle_t*>(prepare_task_));
+#endif
}
std::shared_ptr<v8::TaskRunner>
}
void PerIsolatePlatformData::Shutdown() {
+#ifdef LWNODE
+ if (prepare_task_) {
+ uv_close(reinterpret_cast<uv_handle_t*>(prepare_task_), nullptr);
+ prepare_task_ = nullptr;
+ }
+#endif
+
if (flush_tasks_ == nullptr)
return;
TaskQueue<v8::Task> foreground_tasks_;
TaskQueue<DelayedTask> foreground_delayed_tasks_;
+//@lwnode
+ uv_prepare_t* prepare_task_ = nullptr;
+ static void PrepareTask(uv_prepare_t* handle);
+//end of @lwnode
+
// Use a custom deleter because libuv needs to close the handle first.
typedef std::unique_ptr<DelayedTask, void(*)(DelayedTask*)>
DelayedTaskPointer;
is_verbose = False
-def GetDefinition(var, source, step=30):
+def GetDefinition(var, source, is_reloadable_code=False, step=30):
template = ONE_BYTE_STRING
code_points = [ord(c) for c in source]
if any(c > 127 for c in code_points):
slices = [elements_s[i:i + step] for i in range(0, len(elements_s), step)]
lines = [','.join(s) for s in slices]
array_content = ',\n'.join(lines)
- definition = template.format(var, array_content)
+ if is_reloadable_code == True:
+ definition = template.format(var, '')
+ else:
+ definition = template.format(var, array_content)
return definition, len(code_points)
-def AddModule(filename, definitions, initializers):
+def AddModule(filename, definitions, initializers, is_reloadable_code=False):
code = ReadFile(filename)
name = NormalizeFileName(filename)
slug = SLUGGER_RE.sub('_', name)
var = slug + '_raw'
- definition, size = GetDefinition(var, code)
- initializer = INITIALIZER.format(name, var, size)
- definitions.append(definition)
+ definition, size = GetDefinition(var, code, is_reloadable_code)
+ if is_reloadable_code == True:
+ initializer = INITIALIZER.format(name, var, 0)
+ definitions.append(definition)
+ else:
+ initializer = INITIALIZER.format(name, var, size)
+ definitions.append(definition)
initializers.append(initializer)
def NormalizeFileName(filename):
return os.path.splitext(filename)[0]
-def JS2C(source_files, target):
+def JS2C(source_files, target, is_reloadable_code=False):
# Build source code lines
definitions = []
initializers = []
for filename in source_files['.js']:
- AddModule(filename, definitions, initializers)
+ AddModule(filename, definitions, initializers, is_reloadable_code)
config_def, config_size = handle_config_gypi(source_files['config.gypi'])
definitions.append(config_def)
# later on anyway, so get it out of the way now
config = ReadFile(config_filename)
config = jsonify(config)
- config_def, config_size = GetDefinition(CONFIG_GYPI_ID, config)
+ config_def, config_size = GetDefinition(CONFIG_GYPI_ID, config, False)
return config_def, config_size
)
parser.add_argument('--target', help='output file')
parser.add_argument('--verbose', action='store_true', help='output file')
+ # @lwnode --reloadable
+ parser.add_argument('--reloadable',
+ action='store_true',
+ default=False,
+ help='reloadable string')
parser.add_argument('sources', nargs='*', help='input files')
options = parser.parse_args()
global is_verbose
# Currently config.gypi is the only `.gypi` file allowed
assert source_files['.gypi'] == ['config.gypi']
source_files['config.gypi'] = source_files.pop('.gypi')[0]
- JS2C(source_files, options.target)
+ JS2C(source_files, options.target, options.reloadable)
if __name__ == "__main__":