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");

                }
            }
        }
    }
}