mirror of
https://github.com/Samsung/escargot.git
synced 2026-06-22 10:01:50 +00:00
1. do not ASTScopeContext explicitly. it is used by ByteCode-genaration
2. alloc esprima::Error as Non-GC type. - it can be thrown. but, bdwgc can not see try-catch variable area. 3. Use own context when eval, function are invoked. 4. implement fake-Realm class for v8 vender test Signed-off-by: seonghyun kim <sh8281.kim@samsung.com>
This commit is contained in:
parent
34dad07c79
commit
5d56fd2bb4
14 changed files with 77 additions and 25 deletions
|
|
@ -70,8 +70,8 @@ bool evaluateScript(ExecutionStateRef* es, StringRef* str, StringRef* filename)
|
|||
return false;
|
||||
}
|
||||
|
||||
auto execRet = parseRet.m_script->sandboxExecute(ctx);
|
||||
Escargot::ExecutionState state(ctx);
|
||||
auto execRet = parseRet.m_script->sandboxExecute(state);
|
||||
if (execRet.result.isEmpty()) {
|
||||
printf("Uncaught %s:\n",
|
||||
execRet.msgStr->toUTF8StringData().data());
|
||||
|
|
|
|||
|
|
@ -78,11 +78,11 @@ Value Script::execute(ExecutionState& state, bool isEvalMode, bool needNewEnv, b
|
|||
return resultValue;
|
||||
}
|
||||
|
||||
Script::ScriptSandboxExecuteResult Script::sandboxExecute(Context* ctx)
|
||||
Script::ScriptSandboxExecuteResult Script::sandboxExecute(ExecutionState& state)
|
||||
{
|
||||
ScriptSandboxExecuteResult result;
|
||||
SandBox sb(ctx);
|
||||
ExecutionState stateForInit(ctx);
|
||||
SandBox sb(state.context());
|
||||
ExecutionState stateForInit(state.context(), &state, nullptr);
|
||||
|
||||
auto sandBoxResult = sb.run([&]() -> Value {
|
||||
return execute(stateForInit, false, false, true);
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ public:
|
|||
} error;
|
||||
};
|
||||
Value execute(ExecutionState& state, bool isEvalMode = false, bool needNewEnv = false, bool isOnGlobal = false);
|
||||
ScriptSandboxExecuteResult sandboxExecute(Context* ctx); // execute using sandbox
|
||||
ScriptSandboxExecuteResult sandboxExecute(ExecutionState& state); // execute using sandbox
|
||||
String* fileName()
|
||||
{
|
||||
return m_fileName;
|
||||
|
|
|
|||
|
|
@ -132,10 +132,6 @@ CodeBlock* ScriptParser::generateCodeBlockTreeFromASTWalker(Context* ctx, String
|
|||
codeBlock->m_childBlocks[i] = generateCodeBlockTreeFromASTWalker(ctx, source, script, scopeCtx->m_childScopes[i], codeBlock);
|
||||
}
|
||||
|
||||
#ifdef NDEBUG
|
||||
delete scopeCtx;
|
||||
#endif
|
||||
|
||||
return codeBlock;
|
||||
}
|
||||
|
||||
|
|
@ -245,6 +241,7 @@ ScriptParser::ScriptParserResult ScriptParser::parse(StringView scriptSource, St
|
|||
error->message = orgError->message;
|
||||
error->name = orgError->name;
|
||||
error->errorCode = orgError->errorCode;
|
||||
delete orgError;
|
||||
}
|
||||
|
||||
ScriptParser::ScriptParserResult result(script, error);
|
||||
|
|
|
|||
|
|
@ -484,7 +484,7 @@ public:
|
|||
|
||||
Error* constructError(String* msg, size_t column)
|
||||
{
|
||||
Error* error = new Error(msg);
|
||||
Error* error = new (NoGC) Error(msg);
|
||||
error->column = column;
|
||||
return error;
|
||||
// try {
|
||||
|
|
|
|||
|
|
@ -21,12 +21,12 @@
|
|||
|
||||
namespace Escargot {
|
||||
|
||||
#if ESCARGOT_ENABLE_PROMISE
|
||||
FunctionObject* ExecutionContext::resolveCallee()
|
||||
{
|
||||
ASSERT(m_lexicalEnvironment->record()->isDeclarativeEnvironmentRecord());
|
||||
ASSERT(m_lexicalEnvironment->record()->asDeclarativeEnvironmentRecord()->isFunctionEnvironmentRecord());
|
||||
LexicalEnvironment* env = m_lexicalEnvironment;
|
||||
while (!env->record()->isDeclarativeEnvironmentRecord() && !m_lexicalEnvironment->record()->asDeclarativeEnvironmentRecord()->isFunctionEnvironmentRecord()) {
|
||||
env = env->outerEnvironment();
|
||||
}
|
||||
return m_lexicalEnvironment->record()->asDeclarativeEnvironmentRecord()->asFunctionEnvironmentRecord()->functionObject();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,9 +59,7 @@ public:
|
|||
return m_inStrictMode;
|
||||
}
|
||||
|
||||
#if ESCARGOT_ENABLE_PROMISE
|
||||
FunctionObject* resolveCallee();
|
||||
#endif
|
||||
|
||||
private:
|
||||
bool m_inStrictMode;
|
||||
|
|
|
|||
|
|
@ -171,6 +171,16 @@ NEVER_INLINE void FunctionObject::generateBytecodeBlock(ExecutionState& state)
|
|||
v.pushBack(m_codeBlock);
|
||||
}
|
||||
|
||||
Value FunctionObject::callSlowCase(ExecutionState& state, const Value& callee, const Value& receiver, const size_t& argc, Value* argv, bool isNewExpression)
|
||||
{
|
||||
if (LIKELY(callee.isObject() && callee.asPointerValue()->isFunctionObject())) {
|
||||
return callee.asFunction()->call(state, receiver, argc, argv, isNewExpression);
|
||||
} else {
|
||||
ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, errorMessage_Call_NotFunction);
|
||||
return Value();
|
||||
}
|
||||
}
|
||||
|
||||
Value FunctionObject::call(ExecutionState& state, const Value& receiverSrc, const size_t& argc, Value* argv, bool isNewExpression)
|
||||
{
|
||||
volatile int sp;
|
||||
|
|
@ -183,7 +193,7 @@ Value FunctionObject::call(ExecutionState& state, const Value& receiverSrc, cons
|
|||
ErrorObject::throwBuiltinError(state, ErrorObject::RangeError, "Maximum call stack size exceeded");
|
||||
}
|
||||
|
||||
Context* ctx = state.context();
|
||||
Context* ctx = m_codeBlock->context();
|
||||
bool isStrict = m_codeBlock->isStrict();
|
||||
|
||||
if (m_codeBlock->hasCallNativeFunctionCode()) {
|
||||
|
|
@ -192,7 +202,7 @@ Value FunctionObject::call(ExecutionState& state, const Value& receiverSrc, cons
|
|||
FunctionEnvironmentRecordSimple record(this);
|
||||
LexicalEnvironment env(&record, outerEnvironment());
|
||||
ExecutionContext ec(ctx, state.executionContext(), &env, isStrict);
|
||||
ExecutionState newState(&state, &ec);
|
||||
ExecutionState newState(ctx, &state, &ec);
|
||||
|
||||
size_t len = info.size();
|
||||
if (argc < len) {
|
||||
|
|
|
|||
|
|
@ -78,8 +78,7 @@ public:
|
|||
if (LIKELY(callee.isObject() && callee.asPointerValue()->hasTag(g_functionObjectTag))) {
|
||||
return callee.asFunction()->call(state, receiver, argc, argv, isNewExpression);
|
||||
} else {
|
||||
ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, errorMessage_Call_NotFunction);
|
||||
RELEASE_ASSERT_NOT_REACHED();
|
||||
return callSlowCase(state, callee, receiver, argc, argv, isNewExpression);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -90,6 +89,7 @@ public:
|
|||
}
|
||||
|
||||
protected:
|
||||
static Value callSlowCase(ExecutionState& state, const Value& callee, const Value& receiver, const size_t& argc, Value* argv, bool isNewExpression);
|
||||
void generateArgumentsObject(ExecutionState& state, FunctionEnvironmentRecord* fnRecord, Value* stackStorage);
|
||||
void generateBytecodeBlock(ExecutionState& state);
|
||||
CodeBlock* m_codeBlock;
|
||||
|
|
|
|||
|
|
@ -138,9 +138,21 @@ static Value builtinGc(ExecutionState& state, Value thisValue, size_t argc, Valu
|
|||
return Value();
|
||||
}
|
||||
|
||||
class EvalFunctionObject : public FunctionObject {
|
||||
public:
|
||||
EvalFunctionObject(ExecutionState& state, NativeFunctionInfo info)
|
||||
: FunctionObject(state, info)
|
||||
{
|
||||
m_globalObject = state.context()->globalObject();
|
||||
}
|
||||
|
||||
GlobalObject* m_globalObject;
|
||||
};
|
||||
|
||||
static Value builtinEval(ExecutionState& state, Value thisValue, size_t argc, Value* argv, bool isNewExpression)
|
||||
{
|
||||
return state.context()->globalObject()->eval(state, argv[0]);
|
||||
EvalFunctionObject* fn = (EvalFunctionObject*)state.executionContext()->resolveCallee();
|
||||
return fn->m_globalObject->eval(state, argv[0]);
|
||||
}
|
||||
|
||||
Value GlobalObject::eval(ExecutionState& state, const Value& arg)
|
||||
|
|
@ -165,7 +177,8 @@ Value GlobalObject::eval(ExecutionState& state, const Value& arg)
|
|||
}
|
||||
bool needNewEnv = parserResult.m_script->topCodeBlock()->isStrict();
|
||||
// In case of indirect call, use global execution context
|
||||
return parserResult.m_script->execute(state, true, needNewEnv, true);
|
||||
ExecutionState stateForNewGlobal(m_context);
|
||||
return parserResult.m_script->execute(stateForNewGlobal, true, needNewEnv, true);
|
||||
}
|
||||
return arg;
|
||||
}
|
||||
|
|
@ -804,8 +817,8 @@ void GlobalObject::installOthers(ExecutionState& state)
|
|||
defineOwnProperty(state, strings->undefined, ObjectPropertyDescriptor(Value(), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ValuePresent)));
|
||||
|
||||
// $18.2.1 eval (x)
|
||||
m_eval = new FunctionObject(state,
|
||||
NativeFunctionInfo(strings->eval, builtinEval, 1, nullptr, NativeFunctionInfo::Strict));
|
||||
m_eval = new EvalFunctionObject(state,
|
||||
NativeFunctionInfo(strings->eval, builtinEval, 1, nullptr, NativeFunctionInfo::Strict));
|
||||
defineOwnProperty(state, ObjectPropertyName(strings->eval),
|
||||
ObjectPropertyDescriptor(m_eval, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
|
||||
// $18.2.2 isFinite(number)
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ public:
|
|||
|
||||
GlobalObject(ExecutionState& state)
|
||||
: Object(state, ESCARGOT_OBJECT_BUILTIN_PROPERTY_NUMBER, false)
|
||||
, m_context(state.context())
|
||||
{
|
||||
m_objectPrototype = Object::createBuiltinObjectPrototype(state);
|
||||
m_objectPrototype->markThisObjectDontNeedStructureTransitionTable(state);
|
||||
|
|
@ -385,6 +386,8 @@ public:
|
|||
void* operator new[](size_t size) = delete;
|
||||
|
||||
protected:
|
||||
Context* m_context;
|
||||
|
||||
FunctionObject* m_object;
|
||||
Object* m_objectPrototype;
|
||||
FunctionObject* m_objectPrototypeToString;
|
||||
|
|
|
|||
|
|
@ -45,6 +45,14 @@ static Value builtinAddPromiseReactions(ExecutionState& state, Value thisValue,
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef ESCARGOT_ENABLE_VENDORTEST
|
||||
static Value builtinCreateNewGlobalObject(ExecutionState& state, Value thisValue, size_t argc, Value* argv, bool isNewExpression)
|
||||
{
|
||||
Context* ctx = new Context(state.context()->vmInstance());
|
||||
return ctx->globalObject();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void installTestFunctions(ExecutionState& state)
|
||||
{
|
||||
|
|
@ -64,6 +72,11 @@ void installTestFunctions(ExecutionState& state)
|
|||
(ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::AllPresent)));
|
||||
#endif // ESCARGOT_ENABLE_PROMISE
|
||||
|
||||
AtomicString createNewGlobalObject(state, "createNewGlobalObject");
|
||||
globalObject->defineOwnProperty(state, ObjectPropertyName(createNewGlobalObject),
|
||||
ObjectPropertyDescriptor(new FunctionObject(state,
|
||||
NativeFunctionInfo(createNewGlobalObject, builtinCreateNewGlobalObject, 0, nullptr, NativeFunctionInfo::Strict)),
|
||||
(ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::AllPresent)));
|
||||
#else // ESCARGOT_ENABLE_VENDORTEST
|
||||
/* Do nothong */
|
||||
#endif // ESCARGOT_ENABLE_VENDORTEST
|
||||
|
|
|
|||
|
|
@ -37,8 +37,8 @@ NEVER_INLINE bool eval(Escargot::Context* context, Escargot::String* str, Escarg
|
|||
puts(err.data());
|
||||
return false;
|
||||
} else {
|
||||
Escargot::Script::ScriptSandboxExecuteResult resultValue = result.m_script->sandboxExecute(context);
|
||||
Escargot::ExecutionState state(context);
|
||||
Escargot::Script::ScriptSandboxExecuteResult resultValue = result.m_script->sandboxExecute(state);
|
||||
if (!resultValue.result.isEmpty()) {
|
||||
if (shouldPrintScriptResult)
|
||||
puts(resultValue.msgStr->toUTF8StringData().data());
|
||||
|
|
|
|||
|
|
@ -509,3 +509,21 @@ Object.defineProperty(Object.prototype, "__lookupSetter__", {
|
|||
configurable: true
|
||||
});
|
||||
|
||||
function Realm()
|
||||
{
|
||||
this.global = createNewGlobalObject();
|
||||
}
|
||||
|
||||
Realm.create = function()
|
||||
{
|
||||
return new Realm()
|
||||
}
|
||||
|
||||
Realm.eval = function(rm, code) {
|
||||
try {
|
||||
return rm.global.eval(code);
|
||||
} catch(e) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue