20Heap::CallContext *ExecutionContext::newBlockContext(CppStackFrame *frame,
int blockIndex)
22 Function *function = frame->v4Function;
24 Heap::InternalClass *ic = function->executableCompilationUnit()->runtimeBlocks.at(blockIndex);
25 uint nLocals = ic->size;
26 size_t requiredMemory =
sizeof(CallContext::Data) -
sizeof(Value) +
sizeof(Value) * nLocals;
28 ExecutionEngine *v4 = function->internalClass->engine;
29 Heap::CallContext *c = v4->memoryManager->allocManaged<CallContext>(requiredMemory, ic);
31 c->type = Heap::ExecutionContext::Type_BlockContext;
33 Heap::ExecutionContext *outer =
static_cast<Heap::ExecutionContext *>(frame->context()->m());
34 c->outer.set(v4, outer);
35 if (frame->isJSTypesFrame()) {
36 c->function.set(v4,
static_cast<Heap::JavaScriptFunctionObject *>(
37 Value::fromStaticValue(
38 static_cast<JSTypesStackFrame *>(frame)->jsFrame->function).m()));
40 c->function.set(v4,
nullptr);
43 c->locals.size = nLocals;
44 c->locals.alloc = nLocals;
46 c->setupLocalTemporalDeadZone(function->executableCompilationUnit()->unitData()->blockAt(blockIndex));
51Heap::CallContext *ExecutionContext::cloneBlockContext(ExecutionEngine *engine,
52 Heap::CallContext *callContext)
54 uint nLocals = callContext->locals.alloc;
55 size_t requiredMemory =
sizeof(CallContext::Data) -
sizeof(Value) +
sizeof(Value) * nLocals;
57 Heap::CallContext *c = engine->memoryManager->allocManaged<CallContext>(
58 requiredMemory, callContext->internalClass);
59 memcpy(c, callContext, requiredMemory);
64Heap::CallContext *ExecutionContext::newCallContext(JSTypesStackFrame *frame)
66 Function *function = frame->v4Function;
67 Heap::ExecutionContext *outer =
static_cast<Heap::ExecutionContext *>(frame->context()->m());
69 uint nFormals = qMax(
static_cast<uint>(frame->argc()), function->nFormals);
70 uint localsAndFormals = function->compiledFunction->nLocals + nFormals;
71 size_t requiredMemory =
sizeof(CallContext::Data) -
sizeof(Value) +
sizeof(Value) * (localsAndFormals);
73 ExecutionEngine *v4 = outer->internalClass->engine;
74 Heap::CallContext *c = v4->memoryManager->allocManaged<CallContext>(requiredMemory, function->internalClass);
77 c->outer.set(v4, outer);
78 c->function.set(v4,
static_cast<Heap::JavaScriptFunctionObject *>(
79 Value::fromStaticValue(frame->jsFrame->function).m()));
81 const CompiledData::Function *compiledFunction = function->compiledFunction;
82 uint nLocals = compiledFunction->nLocals;
83 c->locals.size = nLocals;
84 c->locals.alloc = localsAndFormals;
86 Q_ASSERT(Value::undefinedValue().asReturnedValue() == 0);
88 c->setupLocalTemporalDeadZone(compiledFunction);
90 Value *args = c->locals.values + nLocals;
91 ::memcpy(args, frame->argv(), frame->argc() *
sizeof(Value));
92 c->nArgs = frame->argc();
93 for (uint i = frame->argc(); i < function->nFormals; ++i)
94 args[i] = Encode::undefined();
99Heap::ExecutionContext *ExecutionContext::newWithContext(Heap::Object *with)
const
101 Heap::ExecutionContext *c = engine()->memoryManager->alloc<ExecutionContext>(Heap::ExecutionContext::Type_WithContext);
102 c->outer.set(engine(), d());
103 c->activation.set(engine(), with);
108Heap::ExecutionContext *ExecutionContext::newCatchContext(CppStackFrame *frame,
int blockIndex, Heap::String *exceptionVarName)
110 Scope scope(frame->context());
111 ScopedString name(scope, exceptionVarName);
112 ScopedValue val(scope, scope.engine->catchException(
nullptr));
113 ScopedContext ctx(scope, newBlockContext(frame, blockIndex));
114 ctx->setProperty(name, val);
118void ExecutionContext::createMutableBinding(String *name,
bool deletable)
123 ScopedObject activation(scope);
124 ScopedContext ctx(scope,
this);
126 switch (ctx->d()->type) {
127 case Heap::ExecutionContext::Type_CallContext:
129 Heap::CallContext *c =
static_cast<Heap::CallContext *>(ctx->d());
131 c->activation.set(scope.engine, scope.engine->newObject());
132 activation = c->activation;
135 case Heap::ExecutionContext::Type_QmlContext: {
138 activation = ctx->d()->activation;
141 case Heap::ExecutionContext::Type_GlobalContext: {
142 Q_ASSERT(scope.engine->globalObject->d() == ctx->d()->activation);
144 activation = ctx->d()->activation;
147 case Heap::ExecutionContext::Type_BlockContext:
152 ctx = ctx->d()->outer;
155 PropertyKey id = name->toPropertyKey();
156 if (activation->getOwnProperty(id) != Attr_Invalid)
158 ScopedProperty desc(scope);
159 PropertyAttributes attrs(Attr_Data);
160 attrs.setConfigurable(deletable);
161 if (!activation->defineOwnProperty(id, desc, attrs))
162 scope.engine->throwTypeError();
165static bool unscopable(ExecutionEngine *engine, Heap::Object *withObject, PropertyKey id)
170 ScopedObject w(scope, withObject);
171 ScopedObject o(scope, w->get(scope.engine->symbol_unscopables()));
173 ScopedValue blocked(scope, o->get(id));
174 return blocked->toBoolean();
179bool ExecutionContext::deleteProperty(String *name)
181 PropertyKey id = name->toPropertyKey();
183 Heap::ExecutionContext *ctx = d();
184 ExecutionEngine *engine = ctx->internalClass->engine;
186 for (; ctx; ctx = ctx->outer) {
188 case Heap::ExecutionContext::Type_BlockContext:
189 case Heap::ExecutionContext::Type_CallContext: {
190 Heap::CallContext *c =
static_cast<Heap::CallContext *>(ctx);
191 uint index = c->internalClass->indexOfValueOrGetter(id);
192 if (index < UINT_MAX)
197 case Heap::ExecutionContext::Type_WithContext: {
198 if (ctx->activation) {
200 ScopedObject object(scope, ctx->activation);
201 if (object && object->hasProperty(id)) {
202 bool u = ::unscopable(engine, ctx->activation, id);
203 if (engine->hasException)
207 return object->deleteProperty(id);
212 case Heap::ExecutionContext::Type_GlobalContext: {
213 if (ctx->activation) {
215 ScopedObject object(scope, ctx->activation);
216 if (object && object->hasProperty(id))
217 return object->deleteProperty(id);
221 case Heap::ExecutionContext::Type_QmlContext:
227 return !engine->currentStackFrame->v4Function->isStrict();
230ExecutionContext::Error ExecutionContext::setProperty(String *name,
const Value &value)
232 PropertyKey id = name->toPropertyKey();
234 Heap::ExecutionContext *ctx = d();
235 QV4::ExecutionEngine *engine = ctx->internalClass->engine;
237 for (; ctx; ctx = ctx->outer) {
239 case Heap::ExecutionContext::Type_WithContext: {
241 ScopedObject w(scope, ctx->activation);
242 if (w->hasProperty(id)) {
243 bool u = ::unscopable(engine, ctx->activation, id);
244 if (engine->hasException)
248 if (!w->put(name, value))
254 case Heap::ExecutionContext::Type_BlockContext:
255 case Heap::ExecutionContext::Type_CallContext: {
256 Heap::CallContext *c =
static_cast<Heap::CallContext *>(ctx);
257 uint index = c->internalClass->indexOfValueOrGetter(id);
258 if (index < UINT_MAX) {
259 static_cast<Heap::CallContext *>(c)->locals.set(engine, index, value);
264 case Heap::ExecutionContext::Type_GlobalContext:
265 if (ctx->activation) {
266 auto member = ctx->activation->internalClass->findValueOrSetter(id);
267 if (member.index < UINT_MAX) {
269 ScopedObject a(scope, ctx->activation);
270 if (!a->putValue(member.index, member.attrs, value))
276 case Heap::ExecutionContext::Type_QmlContext: {
278 ScopedObject activation(scope, ctx->activation);
279 if (!activation->put(name, value))
290ReturnedValue ExecutionContext::getProperty(String *name)
292 PropertyKey id = name->toPropertyKey();
294 Heap::ExecutionContext *ctx = d();
295 QV4::ExecutionEngine *engine = ctx->internalClass->engine;
297 for (; ctx; ctx = ctx->outer) {
299 case Heap::ExecutionContext::Type_BlockContext:
300 case Heap::ExecutionContext::Type_CallContext: {
301 Heap::CallContext *c =
static_cast<Heap::CallContext *>(ctx);
303 const uint index = c->internalClass->indexOfValueOrGetter(id);
304 if (index < c->locals.alloc)
305 return c->locals[index].asReturnedValue();
313 case Heap::ExecutionContext::Type_WithContext:
314 if (ctx->activation) {
316 ScopedObject activation(scope, ctx->activation);
317 if (activation->hasProperty(id)) {
318 bool u = ::unscopable(engine, ctx->activation, id);
319 if (engine->hasException)
323 return activation->get(id);
327 case Heap::ExecutionContext::Type_GlobalContext:
328 case Heap::ExecutionContext::Type_QmlContext: {
329 if (ctx->activation) {
331 ScopedObject activation(scope, ctx->activation);
332 bool hasProperty =
false;
333 ReturnedValue v = activation->get(id,
nullptr, &hasProperty);
341 return engine->throwReferenceError(*name);
344ReturnedValue ExecutionContext::getPropertyAndBase(String *name, Value *base)
347 PropertyKey id = name->toPropertyKey();
349 Heap::ExecutionContext *ctx = d();
350 QV4::ExecutionEngine *engine = ctx->internalClass->engine;
352 for (; ctx; ctx = ctx->outer) {
354 case Heap::ExecutionContext::Type_BlockContext:
355 case Heap::ExecutionContext::Type_CallContext: {
356 Heap::CallContext *c =
static_cast<Heap::CallContext *>(ctx);
358 const uint index = c->internalClass->indexOfValueOrGetter(id);
359 if (index < c->locals.alloc)
360 return c->locals[index].asReturnedValue();
368 case Heap::ExecutionContext::Type_GlobalContext: {
369 if (ctx->activation) {
371 ScopedObject activation(scope, ctx->activation);
372 bool hasProperty =
false;
373 ReturnedValue v = activation->get(name, &hasProperty);
379 case Heap::ExecutionContext::Type_WithContext:
380 if (ctx->activation) {
382 ScopedObject activation(scope, ctx->activation);
383 if (activation->hasProperty(id)) {
384 bool u = ::unscopable(engine, ctx->activation, id);
385 if (engine->hasException)
389 base->setM(activation->d());
390 return activation->get(id);
394 case Heap::ExecutionContext::Type_QmlContext: {
396 ScopedObject o(scope, ctx->activation);
397 bool hasProperty =
false;
398 ReturnedValue v = o->get(id,
nullptr, &hasProperty);
407 return engine->throwReferenceError(*name);
DEFINE_MANAGED_VTABLE(ExecutionContext)
DEFINE_MANAGED_VTABLE(CallContext)
static bool unscopable(ExecutionEngine *engine, Heap::Object *withObject, PropertyKey id)