ปลอมวันที่ในแอป Electron
ค้นหาเรื่องนี้แล้วทุกคำตอบจะเป็นเรื่องการแก้โค้ดของคุณเอง - จำลองอ็อบเจกต์ Date หรือใช้ตัวจับเวลาปลอมของเฟรมเวิร์กทดสอบ ไม่มีอะไรเลยช่วยได้เมื่อสิ่งที่คุณมีคือแอปที่บิลด์เสร็จแล้ว เครื่องมือนี้รันแอปที่คุณมีอยู่แล้ว
ทำไมการฉีดจึงไปไม่ถึง
โหมดนี้เกิดขึ้นเพราะความล้มเหลวที่เจาะจงอย่างหนึ่ง ตัวจับเวลาโพโมโดโรที่สร้างบน Electron ถูกรันในเซสชัน x60 แล้วการนับถอยหลังของมันไม่ขยับเลย การแกะบันเดิลของแอปออกดูพบเหตุผลอิสระสองข้อ และไม่มีข้อใดมีทางแก้ในฝั่งเนทีฟ:
- การนับถอยหลังไม่ได้อ่านนาฬิกา มันเป็นตัวนับที่เพิ่มด้วย
setIntervalรันอยู่ใน Web Worker ไม่มีการเรียกเวลาให้ดักเลย เพราะแอปไม่เคยถามว่าตอนนี้กี่โมง - worker นั้นอยู่ในโพรเซสเรนเดอเรอร์แบบแซนด์บ็อกซ์ ซึ่งเป็นที่ที่ไลบรารีที่ฉีดจากภายนอกเข้าไปไม่ถึงพอดี
กลไกฝั่ง Windows จึงช่วยไม่ได้ในกรณีนี้ และคำตอบคือคุยกับเอนจิน JavaScript ของแอปเองแทน
สิ่งที่เกิดขึ้นแทน
แอปถูกเปิดพร้อมพอร์ตดีบักและโปรไฟล์ชั่วคราวที่สะอาด และ API เวลาของมันเองถูกย้ายไปอยู่บนนาฬิกาของเซสชันผ่านโปรโตคอล DevTools - Date.now, ตัวสร้าง new Date(), performance.now, setTimeout และ setInterval
การเขียนทับนี้ถูกติดตั้งในทุกคอนเท็กซ์ที่แอปเปิด รวมถึง Web Worker ของมัน - ซึ่งมักเป็นที่ที่ตัวจับเวลาอยู่จริง และเป็นที่เดียวที่การฉีดแบบเนทีฟไม่มีทางไปถึง
วิธีที่คุณสั่งงานไม่เปลี่ยนเลย คำสั่งเดิม หน้าต่างเดิม แผงเซสชันเดิมที่มีนาฬิกาสองเรือนและผลสรุป
# คำสั่งเดียวกับแอปเนทีฟ - ระบบตรวจจับโหมดให้เอง chrono run "%LOCALAPPDATA%\Programs\your-app\YourApp.exe" --at 2038-01-01T00:00:00 --mode x60
สองข้อจำกัดที่ควรรู้ก่อนเริ่ม
การเปิดแอปแบบนี้รุกล้ำ และตั้งใจบอกตรง ๆ ว่าเป็นเช่นนั้น
แอปถูกเริ่มโดยเปิดพอร์ตดีบักระยะไกลไว้และใช้โปรไฟล์ใหม่ที่แยกต่างหากใต้ %TEMP% - มันไม่ได้รันบนโปรไฟล์จริงของคุณ และไม่ใช่สำเนาที่อยู่ใน system tray อยู่แล้ว โปรไฟล์จะถูกลบเมื่อเซสชันจบ และถ้าลบไม่ได้ สรุปของเซสชันจะบอกไว้ แทนที่จะทิ้งไว้เงียบ ๆ
หากคุณส่ง --user-data-dir หรือ --remote-debugging-port ของตัวเองเข้ามา มันจะถูกปฏิเสธแทนที่จะถูกเขียนทับ เพราะอุบัติเหตุที่เห็นได้ชัด - การชี้เซสชันไปที่โปรไฟล์เบราว์เซอร์จริงของคุณ - ไม่ใช่สิ่งที่ควรปล่อยให้เกิด
หน้าเว็บอ่านเขตเวลาของเซสชัน
ทุกหน้าและทุก worker ถูกวางไว้บนเขตเวลาของเซสชัน ซึ่งเป็นค่าเหลื่อมคงที่ที่ไม่มีเวลาออมแสง และตรวจสอบค่าเหลื่อมที่อ่านได้ ดังนั้นหน้าที่อ่านเขตเวลาอื่นจะถูกรายงาน มีข้อจำกัดสองข้อ คือ Intl เรียกเขตเวลานั้นเป็นค่าเหลื่อมเช่น GMT+02:00 ไม่ใช่ชื่อเมือง และโพรเซสหลักของแอปพลิเคชัน Electron รัน JavaScript ใน Node ซึ่งเซสชันเข้าไม่ถึง จึงใช้นาฬิกาจริงต่อไป รายงานจะบอกเรื่องนี้
อีกเรื่องที่ทำให้คนแปลกใจ: อินเทอร์วัลที่ตั้งไว้แล้วจะคงอัตราเดิมเมื่อคุณเปลี่ยนความเร็วกลางเซสชัน Date.now, new Date() และ performance.now ตอบสนองทันที ส่วน setInterval ที่กำลังรันอยู่ไม่ตอบสนอง และเซสชันจะเตือนเรื่องนี้ แทนที่จะปล่อยให้คุณสรุปว่าการเปลี่ยนไม่ได้ทำอะไร
ทดสอบมาแล้วแค่ไหน
ทดลอง และคำนี้มีความหมายที่กำหนดไว้ที่นี่: มันทำงานได้กับเป้าหมายที่มันถูกสร้างมารองรับ ยังไม่ได้ทดสอบอย่างกว้างขวาง และการตรวจสอบในตัวคือแหล่งความจริงของคุณ ไม่ใช่หน้านี้ มันถูกตรวจสอบด้วยมือ ไม่ใช่ด้วยชุดทดสอบอัตโนมัติ กับแอป Electron จริงบน Windows 64 บิต
ความครอบคลุมรายงานตามคอนเท็กซ์ JavaScript ไม่ใช่ตามโพรเซส เพราะนั่นคือหน่วยที่มีอยู่ที่นี่ แอปที่นิ่งอยู่และไม่เคยถามเวลา จะให้ผลเป็นระบุไม่ได้อย่างตรงไปตรงมา - มันไม่ได้อ่านนาฬิกา จึงอ้างอะไรไม่ได้ว่ามันจะเห็นนาฬิกาที่ถูกต้องหรือไม่ ผลสรุปแต่ละแบบหมายความว่าอะไร →