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:
seonghyun kim 2017-03-24 19:03:27 +09:00
commit 5d56fd2bb4
14 changed files with 77 additions and 25 deletions

View file

@ -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());

View file

@ -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);

View file

@ -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;

View file

@ -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);

View file

@ -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 {

View file

@ -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
}

View file

@ -59,9 +59,7 @@ public:
return m_inStrictMode;
}
#if ESCARGOT_ENABLE_PROMISE
FunctionObject* resolveCallee();
#endif
private:
bool m_inStrictMode;

View file

@ -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) {

View file

@ -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;

View file

@ -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)

View file

@ -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;

View file

@ -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

View file

@ -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());

View file

@ -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;
}
}