void __qmljs_llvm_typeof(ExecutionContext *ctx, Value *result, const Value *value)
{
- *result = __qmljs_typeof(*value, ctx);
+ *result = __qmljs_builtin_typeof(*value, ctx);
}
void __qmljs_llvm_throw(ExecutionContext *context, Value *value)
return Value::undefinedValue();
}
+Value ExecutionContext::getPropertyNoThrow(String *name)
+{
+ for (ExecutionContext *ctx = this; ctx; ctx = ctx->outer()) {
+ if (ctx->withObject) {
+ With *w = ctx->withObject;
+ while (w) {
+ if (w->object->__hasProperty__(ctx, name))
+ return w->object->__get__(ctx, name);
+ w = w->next;
+ }
+ }
+
+ for (unsigned int i = 0; i < ctx->variableCount(); ++i)
+ if (__qmljs_string_equal(ctx->variables()[i], name))
+ return ctx->locals[i];
+ for (unsigned int i = 0; i < ctx->formalCount(); ++i)
+ if (__qmljs_string_equal(ctx->formals()[i], name))
+ return ctx->arguments[i];
+ if (ctx->activation && ctx->activation->__hasProperty__(ctx, name))
+ return ctx->activation->__get__(ctx, name);
+ if (name->isEqualTo(ctx->engine->id_arguments)) {
+ Value arguments = Value::fromObject(new (engine->memoryManager) ArgumentsObject(this));
+ createMutableBinding(ctx->engine->id_arguments, false);
+ setMutableBinding(this, ctx->engine->id_arguments, arguments);
+ return arguments;
+ }
+ }
+ return Value::undefinedValue();
+}
+
void ExecutionContext::inplaceBitOp(Value value, String *name, BinOp op)
void setProperty(String *name, Value value);
Value getProperty(String *name);
+ Value getPropertyNoThrow(String *name);
void inplaceBitOp(Value value, String *name, BinOp op);
bool deleteProperty(String *name);
return context->engine->exception;
}
-Value __qmljs_builtin_typeof(Value val, ExecutionContext *context)
+Value __qmljs_builtin_typeof(Value value, ExecutionContext *ctx)
+{
+ switch (value.type()) {
+ case Value::Undefined_Type:
+ return __qmljs_string_literal_undefined(ctx);
+ break;
+ case Value::Null_Type:
+ return __qmljs_string_literal_object(ctx);
+ break;
+ case Value::Boolean_Type:
+ return __qmljs_string_literal_boolean(ctx);
+ break;
+ case Value::String_Type:
+ return __qmljs_string_literal_string(ctx);
+ break;
+ case Value::Object_Type:
+ if (__qmljs_is_callable(value, ctx))
+ return __qmljs_string_literal_function(ctx);
+ else
+ return __qmljs_string_literal_object(ctx); // ### implementation-defined
+ break;
+ default:
+ return __qmljs_string_literal_number(ctx);
+ break;
+ }
+}
+
+Value __qmljs_builtin_typeof_name(String *name, ExecutionContext *context)
+{
+ return __qmljs_builtin_typeof(context->getPropertyNoThrow(name), context);
+}
+
+Value __qmljs_builtin_typeof_member(Value base, String *name, ExecutionContext *context)
+{
+ Value obj = base.toObject(context);
+ return __qmljs_builtin_typeof(obj.objectValue()->__get__(context, name), context);
+}
+
+Value __qmljs_builtin_typeof_element(Value base, Value index, ExecutionContext *context)
{
- return __qmljs_typeof(val, context);
+ String *name = index.toString(context);
+ Value obj = base.toObject(context);
+ return __qmljs_builtin_typeof(obj.objectValue()->__get__(context, name), context);
}
void __qmljs_builtin_throw(Value val, ExecutionContext *context)
Value __qmljs_construct_property(ExecutionContext *context, Value base, String *name, Value *args, int argc);
Value __qmljs_construct_value(ExecutionContext *context, Value func, Value *args, int argc);
-Value __qmljs_builtin_typeof(Value val, ExecutionContext *context);
+Value __qmljs_builtin_typeof(Value val, ExecutionContext *ctx);
+Value __qmljs_builtin_typeof_name(String *name, ExecutionContext *context);
+Value __qmljs_builtin_typeof_member(Value base, String *name, ExecutionContext *context);
+Value __qmljs_builtin_typeof_element(Value base, Value index, ExecutionContext *context);
+
void __qmljs_builtin_throw(Value val, ExecutionContext *context);
void __qmljs_builtin_push_with(Value o, ExecutionContext *ctx);
void __qmljs_builtin_pop_with(ExecutionContext *ctx);
Value __qmljs_delete_member(ExecutionContext *ctx, Value base, String *name);
Value __qmljs_delete_name(ExecutionContext *ctx, String *name);
-Value __qmljs_typeof(Value value, ExecutionContext *ctx);
void __qmljs_throw(Value value, ExecutionContext *context);
// actually returns a jmp_buf *
void *__qmljs_create_exception_handler(ExecutionContext *context);
}
-// unary operators
-inline Value __qmljs_typeof(Value value, ExecutionContext *ctx)
-{
- switch (value.type()) {
- case Value::Undefined_Type:
- return __qmljs_string_literal_undefined(ctx);
- break;
- case Value::Null_Type:
- return __qmljs_string_literal_object(ctx);
- break;
- case Value::Boolean_Type:
- return __qmljs_string_literal_boolean(ctx);
- break;
- case Value::String_Type:
- return __qmljs_string_literal_string(ctx);
- break;
- case Value::Object_Type:
- if (__qmljs_is_callable(value, ctx))
- return __qmljs_string_literal_function(ctx);
- else
- return __qmljs_string_literal_object(ctx); // ### implementation-defined
- break;
- default:
- return __qmljs_string_literal_number(ctx);
- break;
- }
-}
-
inline Value __qmljs_uplus(Value value, ExecutionContext *ctx)
{
TRACE1(value);
{
Result expr = expression(ast->expression);
IR::ExprList *args = _function->New<IR::ExprList>();
- args->init(argument(*expr));
+ args->init(*expr);
_expr.code = call(_block->NAME(IR::Name::builtin_typeof, ast->typeofToken.startLine, ast->typeofToken.startColumn), args);
return false;
}
callRuntimeMethod(result, __qmljs_call_activation_property, call->base, call->args);
break;
case IR::Name::builtin_typeof: {
- IR::Temp *arg = call->args->expr->asTemp();
- assert(arg != 0);
- generateFunctionCall(result, __qmljs_builtin_typeof, arg, ContextRegister);
+ if (IR::Member *m = call->args->expr->asMember()) {
+ generateFunctionCall(result, __qmljs_builtin_typeof_member, m->base->asTemp(), identifier(*m->name), ContextRegister);
+ return;
+ } else if (IR::Subscript *ss = call->args->expr->asSubscript()) {
+ generateFunctionCall(result, __qmljs_builtin_typeof_element, ss->base->asTemp(), ss->index->asTemp(), ContextRegister);
+ return;
+ } else if (IR::Name *n = call->args->expr->asName()) {
+ generateFunctionCall(result, __qmljs_builtin_typeof_name, identifier(*n->id), ContextRegister);
+ return;
+ } else if (IR::Temp *arg = call->args->expr->asTemp()){
+ assert(arg != 0);
+ generateFunctionCall(result, __qmljs_builtin_typeof, arg, ContextRegister);
+ } else {
+ assert(false);
+ }
}
break;
case IR::Name::builtin_delete: {
generateFunctionCall(result, __qmljs_delete_subscript, ContextRegister, ss->base->asTemp(), ss->index->asTemp());
return;
} else if (IR::Name *n = call->args->expr->asName()) {
- generateFunctionCall(result, __qmljs_delete_name, ContextRegister, n);
+ generateFunctionCall(result, __qmljs_delete_name, ContextRegister, identifier(*n->id));
return;
} else if (call->args->expr->asTemp()){
// ### should throw in strict mode