// ECMA262: 15.3.5.3 static EJSBool _ejs_function_specop_has_instance (ejsval F, ejsval V) { /* 1. If V is not an object, return false. */ if (!EJSVAL_IS_OBJECT(V)) return EJS_FALSE; /* 2. Let O be the result of calling the [[Get]] internal method of F with property name "prototype". */ ejsval O = OP(EJSVAL_TO_OBJECT(F),Get)(F, _ejs_atom_prototype, F); /* 3. If Type(O) is not Object, throw a TypeError exception. */ if (!EJSVAL_IS_OBJECT(O)) { printf ("throw TypeError, O is not an object\n"); EJS_NOT_IMPLEMENTED(); } /* 4. Repeat */ while (1) { /* a. Let V be the value of the [[Prototype]] internal property of V. */ V = EJSVAL_TO_OBJECT(V)->proto; /* b. If V is null, return false. */ if (EJSVAL_IS_NULL(V)) return EJS_FALSE; /* c. If O and V refer to the same object, return true. */ if (EJSVAL_EQ(O, V)) return EJS_TRUE; } }
ejsval _ejs_typedarray_new_from_array (EJSTypedArrayType element_type, ejsval arrayObj) { EJSObject *arr = EJSVAL_TO_OBJECT(arrayObj); int arrlen = EJSARRAY_LEN(arr); ejsval typedarr = _ejs_typedarray_new (element_type, arrlen); int i; void* data = _ejs_typedarray_get_data (EJSVAL_TO_OBJECT(typedarr)); // this is woefully underoptimized... for (i = 0; i < arrlen; i ++) { ejsval item = _ejs_object_getprop (arrayObj, NUMBER_TO_EJSVAL(i)); switch (element_type) { case EJS_TYPEDARRAY_INT8: ((int8_t*)data)[i] = (int8_t)EJSVAL_TO_NUMBER(item); break; case EJS_TYPEDARRAY_UINT8: ((uint8_t*)data)[i] = (uint8_t)EJSVAL_TO_NUMBER(item); break; case EJS_TYPEDARRAY_UINT8CLAMPED: EJS_NOT_IMPLEMENTED(); case EJS_TYPEDARRAY_INT16: ((int16_t*)data)[i] = (int16_t)EJSVAL_TO_NUMBER(item); break; case EJS_TYPEDARRAY_UINT16: ((uint16_t*)data)[i] = (uint16_t)EJSVAL_TO_NUMBER(item); break; case EJS_TYPEDARRAY_INT32: ((int32_t*)data)[i] = (int32_t)EJSVAL_TO_NUMBER(item); break; case EJS_TYPEDARRAY_UINT32: ((uint32_t*)data)[i] = (uint32_t)EJSVAL_TO_NUMBER(item); break; case EJS_TYPEDARRAY_FLOAT32: ((float*)data)[i] = (float)EJSVAL_TO_NUMBER(item); break; case EJS_TYPEDARRAY_FLOAT64: ((double*)data)[i] = (double)EJSVAL_TO_NUMBER(item); break; default: EJS_NOT_REACHED(); } } return typedarr; }
void _ejs_module_import_batch(ejsval fromImport, ejsval specifiers, ejsval toExport) { EJSObject* fromObj = EJSVAL_TO_OBJECT(fromImport); EJSObject* toObj = EJSVAL_TO_OBJECT(toExport); EJSArray* specArray = (EJSArray*)EJSVAL_TO_OBJECT(specifiers); ImportBatchData data; data.toObj = toObj; data.specifiers = EJSARRAY_LEN(specArray) == 0 ? NULL : specArray; _ejs_propertymap_foreach_property(&fromObj->map, import_batch_foreach, &data); }
static ejsval DIBuilder_prototype_createFunction (ejsval env, ejsval _this, int argc, ejsval *args) { REQ_LLVM_DISCOPE_ARG(0, discope); REQ_UTF8_ARG(1, name); REQ_UTF8_ARG(2, linkageName); REQ_LLVM_DIFILE_ARG(3, file); REQ_INT_ARG(4, line_no); REQ_BOOL_ARG(5, isLocalToUnit); REQ_BOOL_ARG(6, isDefinition); REQ_INT_ARG(7, scopeLine); REQ_INT_ARG(8, flags); REQ_BOOL_ARG(9, isOptimized); REQ_LLVM_FUN_ARG(10, fn); DIBuilder* dib = ((DIBuilder*)EJSVAL_TO_OBJECT(_this)); return DISubprogram_new(dib->llvm_dibuilder->createFunction (discope, name, linkageName, file, line_no, createDIFunctionType(dib->llvm_dibuilder, file, fn->getFunctionType()), isLocalToUnit, isDefinition, scopeLine, flags, isOptimized, fn)); }
ejsval ArrayType_new(llvm::ArrayType* llvm_ty) { ejsval result = _ejs_object_new (_ejs_ArrayType_prototype, &_ejs_ArrayType_specops); ((ArrayType*)EJSVAL_TO_OBJECT(result))->type = llvm_ty; return result; }
ejsval Call_prototype_setDoesNotThrow(ejsval env, ejsval _this, int argc, ejsval *args) { Call* call = ((Call*)EJSVAL_TO_OBJECT(_this)); call->llvm_call->setDoesNotThrow(); return _ejs_undefined; }
// ECMA262: 26.1.6 Reflect.get ( target, propertyKey [ , receiver ]) static ejsval _ejs_Reflect_get (ejsval env, ejsval _this, uint32_t argc, ejsval *args) { ejsval target = _ejs_undefined; ejsval propertyKey = _ejs_undefined; ejsval receiver = _ejs_undefined; if (argc > 0) target = args[0]; if (argc > 1) propertyKey = args[1]; if (argc > 2) receiver = args[2]; // 1. Let obj be ToObject(target). // 2. ReturnIfAbrupt(obj). ejsval obj = ToObject(target); // 3. Let key be ToPropertyKey(propertyKey). // 4. ReturnIfAbrupt(key). ejsval key = ToPropertyKey(propertyKey); // 5. If receiver is not present, then // a. Let receiver be target. if (argc <= 2) receiver = target; // 6. Return the result of calling the [[Get]] internal method of obj with arguments key, and receiver return OP(EJSVAL_TO_OBJECT(obj),Get)(obj, key, receiver); }
ejsval Invoke_prototype_setOnlyReadsMemory(ejsval env, ejsval _this, int argc, ejsval *args) { Invoke* invoke = ((Invoke*)EJSVAL_TO_OBJECT(_this)); invoke->llvm_invoke->setOnlyReadsMemory(); return _ejs_undefined; }
ejsval Call_new(llvm::CallInst* llvm_call) { ejsval result = _ejs_object_new (_ejs_Call_prototype, &_ejs_Call_specops); ((Call*)EJSVAL_TO_OBJECT(result))->llvm_call = llvm_call; return result; }
ejsval Function_prototype_setOnlyReadsMemory(ejsval env, ejsval _this, int argc, ejsval *args) { Function* fun = ((Function*)EJSVAL_TO_OBJECT(_this)); fun->llvm_fun->setOnlyReadsMemory(); return _ejs_undefined; }
static void _ejs_dataview_specop_put (ejsval obj, ejsval propertyName, ejsval val, ejsval receiver, EJSBool flag) { EJSBool is_index = EJS_FALSE; ejsval idx_val = ToNumber(propertyName); int idx; if (EJSVAL_IS_NUMBER(idx_val)) { double n = EJSVAL_TO_NUMBER(idx_val); if (floor(n) == n) { idx = (int)n; is_index = EJS_TRUE; } } if (is_index) { if (idx < 0 || idx >= EJS_DATA_VIEW_BYTE_LEN(obj)) return; void* data = _ejs_dataview_get_data (EJSVAL_TO_OBJECT(obj)); ((unsigned char*)data)[idx] = (unsigned char)EJSVAL_TO_NUMBER(val); return; } _ejs_Object_specops.put (obj, propertyName, val, receiver, flag); }
ejsval Function_prototype_get_name(ejsval env, ejsval _this, int argc, ejsval *args) { Function* fun = ((Function*)EJSVAL_TO_OBJECT(_this)); std::string fun_name = fun->llvm_fun->getName(); return _ejs_string_new_utf8(fun_name.c_str()); }
ejsval Function_new(llvm::Function* llvm_fun) { ejsval result = _ejs_object_new (_ejs_Function_proto, &function_specops); ((Function*)EJSVAL_TO_OBJECT(result))->llvm_fun = llvm_fun; return result; }
ejsval Function_prototype_setInternalLinkage(ejsval env, ejsval _this, int argc, ejsval *args) { Function* fun = ((Function*)EJSVAL_TO_OBJECT(_this)); fun->llvm_fun->setLinkage (llvm::Function::InternalLinkage); return _ejs_undefined; }
// ECMA262 25.4.4.6 Promise [ @@create ] ( ) static ejsval _ejs_Promise_create (ejsval env, ejsval _this, uint32_t argc, ejsval *args) { // 1. Let F be the this value ejsval F = _this; // 2. Return AllocatePromise(F). // 1. Let obj be OrdinaryCreateFromConstructor(constructor, "%PromisePrototype%", ([[PromiseState]], [[PromiseConstructor]], [[PromiseResult]], [[PromiseFulfillReactions]], [[PromiseRejectReactions]]) ). ejsval proto = _ejs_undefined; if (!EJSVAL_IS_UNDEFINED(F)) { if (!EJSVAL_IS_CONSTRUCTOR(F)) _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, "'this' in Promise[Symbol.create] is not a constructor"); EJSObject* F_ = EJSVAL_TO_OBJECT(F); proto = OP(F_,Get)(F, _ejs_atom_prototype, F); } if (EJSVAL_IS_UNDEFINED(proto)) proto = _ejs_Promise_prototype; EJSObject* obj = (EJSObject*)_ejs_gc_new (EJSPromise); _ejs_init_object (obj, proto, &_ejs_Promise_specops); // 2. Set the value of obj’s [[PromiseConstructor]] internal slot to constructor. ((EJSPromise*)obj)->constructor = F; // 3. Return obj. return OBJECT_TO_EJSVAL(obj); }
static ejsval DIBuilder_prototype_finalize (ejsval env, ejsval _this, int argc, ejsval *args) { DIBuilder* dib = ((DIBuilder*)EJSVAL_TO_OBJECT(_this)); dib->llvm_dibuilder->finalize(); return _ejs_undefined; }
static EJS_NATIVE_FUNC(ArrayType_prototype_toString) { std::string str; llvm::raw_string_ostream str_ostream(str); ((ArrayType*)EJSVAL_TO_OBJECT(*_this))->type->print(str_ostream); return _ejs_string_new_utf8(trim(str_ostream.str()).c_str()); }
ejsval Function_prototype_setDoesNotThrow(ejsval env, ejsval _this, int argc, ejsval *args) { Function* fun = ((Function*)EJSVAL_TO_OBJECT(_this)); fun->llvm_fun->setDoesNotThrow(); return _ejs_undefined; }
ejsval _ejs_invoke_closure (ejsval closure, ejsval _this, uint32_t argc, ejsval* args) { if (!EJSVAL_IS_FUNCTION(closure)) { #if DEBUG_LAST_LOOKUP extern jschar* last_lookup; if (last_lookup) { char *last_utf8 = ucs2_to_utf8(last_lookup); _ejs_log ("last property lookup was for: %s\n", last_utf8); free (last_utf8); } #endif _ejs_throw_nativeerror_utf8 (EJS_TYPE_ERROR, "object not a function"); } #if 0 if (!EJSVAL_IS_NULL_OR_UNDEFINED(_this) && EJSVAL_IS_PRIMITIVE(_this)) { _this = ToObject(_this); } #endif EJSFunction *fun = (EJSFunction*)EJSVAL_TO_OBJECT(closure); return fun->func (fun->env, _this, argc, args); }
ejsval LoadInst_new(llvm::LoadInst* llvm_load) { ejsval result = _ejs_object_new (_ejs_LoadInst_prototype, &_ejs_LoadInst_specops); ((LoadInst*)EJSVAL_TO_OBJECT(result))->llvm_load = llvm_load; return result; }
ejsval Invoke_new(llvm::InvokeInst* llvm_invoke) { ejsval result = _ejs_object_new (_ejs_Invoke_prototype, &_ejs_Invoke_specops); ((Invoke*)EJSVAL_TO_OBJECT(result))->llvm_invoke = llvm_invoke; return result; }
ejsval LandingPad_new(llvm::LandingPadInst* llvm_landingpad) { ejsval result = _ejs_object_new (_ejs_LandingPad_prototype, &_ejs_LandingPad_specops); ((LandingPad*)EJSVAL_TO_OBJECT(result))->llvm_landing_pad = llvm_landingpad; return result; }
ejsval Invoke_prototype_setDoesNotThrow(ejsval env, ejsval _this, int argc, ejsval *args) { Invoke* invoke = ((Invoke*)EJSVAL_TO_OBJECT(_this)); invoke->llvm_invoke->setDoesNotThrow(); return _ejs_undefined; }
ejsval Module_prototype_getOrInsertFunction(ejsval env, ejsval _this, int argc, ejsval *args) { Module *module = ((Module*)EJSVAL_TO_OBJECT(_this)); REQ_UTF8_ARG(0, name); REQ_LLVM_TYPE_ARG(1, returnType); REQ_ARRAY_ARG(2, paramTypes); std::vector< llvm::Type*> param_types; for (int i = 0; i < EJSARRAY_LEN(paramTypes); i ++) { param_types.push_back (Type_GetLLVMObj(EJSDENSEARRAY_ELEMENTS(paramTypes)[i])); } llvm::FunctionType *FT = llvm::FunctionType::get(returnType, param_types, false); llvm::Function* f = static_cast< llvm::Function*>(module->llvm_module->getOrInsertFunction(name, FT)); // XXX this needs to come from the js call, since when we hoist anonymous methods we'll need to give them a private linkage. f->setLinkage (llvm::Function::ExternalLinkage); // XXX the args might not be identifiers but might instead be destructuring expressions. punt for now. #if notyet // Set names for all arguments. unsigned Idx = 0; for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size(); ++AI, ++Idx) AI->setName(Args[Idx]); #endif return Function_new (f); }
ejsval Call_prototype_setOnlyReadsMemory(ejsval env, ejsval _this, int argc, ejsval *args) { Call* call = ((Call*)EJSVAL_TO_OBJECT(_this)); call->llvm_call->setOnlyReadsMemory(); return _ejs_undefined; }
static ejsval _ejs_dataview_specop_get (ejsval obj, ejsval propertyName, ejsval receiver) { // check if propertyName is an integer, or a string that we can convert to an int EJSBool is_index = EJS_FALSE; int idx = 0; if (EJSVAL_IS_NUMBER(propertyName)) { double n = EJSVAL_TO_NUMBER(propertyName); if (floor(n) == n) { idx = (int)n; is_index = EJS_TRUE; } } // Index for DataView is byte-based. if (is_index) { if (idx < 0 || idx > EJS_DATA_VIEW_BYTE_LEN(obj)) return _ejs_undefined; void *data = _ejs_dataview_get_data (EJSVAL_TO_OBJECT(obj)); return NUMBER_TO_EJSVAL ((double)((unsigned char*)data)[idx]); } // otherwise we fallback to the object implementation return _ejs_Object_specops.get (obj, propertyName, receiver); }
static EJS_NATIVE_FUNC(GlobalVariable_prototype_toString) { std::string str; llvm::raw_string_ostream str_ostream(str); ((GlobalVariable*)EJSVAL_TO_OBJECT(*_this))->llvm_global->print(str_ostream); return _ejs_string_new_utf8(trim(str_ostream.str()).c_str()); }
ejsval AllocaInst_new(llvm::AllocaInst* llvm_alloca) { ejsval result = _ejs_object_new (_ejs_AllocaInst_proto, &allocainst_specops); ((AllocaInst*)EJSVAL_TO_OBJECT(result))->llvm_alloca = llvm_alloca; return result; }
ejsval Module_prototype_getOrInsertIntrinsic(ejsval env, ejsval _this, int argc, ejsval *args) { Module* module = ((Module*)EJSVAL_TO_OBJECT(_this)); REQ_UTF8_ARG(0, id); #if false REQ_ARRAY_ARG(1, paramTypes); std::vector< llvm::Type*> param_types; for (int i = 0; i < paramTypes->Length(); i ++) { param_types.push_back (Type_getLLVMObj(EJSARRAY_ELEMENTS(argTypes)[i])); } #endif llvm::Intrinsic::ID intrinsic_id; if (!strcmp (id.c_str(), "@llvm.gcroot")) { intrinsic_id = llvm::Intrinsic::gcroot; } else { abort(); } #if false llvm::Function* f = llvm::Intrinsic::getDeclaration (module->llvm_module, intrinsic_id, param_types); #else llvm::Function* f = llvm::Intrinsic::getDeclaration (module->llvm_module, intrinsic_id); #endif return Function_new (f); }
static ejsval FunctionType_prototype_getParamType (ejsval env, ejsval _this, int argc, ejsval *args) { REQ_INT_ARG(0, i); return Type_new (((FunctionType*)EJSVAL_TO_OBJECT(_this))->type->getParamType(i)); }