void JSFunctionWriter::WriteParameterMarshal(String& source) { // generate args const Vector<JSBFunctionType*>& parameters = function_->GetParameters(); int cparam = 0; if (parameters.Size()) { for (unsigned int i = 0; i < parameters.Size(); i++, cparam++) { JSBFunctionType * ptype = parameters.At(i); // ignore "Context" parameters if (ptype->type_->asClassType()) { JSBClassType* classType = ptype->type_->asClassType(); JSBClass* klass = classType->class_; if (klass->GetName() == "Context") { cparam--; continue; } } String pstring = ptype->ToArgString(cparam); const String& init = ptype->initializer_; if (ptype->type_->asClassType()) { JSBClassType* classType = ptype->type_->asClassType(); JSBClass* klass = classType->class_; if (!klass->IsNumberArray()) { if (init.Length()) { source.AppendWithFormat("%s = duk_get_top(ctx) >= %i ? js_to_class_instance<%s>(ctx, %i, 0) : %s;\n", pstring.CString(), cparam + 1, klass->GetNativeName().CString(), cparam, init.CString()); } else { source.AppendWithFormat("%s = js_to_class_instance<%s>(ctx, %i, 0);\n", pstring.CString(), klass->GetNativeName().CString(), cparam); } } else { int elements = klass->GetNumberArrayElements(); String elementType = klass->GetArrayElementType(); source.AppendWithFormat("%s arrayData%i[%i];\n", elementType.CString(), cparam, elements); if (init.Length()) { source.AppendWithFormat("const %s& defaultArg%i = %s;\n", klass->GetNativeName().CString(), cparam, init.CString()); source.AppendWithFormat("if (duk_get_top(ctx) >= %i) {\n", cparam + 1); } for (int j = 0; j < elements; j++) { source.AppendWithFormat("duk_get_prop_index(ctx, %i, %i);\n", cparam, j); source.AppendWithFormat("arrayData%i[%i] = (%s) duk_to_number(ctx, -1);\n", cparam, j, elementType.CString()); } source.AppendWithFormat("duk_pop_n(ctx, %i);\n", elements); if (init.Length()) { source.Append("}\n"); source.AppendWithFormat("%s __arg%i(duk_get_top(ctx) >= %i ? (const %s *) arrayData%i : defaultArg%i.Data());\n", klass->GetNativeName().CString(), cparam, cparam + 1, elementType.CString(), cparam, cparam); } else { source.AppendWithFormat("%s __arg%i(arrayData%i);\n", klass->GetNativeName().CString(), cparam, cparam); } } } else if (ptype->type_->asStringType() || ptype->type_->asStringHashType()) { if (init.Length()) { source.AppendWithFormat("%s = duk_get_top(ctx) >= %i ? duk_to_string(ctx, %i) : %s;\n", pstring.CString(), cparam + 1, cparam, init.CString()); } else { source.AppendWithFormat("%s = duk_to_string(ctx, %i);\n", pstring.CString(), cparam); } } else if (ptype->type_->asHeapPtrType()) { if (init.Length()) { source.AppendWithFormat("%s = duk_get_top(ctx) >= %i ? duk_get_heapptr(ctx, %i) : %s;\n", pstring.CString(), cparam + 1, cparam, init.CString()); } else { source.AppendWithFormat("%s = duk_get_heapptr(ctx, %i);\n", pstring.CString(), cparam); } } else if (ptype->type_->asPrimitiveType()) { JSBPrimitiveType* prtype = ptype->type_->asPrimitiveType(); if (prtype->kind_ == JSBPrimitiveType::Bool) { if (init.Length()) { source.AppendWithFormat("bool __arg%i = duk_get_top(ctx) >= %i ? (duk_to_boolean(ctx, %i) ? true : false) : %s;\n", cparam, cparam + 1, cparam, init.CString()); } else { source.AppendWithFormat("bool __arg%i = duk_to_boolean(ctx, %i) ? true : false;\n", cparam, cparam); } } else { if (init.Length()) { source.AppendWithFormat("double __arg%i = duk_get_top(ctx) >= %i ? (duk_to_number(ctx, %i)) : %s;\n", cparam, cparam + 1, cparam, init.CString()); } else { source.AppendWithFormat("double __arg%i = duk_to_number(ctx, %i);\n", cparam, cparam); } } } else if (ptype->type_->asEnumType()) { JSBEnumType* etype = ptype->type_->asEnumType(); if (init.Length()) { source.AppendWithFormat("%s __arg%i = duk_get_top(ctx) >= %i ? ((%s) ((int) duk_to_number(ctx, %i))) : %s;\n", etype->enum_->GetName().CString(), cparam, cparam + 1, etype->enum_->GetName().CString(), cparam, init.CString()); } else { source.AppendWithFormat("%s __arg%i = (%s) ((int)duk_to_number(ctx, %i));\n", etype->enum_->GetName().CString(), cparam, etype->enum_->GetName().CString(), cparam); } } else if (ptype->type_->asVectorType()) { JSBVectorType* vtype = ptype->type_->asVectorType(); if (vtype->isVariantVector_) { // variant vector arguments source.AppendWithFormat("VariantVector __arg%i;\nScriptVector* __scriptVectorArg%i = js_to_class_instance<ScriptVector>(ctx, %i, 0);\n", cparam, cparam, cparam); if (!function_->HasMutatedReturn()) source.AppendWithFormat("__scriptVectorArg%i->AdaptToVector(__arg%i);\n", cparam, cparam); } else if (ptype->isConst_) { // JS/TS side needs work for vector parameters, right now we support const (read only) // Vector of String/StringHash source.AppendWithFormat("%s __arg%i;\n", vtype->ToString().CString(), cparam); source.AppendWithFormat("if (duk_get_top(ctx) >= %i)\n{\n", cparam + 1); source.AppendWithFormat("duk_require_object_coercible(ctx, %i);\n", cparam); source.AppendWithFormat("unsigned sz = duk_get_length(ctx, %i);\n", cparam); source.AppendWithFormat("for (unsigned i = 0; i < sz; i++)\n{\n"); source.AppendWithFormat("duk_get_prop_index(ctx, 2, i);\n"); if (vtype->vectorType_->asStringType() || vtype->vectorType_->asStringHashType() ) { source.AppendWithFormat("__arg%i.Push(duk_get_string(ctx, -1));\n", cparam); } source.AppendWithFormat("duk_pop(ctx);\n"); source.AppendWithFormat("\n}\n"); source.AppendWithFormat("\n}\n"); } } } } }