static bool ValidateGlobalVariable(JSContext *cx, const AsmJSModule &module, AsmJSModule::Global &global, HandleValue importVal) { JS_ASSERT(global.which() == AsmJSModule::Global::Variable); void *datum = module.globalVarIndexToGlobalDatum(global.varIndex()); switch (global.varInitKind()) { case AsmJSModule::Global::InitConstant: { const Value &v = global.varInitConstant(); switch (global.varInitCoercion()) { case AsmJS_ToInt32: *(int32_t *)datum = v.toInt32(); break; case AsmJS_ToNumber: *(double *)datum = v.toDouble(); break; case AsmJS_FRound: *(float *)datum = static_cast<float>(v.toDouble()); break; } break; } case AsmJSModule::Global::InitImport: { RootedPropertyName field(cx, global.varImportField()); RootedValue v(cx); if (!GetDataProperty(cx, importVal, field, &v)) return false; switch (global.varInitCoercion()) { case AsmJS_ToInt32: if (!ToInt32(cx, v, (int32_t *)datum)) return false; break; case AsmJS_ToNumber: if (!ToNumber(cx, v, (double *)datum)) return false; break; case AsmJS_FRound: if (!RoundFloat32(cx, v, (float *)datum)) return false; break; } break; } } return true; }
static bool ValidateGlobalVariable(JSContext *cx, const AsmJSModule &module, AsmJSModule::Global &global, HandleValue importVal) { JS_ASSERT(global.which() == AsmJSModule::Global::Variable); void *datum = module.globalVarIndexToGlobalDatum(global.varIndex()); switch (global.varInitKind()) { case AsmJSModule::Global::InitConstant: { const AsmJSNumLit &lit = global.varInitNumLit(); const Value &v = lit.value(); switch (lit.which()) { case AsmJSNumLit::Fixnum: case AsmJSNumLit::NegativeInt: case AsmJSNumLit::BigUnsigned: *(int32_t *)datum = v.toInt32(); break; case AsmJSNumLit::Double: *(double *)datum = v.toDouble(); break; case AsmJSNumLit::Float: *(float *)datum = static_cast<float>(v.toDouble()); break; case AsmJSNumLit::OutOfRangeInt: MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("OutOfRangeInt isn't valid in the first place"); } break; } case AsmJSModule::Global::InitImport: { RootedPropertyName field(cx, global.varImportField()); RootedValue v(cx); if (!GetDataProperty(cx, importVal, field, &v)) return false; if (!v.isPrimitive()) { // Ideally, we'd reject all non-primitives, but Emscripten has a bug // that generates code that passes functions for some imports. To // avoid breaking all the code that contains this bug, we make an // exception for functions that don't have user-defined valueOf or // toString, for their coercions are not observable and coercion via // ToNumber/ToInt32 definitely produces NaN/0. We should remove this // special case later once most apps have been built with newer // Emscripten. jsid toString = NameToId(cx->names().toString); if (!v.toObject().is<JSFunction>() || !HasObjectValueOf(&v.toObject(), cx) || !ClassMethodIsNative(cx, &v.toObject(), &JSFunction::class_, toString, fun_toString)) { return LinkFail(cx, "Imported values must be primitives"); } } switch (global.varInitCoercion()) { case AsmJS_ToInt32: if (!ToInt32(cx, v, (int32_t *)datum)) return false; break; case AsmJS_ToNumber: if (!ToNumber(cx, v, (double *)datum)) return false; break; case AsmJS_FRound: if (!RoundFloat32(cx, v, (float *)datum)) return false; break; } break; } } return true; }