InteropTests.cs 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Linq.Expressions;
  5. using System.Reflection;
  6. using Jint.Native;
  7. using Jint.Native.Array;
  8. using Jint.Native.Object;
  9. using Jint.Tests.Runtime.Converters;
  10. using Jint.Tests.Runtime.Domain;
  11. using Shapes;
  12. using Xunit;
  13. namespace Jint.Tests.Runtime
  14. {
  15. public class InteropTests : IDisposable
  16. {
  17. private readonly Engine _engine;
  18. public InteropTests()
  19. {
  20. _engine = new Engine(cfg => cfg.AllowClr(
  21. typeof(Shape).GetTypeInfo().Assembly,
  22. typeof(Console).GetTypeInfo().Assembly,
  23. typeof(System.IO.File).GetTypeInfo().Assembly))
  24. .SetValue("log", new Action<object>(Console.WriteLine))
  25. .SetValue("assert", new Action<bool>(Assert.True))
  26. .SetValue("equal", new Action<object, object>(Assert.Equal))
  27. ;
  28. }
  29. void IDisposable.Dispose()
  30. {
  31. }
  32. private void RunTest(string source)
  33. {
  34. _engine.Execute(source);
  35. }
  36. [Fact]
  37. public void PrimitiveTypesCanBeSet()
  38. {
  39. _engine.SetValue("x", 10);
  40. _engine.SetValue("y", true);
  41. _engine.SetValue("z", "foo");
  42. RunTest(@"
  43. assert(x === 10);
  44. assert(y === true);
  45. assert(z === 'foo');
  46. ");
  47. }
  48. [Fact]
  49. public void DelegatesCanBeSet()
  50. {
  51. _engine.SetValue("square", new Func<double, double>(x => x * x));
  52. RunTest(@"
  53. assert(square(10) === 100);
  54. ");
  55. }
  56. [Fact]
  57. public void DelegateWithNullableParameterCanBePassedANull()
  58. {
  59. _engine.SetValue("isnull", new Func<double?, bool>(x => x == null));
  60. RunTest(@"
  61. assert(isnull(null) === true);
  62. ");
  63. }
  64. [Fact]
  65. public void DelegateWithObjectParameterCanBePassedANull()
  66. {
  67. _engine.SetValue("isnull", new Func<object, bool>(x => x == null));
  68. RunTest(@"
  69. assert(isnull(null) === true);
  70. ");
  71. }
  72. [Fact]
  73. public void DelegateWithNullableParameterCanBePassedAnUndefined()
  74. {
  75. _engine.SetValue("isnull", new Func<double?, bool>(x => x == null));
  76. RunTest(@"
  77. assert(isnull(undefined) === true);
  78. ");
  79. }
  80. [Fact]
  81. public void DelegateWithObjectParameterCanBePassedAnUndefined()
  82. {
  83. _engine.SetValue("isnull", new Func<object, bool>(x => x == null));
  84. RunTest(@"
  85. assert(isnull(undefined) === true);
  86. ");
  87. }
  88. [Fact]
  89. public void DelegateWithNullableParameterCanBeExcluded()
  90. {
  91. _engine.SetValue("isnull", new Func<double?, bool>(x => x == null));
  92. RunTest(@"
  93. assert(isnull() === true);
  94. ");
  95. }
  96. [Fact]
  97. public void DelegateWithObjectParameterCanBeExcluded()
  98. {
  99. _engine.SetValue("isnull", new Func<object, bool>(x => x == null));
  100. RunTest(@"
  101. assert(isnull() === true);
  102. ");
  103. }
  104. [Fact]
  105. public void DynamicDelegateCanBeSet()
  106. {
  107. #if NETFRAMEWORK
  108. var parameters = new[] { Expression.Parameter(typeof(int)), Expression.Parameter(typeof(int)) };
  109. var exp = Expression.Add(parameters[0], parameters[1]);
  110. var del = Expression.Lambda(exp, parameters).Compile();
  111. _engine.SetValue("add", del);
  112. RunTest(@"
  113. assert(add(1,1) === 2);
  114. ");
  115. #endif
  116. }
  117. [Fact]
  118. public void ExtraParametersAreIgnored()
  119. {
  120. _engine.SetValue("passNumber", new Func<int, int>(x => x));
  121. RunTest(@"
  122. assert(passNumber(123,'test',{},[],null) === 123);
  123. ");
  124. }
  125. private delegate string callParams(params object[] values);
  126. private delegate string callArgumentAndParams(string firstParam, params object[] values);
  127. [Fact]
  128. public void DelegatesWithParamsParameterCanBeInvoked()
  129. {
  130. var a = new A();
  131. _engine.SetValue("callParams", new callParams(a.Call13));
  132. _engine.SetValue("callArgumentAndParams", new callArgumentAndParams(a.Call14));
  133. RunTest(@"
  134. assert(callParams('1','2','3') === '1,2,3');
  135. assert(callParams('1') === '1');
  136. assert(callParams() === '');
  137. assert(callArgumentAndParams('a','1','2','3') === 'a:1,2,3');
  138. assert(callArgumentAndParams('a','1') === 'a:1');
  139. assert(callArgumentAndParams('a') === 'a:');
  140. assert(callArgumentAndParams() === ':');
  141. ");
  142. }
  143. [Fact]
  144. public void CanGetObjectProperties()
  145. {
  146. var p = new Person
  147. {
  148. Name = "Mickey Mouse"
  149. };
  150. _engine.SetValue("p", p);
  151. RunTest(@"
  152. assert(p.Name === 'Mickey Mouse');
  153. ");
  154. }
  155. [Fact]
  156. public void CanInvokeObjectMethods()
  157. {
  158. var p = new Person
  159. {
  160. Name = "Mickey Mouse"
  161. };
  162. _engine.SetValue("p", p);
  163. RunTest(@"
  164. assert(p.ToString() === 'Mickey Mouse');
  165. ");
  166. }
  167. [Fact]
  168. public void CanInvokeObjectMethodsWithPascalCase()
  169. {
  170. var p = new Person
  171. {
  172. Name = "Mickey Mouse"
  173. };
  174. _engine.SetValue("p", p);
  175. RunTest(@"
  176. assert(p.toString() === 'Mickey Mouse');
  177. ");
  178. }
  179. [Fact]
  180. public void CanSetObjectProperties()
  181. {
  182. var p = new Person
  183. {
  184. Name = "Mickey Mouse"
  185. };
  186. _engine.SetValue("p", p);
  187. RunTest(@"
  188. p.Name = 'Donald Duck';
  189. assert(p.Name === 'Donald Duck');
  190. ");
  191. Assert.Equal("Donald Duck", p.Name);
  192. }
  193. [Fact]
  194. public void CanGetIndexUsingStringKey()
  195. {
  196. var dictionary = new Dictionary<string, Person>();
  197. dictionary.Add("person1", new Person { Name = "Mickey Mouse" });
  198. dictionary.Add("person2", new Person { Name = "Goofy" });
  199. _engine.SetValue("dictionary", dictionary);
  200. RunTest(@"
  201. assert(dictionary['person1'].Name === 'Mickey Mouse');
  202. assert(dictionary['person2'].Name === 'Goofy');
  203. ");
  204. }
  205. [Fact]
  206. public void CanSetIndexUsingStringKey()
  207. {
  208. var dictionary = new Dictionary<string, Person>();
  209. dictionary.Add("person1", new Person { Name = "Mickey Mouse" });
  210. dictionary.Add("person2", new Person { Name = "Goofy" });
  211. _engine.SetValue("dictionary", dictionary);
  212. RunTest(@"
  213. dictionary['person2'].Name = 'Donald Duck';
  214. assert(dictionary['person2'].Name === 'Donald Duck');
  215. ");
  216. Assert.Equal("Donald Duck", dictionary["person2"].Name);
  217. }
  218. [Fact]
  219. public void CanGetIndexUsingIntegerKey()
  220. {
  221. var dictionary = new Dictionary<int, string>();
  222. dictionary.Add(1, "Mickey Mouse");
  223. dictionary.Add(2, "Goofy");
  224. _engine.SetValue("dictionary", dictionary);
  225. RunTest(@"
  226. assert(dictionary[1] === 'Mickey Mouse');
  227. assert(dictionary[2] === 'Goofy');
  228. ");
  229. }
  230. [Fact]
  231. public void CanSetIndexUsingIntegerKey()
  232. {
  233. var dictionary = new Dictionary<int, string>();
  234. dictionary.Add(1, "Mickey Mouse");
  235. dictionary.Add(2, "Goofy");
  236. _engine.SetValue("dictionary", dictionary);
  237. RunTest(@"
  238. dictionary[2] = 'Donald Duck';
  239. assert(dictionary[2] === 'Donald Duck');
  240. ");
  241. Assert.Equal("Mickey Mouse", dictionary[1]);
  242. Assert.Equal("Donald Duck", dictionary[2]);
  243. }
  244. private class DoubleIndexedClass
  245. {
  246. public int this[int index]
  247. {
  248. get { return index; }
  249. }
  250. public string this[string index]
  251. {
  252. get { return index; }
  253. }
  254. }
  255. [Fact]
  256. public void CanGetIndexUsingBothIntAndStringIndex()
  257. {
  258. var dictionary = new DoubleIndexedClass();
  259. _engine.SetValue("dictionary", dictionary);
  260. RunTest(@"
  261. assert(dictionary[1] === 1);
  262. assert(dictionary['test'] === 'test');
  263. ");
  264. }
  265. [Fact]
  266. public void CanUseGenericMethods()
  267. {
  268. var dictionary = new Dictionary<int, string>();
  269. dictionary.Add(1, "Mickey Mouse");
  270. _engine.SetValue("dictionary", dictionary);
  271. RunTest(@"
  272. dictionary.Add(2, 'Goofy');
  273. assert(dictionary[2] === 'Goofy');
  274. ");
  275. Assert.Equal("Mickey Mouse", dictionary[1]);
  276. Assert.Equal("Goofy", dictionary[2]);
  277. }
  278. [Fact]
  279. public void CanUseMultiGenericTypes()
  280. {
  281. RunTest(@"
  282. var type = System.Collections.Generic.Dictionary(System.Int32, System.String);
  283. var dictionary = new type();
  284. dictionary.Add(1, 'Mickey Mouse');
  285. dictionary.Add(2, 'Goofy');
  286. assert(dictionary[2] === 'Goofy');
  287. ");
  288. }
  289. [Fact]
  290. public void CanUseIndexOnCollection()
  291. {
  292. var collection = new System.Collections.ObjectModel.Collection<string>();
  293. collection.Add("Mickey Mouse");
  294. collection.Add("Goofy");
  295. _engine.SetValue("dictionary", collection);
  296. RunTest(@"
  297. dictionary[1] = 'Donald Duck';
  298. assert(dictionary[1] === 'Donald Duck');
  299. ");
  300. Assert.Equal("Mickey Mouse", collection[0]);
  301. Assert.Equal("Donald Duck", collection[1]);
  302. }
  303. [Fact]
  304. public void CanUseIndexOnList()
  305. {
  306. var list = new List<object>(2);
  307. list.Add("Mickey Mouse");
  308. list.Add("Goofy");
  309. _engine.SetValue("list", list);
  310. RunTest(@"
  311. list[1] = 'Donald Duck';
  312. assert(list[1] === 'Donald Duck');
  313. ");
  314. Assert.Equal("Mickey Mouse", list[0]);
  315. Assert.Equal("Donald Duck", list[1]);
  316. }
  317. [Fact]
  318. public void CanAccessAnonymousObject()
  319. {
  320. var p = new
  321. {
  322. Name = "Mickey Mouse",
  323. };
  324. _engine.SetValue("p", p);
  325. RunTest(@"
  326. assert(p.Name === 'Mickey Mouse');
  327. ");
  328. }
  329. [Fact]
  330. public void CanAccessAnonymousObjectProperties()
  331. {
  332. var p = new
  333. {
  334. Address = new
  335. {
  336. City = "Mouseton"
  337. }
  338. };
  339. _engine.SetValue("p", p);
  340. RunTest(@"
  341. assert(p.Address.City === 'Mouseton');
  342. ");
  343. }
  344. [Fact]
  345. public void PocosCanReturnJsValueDirectly()
  346. {
  347. var o = new
  348. {
  349. x = new JsNumber(1),
  350. y = new JsString("string"),
  351. };
  352. _engine.SetValue("o", o);
  353. RunTest(@"
  354. assert(o.x === 1);
  355. assert(o.y === 'string');
  356. ");
  357. }
  358. [Fact]
  359. public void PocosCanReturnObjectInstanceDirectly()
  360. {
  361. var x = new ObjectInstance(_engine) { Extensible = true};
  362. x.Put("foo", new JsString("bar"), false);
  363. var o = new
  364. {
  365. x
  366. };
  367. _engine.SetValue("o", o);
  368. RunTest(@"
  369. assert(o.x.foo === 'bar');
  370. ");
  371. }
  372. [Fact]
  373. public void DateTimeIsConvertedToDate()
  374. {
  375. var o = new
  376. {
  377. z = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)
  378. };
  379. _engine.SetValue("o", o);
  380. RunTest(@"
  381. assert(o.z.valueOf() === 0);
  382. ");
  383. }
  384. [Fact]
  385. public void DateTimeOffsetIsConvertedToDate()
  386. {
  387. var o = new
  388. {
  389. z = new DateTimeOffset(1970, 1, 1, 0, 0, 0, new TimeSpan())
  390. };
  391. _engine.SetValue("o", o);
  392. RunTest(@"
  393. assert(o.z.valueOf() === 0);
  394. ");
  395. }
  396. [Fact]
  397. public void EcmaValuesAreAutomaticallyConvertedWhenSetInPoco()
  398. {
  399. var p = new Person
  400. {
  401. Name = "foo",
  402. };
  403. _engine.SetValue("p", p);
  404. RunTest(@"
  405. assert(p.Name === 'foo');
  406. assert(p.Age === 0);
  407. p.Name = 'bar';
  408. p.Age = 10;
  409. ");
  410. Assert.Equal("bar", p.Name);
  411. Assert.Equal(10, p.Age);
  412. }
  413. [Fact]
  414. public void EcmaValuesAreAutomaticallyConvertedToBestMatchWhenSetInPoco()
  415. {
  416. var p = new Person
  417. {
  418. Name = "foo",
  419. };
  420. _engine.SetValue("p", p);
  421. RunTest(@"
  422. p.Name = 10;
  423. p.Age = '20';
  424. ");
  425. Assert.Equal("10", p.Name);
  426. Assert.Equal(20, p.Age);
  427. }
  428. [Fact]
  429. public void ShouldCallInstanceMethodWithoutArgument()
  430. {
  431. _engine.SetValue("a", new A());
  432. RunTest(@"
  433. assert(a.Call1() === 0);
  434. ");
  435. }
  436. [Fact]
  437. public void ShouldCallInstanceMethodOverloadArgument()
  438. {
  439. _engine.SetValue("a", new A());
  440. RunTest(@"
  441. assert(a.Call1(1) === 1);
  442. ");
  443. }
  444. [Fact]
  445. public void ShouldCallInstanceMethodWithString()
  446. {
  447. var p = new Person();
  448. _engine.SetValue("a", new A());
  449. _engine.SetValue("p", p);
  450. RunTest(@"
  451. p.Name = a.Call2('foo');
  452. assert(p.Name === 'foo');
  453. ");
  454. Assert.Equal("foo", p.Name);
  455. }
  456. [Fact]
  457. public void CanUseTrim()
  458. {
  459. var p = new Person { Name = "Mickey Mouse "};
  460. _engine.SetValue("p", p);
  461. RunTest(@"
  462. assert(p.Name === 'Mickey Mouse ');
  463. p.Name = p.Name.trim();
  464. assert(p.Name === 'Mickey Mouse');
  465. ");
  466. Assert.Equal("Mickey Mouse", p.Name);
  467. }
  468. [Fact]
  469. public void CanUseMathFloor()
  470. {
  471. var p = new Person();
  472. _engine.SetValue("p", p);
  473. RunTest(@"
  474. p.Age = Math.floor(1.6);p
  475. assert(p.Age === 1);
  476. ");
  477. Assert.Equal(1, p.Age);
  478. }
  479. [Fact]
  480. public void CanUseDelegateAsFunction()
  481. {
  482. var even = new Func<int, bool>(x => x % 2 == 0);
  483. _engine.SetValue("even", even);
  484. RunTest(@"
  485. assert(even(2) === true);
  486. ");
  487. }
  488. private class TestClass
  489. {
  490. public int? NullableInt { get; set; }
  491. public DateTime? NullableDate { get; set; }
  492. public bool? NullableBool { get; set; }
  493. }
  494. [Fact]
  495. public void CanSetNullablePropertiesOnPocos()
  496. {
  497. var instance = new TestClass();
  498. _engine.SetValue("instance", instance);
  499. RunTest(@"
  500. instance.NullableInt = 2;
  501. instance.NullableDate = new Date();
  502. instance.NullableBool = true;
  503. assert(instance.NullableInt===2);
  504. assert(instance.NullableDate!=null);
  505. assert(instance.NullableBool===true);
  506. ");
  507. }
  508. [Fact]
  509. public void ShouldConvertArrayToArrayInstance()
  510. {
  511. var result = _engine
  512. .SetValue("values", new[] { 1, 2, 3, 4, 5, 6 })
  513. .Execute("values.filter(function(x){ return x % 2 == 0; })");
  514. var parts = result.GetCompletionValue().ToObject();
  515. Assert.True(parts.GetType().IsArray);
  516. Assert.Equal(3, ((object[])parts).Length);
  517. Assert.Equal(2d, ((object[])parts)[0]);
  518. Assert.Equal(4d, ((object[])parts)[1]);
  519. Assert.Equal(6d, ((object[])parts)[2]);
  520. }
  521. [Fact]
  522. public void ShouldConvertListsToArrayInstance()
  523. {
  524. var result = _engine
  525. .SetValue("values", new List<object> { 1, 2, 3, 4, 5, 6 })
  526. .Execute("new Array(values).filter(function(x){ return x % 2 == 0; })");
  527. var parts = result.GetCompletionValue().ToObject();
  528. Assert.True(parts.GetType().IsArray);
  529. Assert.Equal(3, ((object[])parts).Length);
  530. Assert.Equal(2d, ((object[])parts)[0]);
  531. Assert.Equal(4d, ((object[])parts)[1]);
  532. Assert.Equal(6d, ((object[])parts)[2]);
  533. }
  534. [Fact]
  535. public void ShouldConvertArrayInstanceToArray()
  536. {
  537. var result = _engine.Execute("'[email protected]'.split('@');");
  538. var parts = result.GetCompletionValue().ToObject();
  539. Assert.True(parts.GetType().IsArray);
  540. Assert.Equal(2, ((object[])parts).Length);
  541. Assert.Equal("foo", ((object[])parts)[0]);
  542. Assert.Equal("bar.com", ((object[])parts)[1]);
  543. }
  544. [Fact]
  545. public void ShouldLoopWithNativeEnumerator()
  546. {
  547. JsValue adder(JsValue argValue)
  548. {
  549. ArrayInstance args = argValue.AsArray();
  550. double sum = 0;
  551. foreach (var item in args)
  552. {
  553. if (item.IsNumber())
  554. {
  555. sum += item.AsNumber();
  556. }
  557. }
  558. return sum;
  559. }
  560. var result = _engine.SetValue("getSum", new Func<JsValue, JsValue>(adder))
  561. .Execute("getSum([1,2,3]);");
  562. Assert.True(result.GetCompletionValue() == 6);
  563. }
  564. [Fact]
  565. public void ShouldConvertBooleanInstanceToBool()
  566. {
  567. var result = _engine.Execute("new Boolean(true)");
  568. var value = result.GetCompletionValue().ToObject();
  569. Assert.Equal(typeof(bool), value.GetType());
  570. Assert.Equal(true, value);
  571. }
  572. [Fact]
  573. public void ShouldConvertDateInstanceToDateTime()
  574. {
  575. var result = _engine.Execute("new Date(0)");
  576. var value = result.GetCompletionValue().ToObject();
  577. Assert.Equal(typeof(DateTime), value.GetType());
  578. Assert.Equal(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc), value);
  579. }
  580. [Fact]
  581. public void ShouldConvertNumberInstanceToDouble()
  582. {
  583. var result = _engine.Execute("new Number(10)");
  584. var value = result.GetCompletionValue().ToObject();
  585. Assert.Equal(typeof(double), value.GetType());
  586. Assert.Equal(10d, value);
  587. }
  588. [Fact]
  589. public void ShouldConvertStringInstanceToString()
  590. {
  591. var result = _engine.Execute("new String('foo')");
  592. var value = result.GetCompletionValue().ToObject();
  593. Assert.Equal(typeof(string), value.GetType());
  594. Assert.Equal("foo", value);
  595. }
  596. [Fact]
  597. public void ShouldConvertObjectInstanceToExpando()
  598. {
  599. _engine.Execute("var o = {a: 1, b: 'foo'}");
  600. var result = _engine.GetValue("o");
  601. dynamic value = result.ToObject();
  602. Assert.Equal(1, value.a);
  603. Assert.Equal("foo", value.b);
  604. var dic = (IDictionary<string, object>)result.ToObject();
  605. Assert.Equal(1d, dic["a"]);
  606. Assert.Equal("foo", dic["b"]);
  607. }
  608. [Fact]
  609. public void ShouldNotTryToConvertCompatibleTypes()
  610. {
  611. _engine.SetValue("a", new A());
  612. RunTest(@"
  613. assert(a.Call3('foo') === 'foo');
  614. assert(a.Call3(1) === '1');
  615. ");
  616. }
  617. [Fact]
  618. public void ShouldNotTryToConvertDerivedTypes()
  619. {
  620. _engine.SetValue("a", new A());
  621. _engine.SetValue("p", new Person { Name = "Mickey" });
  622. RunTest(@"
  623. assert(a.Call4(p) === 'Mickey');
  624. ");
  625. }
  626. [Fact]
  627. public void ShouldExecuteFunctionCallBackAsDelegate()
  628. {
  629. _engine.SetValue("a", new A());
  630. RunTest(@"
  631. assert(a.Call5(function(a,b){ return a+b }) === '1foo');
  632. ");
  633. }
  634. [Fact]
  635. public void ShouldExecuteFunctionCallBackAsFuncAndThisCanBeAssigned()
  636. {
  637. _engine.SetValue("a", new A());
  638. RunTest(@"
  639. assert(a.Call6(function(a,b){ return this+a+b }) === 'bar1foo');
  640. ");
  641. }
  642. [Fact]
  643. public void ShouldExecuteFunctionCallBackAsPredicate()
  644. {
  645. _engine.SetValue("a", new A());
  646. // Func<>
  647. RunTest(@"
  648. assert(a.Call8(function(){ return 'foo'; }) === 'foo');
  649. ");
  650. }
  651. [Fact]
  652. public void ShouldExecuteFunctionWithParameterCallBackAsPredicate()
  653. {
  654. _engine.SetValue("a", new A());
  655. // Func<,>
  656. RunTest(@"
  657. assert(a.Call7('foo', function(a){ return a === 'foo'; }) === true);
  658. ");
  659. }
  660. [Fact]
  661. public void ShouldExecuteActionCallBackAsPredicate()
  662. {
  663. _engine.SetValue("a", new A());
  664. // Action
  665. RunTest(@"
  666. var value;
  667. a.Call9(function(){ value = 'foo'; });
  668. assert(value === 'foo');
  669. ");
  670. }
  671. [Fact]
  672. public void ShouldExecuteActionWithParameterCallBackAsPredicate()
  673. {
  674. _engine.SetValue("a", new A());
  675. // Action<>
  676. RunTest(@"
  677. var value;
  678. a.Call10('foo', function(b){ value = b; });
  679. assert(value === 'foo');
  680. ");
  681. }
  682. [Fact]
  683. public void ShouldExecuteActionWithMultipleParametersCallBackAsPredicate()
  684. {
  685. _engine.SetValue("a", new A());
  686. // Action<,>
  687. RunTest(@"
  688. var value;
  689. a.Call11('foo', 'bar', function(a,b){ value = a + b; });
  690. assert(value === 'foobar');
  691. ");
  692. }
  693. [Fact]
  694. public void ShouldExecuteFunc()
  695. {
  696. _engine.SetValue("a", new A());
  697. // Func<int, int>
  698. RunTest(@"
  699. var result = a.Call12(42, function(a){ return a + a; });
  700. assert(result === 84);
  701. ");
  702. }
  703. [Fact]
  704. public void ShouldExecuteActionCallbackOnEventChanged()
  705. {
  706. var collection = new System.Collections.ObjectModel.ObservableCollection<string>();
  707. Assert.True(collection.Count == 0);
  708. _engine.SetValue("collection", collection);
  709. RunTest(@"
  710. var eventAction;
  711. collection.add_CollectionChanged(function(sender, eventArgs) { eventAction = eventArgs.Action; } );
  712. collection.Add('test');
  713. ");
  714. var eventAction = _engine.GetValue("eventAction").AsNumber();
  715. Assert.True(eventAction == 0);
  716. Assert.True(collection.Count == 1);
  717. }
  718. [Fact]
  719. public void ShouldUseSystemIO()
  720. {
  721. RunTest(@"
  722. var filename = System.IO.Path.GetTempFileName();
  723. var sw = System.IO.File.CreateText(filename);
  724. sw.Write('Hello World');
  725. sw.Dispose();
  726. var content = System.IO.File.ReadAllText(filename);
  727. System.Console.WriteLine(content);
  728. assert(content === 'Hello World');
  729. ");
  730. }
  731. [Fact]
  732. public void ShouldBeInstanceOfTypeReferenceType()
  733. {
  734. _engine.SetValue("A", typeof(A));
  735. RunTest(@"
  736. var a = new A();
  737. assert(a instanceof A);
  738. ");
  739. }
  740. [Fact]
  741. public void ShouldImportNamespace()
  742. {
  743. RunTest(@"
  744. var Shapes = importNamespace('Shapes');
  745. var circle = new Shapes.Circle();
  746. assert(circle.Radius === 0);
  747. assert(circle.Perimeter() === 0);
  748. ");
  749. }
  750. [Fact]
  751. public void ShouldConstructReferenceTypeWithParameters()
  752. {
  753. RunTest(@"
  754. var Shapes = importNamespace('Shapes');
  755. var circle = new Shapes.Circle(1);
  756. assert(circle.Radius === 1);
  757. assert(circle.Perimeter() === Math.PI);
  758. ");
  759. }
  760. [Fact]
  761. public void ShouldConstructValueTypeWithoutParameters()
  762. {
  763. RunTest(@"
  764. var guid = new System.Guid();
  765. assert('00000000-0000-0000-0000-000000000000' === guid.ToString());
  766. ");
  767. }
  768. [Fact]
  769. public void ShouldInvokeAFunctionByName()
  770. {
  771. RunTest(@"
  772. function add(x, y) { return x + y; }
  773. ");
  774. Assert.Equal(3, _engine.Invoke("add", 1, 2));
  775. }
  776. [Fact]
  777. public void ShouldNotInvokeNonFunctionValue()
  778. {
  779. RunTest(@"
  780. var x= 10;
  781. ");
  782. Assert.Throws<ArgumentException>(() => _engine.Invoke("x", 1, 2));
  783. }
  784. [Fact]
  785. public void CanGetField()
  786. {
  787. var o = new ClassWithField
  788. {
  789. Field = "Mickey Mouse"
  790. };
  791. _engine.SetValue("o", o);
  792. RunTest(@"
  793. assert(o.Field === 'Mickey Mouse');
  794. ");
  795. }
  796. [Fact]
  797. public void CanSetField()
  798. {
  799. var o = new ClassWithField();
  800. _engine.SetValue("o", o);
  801. RunTest(@"
  802. o.Field = 'Mickey Mouse';
  803. assert(o.Field === 'Mickey Mouse');
  804. ");
  805. Assert.Equal("Mickey Mouse", o.Field);
  806. }
  807. [Fact]
  808. public void CanGetStaticField()
  809. {
  810. RunTest(@"
  811. var domain = importNamespace('Jint.Tests.Runtime.Domain');
  812. var statics = domain.ClassWithStaticFields;
  813. assert(statics.Get == 'Get');
  814. ");
  815. }
  816. [Fact]
  817. public void CanSetStaticField()
  818. {
  819. RunTest(@"
  820. var domain = importNamespace('Jint.Tests.Runtime.Domain');
  821. var statics = domain.ClassWithStaticFields;
  822. statics.Set = 'hello';
  823. assert(statics.Set == 'hello');
  824. ");
  825. Assert.Equal(ClassWithStaticFields.Set, "hello");
  826. }
  827. [Fact]
  828. public void CanGetStaticAccessor()
  829. {
  830. RunTest(@"
  831. var domain = importNamespace('Jint.Tests.Runtime.Domain');
  832. var statics = domain.ClassWithStaticFields;
  833. assert(statics.Getter == 'Getter');
  834. ");
  835. }
  836. [Fact]
  837. public void CanSetStaticAccessor()
  838. {
  839. RunTest(@"
  840. var domain = importNamespace('Jint.Tests.Runtime.Domain');
  841. var statics = domain.ClassWithStaticFields;
  842. statics.Setter = 'hello';
  843. assert(statics.Setter == 'hello');
  844. ");
  845. Assert.Equal(ClassWithStaticFields.Setter, "hello");
  846. }
  847. [Fact]
  848. public void CantSetStaticReadonly()
  849. {
  850. RunTest(@"
  851. var domain = importNamespace('Jint.Tests.Runtime.Domain');
  852. var statics = domain.ClassWithStaticFields;
  853. statics.Readonly = 'hello';
  854. assert(statics.Readonly == 'Readonly');
  855. ");
  856. Assert.Equal(ClassWithStaticFields.Readonly, "Readonly");
  857. }
  858. [Fact]
  859. public void CanSetCustomConverters()
  860. {
  861. var engine1 = new Engine();
  862. engine1.SetValue("p", new { Test = true });
  863. engine1.Execute("var result = p.Test;");
  864. Assert.True((bool)engine1.GetValue("result").ToObject());
  865. var engine2 = new Engine(o => o.AddObjectConverter(new NegateBoolConverter()));
  866. engine2.SetValue("p", new { Test = true });
  867. engine2.Execute("var result = p.Test;");
  868. Assert.False((bool)engine2.GetValue("result").ToObject());
  869. }
  870. [Fact]
  871. public void CanConvertEnumsToString()
  872. {
  873. var engine1 = new Engine(o => o.AddObjectConverter(new EnumsToStringConverter()))
  874. .SetValue("assert", new Action<bool>(Assert.True));
  875. engine1.SetValue("p", new { Comparison = StringComparison.CurrentCulture });
  876. engine1.Execute("assert(p.Comparison === 'CurrentCulture');");
  877. engine1.Execute("var result = p.Comparison;");
  878. Assert.Equal("CurrentCulture", (string)engine1.GetValue("result").ToObject());
  879. }
  880. [Fact]
  881. public void CanUserIncrementOperator()
  882. {
  883. var p = new Person
  884. {
  885. Age = 1,
  886. };
  887. _engine.SetValue("p", p);
  888. RunTest(@"
  889. assert(++p.Age === 2);
  890. ");
  891. Assert.Equal(2, p.Age);
  892. }
  893. [Fact]
  894. public void CanOverwriteValues()
  895. {
  896. _engine.SetValue("x", 3);
  897. _engine.SetValue("x", 4);
  898. RunTest(@"
  899. assert(x === 4);
  900. ");
  901. }
  902. [Fact]
  903. public void ShouldCreateGenericType()
  904. {
  905. RunTest(@"
  906. var ListOfString = System.Collections.Generic.List(System.String);
  907. var list = new ListOfString();
  908. list.Add('foo');
  909. list.Add(1);
  910. assert(2 === list.Count);
  911. ");
  912. }
  913. [Fact]
  914. public void EnumComparesByName()
  915. {
  916. var o = new
  917. {
  918. r = Colors.Red,
  919. b = Colors.Blue,
  920. g = Colors.Green,
  921. b2 = Colors.Red
  922. };
  923. _engine.SetValue("o", o);
  924. _engine.SetValue("assertFalse", new Action<bool>(Assert.False));
  925. RunTest(@"
  926. var domain = importNamespace('Jint.Tests.Runtime.Domain');
  927. var colors = domain.Colors;
  928. assert(o.r === colors.Red);
  929. assert(o.g === colors.Green);
  930. assert(o.b === colors.Blue);
  931. assertFalse(o.b2 === colors.Blue);
  932. ");
  933. }
  934. [Fact]
  935. public void ShouldSetEnumProperty()
  936. {
  937. var s = new Circle
  938. {
  939. Color = Colors.Red,
  940. };
  941. _engine.SetValue("s", s);
  942. RunTest(@"
  943. var domain = importNamespace('Jint.Tests.Runtime.Domain');
  944. var colors = domain.Colors;
  945. s.Color = colors.Blue;
  946. assert(s.Color === colors.Blue);
  947. ");
  948. _engine.SetValue("s", s);
  949. RunTest(@"
  950. s.Color = colors.Blue | colors.Green;
  951. assert(s.Color === colors.Blue | colors.Green);
  952. ");
  953. Assert.Equal(Colors.Blue | Colors.Green, s.Color);
  954. }
  955. [Fact]
  956. public void EnumIsConvertedToNumber()
  957. {
  958. var o = new
  959. {
  960. r = Colors.Red,
  961. b = Colors.Blue,
  962. g = Colors.Green
  963. };
  964. _engine.SetValue("o", o);
  965. RunTest(@"
  966. assert(o.r === 0);
  967. assert(o.g === 1);
  968. assert(o.b === 10);
  969. ");
  970. }
  971. [Fact]
  972. public void ShouldConvertToEnum()
  973. {
  974. var s = new Circle
  975. {
  976. Color = Colors.Red,
  977. };
  978. _engine.SetValue("s", s);
  979. RunTest(@"
  980. assert(s.Color === 0);
  981. s.Color = 10;
  982. assert(s.Color === 10);
  983. ");
  984. _engine.SetValue("s", s);
  985. RunTest(@"
  986. s.Color = 11;
  987. assert(s.Color === 11);
  988. ");
  989. Assert.Equal(Colors.Blue | Colors.Green, s.Color);
  990. }
  991. [Fact]
  992. public void ShouldUseExplicitPropertyGetter()
  993. {
  994. _engine.SetValue("c", new Company("ACME"));
  995. RunTest(@"
  996. assert(c.Name === 'ACME');
  997. ");
  998. }
  999. [Fact]
  1000. public void ShouldUseExplicitIndexerPropertyGetter()
  1001. {
  1002. var company = new Company("ACME");
  1003. ((ICompany)company)["Foo"] = "Bar";
  1004. _engine.SetValue("c", company);
  1005. RunTest(@"
  1006. assert(c.Foo === 'Bar');
  1007. ");
  1008. }
  1009. [Fact]
  1010. public void ShouldUseExplicitPropertySetter()
  1011. {
  1012. _engine.SetValue("c", new Company("ACME"));
  1013. RunTest(@"
  1014. c.Name = 'Foo';
  1015. assert(c.Name === 'Foo');
  1016. ");
  1017. }
  1018. [Fact]
  1019. public void ShouldUseExplicitIndexerPropertySetter()
  1020. {
  1021. var company = new Company("ACME");
  1022. ((ICompany)company)["Foo"] = "Bar";
  1023. _engine.SetValue("c", company);
  1024. RunTest(@"
  1025. c.Foo = 'Baz';
  1026. assert(c.Foo === 'Baz');
  1027. ");
  1028. }
  1029. [Fact]
  1030. public void ShouldUseExplicitMethod()
  1031. {
  1032. _engine.SetValue("c", new Company("ACME"));
  1033. RunTest(@"
  1034. assert(0 === c.CompareTo(c));
  1035. ");
  1036. }
  1037. [Fact]
  1038. public void ShouldCallInstanceMethodWithParams()
  1039. {
  1040. _engine.SetValue("a", new A());
  1041. RunTest(@"
  1042. assert(a.Call13('1','2','3') === '1,2,3');
  1043. assert(a.Call13('1') === '1');
  1044. assert(a.Call13(1) === '1');
  1045. assert(a.Call13() === '');
  1046. assert(a.Call14('a','1','2','3') === 'a:1,2,3');
  1047. assert(a.Call14('a','1') === 'a:1');
  1048. assert(a.Call14('a') === 'a:');
  1049. function call13wrapper(){ return a.Call13.apply(a, Array.prototype.slice.call(arguments)); }
  1050. assert(call13wrapper('1','2','3') === '1,2,3');
  1051. assert(a.Call13('1','2','3') === a.Call13(['1','2','3']));
  1052. ");
  1053. }
  1054. [Fact]
  1055. public void ShouldCallInstanceMethodWithJsValueParams()
  1056. {
  1057. _engine.SetValue("a", new A());
  1058. RunTest(@"
  1059. assert(a.Call16('1','2','3') === '1,2,3');
  1060. assert(a.Call16('1') === '1');
  1061. assert(a.Call16(1) === '1');
  1062. assert(a.Call16() === '');
  1063. assert(a.Call16('1','2','3') === a.Call16(['1','2','3']));
  1064. ");
  1065. }
  1066. [Fact]
  1067. public void NullValueAsArgumentShouldWork()
  1068. {
  1069. _engine.SetValue("a", new A());
  1070. RunTest(@"
  1071. var x = a.Call2(null);
  1072. assert(x === null);
  1073. ");
  1074. }
  1075. [Fact]
  1076. public void ShouldSetPropertyToNull()
  1077. {
  1078. var p = new Person { Name = "Mickey" };
  1079. _engine.SetValue("p", p);
  1080. RunTest(@"
  1081. assert(p.Name != null);
  1082. p.Name = null;
  1083. assert(p.Name == null);
  1084. ");
  1085. Assert.True(p.Name == null);
  1086. }
  1087. [Fact]
  1088. public void ShouldCallMethodWithNull()
  1089. {
  1090. _engine.SetValue("a", new A());
  1091. RunTest(@"
  1092. a.Call15(null);
  1093. var result = a.Call2(null);
  1094. assert(result == null);
  1095. ");
  1096. }
  1097. [Fact]
  1098. public void ShouldReturnUndefinedProperty()
  1099. {
  1100. _engine.SetValue("uo", new { foo = "bar" });
  1101. _engine.SetValue("ud", new Dictionary<string, object> { {"foo", "bar"} });
  1102. _engine.SetValue("ul", new List<string> { "foo", "bar" });
  1103. RunTest(@"
  1104. assert(!uo.undefinedProperty);
  1105. assert(!ul[5]);
  1106. assert(!ud.undefinedProperty);
  1107. ");
  1108. }
  1109. [Fact]
  1110. public void ShouldAutomaticallyConvertArraysToFindBestInteropResulution()
  1111. {
  1112. _engine.SetValue("a", new ArrayConverterTestClass());
  1113. _engine.SetValue("item1", new ArrayConverterItem(1));
  1114. _engine.SetValue("item2", new ArrayConverterItem(2));
  1115. RunTest(@"
  1116. assert(a.MethodAcceptsArrayOfInt([false, '1', 2]) === a.MethodAcceptsArrayOfInt([0, 1, 2]));
  1117. assert(a.MethodAcceptsArrayOfStrings(['1', 2]) === a.MethodAcceptsArrayOfStrings([1, 2]));
  1118. assert(a.MethodAcceptsArrayOfBool(['1', 0]) === a.MethodAcceptsArrayOfBool([true, false]));
  1119. assert(a.MethodAcceptsArrayOfStrings([item1, item2]) === a.MethodAcceptsArrayOfStrings(['1', '2']));
  1120. assert(a.MethodAcceptsArrayOfInt([item1, item2]) === a.MethodAcceptsArrayOfInt([1, 2]));
  1121. ");
  1122. }
  1123. [Fact]
  1124. public void ShouldImportNamespaceNestedType()
  1125. {
  1126. RunTest(@"
  1127. var shapes = importNamespace('Shapes.Circle');
  1128. var kinds = shapes.Kind;
  1129. assert(kinds.Unit === 0);
  1130. assert(kinds.Ellipse === 1);
  1131. assert(kinds.Round === 5);
  1132. ");
  1133. }
  1134. [Fact]
  1135. public void ShouldImportNamespaceNestedNestedType()
  1136. {
  1137. RunTest(@"
  1138. var meta = importNamespace('Shapes.Circle.Meta');
  1139. var usages = meta.Usage;
  1140. assert(usages.Public === 0);
  1141. assert(usages.Private === 1);
  1142. assert(usages.Internal === 11);
  1143. ");
  1144. }
  1145. [Fact]
  1146. public void ShouldGetNestedNestedProp()
  1147. {
  1148. RunTest(@"
  1149. var meta = importNamespace('Shapes.Circle');
  1150. var m = new meta.Meta();
  1151. assert(m.Description === 'descp');
  1152. ");
  1153. }
  1154. [Fact]
  1155. public void ShouldSetNestedNestedProp()
  1156. {
  1157. RunTest(@"
  1158. var meta = importNamespace('Shapes.Circle');
  1159. var m = new meta.Meta();
  1160. m.Description = 'hello';
  1161. assert(m.Description === 'hello');
  1162. ");
  1163. }
  1164. [Fact]
  1165. public void CanGetStaticNestedField()
  1166. {
  1167. RunTest(@"
  1168. var domain = importNamespace('Jint.Tests.Runtime.Domain.Nested');
  1169. var statics = domain.ClassWithStaticFields;
  1170. assert(statics.Get == 'Get');
  1171. ");
  1172. }
  1173. [Fact]
  1174. public void CanSetStaticNestedField()
  1175. {
  1176. RunTest(@"
  1177. var domain = importNamespace('Jint.Tests.Runtime.Domain.Nested');
  1178. var statics = domain.ClassWithStaticFields;
  1179. statics.Set = 'hello';
  1180. assert(statics.Set == 'hello');
  1181. ");
  1182. Assert.Equal(Nested.ClassWithStaticFields.Set, "hello");
  1183. }
  1184. [Fact]
  1185. public void CanGetStaticNestedAccessor()
  1186. {
  1187. RunTest(@"
  1188. var domain = importNamespace('Jint.Tests.Runtime.Domain.Nested');
  1189. var statics = domain.ClassWithStaticFields;
  1190. assert(statics.Getter == 'Getter');
  1191. ");
  1192. }
  1193. [Fact]
  1194. public void CanSetStaticNestedAccessor()
  1195. {
  1196. RunTest(@"
  1197. var domain = importNamespace('Jint.Tests.Runtime.Domain.Nested');
  1198. var statics = domain.ClassWithStaticFields;
  1199. statics.Setter = 'hello';
  1200. assert(statics.Setter == 'hello');
  1201. ");
  1202. Assert.Equal(Nested.ClassWithStaticFields.Setter, "hello");
  1203. }
  1204. [Fact]
  1205. public void CantSetStaticNestedReadonly()
  1206. {
  1207. RunTest(@"
  1208. var domain = importNamespace('Jint.Tests.Runtime.Domain.Nested');
  1209. var statics = domain.ClassWithStaticFields;
  1210. statics.Readonly = 'hello';
  1211. assert(statics.Readonly == 'Readonly');
  1212. ");
  1213. Assert.Equal(Nested.ClassWithStaticFields.Readonly, "Readonly");
  1214. }
  1215. [Fact]
  1216. public void ShouldExecuteFunctionWithValueTypeParameterCorrectly()
  1217. {
  1218. _engine.SetValue("a", new A());
  1219. // Func<int, int>
  1220. RunTest(@"
  1221. assert(a.Call17(function(value){ return value; }) === 17);
  1222. ");
  1223. }
  1224. [Fact]
  1225. public void ShouldExecuteActionWithValueTypeParameterCorrectly()
  1226. {
  1227. _engine.SetValue("a", new A());
  1228. // Action<int>
  1229. RunTest(@"
  1230. a.Call18(function(value){ assert(value === 18); });
  1231. ");
  1232. }
  1233. [Fact]
  1234. public void ShouldConvertToJsValue()
  1235. {
  1236. RunTest(@"
  1237. var now = System.DateTime.Now;
  1238. assert(new String(now) == now.toString());
  1239. var zero = System.Int32.MaxValue;
  1240. assert(new String(zero) == zero.toString());
  1241. ");
  1242. }
  1243. [Fact]
  1244. public void ShouldNotCatchClrExceptions()
  1245. {
  1246. var engine = new Engine()
  1247. .SetValue("throwMyException", new Action(() => { throw new NotSupportedException(); }))
  1248. .SetValue("Thrower", typeof(Thrower))
  1249. .Execute(@"
  1250. function throwException1(){
  1251. try {
  1252. throwMyException();
  1253. return;
  1254. }
  1255. catch(e) {
  1256. return;
  1257. }
  1258. }
  1259. function throwException2(){
  1260. try {
  1261. new Thrower().ThrowNotSupportedException();
  1262. return;
  1263. }
  1264. catch(e) {
  1265. return;
  1266. }
  1267. }
  1268. ");
  1269. Assert.ThrowsAny<NotSupportedException>(() => engine.Invoke("throwException1"));
  1270. Assert.ThrowsAny<NotSupportedException>(() => engine.Invoke("throwException2"));
  1271. }
  1272. [Fact]
  1273. public void ShouldCatchAllClrExceptions()
  1274. {
  1275. string exceptionMessage = "myExceptionMessage";
  1276. var engine = new Engine(o => o.CatchClrExceptions())
  1277. .SetValue("throwMyException", new Action(() => { throw new Exception(exceptionMessage); }))
  1278. .SetValue("Thrower", typeof(Thrower))
  1279. .Execute(@"
  1280. function throwException1(){
  1281. try {
  1282. throwMyException();
  1283. return '';
  1284. }
  1285. catch(e) {
  1286. return e.message;
  1287. }
  1288. }
  1289. function throwException2(){
  1290. try {
  1291. new Thrower().ThrowExceptionWithMessage('myExceptionMessage');
  1292. return;
  1293. }
  1294. catch(e) {
  1295. return e.message;
  1296. }
  1297. }
  1298. ");
  1299. Assert.Equal(engine.Invoke("throwException1").AsString(), exceptionMessage);
  1300. Assert.Equal(engine.Invoke("throwException2").AsString(), exceptionMessage);
  1301. }
  1302. [Fact]
  1303. public void ShouldCatchSomeExceptions()
  1304. {
  1305. string exceptionMessage = "myExceptionMessage";
  1306. var engine = new Engine(o => o.CatchClrExceptions(e => e is NotSupportedException))
  1307. .SetValue("throwMyException1", new Action(() => { throw new NotSupportedException(exceptionMessage); }))
  1308. .SetValue("throwMyException2", new Action(() => { throw new ArgumentNullException(); }))
  1309. .SetValue("Thrower", typeof(Thrower))
  1310. .Execute(@"
  1311. function throwException1(){
  1312. try {
  1313. throwMyException1();
  1314. return '';
  1315. }
  1316. catch(e) {
  1317. return e.message;
  1318. }
  1319. }
  1320. function throwException2(){
  1321. try {
  1322. throwMyException2();
  1323. return '';
  1324. }
  1325. catch(e) {
  1326. return e.message;
  1327. }
  1328. }
  1329. function throwException3(){
  1330. try {
  1331. new Thrower().ThrowNotSupportedExceptionWithMessage('myExceptionMessage');
  1332. return '';
  1333. }
  1334. catch(e) {
  1335. return e.message;
  1336. }
  1337. }
  1338. function throwException4(){
  1339. try {
  1340. new Thrower().ThrowArgumentNullException();
  1341. return '';
  1342. }
  1343. catch(e) {
  1344. return e.message;
  1345. }
  1346. }
  1347. ");
  1348. Assert.Equal(engine.Invoke("throwException1").AsString(), exceptionMessage);
  1349. Assert.Throws<ArgumentNullException>(() => engine.Invoke("throwException2"));
  1350. Assert.Equal(engine.Invoke("throwException3").AsString(), exceptionMessage);
  1351. Assert.Throws<ArgumentNullException>(() => engine.Invoke("throwException4"));
  1352. }
  1353. [Fact]
  1354. public void ArrayFromShouldConvertListToArrayLike()
  1355. {
  1356. var list = new List<Person>
  1357. {
  1358. new Person {Name = "Mike"},
  1359. new Person {Name = "Mika"}
  1360. };
  1361. _engine.SetValue("a", list);
  1362. RunTest(@"
  1363. var arr = new Array(a);
  1364. assert(arr.length === 2);
  1365. assert(arr[0].Name === 'Mike');
  1366. assert(arr[1].Name === 'Mika');
  1367. ");
  1368. RunTest(@"
  1369. var arr = Array.from(a);
  1370. assert(arr.length === 2);
  1371. assert(arr[0].Name === 'Mike');
  1372. assert(arr[1].Name === 'Mika');
  1373. ");
  1374. }
  1375. [Fact]
  1376. public void ArrayFromShouldConvertArrayToArrayLike()
  1377. {
  1378. var list = new []
  1379. {
  1380. new Person {Name = "Mike"},
  1381. new Person {Name = "Mika"}
  1382. };
  1383. _engine.SetValue("a", list);
  1384. RunTest(@"
  1385. var arr = new Array(a);
  1386. assert(arr.length === 2);
  1387. assert(arr[0].Name === 'Mike');
  1388. assert(arr[1].Name === 'Mika');
  1389. ");
  1390. RunTest(@"
  1391. var arr = Array.from(a);
  1392. assert(arr.length === 2);
  1393. assert(arr[0].Name === 'Mike');
  1394. assert(arr[1].Name === 'Mika');
  1395. ");
  1396. }
  1397. [Fact]
  1398. public void ArrayFromShouldConvertIEnumerable()
  1399. {
  1400. var enumerable = new []
  1401. {
  1402. new Person {Name = "Mike"},
  1403. new Person {Name = "Mika"}
  1404. }.Select(x => x);
  1405. _engine.SetValue("a", enumerable);
  1406. RunTest(@"
  1407. var arr = new Array(a);
  1408. assert(arr.length === 2);
  1409. assert(arr[0].Name === 'Mike');
  1410. assert(arr[1].Name === 'Mika');
  1411. ");
  1412. RunTest(@"
  1413. var arr = Array.from(a);
  1414. assert(arr.length === 2);
  1415. assert(arr[0].Name === 'Mike');
  1416. assert(arr[1].Name === 'Mika');
  1417. ");
  1418. }
  1419. }
  1420. }