public JsValue CreateValue(Type targetType, JavaScriptValueSafeHandle valueHandle) { if (targetType == null) { throw new ArgumentNullException(nameof(targetType)); } if (targetType.IsSubclassOf(typeof(JsValue)) == false) { throw new ArgumentOutOfRangeException(nameof(targetType)); } if (valueHandle == JavaScriptValueSafeHandle.Invalid) { return(null); } return(m_valuePool.GetOrAdd(valueHandle, () => { JsValue result; if (typeof(JsObject).IsSameOrSubclass(targetType)) { result = Activator.CreateInstance(targetType, new object[] { m_engine, Context, valueHandle }) as JsValue; } else if (typeof(JsExternalObject).IsSameOrSubclass(targetType)) { //TODO: This isn't exactly true, we should set the ExternalData to the GCHandle. //Then we can new JsExternalObject(m_engine, Context, valueHandle, Engine.GetExternalData(valueHandle)); throw new InvalidOperationException("External Objects must first be created by ..."); } else if (typeof(JsBoolean) == targetType) { result = new JsBoolean(m_engine, Context, valueHandle); } else if (typeof(JsNumber) == targetType) { result = new JsNumber(m_engine, Context, valueHandle); } else if (typeof(JsString) == targetType) { result = new JsString(m_engine, Context, valueHandle); } else if (typeof(JsSymbol) == targetType) { result = new JsSymbol(m_engine, Context, valueHandle); } else if (typeof(JsUndefined) == targetType) { result = new JsUndefined(m_engine, Context, valueHandle); } else if (typeof(JsNull) == targetType) { result = new JsNull(m_engine, Context, valueHandle); } else { throw new InvalidOperationException($"Type {targetType} must subclass JsValue"); } if (result == null) { throw new ArgumentOutOfRangeException(nameof(targetType), $"Unable to create an object of type {targetType}."); } result.BeforeCollect += JsValueBeforeCollectCallback; return result; })); }
/// <summary> /// Returns a new JavaScriptValue for the specified handle querying for the handle's value type. /// </summary> /// <remarks> /// Use the valueType parameter carefully. If the resulting type does not match the handle type unexpected issues may occur. /// </remarks> /// <returns>The JavaScript Value that represents the handle</returns> public JsValue CreateValue(JavaScriptValueSafeHandle valueHandle, JsValueType?valueType = null) { if (valueHandle == JavaScriptValueSafeHandle.Invalid) { return(null); } return(m_valuePool.GetOrAdd(valueHandle, () => { if (valueType.HasValue == false) { valueType = m_engine.JsGetValueType(valueHandle); } JsValue result; switch (valueType.Value) { case JsValueType.Array: result = new JsArray(m_engine, Context, valueHandle); break; case JsValueType.ArrayBuffer: result = new JsArrayBuffer(m_engine, Context, valueHandle); break; case JsValueType.Boolean: result = new JsBoolean(m_engine, Context, valueHandle); break; case JsValueType.DataView: result = new JsDataView(m_engine, Context, valueHandle); break; case JsValueType.Error: result = new JsError(m_engine, Context, valueHandle); break; case JsValueType.Function: result = new JsFunction(m_engine, Context, valueHandle); break; case JsValueType.Null: result = new JsNull(m_engine, Context, valueHandle); break; case JsValueType.Number: result = new JsNumber(m_engine, Context, valueHandle); break; case JsValueType.Object: result = new JsObject(m_engine, Context, valueHandle); break; case JsValueType.String: result = new JsString(m_engine, Context, valueHandle); break; case JsValueType.Symbol: result = new JsSymbol(m_engine, Context, valueHandle); break; case JsValueType.TypedArray: result = new JsTypedArray(m_engine, Context, valueHandle); break; case JsValueType.Undefined: result = new JsUndefined(m_engine, Context, valueHandle); break; default: throw new NotImplementedException($"Error Creating JavaScript Value: The JavaScript Value Type '{valueType}' is unknown, invalid, or has not been implemented."); } result.BeforeCollect += JsValueBeforeCollectCallback; return result; })); }