|
1 | 1 | package jsenv.playwright |
2 | 2 |
|
| 3 | +import cats.effect.IO |
3 | 4 | import cats.effect.unsafe.implicits.global |
4 | | -import cats.effect.{IO, Resource} |
5 | | -import com.microsoft.playwright.BrowserType.LaunchOptions |
6 | 5 | import jsenv.playwright.PWEnv.Config |
7 | | -import jsenv.playwright.PageFactory._ |
8 | | -import jsenv.playwright.ResourcesFactory._ |
9 | | -import org.scalajs.jsenv.{Input, JSComRun, JSRun, RunConfig} |
| 6 | +import org.scalajs.jsenv.Input |
| 7 | +import org.scalajs.jsenv.JSRun |
| 8 | +import org.scalajs.jsenv.RunConfig |
10 | 9 |
|
11 | | -import java.util.concurrent.ConcurrentLinkedQueue |
12 | | -import java.util.concurrent.atomic.AtomicBoolean |
13 | 10 | import scala.concurrent._ |
14 | | -import scala.concurrent.duration.DurationInt |
15 | 11 |
|
16 | 12 | class CERun( |
17 | | - browserName: String, |
18 | | - headless: Boolean, |
19 | | - pwConfig: Config, |
20 | | - runConfig: RunConfig, |
21 | | - input: Seq[Input] |
22 | | -) extends JSRun { |
23 | | - |
24 | | - implicit val ec: scala.concurrent.ExecutionContext = |
25 | | - scala.concurrent.ExecutionContext.global |
26 | | - |
27 | | - // enableCom is false for CERun and true for CEComRun |
28 | | - protected val enableCom = false |
29 | | - protected val intf = "this.scalajsPlayWrightInternalInterface" |
30 | | - protected val sendQueue = new ConcurrentLinkedQueue[String] |
31 | | - // receivedMessage is called only from JSComRun. Hence its implementation is empty in CERun |
32 | | - protected def receivedMessage(msg: String): Unit = () |
33 | | - |
34 | | - /** A Future that completes if the run completes. |
35 | | - * |
36 | | - * The future is failed if the run fails. |
37 | | - * |
38 | | - * Note that a JSRun is not required to ever terminate on it's own. That |
39 | | - * means even if all code is executed and the event loop is empty, the run |
40 | | - * may continue to run. As a consequence, it is *not* correct to rely on |
41 | | - * termination of a JSRun without any external means of stopping it (i.e. |
42 | | - * calling [[close]]). |
43 | | - */ |
44 | | - var wantToClose = new AtomicBoolean(false) |
45 | | - // List of programs |
46 | | - // 1. isInterfaceUp() |
47 | | - // Create PW resource if not created. Create browser,context and page |
48 | | - // 2. Sleep |
49 | | - // 3. wantClose |
50 | | - // 4. sendAll() |
51 | | - // 5. fetchAndProcess() |
52 | | - // 6. Close diver |
53 | | - // 7. Close streams |
54 | | - // 8. Close materializer |
55 | | - // Flow |
56 | | - // if interface is down and dont want to close wait for 100 milliseconds |
57 | | - // interface is up and dont want to close sendAll(), fetchAndProcess() Sleep for 100 milliseconds |
58 | | - // If want to close then close driver, streams, materializer |
59 | | - // After future is completed close driver, streams, materializer |
60 | | - |
61 | | - def jsRunPrg( |
62 | | - browserName: String, |
63 | | - headless: Boolean, |
64 | | - isComEnabled: Boolean, |
65 | | - launchOptions: Option[LaunchOptions] |
66 | | - ): Resource[IO, Unit] = for { |
67 | | - _ <- Resource.pure( |
68 | | - scribe.info( |
69 | | - s"Begin Main with isComEnabled $isComEnabled " + |
70 | | - s"and browserName $browserName " + |
71 | | - s"and headless is $headless " |
72 | | - ) |
73 | | - ) |
74 | | - pageInstance <- createPage( |
75 | | - browserName, |
76 | | - headless, |
77 | | - launchOptions |
78 | | - ) |
79 | | - _ <- preparePageForJsRun( |
80 | | - pageInstance, |
81 | | - materializer(pwConfig), |
82 | | - input, |
83 | | - isComEnabled |
84 | | - ) |
85 | | - connectionReady <- isConnectionUp(pageInstance, intf) |
86 | | - _ <- |
87 | | - if (!connectionReady) Resource.pure[IO, Unit](IO.sleep(100.milliseconds)) |
88 | | - else Resource.pure[IO, Unit](IO.unit) |
89 | | - _ <- isConnectionUp(pageInstance, intf) |
90 | | - out <- outputStream(runConfig) |
91 | | - _ <- processUntilStop( |
92 | | - wantToClose, |
93 | | - pageInstance, |
94 | | - intf, |
95 | | - sendQueue, |
96 | | - out, |
97 | | - receivedMessage, |
98 | | - isComEnabled |
99 | | - ) |
100 | | - } yield () |
101 | | - |
| 13 | + override val browserName: String, |
| 14 | + override val headless: Boolean, |
| 15 | + override val pwConfig: Config, |
| 16 | + override val runConfig: RunConfig, |
| 17 | + override val input: Seq[Input] |
| 18 | +) extends JSRun |
| 19 | + with Runner { |
| 20 | + scribe.debug(s"Creating CERun for $browserName") |
102 | 21 | lazy val future: Future[Unit] = |
103 | | - jsRunPrg(browserName, headless, enableCom, None) |
| 22 | + jsRunPrg(browserName, headless, isComEnabled = false, None) |
104 | 23 | .use(_ => IO.unit) |
105 | 24 | .unsafeToFuture() |
106 | 25 |
|
107 | | - /** Stops the run and releases all the resources. |
108 | | - * |
109 | | - * This <strong>must</strong> be called to ensure the run's resources are |
110 | | - * released. |
111 | | - * |
112 | | - * Whether or not this makes the run fail or not is up to the implementation. |
113 | | - * However, in the following cases, calling [[close]] may not fail the run: |
114 | | - * <ul> <li>[[future]] is already completed when [[close]] is called. |
115 | | - * <li>This is a [[CERun]] and the event loop inside the VM is empty. |
116 | | - * </ul> |
117 | | - * |
118 | | - * Idempotent, async, nothrow. |
119 | | - */ |
120 | | - |
121 | | - override def close(): Unit = { |
122 | | - wantToClose.set(true) |
123 | | - scribe.info(s"StopSignal is ${wantToClose.get()}") |
124 | | - } |
125 | | - |
| 26 | + override protected def receivedMessage(msg: String): Unit = () |
126 | 27 | } |
127 | | -// browserName, headless, pwConfig, runConfig, input, onMessage |
128 | | -class CEComRun( |
129 | | - browserName: String, |
130 | | - headless: Boolean, |
131 | | - pwConfig: Config, |
132 | | - runConfig: RunConfig, |
133 | | - input: Seq[Input], |
134 | | - onMessage: String => Unit |
135 | | -) extends CERun( |
136 | | - browserName, |
137 | | - headless, |
138 | | - pwConfig, |
139 | | - runConfig, |
140 | | - input |
141 | | - ) |
142 | | - with JSComRun { |
143 | | - // enableCom is false for CERun and true for CEComRun |
144 | | - override protected val enableCom = true |
145 | | - // send is called only from JSComRun |
146 | | - override def send(msg: String): Unit = sendQueue.offer(msg) |
147 | | - // receivedMessage is called only from JSComRun. Hence its implementation is empty in CERun |
148 | | - override protected def receivedMessage(msg: String): Unit = onMessage(msg) |
149 | | -} |
150 | | - |
151 | | -private class WindowOnErrorException(errs: List[String]) |
152 | | - extends Exception(s"JS error: $errs") |
0 commit comments