1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtQml module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 #include "qv4lookup_p.h"
40 #include "qv4functionobject_p.h"
41 #include "qv4jscall_p.h"
42 #include "qv4string_p.h"
43 #include <private/qv4identifiertable_p.h>
44
45 QT_BEGIN_NAMESPACE
46
47 using namespace QV4;
48
49
resolveProtoGetter(PropertyKey name,const Heap::Object * proto)50 void Lookup::resolveProtoGetter(PropertyKey name, const Heap::Object *proto)
51 {
52 while (proto) {
53 auto index = proto->internalClass->findValueOrGetter(name);
54 if (index.isValid()) {
55 PropertyAttributes attrs = index.attrs;
56 protoLookup.data = proto->propertyData(index.index);
57 if (attrs.isData()) {
58 getter = getterProto;
59 } else {
60 getter = getterProtoAccessor;
61 }
62 return;
63 }
64 proto = proto->prototype();
65 }
66 // ### put in a getterNotFound!
67 getter = getterFallback;
68 }
69
resolveGetter(ExecutionEngine * engine,const Object * object)70 ReturnedValue Lookup::resolveGetter(ExecutionEngine *engine, const Object *object)
71 {
72 return object->resolveLookupGetter(engine, this);
73 }
74
resolvePrimitiveGetter(ExecutionEngine * engine,const Value & object)75 ReturnedValue Lookup::resolvePrimitiveGetter(ExecutionEngine *engine, const Value &object)
76 {
77 primitiveLookup.type = object.type();
78 switch (primitiveLookup.type) {
79 case Value::Undefined_Type:
80 case Value::Null_Type: {
81 Scope scope(engine);
82 ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
83 const QString message = QStringLiteral("Cannot read property '%1' of %2").arg(name->toQString())
84 .arg(QLatin1String(primitiveLookup.type == Value::Undefined_Type ? "undefined" : "null"));
85 return engine->throwTypeError(message);
86 }
87 case Value::Boolean_Type:
88 primitiveLookup.proto = engine->booleanPrototype()->d();
89 break;
90 case Value::Managed_Type: {
91 // ### Should move this over to the Object path, as strings also have an internalClass
92 Q_ASSERT(object.isStringOrSymbol());
93 primitiveLookup.proto = static_cast<const Managed &>(object).internalClass()->prototype;
94 Q_ASSERT(primitiveLookup.proto);
95 Scope scope(engine);
96 ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
97 if (object.isString() && name->equals(engine->id_length())) {
98 // special case, as the property is on the object itself
99 getter = stringLengthGetter;
100 return stringLengthGetter(this, engine, object);
101 }
102 break;
103 }
104 case Value::Integer_Type:
105 default: // Number
106 primitiveLookup.proto = engine->numberPrototype()->d();
107 }
108
109 PropertyKey name = engine->identifierTable->asPropertyKey(engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
110 protoLookup.protoId = primitiveLookup.proto->internalClass->protoId;
111 resolveProtoGetter(name, primitiveLookup.proto);
112
113 if (getter == getterProto)
114 getter = primitiveGetterProto;
115 else if (getter == getterProtoAccessor)
116 getter = primitiveGetterAccessor;
117 return getter(this, engine, object);
118 }
119
resolveGlobalGetter(ExecutionEngine * engine)120 ReturnedValue Lookup::resolveGlobalGetter(ExecutionEngine *engine)
121 {
122 Object *o = engine->globalObject;
123 PropertyKey name = engine->identifierTable->asPropertyKey(engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
124 protoLookup.protoId = o->internalClass()->protoId;
125 resolveProtoGetter(name, o->d());
126
127 if (getter == getterProto)
128 globalGetter = globalGetterProto;
129 else if (getter == getterProtoAccessor)
130 globalGetter = globalGetterProtoAccessor;
131 else {
132 globalGetter = globalGetterGeneric;
133 Scope scope(engine);
134 ScopedString n(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
135 return engine->throwReferenceError(n);
136 }
137 return globalGetter(this, engine);
138 }
139
getterGeneric(Lookup * l,ExecutionEngine * engine,const Value & object)140 ReturnedValue Lookup::getterGeneric(Lookup *l, ExecutionEngine *engine, const Value &object)
141 {
142 if (const Object *o = object.as<Object>())
143 return l->resolveGetter(engine, o);
144 return l->resolvePrimitiveGetter(engine, object);
145 }
146
getterTwoClasses(Lookup * l,ExecutionEngine * engine,const Value & object)147 ReturnedValue Lookup::getterTwoClasses(Lookup *l, ExecutionEngine *engine, const Value &object)
148 {
149 if (const Object *o = object.as<Object>()) {
150 Lookup first = *l;
151 Lookup second = *l;
152
153 ReturnedValue result = second.resolveGetter(engine, o);
154
155 if (first.getter == getter0Inline && (second.getter == getter0Inline || second.getter == getter0MemberData)) {
156 l->objectLookupTwoClasses.ic = first.objectLookup.ic;
157 l->objectLookupTwoClasses.ic2 = second.objectLookup.ic;
158 l->objectLookupTwoClasses.offset = first.objectLookup.offset;
159 l->objectLookupTwoClasses.offset2 = second.objectLookup.offset;
160 l->getter = second.getter == getter0Inline ? getter0Inlinegetter0Inline : getter0Inlinegetter0MemberData;
161 return result;
162 }
163 if (first.getter == getter0MemberData && (second.getter == getter0Inline || second.getter == getter0MemberData)) {
164 l->objectLookupTwoClasses.ic = second.objectLookup.ic;
165 l->objectLookupTwoClasses.ic2 = first.objectLookup.ic;
166 l->objectLookupTwoClasses.offset = second.objectLookup.offset;
167 l->objectLookupTwoClasses.offset2 = first.objectLookup.offset;
168 l->getter = second.getter == getter0Inline ? getter0Inlinegetter0MemberData : getter0MemberDatagetter0MemberData;
169 return result;
170 }
171 if (first.getter == getterProto && second.getter == getterProto) {
172 l->protoLookupTwoClasses.protoId = first.protoLookup.protoId;
173 l->protoLookupTwoClasses.protoId2 = second.protoLookup.protoId;
174 l->protoLookupTwoClasses.data = first.protoLookup.data;
175 l->protoLookupTwoClasses.data2 = second.protoLookup.data;
176 l->getter = getterProtoTwoClasses;
177 return result;
178 }
179 if (first.getter == getterProtoAccessor && second.getter == getterProtoAccessor) {
180 l->protoLookupTwoClasses.protoId = first.protoLookup.protoId;
181 l->protoLookupTwoClasses.protoId2 = second.protoLookup.protoId;
182 l->protoLookupTwoClasses.data = first.protoLookup.data;
183 l->protoLookupTwoClasses.data2 = second.protoLookup.data;
184 l->getter = getterProtoAccessorTwoClasses;
185 return result;
186 }
187
188 }
189
190 l->getter = getterFallback;
191 return getterFallback(l, engine, object);
192 }
193
getterFallback(Lookup * l,ExecutionEngine * engine,const Value & object)194 ReturnedValue Lookup::getterFallback(Lookup *l, ExecutionEngine *engine, const Value &object)
195 {
196 QV4::Scope scope(engine);
197 QV4::ScopedObject o(scope, object.toObject(scope.engine));
198 if (!o)
199 return Encode::undefined();
200 ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[l->nameIndex]);
201 return o->get(name);
202 }
203
getter0MemberData(Lookup * l,ExecutionEngine * engine,const Value & object)204 ReturnedValue Lookup::getter0MemberData(Lookup *l, ExecutionEngine *engine, const Value &object)
205 {
206 // we can safely cast to a QV4::Object here. If object is actually a string,
207 // the internal class won't match
208 Heap::Object *o = static_cast<Heap::Object *>(object.heapObject());
209 if (o) {
210 if (l->objectLookup.ic == o->internalClass)
211 return o->memberData->values.data()[l->objectLookup.offset].asReturnedValue();
212 }
213 return getterTwoClasses(l, engine, object);
214 }
215
getter0Inline(Lookup * l,ExecutionEngine * engine,const Value & object)216 ReturnedValue Lookup::getter0Inline(Lookup *l, ExecutionEngine *engine, const Value &object)
217 {
218 // we can safely cast to a QV4::Object here. If object is actually a string,
219 // the internal class won't match
220 Heap::Object *o = static_cast<Heap::Object *>(object.heapObject());
221 if (o) {
222 if (l->objectLookup.ic == o->internalClass)
223 return o->inlinePropertyDataWithOffset(l->objectLookup.offset)->asReturnedValue();
224 }
225 return getterTwoClasses(l, engine, object);
226 }
227
getterProto(Lookup * l,ExecutionEngine * engine,const Value & object)228 ReturnedValue Lookup::getterProto(Lookup *l, ExecutionEngine *engine, const Value &object)
229 {
230 // we can safely cast to a QV4::Object here. If object is actually a string,
231 // the internal class won't match
232 Heap::Object *o = static_cast<Heap::Object *>(object.heapObject());
233 if (o) {
234 if (l->protoLookup.protoId == o->internalClass->protoId)
235 return l->protoLookup.data->asReturnedValue();
236 }
237 return getterTwoClasses(l, engine, object);
238 }
239
getter0Inlinegetter0Inline(Lookup * l,ExecutionEngine * engine,const Value & object)240 ReturnedValue Lookup::getter0Inlinegetter0Inline(Lookup *l, ExecutionEngine *engine, const Value &object)
241 {
242 // we can safely cast to a QV4::Object here. If object is actually a string,
243 // the internal class won't match
244 Heap::Object *o = static_cast<Heap::Object *>(object.heapObject());
245 if (o) {
246 if (l->objectLookupTwoClasses.ic == o->internalClass)
247 return o->inlinePropertyDataWithOffset(l->objectLookupTwoClasses.offset)->asReturnedValue();
248 if (l->objectLookupTwoClasses.ic2 == o->internalClass)
249 return o->inlinePropertyDataWithOffset(l->objectLookupTwoClasses.offset2)->asReturnedValue();
250 }
251 l->getter = getterFallback;
252 return getterFallback(l, engine, object);
253 }
254
getter0Inlinegetter0MemberData(Lookup * l,ExecutionEngine * engine,const Value & object)255 ReturnedValue Lookup::getter0Inlinegetter0MemberData(Lookup *l, ExecutionEngine *engine, const Value &object)
256 {
257 // we can safely cast to a QV4::Object here. If object is actually a string,
258 // the internal class won't match
259 Heap::Object *o = static_cast<Heap::Object *>(object.heapObject());
260 if (o) {
261 if (l->objectLookupTwoClasses.ic == o->internalClass)
262 return o->inlinePropertyDataWithOffset(l->objectLookupTwoClasses.offset)->asReturnedValue();
263 if (l->objectLookupTwoClasses.ic2 == o->internalClass)
264 return o->memberData->values.data()[l->objectLookupTwoClasses.offset2].asReturnedValue();
265 }
266 l->getter = getterFallback;
267 return getterFallback(l, engine, object);
268 }
269
getter0MemberDatagetter0MemberData(Lookup * l,ExecutionEngine * engine,const Value & object)270 ReturnedValue Lookup::getter0MemberDatagetter0MemberData(Lookup *l, ExecutionEngine *engine, const Value &object)
271 {
272 // we can safely cast to a QV4::Object here. If object is actually a string,
273 // the internal class won't match
274 Heap::Object *o = static_cast<Heap::Object *>(object.heapObject());
275 if (o) {
276 if (l->objectLookupTwoClasses.ic == o->internalClass)
277 return o->memberData->values.data()[l->objectLookupTwoClasses.offset].asReturnedValue();
278 if (l->objectLookupTwoClasses.ic2 == o->internalClass)
279 return o->memberData->values.data()[l->objectLookupTwoClasses.offset2].asReturnedValue();
280 }
281 l->getter = getterFallback;
282 return getterFallback(l, engine, object);
283 }
284
getterProtoTwoClasses(Lookup * l,ExecutionEngine * engine,const Value & object)285 ReturnedValue Lookup::getterProtoTwoClasses(Lookup *l, ExecutionEngine *engine, const Value &object)
286 {
287 // we can safely cast to a QV4::Object here. If object is actually a string,
288 // the internal class won't match
289 Heap::Object *o = static_cast<Heap::Object *>(object.heapObject());
290 if (o) {
291 if (l->protoLookupTwoClasses.protoId == o->internalClass->protoId)
292 return l->protoLookupTwoClasses.data->asReturnedValue();
293 if (l->protoLookupTwoClasses.protoId2 == o->internalClass->protoId)
294 return l->protoLookupTwoClasses.data2->asReturnedValue();
295 return getterFallback(l, engine, object);
296 }
297 l->getter = getterFallback;
298 return getterFallback(l, engine, object);
299 }
300
getterAccessor(Lookup * l,ExecutionEngine * engine,const Value & object)301 ReturnedValue Lookup::getterAccessor(Lookup *l, ExecutionEngine *engine, const Value &object)
302 {
303 // we can safely cast to a QV4::Object here. If object is actually a string,
304 // the internal class won't match
305 Heap::Object *o = static_cast<Heap::Object *>(object.heapObject());
306 if (o) {
307 if (l->objectLookup.ic == o->internalClass) {
308 const Value *getter = o->propertyData(l->objectLookup.offset);
309 if (!getter->isFunctionObject()) // ### catch at resolve time
310 return Encode::undefined();
311
312 return checkedResult(engine, static_cast<const FunctionObject *>(getter)->call(
313 &object, nullptr, 0));
314 }
315 }
316 l->getter = getterFallback;
317 return getterFallback(l, engine, object);
318 }
319
getterProtoAccessor(Lookup * l,ExecutionEngine * engine,const Value & object)320 ReturnedValue Lookup::getterProtoAccessor(Lookup *l, ExecutionEngine *engine, const Value &object)
321 {
322 // we can safely cast to a QV4::Object here. If object is actually a string,
323 // the internal class won't match
324 Heap::Object *o = static_cast<Heap::Object *>(object.heapObject());
325 if (o && l->protoLookup.protoId == o->internalClass->protoId) {
326 const Value *getter = l->protoLookup.data;
327 if (!getter->isFunctionObject()) // ### catch at resolve time
328 return Encode::undefined();
329
330 return checkedResult(engine, static_cast<const FunctionObject *>(getter)->call(
331 &object, nullptr, 0));
332 }
333 return getterTwoClasses(l, engine, object);
334 }
335
getterProtoAccessorTwoClasses(Lookup * l,ExecutionEngine * engine,const Value & object)336 ReturnedValue Lookup::getterProtoAccessorTwoClasses(Lookup *l, ExecutionEngine *engine, const Value &object)
337 {
338 // we can safely cast to a QV4::Object here. If object is actually a string,
339 // the internal class won't match
340 Heap::Object *o = static_cast<Heap::Object *>(object.heapObject());
341 if (o) {
342 const Value *getter = nullptr;
343 if (l->protoLookupTwoClasses.protoId == o->internalClass->protoId)
344 getter = l->protoLookupTwoClasses.data;
345 else if (l->protoLookupTwoClasses.protoId2 == o->internalClass->protoId)
346 getter = l->protoLookupTwoClasses.data2;
347 if (getter) {
348 if (!getter->isFunctionObject()) // ### catch at resolve time
349 return Encode::undefined();
350
351 return checkedResult(engine, static_cast<const FunctionObject *>(getter)->call(
352 &object, nullptr, 0));
353 }
354 }
355 l->getter = getterFallback;
356 return getterFallback(l, engine, object);
357 }
358
getterIndexed(Lookup * l,ExecutionEngine * engine,const Value & object)359 ReturnedValue Lookup::getterIndexed(Lookup *l, ExecutionEngine *engine, const Value &object)
360 {
361 Object *o = object.objectValue();
362 if (o) {
363 Heap::Object *ho = o->d();
364 if (ho->arrayData && ho->arrayData->type == Heap::ArrayData::Simple) {
365 Heap::SimpleArrayData *s = ho->arrayData.cast<Heap::SimpleArrayData>();
366 if (l->indexedLookup.index < s->values.size)
367 if (!s->data(l->indexedLookup.index).isEmpty())
368 return s->data(l->indexedLookup.index).asReturnedValue();
369 }
370 return o->get(l->indexedLookup.index);
371 }
372 l->getter = getterFallback;
373 return getterFallback(l, engine, object);
374
375 }
376
primitiveGetterProto(Lookup * l,ExecutionEngine * engine,const Value & object)377 ReturnedValue Lookup::primitiveGetterProto(Lookup *l, ExecutionEngine *engine, const Value &object)
378 {
379 if (object.type() == l->primitiveLookup.type && !object.isObject()) {
380 Heap::Object *o = l->primitiveLookup.proto;
381 if (l->primitiveLookup.protoId == o->internalClass->protoId)
382 return l->primitiveLookup.data->asReturnedValue();
383 }
384 l->getter = getterGeneric;
385 return getterGeneric(l, engine, object);
386 }
387
primitiveGetterAccessor(Lookup * l,ExecutionEngine * engine,const Value & object)388 ReturnedValue Lookup::primitiveGetterAccessor(Lookup *l, ExecutionEngine *engine, const Value &object)
389 {
390 if (object.type() == l->primitiveLookup.type && !object.isObject()) {
391 Heap::Object *o = l->primitiveLookup.proto;
392 if (l->primitiveLookup.protoId == o->internalClass->protoId) {
393 const Value *getter = l->primitiveLookup.data;
394 if (!getter->isFunctionObject()) // ### catch at resolve time
395 return Encode::undefined();
396
397 return checkedResult(engine, static_cast<const FunctionObject *>(getter)->call(
398 &object, nullptr, 0));
399 }
400 }
401 l->getter = getterGeneric;
402 return getterGeneric(l, engine, object);
403 }
404
stringLengthGetter(Lookup * l,ExecutionEngine * engine,const Value & object)405 ReturnedValue Lookup::stringLengthGetter(Lookup *l, ExecutionEngine *engine, const Value &object)
406 {
407 if (const String *s = object.as<String>())
408 return Encode(s->d()->length());
409
410 l->getter = getterGeneric;
411 return getterGeneric(l, engine, object);
412 }
413
globalGetterGeneric(Lookup * l,ExecutionEngine * engine)414 ReturnedValue Lookup::globalGetterGeneric(Lookup *l, ExecutionEngine *engine)
415 {
416 return l->resolveGlobalGetter(engine);
417 }
418
globalGetterProto(Lookup * l,ExecutionEngine * engine)419 ReturnedValue Lookup::globalGetterProto(Lookup *l, ExecutionEngine *engine)
420 {
421 Heap::Object *o = engine->globalObject->d();
422 if (l->protoLookup.protoId == o->internalClass->protoId)
423 return l->protoLookup.data->asReturnedValue();
424 l->globalGetter = globalGetterGeneric;
425 return globalGetterGeneric(l, engine);
426 }
427
globalGetterProtoAccessor(Lookup * l,ExecutionEngine * engine)428 ReturnedValue Lookup::globalGetterProtoAccessor(Lookup *l, ExecutionEngine *engine)
429 {
430 Heap::Object *o = engine->globalObject->d();
431 if (l->protoLookup.protoId == o->internalClass->protoId) {
432 const Value *getter = l->protoLookup.data;
433 if (!getter->isFunctionObject()) // ### catch at resolve time
434 return Encode::undefined();
435
436 return checkedResult(engine, static_cast<const FunctionObject *>(getter)->call(
437 engine->globalObject, nullptr, 0));
438 }
439 l->globalGetter = globalGetterGeneric;
440 return globalGetterGeneric(l, engine);
441 }
442
resolveSetter(ExecutionEngine * engine,Object * object,const Value & value)443 bool Lookup::resolveSetter(ExecutionEngine *engine, Object *object, const Value &value)
444 {
445 return object->resolveLookupSetter(engine, this, value);
446 }
447
setterGeneric(Lookup * l,ExecutionEngine * engine,Value & object,const Value & value)448 bool Lookup::setterGeneric(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
449 {
450 if (object.isObject())
451 return l->resolveSetter(engine, static_cast<Object *>(&object), value);
452
453 if (engine->currentStackFrame->v4Function->isStrict())
454 return false;
455
456 Scope scope(engine);
457 ScopedObject o(scope, RuntimeHelpers::convertToObject(scope.engine, object));
458 if (!o) // type error
459 return false;
460 ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[l->nameIndex]);
461 return o->put(name, value);
462 }
463
setterTwoClasses(Lookup * l,ExecutionEngine * engine,Value & object,const Value & value)464 bool Lookup::setterTwoClasses(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
465 {
466 Lookup first = *l;
467 Lookup second = *l;
468
469 if (object.isObject()) {
470 if (!l->resolveSetter(engine, static_cast<Object *>(&object), value)) {
471 l->setter = setterFallback;
472 return false;
473 }
474
475 if (l->setter == Lookup::setter0MemberData || l->setter == Lookup::setter0Inline) {
476 l->objectLookupTwoClasses.ic = first.objectLookup.ic;
477 l->objectLookupTwoClasses.ic2 = second.objectLookup.ic;
478 l->objectLookupTwoClasses.offset = first.objectLookup.index;
479 l->objectLookupTwoClasses.offset2 = second.objectLookup.index;
480 l->setter = setter0setter0;
481 return true;
482 }
483 }
484
485 l->setter = setterFallback;
486 return setterFallback(l, engine, object, value);
487 }
488
setterFallback(Lookup * l,ExecutionEngine * engine,Value & object,const Value & value)489 bool Lookup::setterFallback(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
490 {
491 QV4::Scope scope(engine);
492 QV4::ScopedObject o(scope, object.toObject(scope.engine));
493 if (!o)
494 return false;
495
496 ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[l->nameIndex]);
497 return o->put(name, value);
498 }
499
setter0MemberData(Lookup * l,ExecutionEngine * engine,Value & object,const Value & value)500 bool Lookup::setter0MemberData(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
501 {
502 Heap::Object *o = static_cast<Heap::Object *>(object.heapObject());
503 if (o && o->internalClass == l->objectLookup.ic) {
504 o->memberData->values.set(engine, l->objectLookup.offset, value);
505 return true;
506 }
507
508 return setterTwoClasses(l, engine, object, value);
509 }
510
setter0Inline(Lookup * l,ExecutionEngine * engine,Value & object,const Value & value)511 bool Lookup::setter0Inline(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
512 {
513 Heap::Object *o = static_cast<Heap::Object *>(object.heapObject());
514 if (o && o->internalClass == l->objectLookup.ic) {
515 o->setInlinePropertyWithOffset(engine, l->objectLookup.offset, value);
516 return true;
517 }
518
519 return setterTwoClasses(l, engine, object, value);
520 }
521
setter0setter0(Lookup * l,ExecutionEngine * engine,Value & object,const Value & value)522 bool Lookup::setter0setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
523 {
524 Heap::Object *o = static_cast<Heap::Object *>(object.heapObject());
525 if (o) {
526 if (o->internalClass == l->objectLookupTwoClasses.ic) {
527 o->setProperty(engine, l->objectLookupTwoClasses.offset, value);
528 return true;
529 }
530 if (o->internalClass == l->objectLookupTwoClasses.ic2) {
531 o->setProperty(engine, l->objectLookupTwoClasses.offset2, value);
532 return true;
533 }
534 }
535
536 l->setter = setterFallback;
537 return setterFallback(l, engine, object, value);
538 }
539
setterInsert(Lookup * l,ExecutionEngine * engine,Value & object,const Value & value)540 bool Lookup::setterInsert(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
541 {
542 Object *o = static_cast<Object *>(object.managed());
543 if (o && o->internalClass()->protoId == l->insertionLookup.protoId) {
544 o->setInternalClass(l->insertionLookup.newClass);
545 o->d()->setProperty(engine, l->insertionLookup.offset, value);
546 return true;
547 }
548
549 l->setter = setterFallback;
550 return setterFallback(l, engine, object, value);
551 }
552
arrayLengthSetter(Lookup *,ExecutionEngine * engine,Value & object,const Value & value)553 bool Lookup::arrayLengthSetter(Lookup *, ExecutionEngine *engine, Value &object, const Value &value)
554 {
555 Q_ASSERT(object.isObject() && static_cast<Object &>(object).isArrayObject());
556 bool ok;
557 uint len = value.asArrayLength(&ok);
558 if (!ok) {
559 engine->throwRangeError(value);
560 return false;
561 }
562 ok = static_cast<Object &>(object).setArrayLength(len);
563 if (!ok)
564 return false;
565 return true;
566 }
567
568 QT_END_NAMESPACE
569