InteropTests.cs 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362
  1. using System;
  2. using System.Collections.Generic;
  3. using Jint.Native;
  4. using Jint.Native.Object;
  5. using Jint.Tests.Runtime.Converters;
  6. using Jint.Tests.Runtime.Domain;
  7. using Shapes;
  8. using Xunit;
  9. namespace Jint.Tests.Runtime
  10. {
  11. public class InteropTests : IDisposable
  12. {
  13. private readonly Engine _engine;
  14. public InteropTests()
  15. {
  16. _engine = new Engine(cfg => cfg.AllowClr(typeof(Shape).Assembly))
  17. .SetValue("log", new Action<object>(Console.WriteLine))
  18. .SetValue("assert", new Action<bool>(Assert.True))
  19. ;
  20. }
  21. void IDisposable.Dispose()
  22. {
  23. }
  24. private void RunTest(string source)
  25. {
  26. _engine.Execute(source);
  27. }
  28. [Fact]
  29. public void PrimitiveTypesCanBeSet()
  30. {
  31. _engine.SetValue("x", 10);
  32. _engine.SetValue("y", true);
  33. _engine.SetValue("z", "foo");
  34. RunTest(@"
  35. assert(x === 10);
  36. assert(y === true);
  37. assert(z === 'foo');
  38. ");
  39. }
  40. [Fact]
  41. public void DelegatesCanBeSet()
  42. {
  43. _engine.SetValue("square", new Func<double, double>(x => x * x));
  44. RunTest(@"
  45. assert(square(10) === 100);
  46. ");
  47. }
  48. [Fact]
  49. public void DelegateWithNullableParameterCanBePassedANull()
  50. {
  51. _engine.SetValue("isnull", new Func<double?, bool>(x => x == null));
  52. RunTest(@"
  53. assert(isnull(null) === true);
  54. ");
  55. }
  56. [Fact]
  57. public void DelegateWithObjectParameterCanBePassedANull()
  58. {
  59. _engine.SetValue("isnull", new Func<object, bool>(x => x == null));
  60. RunTest(@"
  61. assert(isnull(null) === true);
  62. ");
  63. }
  64. [Fact]
  65. public void DelegateWithNullableParameterCanBePassedAnUndefined()
  66. {
  67. _engine.SetValue("isnull", new Func<double?, bool>(x => x == null));
  68. RunTest(@"
  69. assert(isnull(undefined) === true);
  70. ");
  71. }
  72. [Fact]
  73. public void DelegateWithObjectParameterCanBePassedAnUndefined()
  74. {
  75. _engine.SetValue("isnull", new Func<object, bool>(x => x == null));
  76. RunTest(@"
  77. assert(isnull(undefined) === true);
  78. ");
  79. }
  80. [Fact]
  81. public void DelegateWithNullableParameterCanBeExcluded()
  82. {
  83. _engine.SetValue("isnull", new Func<double?, bool>(x => x == null));
  84. RunTest(@"
  85. assert(isnull() === true);
  86. ");
  87. }
  88. [Fact]
  89. public void DelegateWithObjectParameterCanBeExcluded()
  90. {
  91. _engine.SetValue("isnull", new Func<object, bool>(x => x == null));
  92. RunTest(@"
  93. assert(isnull() === true);
  94. ");
  95. }
  96. [Fact]
  97. public void ExtraParametersAreIgnored()
  98. {
  99. _engine.SetValue("passNumber", new Func<int, int>(x => x));
  100. RunTest(@"
  101. assert(passNumber(123,'test',{},[],null) === 123);
  102. ");
  103. }
  104. private delegate string callParams(params object[] values);
  105. private delegate string callArgumentAndParams(string firstParam, params object[] values);
  106. [Fact]
  107. public void DelegatesWithParamsParameterCanBeInvoked()
  108. {
  109. var a = new A();
  110. _engine.SetValue("callParams", new callParams(a.Call13));
  111. _engine.SetValue("callArgumentAndParams", new callArgumentAndParams(a.Call14));
  112. RunTest(@"
  113. assert(callParams('1','2','3') === '1,2,3');
  114. assert(callParams('1') === '1');
  115. assert(callParams() === '');
  116. assert(callArgumentAndParams('a','1','2','3') === 'a:1,2,3');
  117. assert(callArgumentAndParams('a','1') === 'a:1');
  118. assert(callArgumentAndParams('a') === 'a:');
  119. assert(callArgumentAndParams() === ':');
  120. ");
  121. }
  122. [Fact]
  123. public void CanGetObjectProperties()
  124. {
  125. var p = new Person
  126. {
  127. Name = "Mickey Mouse"
  128. };
  129. _engine.SetValue("p", p);
  130. RunTest(@"
  131. assert(p.Name === 'Mickey Mouse');
  132. ");
  133. }
  134. [Fact]
  135. public void CanInvokeObjectMethods()
  136. {
  137. var p = new Person
  138. {
  139. Name = "Mickey Mouse"
  140. };
  141. _engine.SetValue("p", p);
  142. RunTest(@"
  143. assert(p.ToString() === 'Mickey Mouse');
  144. ");
  145. }
  146. [Fact]
  147. public void CanInvokeObjectMethodsWithPascalCase()
  148. {
  149. var p = new Person
  150. {
  151. Name = "Mickey Mouse"
  152. };
  153. _engine.SetValue("p", p);
  154. RunTest(@"
  155. assert(p.toString() === 'Mickey Mouse');
  156. ");
  157. }
  158. [Fact]
  159. public void CanSetObjectProperties()
  160. {
  161. var p = new Person
  162. {
  163. Name = "Mickey Mouse"
  164. };
  165. _engine.SetValue("p", p);
  166. RunTest(@"
  167. p.Name = 'Donald Duck';
  168. assert(p.Name === 'Donald Duck');
  169. ");
  170. Assert.Equal("Donald Duck", p.Name);
  171. }
  172. [Fact]
  173. public void CanGetIndexUsingStringKey()
  174. {
  175. var dictionary = new Dictionary<string, Person>();
  176. dictionary.Add("person1", new Person { Name = "Mickey Mouse" });
  177. dictionary.Add("person2", new Person { Name = "Goofy" });
  178. _engine.SetValue("dictionary", dictionary);
  179. RunTest(@"
  180. assert(dictionary['person1'].Name === 'Mickey Mouse');
  181. assert(dictionary['person2'].Name === 'Goofy');
  182. ");
  183. }
  184. [Fact]
  185. public void CanSetIndexUsingStringKey()
  186. {
  187. var dictionary = new Dictionary<string, Person>();
  188. dictionary.Add("person1", new Person { Name = "Mickey Mouse" });
  189. dictionary.Add("person2", new Person { Name = "Goofy" });
  190. _engine.SetValue("dictionary", dictionary);
  191. RunTest(@"
  192. dictionary['person2'].Name = 'Donald Duck';
  193. assert(dictionary['person2'].Name === 'Donald Duck');
  194. ");
  195. Assert.Equal("Donald Duck", dictionary["person2"].Name);
  196. }
  197. [Fact]
  198. public void CanGetIndexUsingIntegerKey()
  199. {
  200. var dictionary = new Dictionary<int, string>();
  201. dictionary.Add(1, "Mickey Mouse");
  202. dictionary.Add(2, "Goofy");
  203. _engine.SetValue("dictionary", dictionary);
  204. RunTest(@"
  205. assert(dictionary[1] === 'Mickey Mouse');
  206. assert(dictionary[2] === 'Goofy');
  207. ");
  208. }
  209. [Fact]
  210. public void CanSetIndexUsingIntegerKey()
  211. {
  212. var dictionary = new Dictionary<int, string>();
  213. dictionary.Add(1, "Mickey Mouse");
  214. dictionary.Add(2, "Goofy");
  215. _engine.SetValue("dictionary", dictionary);
  216. RunTest(@"
  217. dictionary[2] = 'Donald Duck';
  218. assert(dictionary[2] === 'Donald Duck');
  219. ");
  220. Assert.Equal("Mickey Mouse", dictionary[1]);
  221. Assert.Equal("Donald Duck", dictionary[2]);
  222. }
  223. [Fact]
  224. public void CanUseGenericMethods()
  225. {
  226. var dictionary = new Dictionary<int, string>();
  227. dictionary.Add(1, "Mickey Mouse");
  228. _engine.SetValue("dictionary", dictionary);
  229. RunTest(@"
  230. dictionary.Add(2, 'Goofy');
  231. assert(dictionary[2] === 'Goofy');
  232. ");
  233. Assert.Equal("Mickey Mouse", dictionary[1]);
  234. Assert.Equal("Goofy", dictionary[2]);
  235. }
  236. [Fact]
  237. public void CanUseMultiGenericTypes()
  238. {
  239. RunTest(@"
  240. var type = System.Collections.Generic.Dictionary(System.Int32, System.String);
  241. var dictionary = new type();
  242. dictionary.Add(1, 'Mickey Mouse');
  243. dictionary.Add(2, 'Goofy');
  244. assert(dictionary[2] === 'Goofy');
  245. ");
  246. }
  247. [Fact]
  248. public void CanUseIndexOnCollection()
  249. {
  250. var collection = new System.Collections.ObjectModel.Collection<string>();
  251. collection.Add("Mickey Mouse");
  252. collection.Add("Goofy");
  253. _engine.SetValue("dictionary", collection);
  254. RunTest(@"
  255. dictionary[1] = 'Donald Duck';
  256. assert(dictionary[1] === 'Donald Duck');
  257. ");
  258. Assert.Equal("Mickey Mouse", collection[0]);
  259. Assert.Equal("Donald Duck", collection[1]);
  260. }
  261. [Fact]
  262. public void CanUseIndexOnList()
  263. {
  264. var arrayList = new System.Collections.ArrayList(2);
  265. arrayList.Add("Mickey Mouse");
  266. arrayList.Add("Goofy");
  267. _engine.SetValue("dictionary", arrayList);
  268. RunTest(@"
  269. dictionary[1] = 'Donald Duck';
  270. assert(dictionary[1] === 'Donald Duck');
  271. ");
  272. Assert.Equal("Mickey Mouse", arrayList[0]);
  273. Assert.Equal("Donald Duck", arrayList[1]);
  274. }
  275. [Fact]
  276. public void CanAccessAnonymousObject()
  277. {
  278. var p = new
  279. {
  280. Name = "Mickey Mouse",
  281. };
  282. _engine.SetValue("p", p);
  283. RunTest(@"
  284. assert(p.Name === 'Mickey Mouse');
  285. ");
  286. }
  287. [Fact]
  288. public void CanAccessAnonymousObjectProperties()
  289. {
  290. var p = new
  291. {
  292. Address = new
  293. {
  294. City = "Mouseton"
  295. }
  296. };
  297. _engine.SetValue("p", p);
  298. RunTest(@"
  299. assert(p.Address.City === 'Mouseton');
  300. ");
  301. }
  302. [Fact]
  303. public void PocosCanReturnJsValueDirectly()
  304. {
  305. var o = new
  306. {
  307. x = new JsValue(1),
  308. y = new JsValue("string"),
  309. };
  310. _engine.SetValue("o", o);
  311. RunTest(@"
  312. assert(o.x === 1);
  313. assert(o.y === 'string');
  314. ");
  315. }
  316. [Fact]
  317. public void PocosCanReturnObjectInstanceDirectly()
  318. {
  319. var x = new ObjectInstance(_engine) { Extensible = true};
  320. x.Put("foo", new JsValue("bar"), false);
  321. var o = new
  322. {
  323. x
  324. };
  325. _engine.SetValue("o", o);
  326. RunTest(@"
  327. assert(o.x.foo === 'bar');
  328. ");
  329. }
  330. [Fact]
  331. public void DateTimeIsConvertedToDate()
  332. {
  333. var o = new
  334. {
  335. z = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)
  336. };
  337. _engine.SetValue("o", o);
  338. RunTest(@"
  339. assert(o.z.valueOf() === 0);
  340. ");
  341. }
  342. [Fact]
  343. public void DateTimeOffsetIsConvertedToDate()
  344. {
  345. var o = new
  346. {
  347. z = new DateTimeOffset(1970, 1, 1, 0, 0, 0, new TimeSpan())
  348. };
  349. _engine.SetValue("o", o);
  350. RunTest(@"
  351. assert(o.z.valueOf() === 0);
  352. ");
  353. }
  354. [Fact]
  355. public void EcmaValuesAreAutomaticallyConvertedWhenSetInPoco()
  356. {
  357. var p = new Person
  358. {
  359. Name = "foo",
  360. };
  361. _engine.SetValue("p", p);
  362. RunTest(@"
  363. assert(p.Name === 'foo');
  364. assert(p.Age === 0);
  365. p.Name = 'bar';
  366. p.Age = 10;
  367. ");
  368. Assert.Equal("bar", p.Name);
  369. Assert.Equal(10, p.Age);
  370. }
  371. [Fact]
  372. public void EcmaValuesAreAutomaticallyConvertedToBestMatchWhenSetInPoco()
  373. {
  374. var p = new Person
  375. {
  376. Name = "foo",
  377. };
  378. _engine.SetValue("p", p);
  379. RunTest(@"
  380. p.Name = 10;
  381. p.Age = '20';
  382. ");
  383. Assert.Equal("10", p.Name);
  384. Assert.Equal(20, p.Age);
  385. }
  386. [Fact]
  387. public void ShouldCallInstanceMethodWithoutArgument()
  388. {
  389. _engine.SetValue("a", new A());
  390. RunTest(@"
  391. assert(a.Call1() === 0);
  392. ");
  393. }
  394. [Fact]
  395. public void ShouldCallInstanceMethodOverloadArgument()
  396. {
  397. _engine.SetValue("a", new A());
  398. RunTest(@"
  399. assert(a.Call1(1) === 1);
  400. ");
  401. }
  402. [Fact]
  403. public void ShouldCallInstanceMethodWithString()
  404. {
  405. var p = new Person();
  406. _engine.SetValue("a", new A());
  407. _engine.SetValue("p", p);
  408. RunTest(@"
  409. p.Name = a.Call2('foo');
  410. assert(p.Name === 'foo');
  411. ");
  412. Assert.Equal("foo", p.Name);
  413. }
  414. [Fact]
  415. public void CanUseTrim()
  416. {
  417. var p = new Person { Name = "Mickey Mouse "};
  418. _engine.SetValue("p", p);
  419. RunTest(@"
  420. assert(p.Name === 'Mickey Mouse ');
  421. p.Name = p.Name.trim();
  422. assert(p.Name === 'Mickey Mouse');
  423. ");
  424. Assert.Equal("Mickey Mouse", p.Name);
  425. }
  426. [Fact]
  427. public void CanUseMathFloor()
  428. {
  429. var p = new Person();
  430. _engine.SetValue("p", p);
  431. RunTest(@"
  432. p.Age = Math.floor(1.6);p
  433. assert(p.Age === 1);
  434. ");
  435. Assert.Equal(1, p.Age);
  436. }
  437. [Fact]
  438. public void CanUseDelegateAsFunction()
  439. {
  440. var even = new Func<int, bool>(x => x % 2 == 0);
  441. _engine.SetValue("even", even);
  442. RunTest(@"
  443. assert(even(2) === true);
  444. ");
  445. }
  446. [Fact]
  447. public void ShouldConvertArrayToArrayInstance()
  448. {
  449. var result = _engine
  450. .SetValue("values", new[] { 1, 2, 3, 4, 5, 6 })
  451. .Execute("values.filter(function(x){ return x % 2 == 0; })");
  452. var parts = result.GetCompletionValue().ToObject();
  453. Assert.True(parts.GetType().IsArray);
  454. Assert.Equal(3, ((object[])parts).Length);
  455. Assert.Equal(2d, ((object[])parts)[0]);
  456. Assert.Equal(4d, ((object[])parts)[1]);
  457. Assert.Equal(6d, ((object[])parts)[2]);
  458. }
  459. [Fact]
  460. public void ShouldConvertListsToArrayInstance()
  461. {
  462. var result = _engine
  463. .SetValue("values", new List<object> { 1, 2, 3, 4, 5, 6 })
  464. .Execute("new Array(values).filter(function(x){ return x % 2 == 0; })");
  465. var parts = result.GetCompletionValue().ToObject();
  466. Assert.True(parts.GetType().IsArray);
  467. Assert.Equal(3, ((object[])parts).Length);
  468. Assert.Equal(2d, ((object[])parts)[0]);
  469. Assert.Equal(4d, ((object[])parts)[1]);
  470. Assert.Equal(6d, ((object[])parts)[2]);
  471. }
  472. [Fact]
  473. public void ShouldConvertArrayInstanceToArray()
  474. {
  475. var result = _engine.Execute("'[email protected]'.split('@');");
  476. var parts = result.GetCompletionValue().ToObject();
  477. Assert.True(parts.GetType().IsArray);
  478. Assert.Equal(2, ((object[])parts).Length);
  479. Assert.Equal("foo", ((object[])parts)[0]);
  480. Assert.Equal("bar.com", ((object[])parts)[1]);
  481. }
  482. [Fact]
  483. public void ShouldConvertBooleanInstanceToBool()
  484. {
  485. var result = _engine.Execute("new Boolean(true)");
  486. var value = result.GetCompletionValue().ToObject();
  487. Assert.Equal(typeof(bool), value.GetType());
  488. Assert.Equal(true, value);
  489. }
  490. [Fact]
  491. public void ShouldConvertDateInstanceToDateTime()
  492. {
  493. var result = _engine.Execute("new Date(0)");
  494. var value = result.GetCompletionValue().ToObject();
  495. Assert.Equal(typeof(DateTime), value.GetType());
  496. Assert.Equal(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc), value);
  497. }
  498. [Fact]
  499. public void ShouldConvertNumberInstanceToDouble()
  500. {
  501. var result = _engine.Execute("new Number(10)");
  502. var value = result.GetCompletionValue().ToObject();
  503. Assert.Equal(typeof(double), value.GetType());
  504. Assert.Equal(10d, value);
  505. }
  506. [Fact]
  507. public void ShouldConvertStringInstanceToString()
  508. {
  509. var result = _engine.Execute("new String('foo')");
  510. var value = result.GetCompletionValue().ToObject();
  511. Assert.Equal(typeof(string), value.GetType());
  512. Assert.Equal("foo", value);
  513. }
  514. [Fact]
  515. public void ShouldConvertObjectInstanceToExpando()
  516. {
  517. _engine.Execute("var o = {a: 1, b: 'foo'}");
  518. var result = _engine.GetValue("o");
  519. dynamic value = result.ToObject();
  520. Assert.Equal(1, value.a);
  521. Assert.Equal("foo", value.b);
  522. var dic = (IDictionary<string, object>)result.ToObject();
  523. Assert.Equal(1d, dic["a"]);
  524. Assert.Equal("foo", dic["b"]);
  525. }
  526. [Fact]
  527. public void ShouldNotTryToConvertCompatibleTypes()
  528. {
  529. _engine.SetValue("a", new A());
  530. RunTest(@"
  531. assert(a.Call3('foo') === 'foo');
  532. assert(a.Call3(1) === '1');
  533. ");
  534. }
  535. [Fact]
  536. public void ShouldNotTryToConvertDerivedTypes()
  537. {
  538. _engine.SetValue("a", new A());
  539. _engine.SetValue("p", new Person { Name = "Mickey" });
  540. RunTest(@"
  541. assert(a.Call4(p) === 'Mickey');
  542. ");
  543. }
  544. [Fact]
  545. public void ShouldExecuteFunctionCallBackAsDelegate()
  546. {
  547. _engine.SetValue("a", new A());
  548. RunTest(@"
  549. assert(a.Call5(function(a,b){ return a+b }) === '1foo');
  550. ");
  551. }
  552. [Fact]
  553. public void ShouldExecuteFunctionCallBackAsFuncAndThisCanBeAssigned()
  554. {
  555. _engine.SetValue("a", new A());
  556. RunTest(@"
  557. assert(a.Call6(function(a,b){ return this+a+b }) === 'bar1foo');
  558. ");
  559. }
  560. [Fact]
  561. public void ShouldExecuteFunctionCallBackAsPredicate()
  562. {
  563. _engine.SetValue("a", new A());
  564. // Func<>
  565. RunTest(@"
  566. assert(a.Call8(function(){ return 'foo'; }) === 'foo');
  567. ");
  568. }
  569. [Fact]
  570. public void ShouldExecuteFunctionWithParameterCallBackAsPredicate()
  571. {
  572. _engine.SetValue("a", new A());
  573. // Func<,>
  574. RunTest(@"
  575. assert(a.Call7('foo', function(a){ return a === 'foo'; }) === true);
  576. ");
  577. }
  578. [Fact]
  579. public void ShouldExecuteActionCallBackAsPredicate()
  580. {
  581. _engine.SetValue("a", new A());
  582. // Action
  583. RunTest(@"
  584. var value;
  585. a.Call9(function(){ value = 'foo'; });
  586. assert(value === 'foo');
  587. ");
  588. }
  589. [Fact]
  590. public void ShouldExecuteActionWithParameterCallBackAsPredicate()
  591. {
  592. _engine.SetValue("a", new A());
  593. // Action<>
  594. RunTest(@"
  595. var value;
  596. a.Call10('foo', function(b){ value = b; });
  597. assert(value === 'foo');
  598. ");
  599. }
  600. [Fact]
  601. public void ShouldExecuteActionWithMultipleParametersCallBackAsPredicate()
  602. {
  603. _engine.SetValue("a", new A());
  604. // Action<,>
  605. RunTest(@"
  606. var value;
  607. a.Call11('foo', 'bar', function(a,b){ value = a + b; });
  608. assert(value === 'foobar');
  609. ");
  610. }
  611. [Fact]
  612. public void ShouldExecuteFunc()
  613. {
  614. _engine.SetValue("a", new A());
  615. // Func<int, int>
  616. RunTest(@"
  617. var result = a.Call12(42, function(a){ return a + a; });
  618. assert(result === 84);
  619. ");
  620. }
  621. [Fact]
  622. public void ShouldExecuteActionCallbackOnEventChanged()
  623. {
  624. var collection = new System.Collections.ObjectModel.ObservableCollection<string>();
  625. Assert.True(collection.Count == 0);
  626. _engine.SetValue("collection", collection);
  627. RunTest(@"
  628. var eventAction;
  629. collection.add_CollectionChanged(function(sender, eventArgs) { eventAction = eventArgs.Action; } );
  630. collection.Add('test');
  631. ");
  632. var eventAction = _engine.GetValue("eventAction").AsNumber();
  633. Assert.True(eventAction == 0);
  634. Assert.True(collection.Count == 1);
  635. }
  636. [Fact]
  637. public void ShouldUseSystemIO()
  638. {
  639. RunTest(@"
  640. var filename = System.IO.Path.GetTempFileName();
  641. var sw = System.IO.File.CreateText(filename);
  642. sw.Write('Hello World');
  643. sw.Dispose();
  644. var content = System.IO.File.ReadAllText(filename);
  645. System.Console.WriteLine(content);
  646. assert(content === 'Hello World');
  647. ");
  648. }
  649. [Fact]
  650. public void ShouldImportNamespace()
  651. {
  652. RunTest(@"
  653. var Shapes = importNamespace('Shapes');
  654. var circle = new Shapes.Circle();
  655. assert(circle.Radius === 0);
  656. assert(circle.Perimeter() === 0);
  657. ");
  658. }
  659. [Fact]
  660. public void ShouldConstructWithParameters()
  661. {
  662. RunTest(@"
  663. var Shapes = importNamespace('Shapes');
  664. var circle = new Shapes.Circle(1);
  665. assert(circle.Radius === 1);
  666. assert(circle.Perimeter() === Math.PI);
  667. ");
  668. }
  669. [Fact]
  670. public void ShouldInvokeAFunctionByName()
  671. {
  672. RunTest(@"
  673. function add(x, y) { return x + y; }
  674. ");
  675. Assert.Equal(3, _engine.Invoke("add", 1, 2));
  676. }
  677. [Fact]
  678. public void ShouldNotInvokeNonFunctionValue()
  679. {
  680. RunTest(@"
  681. var x= 10;
  682. ");
  683. Assert.Throws<ArgumentException>(() => _engine.Invoke("x", 1, 2));
  684. }
  685. [Fact]
  686. public void CanGetField()
  687. {
  688. var o = new ClassWithField
  689. {
  690. Field = "Mickey Mouse"
  691. };
  692. _engine.SetValue("o", o);
  693. RunTest(@"
  694. assert(o.Field === 'Mickey Mouse');
  695. ");
  696. }
  697. [Fact]
  698. public void CanSetField()
  699. {
  700. var o = new ClassWithField();
  701. _engine.SetValue("o", o);
  702. RunTest(@"
  703. o.Field = 'Mickey Mouse';
  704. assert(o.Field === 'Mickey Mouse');
  705. ");
  706. Assert.Equal("Mickey Mouse", o.Field);
  707. }
  708. [Fact]
  709. public void CanGetStaticField()
  710. {
  711. RunTest(@"
  712. var domain = importNamespace('Jint.Tests.Runtime.Domain');
  713. var statics = domain.ClassWithStaticFields;
  714. assert(statics.Get == 'Get');
  715. ");
  716. }
  717. [Fact]
  718. public void CanSetStaticField()
  719. {
  720. RunTest(@"
  721. var domain = importNamespace('Jint.Tests.Runtime.Domain');
  722. var statics = domain.ClassWithStaticFields;
  723. statics.Set = 'hello';
  724. assert(statics.Set == 'hello');
  725. ");
  726. Assert.Equal(ClassWithStaticFields.Set, "hello");
  727. }
  728. [Fact]
  729. public void CanGetStaticAccessor()
  730. {
  731. RunTest(@"
  732. var domain = importNamespace('Jint.Tests.Runtime.Domain');
  733. var statics = domain.ClassWithStaticFields;
  734. assert(statics.Getter == 'Getter');
  735. ");
  736. }
  737. [Fact]
  738. public void CanSetStaticAccessor()
  739. {
  740. RunTest(@"
  741. var domain = importNamespace('Jint.Tests.Runtime.Domain');
  742. var statics = domain.ClassWithStaticFields;
  743. statics.Setter = 'hello';
  744. assert(statics.Setter == 'hello');
  745. ");
  746. Assert.Equal(ClassWithStaticFields.Setter, "hello");
  747. }
  748. [Fact]
  749. public void CantSetStaticReadonly()
  750. {
  751. RunTest(@"
  752. var domain = importNamespace('Jint.Tests.Runtime.Domain');
  753. var statics = domain.ClassWithStaticFields;
  754. statics.Readonly = 'hello';
  755. assert(statics.Readonly == 'Readonly');
  756. ");
  757. Assert.Equal(ClassWithStaticFields.Readonly, "Readonly");
  758. }
  759. [Fact]
  760. public void CanSetCustomConverters()
  761. {
  762. var engine1 = new Engine();
  763. engine1.SetValue("p", new { Test = true });
  764. engine1.Execute("var result = p.Test;");
  765. Assert.True((bool)engine1.GetValue("result").ToObject());
  766. var engine2 = new Engine(o => o.AddObjectConverter(new NegateBoolConverter()));
  767. engine2.SetValue("p", new { Test = true });
  768. engine2.Execute("var result = p.Test;");
  769. Assert.False((bool)engine2.GetValue("result").ToObject());
  770. }
  771. [Fact]
  772. public void CanUserIncrementOperator()
  773. {
  774. var p = new Person
  775. {
  776. Age = 1,
  777. };
  778. _engine.SetValue("p", p);
  779. RunTest(@"
  780. assert(++p.Age === 2);
  781. ");
  782. Assert.Equal(2, p.Age);
  783. }
  784. [Fact]
  785. public void CanOverwriteValues()
  786. {
  787. _engine.SetValue("x", 3);
  788. _engine.SetValue("x", 4);
  789. RunTest(@"
  790. assert(x === 4);
  791. ");
  792. }
  793. [Fact]
  794. public void ShouldCreateGenericType()
  795. {
  796. RunTest(@"
  797. var ListOfString = System.Collections.Generic.List(System.String);
  798. var list = new ListOfString();
  799. list.Add('foo');
  800. list.Add(1);
  801. assert(2 === list.Count);
  802. ");
  803. }
  804. [Fact]
  805. public void EnumComparesByName()
  806. {
  807. var o = new
  808. {
  809. r = Colors.Red,
  810. b = Colors.Blue,
  811. g = Colors.Green,
  812. b2 = Colors.Red
  813. };
  814. _engine.SetValue("o", o);
  815. _engine.SetValue("assertFalse", new Action<bool>(Assert.False));
  816. RunTest(@"
  817. var domain = importNamespace('Jint.Tests.Runtime.Domain');
  818. var colors = domain.Colors;
  819. assert(o.r === colors.Red);
  820. assert(o.g === colors.Green);
  821. assert(o.b === colors.Blue);
  822. assertFalse(o.b2 === colors.Blue);
  823. ");
  824. }
  825. [Fact]
  826. public void ShouldSetEnumProperty()
  827. {
  828. var s = new Circle
  829. {
  830. Color = Colors.Red,
  831. };
  832. _engine.SetValue("s", s);
  833. RunTest(@"
  834. var domain = importNamespace('Jint.Tests.Runtime.Domain');
  835. var colors = domain.Colors;
  836. s.Color = colors.Blue;
  837. assert(s.Color === colors.Blue);
  838. ");
  839. _engine.SetValue("s", s);
  840. RunTest(@"
  841. s.Color = colors.Blue | colors.Green;
  842. assert(s.Color === colors.Blue | colors.Green);
  843. ");
  844. Assert.Equal(Colors.Blue | Colors.Green, s.Color);
  845. }
  846. [Fact]
  847. public void EnumIsConvertedToNumber()
  848. {
  849. var o = new
  850. {
  851. r = Colors.Red,
  852. b = Colors.Blue,
  853. g = Colors.Green
  854. };
  855. _engine.SetValue("o", o);
  856. RunTest(@"
  857. assert(o.r === 0);
  858. assert(o.g === 1);
  859. assert(o.b === 10);
  860. ");
  861. }
  862. [Fact]
  863. public void ShouldConvertToEnum()
  864. {
  865. var s = new Circle
  866. {
  867. Color = Colors.Red,
  868. };
  869. _engine.SetValue("s", s);
  870. RunTest(@"
  871. assert(s.Color === 0);
  872. s.Color = 10;
  873. assert(s.Color === 10);
  874. ");
  875. _engine.SetValue("s", s);
  876. RunTest(@"
  877. s.Color = 11;
  878. assert(s.Color === 11);
  879. ");
  880. Assert.Equal(Colors.Blue | Colors.Green, s.Color);
  881. }
  882. [Fact]
  883. public void ShouldUseExplicitPropertyGetter()
  884. {
  885. _engine.SetValue("c", new Company("ACME"));
  886. RunTest(@"
  887. assert(c.Name === 'ACME');
  888. ");
  889. }
  890. [Fact]
  891. public void ShouldUseExplicitIndexerPropertyGetter()
  892. {
  893. var company = new Company("ACME");
  894. ((ICompany)company)["Foo"] = "Bar";
  895. _engine.SetValue("c", company);
  896. RunTest(@"
  897. assert(c.Foo === 'Bar');
  898. ");
  899. }
  900. [Fact]
  901. public void ShouldUseExplicitPropertySetter()
  902. {
  903. _engine.SetValue("c", new Company("ACME"));
  904. RunTest(@"
  905. c.Name = 'Foo';
  906. assert(c.Name === 'Foo');
  907. ");
  908. }
  909. [Fact]
  910. public void ShouldUseExplicitIndexerPropertySetter()
  911. {
  912. var company = new Company("ACME");
  913. ((ICompany)company)["Foo"] = "Bar";
  914. _engine.SetValue("c", company);
  915. RunTest(@"
  916. c.Foo = 'Baz';
  917. assert(c.Foo === 'Baz');
  918. ");
  919. }
  920. [Fact]
  921. public void ShouldUseExplicitMethod()
  922. {
  923. _engine.SetValue("c", new Company("ACME"));
  924. RunTest(@"
  925. assert(0 === c.CompareTo(c));
  926. ");
  927. }
  928. [Fact]
  929. public void ShouldCallInstanceMethodWithParams()
  930. {
  931. _engine.SetValue("a", new A());
  932. RunTest(@"
  933. assert(a.Call13('1','2','3') === '1,2,3');
  934. assert(a.Call13('1') === '1');
  935. assert(a.Call13(1) === '1');
  936. assert(a.Call13() === '');
  937. assert(a.Call14('a','1','2','3') === 'a:1,2,3');
  938. assert(a.Call14('a','1') === 'a:1');
  939. assert(a.Call14('a') === 'a:');
  940. function call13wrapper(){ return a.Call13.apply(a, Array.prototype.slice.call(arguments)); }
  941. assert(call13wrapper('1','2','3') === '1,2,3');
  942. assert(a.Call13('1','2','3') === a.Call13(['1','2','3']));
  943. ");
  944. }
  945. [Fact]
  946. public void ShouldCallInstanceMethodWithJsValueParams()
  947. {
  948. _engine.SetValue("a", new A());
  949. RunTest(@"
  950. assert(a.Call16('1','2','3') === '1,2,3');
  951. assert(a.Call16('1') === '1');
  952. assert(a.Call16(1) === '1');
  953. assert(a.Call16() === '');
  954. assert(a.Call16('1','2','3') === a.Call16(['1','2','3']));
  955. ");
  956. }
  957. [Fact]
  958. public void NullValueAsArgumentShouldWork()
  959. {
  960. _engine.SetValue("a", new A());
  961. RunTest(@"
  962. var x = a.Call2(null);
  963. assert(x === null);
  964. ");
  965. }
  966. [Fact]
  967. public void ShouldSetPropertyToNull()
  968. {
  969. var p = new Person { Name = "Mickey" };
  970. _engine.SetValue("p", p);
  971. RunTest(@"
  972. assert(p.Name != null);
  973. p.Name = null;
  974. assert(p.Name == null);
  975. ");
  976. Assert.True(p.Name == null);
  977. }
  978. [Fact]
  979. public void ShouldCallMethodWithNull()
  980. {
  981. _engine.SetValue("a", new A());
  982. RunTest(@"
  983. a.Call15(null);
  984. var result = a.Call2(null);
  985. assert(result == null);
  986. ");
  987. }
  988. [Fact]
  989. public void ShouldReturnUndefinedProperty()
  990. {
  991. _engine.SetValue("uo", new { foo = "bar" });
  992. _engine.SetValue("ud", new Dictionary<string, object>() { {"foo", "bar"} });
  993. _engine.SetValue("ul", new List<string>() { "foo", "bar" });
  994. RunTest(@"
  995. assert(!uo.undefinedProperty);
  996. assert(!ul[5]);
  997. assert(!ud.undefinedProperty);
  998. ");
  999. }
  1000. [Fact]
  1001. public void ShouldAutomaticallyConvertArraysToFindBestInteropResulution()
  1002. {
  1003. _engine.SetValue("a", new ArrayConverterTestClass());
  1004. _engine.SetValue("item1", new ArrayConverterItem(1));
  1005. _engine.SetValue("item2", new ArrayConverterItem(2));
  1006. RunTest(@"
  1007. assert(a.MethodAcceptsArrayOfInt([false, '1', 2]) === a.MethodAcceptsArrayOfInt([0, 1, 2]));
  1008. assert(a.MethodAcceptsArrayOfStrings(['1', 2]) === a.MethodAcceptsArrayOfStrings([1, 2]));
  1009. assert(a.MethodAcceptsArrayOfBool(['1', 0]) === a.MethodAcceptsArrayOfBool([true, false]));
  1010. assert(a.MethodAcceptsArrayOfStrings([item1, item2]) === a.MethodAcceptsArrayOfStrings(['1', '2']));
  1011. assert(a.MethodAcceptsArrayOfInt([item1, item2]) === a.MethodAcceptsArrayOfInt([1, 2]));
  1012. ");
  1013. }
  1014. [Fact]
  1015. public void ShouldImportNamespaceNestedType()
  1016. {
  1017. RunTest(@"
  1018. var shapes = importNamespace('Shapes.Circle');
  1019. var kinds = shapes.Kind;
  1020. assert(kinds.Unit === 0);
  1021. assert(kinds.Ellipse === 1);
  1022. assert(kinds.Round === 5);
  1023. ");
  1024. }
  1025. [Fact]
  1026. public void ShouldImportNamespaceNestedNestedType()
  1027. {
  1028. RunTest(@"
  1029. var meta = importNamespace('Shapes.Circle.Meta');
  1030. var usages = meta.Usage;
  1031. assert(usages.Public === 0);
  1032. assert(usages.Private === 1);
  1033. assert(usages.Internal === 11);
  1034. ");
  1035. }
  1036. [Fact]
  1037. public void ShouldGetNestedNestedProp()
  1038. {
  1039. RunTest(@"
  1040. var meta = importNamespace('Shapes.Circle');
  1041. var m = new meta.Meta();
  1042. assert(m.Description === 'descp');
  1043. ");
  1044. }
  1045. [Fact]
  1046. public void ShouldSetNestedNestedProp()
  1047. {
  1048. RunTest(@"
  1049. var meta = importNamespace('Shapes.Circle');
  1050. var m = new meta.Meta();
  1051. m.Description = 'hello';
  1052. assert(m.Description === 'hello');
  1053. ");
  1054. }
  1055. [Fact]
  1056. public void CanGetStaticNestedField()
  1057. {
  1058. RunTest(@"
  1059. var domain = importNamespace('Jint.Tests.Runtime.Domain.Nested');
  1060. var statics = domain.ClassWithStaticFields;
  1061. assert(statics.Get == 'Get');
  1062. ");
  1063. }
  1064. [Fact]
  1065. public void CanSetStaticNestedField()
  1066. {
  1067. RunTest(@"
  1068. var domain = importNamespace('Jint.Tests.Runtime.Domain.Nested');
  1069. var statics = domain.ClassWithStaticFields;
  1070. statics.Set = 'hello';
  1071. assert(statics.Set == 'hello');
  1072. ");
  1073. Assert.Equal(Nested.ClassWithStaticFields.Set, "hello");
  1074. }
  1075. [Fact]
  1076. public void CanGetStaticNestedAccessor()
  1077. {
  1078. RunTest(@"
  1079. var domain = importNamespace('Jint.Tests.Runtime.Domain.Nested');
  1080. var statics = domain.ClassWithStaticFields;
  1081. assert(statics.Getter == 'Getter');
  1082. ");
  1083. }
  1084. [Fact]
  1085. public void CanSetStaticNestedAccessor()
  1086. {
  1087. RunTest(@"
  1088. var domain = importNamespace('Jint.Tests.Runtime.Domain.Nested');
  1089. var statics = domain.ClassWithStaticFields;
  1090. statics.Setter = 'hello';
  1091. assert(statics.Setter == 'hello');
  1092. ");
  1093. Assert.Equal(Nested.ClassWithStaticFields.Setter, "hello");
  1094. }
  1095. [Fact]
  1096. public void CantSetStaticNestedReadonly()
  1097. {
  1098. RunTest(@"
  1099. var domain = importNamespace('Jint.Tests.Runtime.Domain.Nested');
  1100. var statics = domain.ClassWithStaticFields;
  1101. statics.Readonly = 'hello';
  1102. assert(statics.Readonly == 'Readonly');
  1103. ");
  1104. Assert.Equal(Nested.ClassWithStaticFields.Readonly, "Readonly");
  1105. }
  1106. }
  1107. }