@swf2es/player-hosts 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/LICENSE.third-party +759 -0
- package/README.md +43 -2
- package/dist/indexeddb.d.ts +27 -0
- package/dist/indexeddb.d.ts.map +1 -0
- package/dist/indexeddb.js +170 -0
- package/dist/indexeddb.js.map +1 -0
- package/dist/node-worker.d.ts +2 -0
- package/dist/node-worker.d.ts.map +1 -0
- package/dist/node-worker.js +12 -0
- package/dist/node-worker.js.map +1 -0
- package/dist/node.d.ts +8 -0
- package/dist/node.d.ts.map +1 -0
- package/dist/node.js +43 -0
- package/dist/node.js.map +1 -0
- package/dist/precompiled.d.ts +31 -0
- package/dist/precompiled.d.ts.map +1 -0
- package/dist/precompiled.js +125 -0
- package/dist/precompiled.js.map +1 -0
- package/dist/stage3d.d.ts +13 -0
- package/dist/stage3d.d.ts.map +1 -0
- package/dist/stage3d.js +61 -0
- package/dist/stage3d.js.map +1 -0
- package/dist/thread/codegen/codegen.js +308 -0
- package/dist/thread/codegen/index.js +405 -0
- package/dist/thread/format/abc-names.js +126 -0
- package/dist/thread/format/actions.js +222 -0
- package/dist/thread/format/air-descriptor.js +63 -0
- package/dist/thread/format/api-versions.js +22 -0
- package/dist/thread/format/bitmap.js +199 -0
- package/dist/thread/format/button.js +60 -0
- package/dist/thread/format/compression.js +200 -0
- package/dist/thread/format/display.js +305 -0
- package/dist/thread/format/filters.js +136 -0
- package/dist/thread/format/font.js +168 -0
- package/dist/thread/format/index.js +26 -0
- package/dist/thread/format/pbj.js +484 -0
- package/dist/thread/format/shape.js +411 -0
- package/dist/thread/format/sound.js +91 -0
- package/dist/thread/format/swf.js +163 -0
- package/dist/thread/format/tags.js +58 -0
- package/dist/thread/format/text.js +135 -0
- package/dist/thread/format/zip.js +91 -0
- package/dist/thread/native/audio/binary.js +3 -0
- package/dist/thread/native/audio/index.js +72 -0
- package/dist/thread/native/base64.js +9 -0
- package/dist/thread/native/compress/binary.js +3 -0
- package/dist/thread/native/compress/index.js +145 -0
- package/dist/thread/native/instance.js +49 -0
- package/dist/thread/native/mp3/binary.js +3 -0
- package/dist/thread/native/mp3/index.js +48 -0
- package/dist/thread/native/render/binary.js +3 -0
- package/dist/thread/native/render/bitmap-kernel.js +591 -0
- package/dist/thread/native/render/draw-kernel.js +204 -0
- package/dist/thread/native/render/dxt-encoder.js +94 -0
- package/dist/thread/native/render/index.js +10 -0
- package/dist/thread/native/render/lines.js +122 -0
- package/dist/thread/native/render/module.js +26 -0
- package/dist/thread/native/render/pixel-ops.js +235 -0
- package/dist/thread/native/render/tessellator.js +250 -0
- package/dist/thread/player/avm1/amf.js +507 -0
- package/dist/thread/player/avm1/avm1.js +1304 -0
- package/dist/thread/player/avm1/bindings.js +214 -0
- package/dist/thread/player/avm1/classes.js +75 -0
- package/dist/thread/player/avm1/clips.js +229 -0
- package/dist/thread/player/avm1/compile.js +140 -0
- package/dist/thread/player/avm1/external.js +79 -0
- package/dist/thread/player/avm1/focus.js +278 -0
- package/dist/thread/player/avm1/globals/BitmapData.js +542 -0
- package/dist/thread/player/avm1/globals/Button.js +31 -0
- package/dist/thread/player/avm1/globals/Color.js +115 -0
- package/dist/thread/player/avm1/globals/ExternalInterface.js +310 -0
- package/dist/thread/player/avm1/globals/FileReference.js +217 -0
- package/dist/thread/player/avm1/globals/Key.js +60 -0
- package/dist/thread/player/avm1/globals/LoadVars.js +208 -0
- package/dist/thread/player/avm1/globals/LocalConnection.js +92 -0
- package/dist/thread/player/avm1/globals/MovieClip.js +1070 -0
- package/dist/thread/player/avm1/globals/MovieClipLoader.js +90 -0
- package/dist/thread/player/avm1/globals/NetConnection.js +261 -0
- package/dist/thread/player/avm1/globals/PrintJob.js +37 -0
- package/dist/thread/player/avm1/globals/Selection.js +62 -0
- package/dist/thread/player/avm1/globals/SharedObject.js +245 -0
- package/dist/thread/player/avm1/globals/Sound.js +238 -0
- package/dist/thread/player/avm1/globals/Stage.js +12 -0
- package/dist/thread/player/avm1/globals/StyleSheet.js +205 -0
- package/dist/thread/player/avm1/globals/TextField.js +396 -0
- package/dist/thread/player/avm1/globals/TextFormat.js +194 -0
- package/dist/thread/player/avm1/globals/TextSnapshot.js +88 -0
- package/dist/thread/player/avm1/globals/XML.js +396 -0
- package/dist/thread/player/avm1/globals/XMLNode.js +413 -0
- package/dist/thread/player/avm1/globals/XMLSocket.js +205 -0
- package/dist/thread/player/avm1/globals/drawing.js +202 -0
- package/dist/thread/player/avm1/globals/filters.js +635 -0
- package/dist/thread/player/avm1/globals/geom.js +600 -0
- package/dist/thread/player/avm1/input.js +483 -0
- package/dist/thread/player/avm1/keyboard.js +113 -0
- package/dist/thread/player/avm1/loads.js +352 -0
- package/dist/thread/player/avm1/net.js +219 -0
- package/dist/thread/player/avm1/paths.js +104 -0
- package/dist/thread/player/avm1/pointer.js +512 -0
- package/dist/thread/player/avm1/queue.js +303 -0
- package/dist/thread/player/avm1/sound.js +106 -0
- package/dist/thread/player/avm1/swf.js +141 -0
- package/dist/thread/player/avm1/timers.js +113 -0
- package/dist/thread/player/bitmap/bitmap.js +627 -0
- package/dist/thread/player/bitmap/draw.js +68 -0
- package/dist/thread/player/bitmap/dxt.js +11 -0
- package/dist/thread/player/bitmap/filters.js +656 -0
- package/dist/thread/player/bitmap/images.js +240 -0
- package/dist/thread/player/bitmap/kernel.js +65 -0
- package/dist/thread/player/bitmap/ops.js +1239 -0
- package/dist/thread/player/bitmap/pixel-bender.js +911 -0
- package/dist/thread/player/bitmap/png.js +139 -0
- package/dist/thread/player/bitmap/turbulence.js +89 -0
- package/dist/thread/player/clock.js +182 -0
- package/dist/thread/player/display/bitmapobject.js +25 -0
- package/dist/thread/player/display/bounds.js +520 -0
- package/dist/thread/player/display/buttonobject.js +305 -0
- package/dist/thread/player/display/color.js +40 -0
- package/dist/thread/player/display/container.js +150 -0
- package/dist/thread/player/display/display.js +14 -0
- package/dist/thread/player/display/displayobject.js +664 -0
- package/dist/thread/player/display/drawing.js +613 -0
- package/dist/thread/player/display/filters.js +285 -0
- package/dist/thread/player/display/geometry.js +189 -0
- package/dist/thread/player/display/gradients.js +117 -0
- package/dist/thread/player/display/graphicsdata.js +592 -0
- package/dist/thread/player/display/instantiate.js +71 -0
- package/dist/thread/player/display/matrix3d.js +373 -0
- package/dist/thread/player/display/morph.js +226 -0
- package/dist/thread/player/display/movieclip.js +680 -0
- package/dist/thread/player/display/perspective.js +193 -0
- package/dist/thread/player/display/scale9.js +236 -0
- package/dist/thread/player/display/shapeobject.js +131 -0
- package/dist/thread/player/display/shapes.js +407 -0
- package/dist/thread/player/display/textobjects.js +222 -0
- package/dist/thread/player/display/timeline.js +471 -0
- package/dist/thread/player/display/value-lists.js +40 -0
- package/dist/thread/player/display/videoobject.js +6 -0
- package/dist/thread/player/display/walk.js +127 -0
- package/dist/thread/player/files.js +334 -0
- package/dist/thread/player/hosts.js +207 -0
- package/dist/thread/player/input/avm1.js +82 -0
- package/dist/thread/player/input/context-menu.js +63 -0
- package/dist/thread/player/input/keyboard.js +458 -0
- package/dist/thread/player/input/pointer.js +863 -0
- package/dist/thread/player/input/text-editor.js +319 -0
- package/dist/thread/player/input/touch.js +209 -0
- package/dist/thread/player/localconnection.js +90 -0
- package/dist/thread/player/media/audio.js +376 -0
- package/dist/thread/player/media/dynamic-sound.js +90 -0
- package/dist/thread/player/media/extract.js +135 -0
- package/dist/thread/player/media/mp3.js +152 -0
- package/dist/thread/player/media/sounds.js +507 -0
- package/dist/thread/player/media/streaming-audio.js +133 -0
- package/dist/thread/player/player.js +616 -0
- package/dist/thread/player/playerglobal/air/net/WebSocket.js +250 -0
- package/dist/thread/player/playerglobal/air-library.js +8 -0
- package/dist/thread/player/playerglobal/flash/accessibility/Accessibility.js +21 -0
- package/dist/thread/player/playerglobal/flash/crypto/generateRandomBytes.js +32 -0
- package/dist/thread/player/playerglobal/flash/data/EncryptedLocalStore.js +61 -0
- package/dist/thread/player/playerglobal/flash/desktop/Clipboard.js +173 -0
- package/dist/thread/player/playerglobal/flash/desktop/NativeApplication.js +179 -0
- package/dist/thread/player/playerglobal/flash/display/AVM1Movie.js +19 -0
- package/dist/thread/player/playerglobal/flash/display/Bitmap.js +58 -0
- package/dist/thread/player/playerglobal/flash/display/BitmapData.js +633 -0
- package/dist/thread/player/playerglobal/flash/display/DisplayObject.js +614 -0
- package/dist/thread/player/playerglobal/flash/display/DisplayObjectContainer.js +224 -0
- package/dist/thread/player/playerglobal/flash/display/Graphics.js +345 -0
- package/dist/thread/player/playerglobal/flash/display/InteractiveObject.js +87 -0
- package/dist/thread/player/playerglobal/flash/display/Loader.js +79 -0
- package/dist/thread/player/playerglobal/flash/display/LoaderInfo.js +128 -0
- package/dist/thread/player/playerglobal/flash/display/MovieClip.js +194 -0
- package/dist/thread/player/playerglobal/flash/display/NativeWindow.js +245 -0
- package/dist/thread/player/playerglobal/flash/display/Shader.js +26 -0
- package/dist/thread/player/playerglobal/flash/display/ShaderData.js +85 -0
- package/dist/thread/player/playerglobal/flash/display/ShaderInput.js +64 -0
- package/dist/thread/player/playerglobal/flash/display/ShaderJob.js +181 -0
- package/dist/thread/player/playerglobal/flash/display/ShaderParameter.js +23 -0
- package/dist/thread/player/playerglobal/flash/display/Shape.js +13 -0
- package/dist/thread/player/playerglobal/flash/display/SimpleButton.js +103 -0
- package/dist/thread/player/playerglobal/flash/display/Sprite.js +84 -0
- package/dist/thread/player/playerglobal/flash/display/Stage.js +231 -0
- package/dist/thread/player/playerglobal/flash/display/Stage3D.js +54 -0
- package/dist/thread/player/playerglobal/flash/display/shaders.js +228 -0
- package/dist/thread/player/playerglobal/flash/events/Event.js +58 -0
- package/dist/thread/player/playerglobal/flash/events/EventDispatcher.js +103 -0
- package/dist/thread/player/playerglobal/flash/events/GestureEvent.js +34 -0
- package/dist/thread/player/playerglobal/flash/events/HTTPStatusEvent.js +8 -0
- package/dist/thread/player/playerglobal/flash/events/KeyboardEvent.js +51 -0
- package/dist/thread/player/playerglobal/flash/events/MouseEvent.js +59 -0
- package/dist/thread/player/playerglobal/flash/events/PressAndTapGestureEvent.js +30 -0
- package/dist/thread/player/playerglobal/flash/events/TimerEvent.js +16 -0
- package/dist/thread/player/playerglobal/flash/events/TouchEvent.js +45 -0
- package/dist/thread/player/playerglobal/flash/external/ExternalInterface.js +73 -0
- package/dist/thread/player/playerglobal/flash/filesystem/File.js +340 -0
- package/dist/thread/player/playerglobal/flash/filesystem/FileStream.js +453 -0
- package/dist/thread/player/playerglobal/flash/filesystem/paths.js +156 -0
- package/dist/thread/player/playerglobal/flash/filesystem/writes.js +143 -0
- package/dist/thread/player/playerglobal/flash/filters/BevelFilter.js +4 -0
- package/dist/thread/player/playerglobal/flash/filters/BitmapFilter.js +205 -0
- package/dist/thread/player/playerglobal/flash/filters/BlurFilter.js +4 -0
- package/dist/thread/player/playerglobal/flash/filters/ColorMatrixFilter.js +11 -0
- package/dist/thread/player/playerglobal/flash/filters/ConvolutionFilter.js +26 -0
- package/dist/thread/player/playerglobal/flash/filters/DisplacementMapFilter.js +51 -0
- package/dist/thread/player/playerglobal/flash/filters/DropShadowFilter.js +4 -0
- package/dist/thread/player/playerglobal/flash/filters/GlowFilter.js +4 -0
- package/dist/thread/player/playerglobal/flash/filters/GradientBevelFilter.js +4 -0
- package/dist/thread/player/playerglobal/flash/filters/GradientGlowFilter.js +4 -0
- package/dist/thread/player/playerglobal/flash/filters/ShaderFilter.js +53 -0
- package/dist/thread/player/playerglobal/flash/geom/Matrix3D.js +361 -0
- package/dist/thread/player/playerglobal/flash/geom/PerspectiveProjection.js +122 -0
- package/dist/thread/player/playerglobal/flash/geom/Transform.js +245 -0
- package/dist/thread/player/playerglobal/flash/geom/Utils3D.js +85 -0
- package/dist/thread/player/playerglobal/flash/globalization/Collator.js +149 -0
- package/dist/thread/player/playerglobal/flash/globalization/CurrencyFormatter.js +272 -0
- package/dist/thread/player/playerglobal/flash/globalization/CurrencyParseResult.js +21 -0
- package/dist/thread/player/playerglobal/flash/globalization/DateTimeFormatter.js +463 -0
- package/dist/thread/player/playerglobal/flash/globalization/LocaleID.js +144 -0
- package/dist/thread/player/playerglobal/flash/globalization/NumberFormatter.js +444 -0
- package/dist/thread/player/playerglobal/flash/globalization/NumberParseResult.js +22 -0
- package/dist/thread/player/playerglobal/flash/globalization/StringTools.js +59 -0
- package/dist/thread/player/playerglobal/flash/globalization/locale.js +190 -0
- package/dist/thread/player/playerglobal/flash/media/Camera.js +89 -0
- package/dist/thread/player/playerglobal/flash/media/Microphone.js +126 -0
- package/dist/thread/player/playerglobal/flash/media/Sound.js +543 -0
- package/dist/thread/player/playerglobal/flash/media/SoundMixer.js +74 -0
- package/dist/thread/player/playerglobal/flash/media/SoundTransform.js +40 -0
- package/dist/thread/player/playerglobal/flash/media/Video.js +43 -0
- package/dist/thread/player/playerglobal/flash/net/FileFilter.js +27 -0
- package/dist/thread/player/playerglobal/flash/net/FileReference.js +197 -0
- package/dist/thread/player/playerglobal/flash/net/LocalConnection.js +167 -0
- package/dist/thread/player/playerglobal/flash/net/NetConnection.js +155 -0
- package/dist/thread/player/playerglobal/flash/net/SharedObject.js +299 -0
- package/dist/thread/player/playerglobal/flash/net/Socket.js +282 -0
- package/dist/thread/player/playerglobal/flash/net/URLRequest.js +93 -0
- package/dist/thread/player/playerglobal/flash/net/URLStream.js +146 -0
- package/dist/thread/player/playerglobal/flash/net/XMLSocket.js +14 -0
- package/dist/thread/player/playerglobal/flash/net/local-modern.js +142 -0
- package/dist/thread/player/playerglobal/flash/net/local-values.js +217 -0
- package/dist/thread/player/playerglobal/flash/net/navigateToURL.js +29 -0
- package/dist/thread/player/playerglobal/flash/profiler/Telemetry.js +25 -0
- package/dist/thread/player/playerglobal/flash/sensors/Accelerometer.js +12 -0
- package/dist/thread/player/playerglobal/flash/system/ApplicationDomain.js +69 -0
- package/dist/thread/player/playerglobal/flash/system/Capabilities.js +163 -0
- package/dist/thread/player/playerglobal/flash/system/FSCommandHost.js +17 -0
- package/dist/thread/player/playerglobal/flash/system/Security.js +46 -0
- package/dist/thread/player/playerglobal/flash/system/SecurityDomain.js +21 -0
- package/dist/thread/player/playerglobal/flash/system/System.js +73 -0
- package/dist/thread/player/playerglobal/flash/system/Worker.js +112 -0
- package/dist/thread/player/playerglobal/flash/text/Font.js +95 -0
- package/dist/thread/player/playerglobal/flash/text/StaticText.js +16 -0
- package/dist/thread/player/playerglobal/flash/text/StyleSheet.js +65 -0
- package/dist/thread/player/playerglobal/flash/text/TextField.js +707 -0
- package/dist/thread/player/playerglobal/flash/text/TextRenderer.js +77 -0
- package/dist/thread/player/playerglobal/flash/text/engine/FontDescription.js +141 -0
- package/dist/thread/player/playerglobal/flash/text/engine/TabStop.js +46 -0
- package/dist/thread/player/playerglobal/flash/trace/Trace.js +17 -0
- package/dist/thread/player/playerglobal/flash/ui/ContextMenu.js +17 -0
- package/dist/thread/player/playerglobal/flash/ui/GameInput.js +19 -0
- package/dist/thread/player/playerglobal/flash/ui/Keyboard.js +27 -0
- package/dist/thread/player/playerglobal/flash/ui/Mouse.js +127 -0
- package/dist/thread/player/playerglobal/flash/ui/Multitouch.js +46 -0
- package/dist/thread/player/playerglobal/flash/utils/ByteArray.js +155 -0
- package/dist/thread/player/playerglobal/flash/utils/Timer.js +25 -0
- package/dist/thread/player/playerglobal/flash/xml/XMLDocument.js +74 -0
- package/dist/thread/player/playerglobal/index.js +224 -0
- package/dist/thread/player/playerglobal/libraries.js +10 -0
- package/dist/thread/player/playerglobal/playerglobal-library.js +22 -0
- package/dist/thread/player/playerglobal/toplevel.js +122 -0
- package/dist/thread/player/scripting/clipboard.js +146 -0
- package/dist/thread/player/scripting/code.js +900 -0
- package/dist/thread/player/scripting/evaluate.js +144 -0
- package/dist/thread/player/scripting/events.js +172 -0
- package/dist/thread/player/scripting/handover.js +182 -0
- package/dist/thread/player/scripting/lazy.js +38 -0
- package/dist/thread/player/scripting/lifecycle.js +272 -0
- package/dist/thread/player/scripting/loads.js +860 -0
- package/dist/thread/player/scripting/sha256.js +95 -0
- package/dist/thread/player/scripting/symbols.js +348 -0
- package/dist/thread/player/scripting/timers.js +434 -0
- package/dist/thread/player/scripting/workers.js +923 -0
- package/dist/thread/player/scripting.js +1018 -0
- package/dist/thread/player/stage.js +4 -0
- package/dist/thread/player/text/csm.js +113 -0
- package/dist/thread/player/text/css.js +167 -0
- package/dist/thread/player/text/fonts.js +97 -0
- package/dist/thread/player/text/layout.js +393 -0
- package/dist/thread/player/text/static.js +109 -0
- package/dist/thread/player/text/text.js +431 -0
- package/dist/thread/player/workers/thread.js +159 -0
- package/dist/thread/player/workers/wire.js +198 -0
- package/dist/thread/player-hosts/web-worker.js +19 -0
- package/dist/thread/runtime/avm1/activation.js +89 -0
- package/dist/thread/runtime/avm1/case.js +249 -0
- package/dist/thread/runtime/avm1/clips.js +334 -0
- package/dist/thread/runtime/avm1/control.js +280 -0
- package/dist/thread/runtime/avm1/errors.js +50 -0
- package/dist/thread/runtime/avm1/functions.js +249 -0
- package/dist/thread/runtime/avm1/globals/array.js +549 -0
- package/dist/thread/runtime/avm1/globals/broadcaster.js +131 -0
- package/dist/thread/runtime/avm1/globals/date.js +436 -0
- package/dist/thread/runtime/avm1/globals/global.js +344 -0
- package/dist/thread/runtime/avm1/globals/math.js +139 -0
- package/dist/thread/runtime/avm1/globals/number.js +93 -0
- package/dist/thread/runtime/avm1/globals/string.js +201 -0
- package/dist/thread/runtime/avm1/globals/timers.js +129 -0
- package/dist/thread/runtime/avm1/host.js +5 -0
- package/dist/thread/runtime/avm1/index.js +14 -0
- package/dist/thread/runtime/avm1/inheritance.js +132 -0
- package/dist/thread/runtime/avm1/numbers.js +298 -0
- package/dist/thread/runtime/avm1/objects.js +896 -0
- package/dist/thread/runtime/avm1/operators.js +170 -0
- package/dist/thread/runtime/avm1/realm.js +529 -0
- package/dist/thread/runtime/avm1/runtime.js +882 -0
- package/dist/thread/runtime/avm1/scope.js +385 -0
- package/dist/thread/runtime/avm1/urls.js +180 -0
- package/dist/thread/runtime/avm1/values.js +97 -0
- package/dist/thread/runtime/avm2/amf-classes.js +66 -0
- package/dist/thread/runtime/avm2/amf.js +801 -0
- package/dist/thread/runtime/avm2/array-conversion.js +100 -0
- package/dist/thread/runtime/avm2/builtin-library.js +21 -0
- package/dist/thread/runtime/avm2/cache-fill.js +86 -0
- package/dist/thread/runtime/avm2/classes.js +211 -0
- package/dist/thread/runtime/avm2/definitions.js +69 -0
- package/dist/thread/runtime/avm2/descriptors.js +5 -0
- package/dist/thread/runtime/avm2/dictionary-keys.js +295 -0
- package/dist/thread/runtime/avm2/domain-memory.js +75 -0
- package/dist/thread/runtime/avm2/domain.js +280 -0
- package/dist/thread/runtime/avm2/dynamic-properties.js +182 -0
- package/dist/thread/runtime/avm2/enumeration.js +393 -0
- package/dist/thread/runtime/avm2/errors.js +45 -0
- package/dist/thread/runtime/avm2/float-library.js +66 -0
- package/dist/thread/runtime/avm2/float.js +26 -0
- package/dist/thread/runtime/avm2/hooks.js +19 -0
- package/dist/thread/runtime/avm2/index.js +38 -0
- package/dist/thread/runtime/avm2/messages.js +177 -0
- package/dist/thread/runtime/avm2/method-factories.js +95 -0
- package/dist/thread/runtime/avm2/modules.js +105 -0
- package/dist/thread/runtime/avm2/names.js +248 -0
- package/dist/thread/runtime/avm2/natives/aliases.js +47 -0
- package/dist/thread/runtime/avm2/natives/array.js +390 -0
- package/dist/thread/runtime/avm2/natives/bytearray.js +1227 -0
- package/dist/thread/runtime/avm2/natives/case.js +88 -0
- package/dist/thread/runtime/avm2/natives/concurrent.js +199 -0
- package/dist/thread/runtime/avm2/natives/date.js +581 -0
- package/dist/thread/runtime/avm2/natives/define.js +130 -0
- package/dist/thread/runtime/avm2/natives/describe.js +351 -0
- package/dist/thread/runtime/avm2/natives/dictionary.js +12 -0
- package/dist/thread/runtime/avm2/natives/float-vector.js +81 -0
- package/dist/thread/runtime/avm2/natives/float.js +96 -0
- package/dist/thread/runtime/avm2/natives/index.js +64 -0
- package/dist/thread/runtime/avm2/natives/json.js +514 -0
- package/dist/thread/runtime/avm2/natives/number.js +162 -0
- package/dist/thread/runtime/avm2/natives/object.js +237 -0
- package/dist/thread/runtime/avm2/natives/proxy.js +75 -0
- package/dist/thread/runtime/avm2/natives/regexp.js +485 -0
- package/dist/thread/runtime/avm2/natives/shell-workers.js +404 -0
- package/dist/thread/runtime/avm2/natives/shell.js +557 -0
- package/dist/thread/runtime/avm2/natives/sort.js +377 -0
- package/dist/thread/runtime/avm2/natives/string.js +132 -0
- package/dist/thread/runtime/avm2/natives/sync.js +821 -0
- package/dist/thread/runtime/avm2/natives/toplevel.js +139 -0
- package/dist/thread/runtime/avm2/natives/vector-elements.js +46 -0
- package/dist/thread/runtime/avm2/natives/vector.js +406 -0
- package/dist/thread/runtime/avm2/natives/xml/access.js +633 -0
- package/dist/thread/runtime/avm2/natives/xml/build.js +291 -0
- package/dist/thread/runtime/avm2/natives/xml/chars.js +112 -0
- package/dist/thread/runtime/avm2/natives/xml/escape.js +38 -0
- package/dist/thread/runtime/avm2/natives/xml/names.js +204 -0
- package/dist/thread/runtime/avm2/natives/xml/node.js +272 -0
- package/dist/thread/runtime/avm2/natives/xml/operators.js +69 -0
- package/dist/thread/runtime/avm2/natives/xml/parser.js +356 -0
- package/dist/thread/runtime/avm2/natives/xml/strings.js +191 -0
- package/dist/thread/runtime/avm2/natives/xml/values.js +122 -0
- package/dist/thread/runtime/avm2/natives/xml/xml.js +645 -0
- package/dist/thread/runtime/avm2/number-strings.js +110 -0
- package/dist/thread/runtime/avm2/numbers.js +558 -0
- package/dist/thread/runtime/avm2/options.js +16 -0
- package/dist/thread/runtime/avm2/player-messages.js +550 -0
- package/dist/thread/runtime/avm2/property-cache.js +135 -0
- package/dist/thread/runtime/avm2/runtime.js +2644 -0
- package/dist/thread/runtime/avm2/traits.js +509 -0
- package/dist/thread/runtime/index.js +7 -0
- package/dist/web-worker.d.ts +2 -0
- package/dist/web-worker.d.ts.map +1 -0
- package/dist/web-worker.js +20 -0
- package/dist/web-worker.js.map +1 -0
- package/dist/websocket.d.ts +4 -0
- package/dist/websocket.d.ts.map +1 -0
- package/dist/websocket.js +27 -0
- package/dist/websocket.js.map +1 -0
- package/dist/workers.d.ts +35 -0
- package/dist/workers.d.ts.map +1 -0
- package/dist/workers.js +171 -0
- package/dist/workers.js.map +1 -0
- package/package.json +62 -3
- package/src/indexeddb.ts +227 -0
- package/src/node-worker.ts +13 -0
- package/src/node.ts +49 -0
- package/src/precompiled.ts +166 -0
- package/src/stage3d.ts +76 -0
- package/src/web-worker.ts +24 -0
- package/src/websocket.ts +32 -0
- package/src/workers.ts +255 -0
|
@@ -0,0 +1,923 @@
|
|
|
1
|
+
// flash.system's workers as one VM sees them (docs/workers.md): the
|
|
2
|
+
// primordial starts each background worker on a thread of its host's and
|
|
3
|
+
// routes what crosses between them; a background worker's VM reaches only
|
|
4
|
+
// the primordial. Shared properties and channels' messages cross as copies,
|
|
5
|
+
// made as avmplus' ChannelItem makes them, so a host's channel carries
|
|
6
|
+
// plain data, but for a shareable ByteArray's memory, which every worker
|
|
7
|
+
// shares, and a Mutex or a Condition, an address in the memory every
|
|
8
|
+
// worker is given (avm2.Sync). Where memory is shared, the shared
|
|
9
|
+
// properties are a table in it and a channel's queue is in it, so that
|
|
10
|
+
// every worker sees them at once and a receiver can block on a queue, and
|
|
11
|
+
// a background worker starts a worker through a queue the primordial takes
|
|
12
|
+
// even while it waits. Elsewhere each side keeps its own copy of a worker's
|
|
13
|
+
// shared properties and of a channel's queue, and what one side sets or
|
|
14
|
+
// sends reaches the other between its frames.
|
|
15
|
+
import { avm2 } from "../../runtime/index.js";
|
|
16
|
+
import { pack, packEnd, packJob, packTable, unpack, unpackRequest, unpackTable, } from "../workers/wire.js";
|
|
17
|
+
import { dispatchEvent } from "./events.js";
|
|
18
|
+
/** The primordial worker's id; background workers count up from 1. */
|
|
19
|
+
const PRIMORDIAL = 0;
|
|
20
|
+
/** How long a terminated worker's thread is given to stop itself before its host stops it. */
|
|
21
|
+
const STOP_WAIT = 1000;
|
|
22
|
+
/**
|
|
23
|
+
* Stop the thread of worker `id`, terminated. A thread may be stopped
|
|
24
|
+
* anywhere, even where it writes what a Mutex it holds guards, so its
|
|
25
|
+
* Mutexes are let go only once it has stopped. The thread stops itself
|
|
26
|
+
* between frames once it sees it was terminated, which one that waits or
|
|
27
|
+
* is idle does at once and one that plays at the end of its frame, and
|
|
28
|
+
* says so (thread.ts); one that has not within STOP_WAIT is stopped by its
|
|
29
|
+
* host, and its Mutexes let go once the host says it has gone.
|
|
30
|
+
*/
|
|
31
|
+
function stopThread(sync, id, thread) {
|
|
32
|
+
const start = Date.now();
|
|
33
|
+
const look = () => {
|
|
34
|
+
if (sync.stopped(id)) {
|
|
35
|
+
void thread.terminate();
|
|
36
|
+
}
|
|
37
|
+
else if (Date.now() - start >= STOP_WAIT) {
|
|
38
|
+
void Promise.resolve(thread.terminate()).then(() => sync.end(id));
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
setTimeout(look, 10);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
setTimeout(look, 10);
|
|
45
|
+
}
|
|
46
|
+
/** A shared property's key in the shared table. */
|
|
47
|
+
const tableKey = (worker, key) => `${worker}${key === null ? "" : `:${key}`}`;
|
|
48
|
+
const STATES = { new: "new", starting: "new", running: "running", terminated: "terminated" };
|
|
49
|
+
export class Workers {
|
|
50
|
+
s;
|
|
51
|
+
/** This VM's worker: the primordial's 0, or a background worker's own. */
|
|
52
|
+
id;
|
|
53
|
+
host;
|
|
54
|
+
parent;
|
|
55
|
+
/** The background workers made and not terminated; what they held goes with them. */
|
|
56
|
+
backgrounds = new Map();
|
|
57
|
+
/** Those terminated, by id alone. */
|
|
58
|
+
ended = new Set();
|
|
59
|
+
/** The Worker objects of this VM, one a worker. */
|
|
60
|
+
objects = new Map();
|
|
61
|
+
shared = new Map();
|
|
62
|
+
channels = new Map();
|
|
63
|
+
/** Each shareable ByteArray's memory this VM has seen, by its id, for a message in a shared queue that names it. */
|
|
64
|
+
memories = new Map();
|
|
65
|
+
nextChannel = 1;
|
|
66
|
+
/** The shared table as last read, by tableKey, and its version. */
|
|
67
|
+
table = null;
|
|
68
|
+
/** Whether the primordial is starting the workers background workers asked for. */
|
|
69
|
+
servicing = false;
|
|
70
|
+
/** The libraries the SWFs link against, as loaded, which a worker's thread loads too. */
|
|
71
|
+
libraries = [];
|
|
72
|
+
constructor(s, options) {
|
|
73
|
+
this.s = s;
|
|
74
|
+
this.parent = options.workerParent ?? null;
|
|
75
|
+
this.host = this.parent ? null : (options.workerHost ?? null);
|
|
76
|
+
this.id = this.parent?.id ?? PRIMORDIAL;
|
|
77
|
+
if (this.parent) {
|
|
78
|
+
for (const message of this.parent.shared) {
|
|
79
|
+
this.applyShared(message);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/** Worker.isSupported: whether another worker can run beside this one. */
|
|
84
|
+
get supported() {
|
|
85
|
+
return this.parent !== null || this.host !== null;
|
|
86
|
+
}
|
|
87
|
+
/** The Worker object of worker `id` in this VM; `cls` is Worker's class, while it is being made. */
|
|
88
|
+
objectOf(id, cls) {
|
|
89
|
+
let o = this.objects.get(id);
|
|
90
|
+
if (!o) {
|
|
91
|
+
const rt = this.s.rt;
|
|
92
|
+
o = rt.constructClass(cls ?? rt.classNamed("flash.system::Worker"), []);
|
|
93
|
+
o.$worker = id;
|
|
94
|
+
this.objects.set(id, o);
|
|
95
|
+
}
|
|
96
|
+
return o;
|
|
97
|
+
}
|
|
98
|
+
/** WorkerDomain.createWorker: a worker in state "new" that will run `swf`, copied now. */
|
|
99
|
+
create(swf) {
|
|
100
|
+
const rt = this.s.rt;
|
|
101
|
+
if (swf === null || swf === undefined) {
|
|
102
|
+
throw rt.error("TypeError", 2007, "swf");
|
|
103
|
+
}
|
|
104
|
+
if (!this.parent && !this.host) {
|
|
105
|
+
throw rt.unsupported("creating a Worker without a worker host");
|
|
106
|
+
}
|
|
107
|
+
// Numbered in the memory every worker shares, so that one a background
|
|
108
|
+
// worker makes has a number of its own.
|
|
109
|
+
const sync = avm2.syncOf(rt);
|
|
110
|
+
if (this.parent && !sync.shared) {
|
|
111
|
+
throw avm2.notIsolated("a Worker a background worker makes");
|
|
112
|
+
}
|
|
113
|
+
const bytes = avm2.bytesOf(rt, swf);
|
|
114
|
+
const id = sync.newThread();
|
|
115
|
+
this.backgrounds.set(id, {
|
|
116
|
+
id,
|
|
117
|
+
creator: this.parent ? this.id : null,
|
|
118
|
+
swf: bytes.buffer.slice(0, bytes.length),
|
|
119
|
+
state: "new",
|
|
120
|
+
thread: null,
|
|
121
|
+
pending: [],
|
|
122
|
+
sent: 0,
|
|
123
|
+
waits: [],
|
|
124
|
+
});
|
|
125
|
+
return this.objectOf(id);
|
|
126
|
+
}
|
|
127
|
+
start(id) {
|
|
128
|
+
const rt = this.s.rt;
|
|
129
|
+
const background = this.backgrounds.get(id);
|
|
130
|
+
if (!background) {
|
|
131
|
+
throw rt.error("flash.errors::IllegalOperationError", id === this.id || id === PRIMORDIAL || this.ended.has(id) ? 1511 : 1521);
|
|
132
|
+
}
|
|
133
|
+
if (background.state !== "new") {
|
|
134
|
+
throw rt.error("flash.errors::IllegalOperationError", 1511);
|
|
135
|
+
}
|
|
136
|
+
if (this.parent) {
|
|
137
|
+
// The primordial starts it on its host, and tells this VM its state.
|
|
138
|
+
// The request goes in its queue in shared memory, which it takes
|
|
139
|
+
// even while it waits, as Crossbridge's primordial may wait for
|
|
140
|
+
// what this worker is starting the new one for.
|
|
141
|
+
const sync = avm2.syncOf(rt);
|
|
142
|
+
if (sync.requests === 0) {
|
|
143
|
+
throw rt.unsupported("starting a Worker from a background worker the primordial did not start");
|
|
144
|
+
}
|
|
145
|
+
background.state = "starting";
|
|
146
|
+
const shared = [...this.propertiesOf(id)].map(([key, p]) => ({
|
|
147
|
+
worker: id,
|
|
148
|
+
key,
|
|
149
|
+
value: p.wire,
|
|
150
|
+
}));
|
|
151
|
+
this.request(packJob(id, this.id, background.swf, shared));
|
|
152
|
+
background.swf = new Uint8Array(0);
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
this.takeRequests();
|
|
156
|
+
const host = this.host;
|
|
157
|
+
background.state = "starting";
|
|
158
|
+
const shared = [id, PRIMORDIAL].flatMap((worker) => [...this.propertiesOf(worker)].map(([key, p]) => ({ type: "shared", worker, key, value: p.wire })));
|
|
159
|
+
const swf = background.swf;
|
|
160
|
+
background.swf = new Uint8Array(0);
|
|
161
|
+
background.sent = 1;
|
|
162
|
+
this.wait(background, 1);
|
|
163
|
+
try {
|
|
164
|
+
background.thread = host.start({
|
|
165
|
+
type: "init",
|
|
166
|
+
id,
|
|
167
|
+
swf,
|
|
168
|
+
url: this.s.url,
|
|
169
|
+
sandboxType: this.s.sandboxType,
|
|
170
|
+
air: this.s.air,
|
|
171
|
+
libraries: this.libraries,
|
|
172
|
+
shared,
|
|
173
|
+
sync: avm2.syncOf(rt).memory,
|
|
174
|
+
modules: this.s.code.handedModules(),
|
|
175
|
+
}, (message) => this.fromBackground(background, message), (error) => {
|
|
176
|
+
if (background.state !== "terminated") {
|
|
177
|
+
this.s.reportUncaught(error);
|
|
178
|
+
this.end(background);
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
catch {
|
|
183
|
+
// The host could start no thread, as a page's policy may forbid the
|
|
184
|
+
// worker's script. Flash's nearest is a player that has workers
|
|
185
|
+
// disabled, which start reports with 3807; the worker is terminated.
|
|
186
|
+
this.end(background);
|
|
187
|
+
throw rt.error("flash.errors::IllegalOperationError", 3807);
|
|
188
|
+
}
|
|
189
|
+
for (const message of background.pending.splice(0)) {
|
|
190
|
+
this.post(background, message);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
/** Worker.terminate: true where it was started and still runs. */
|
|
194
|
+
terminate(id) {
|
|
195
|
+
if (id === PRIMORDIAL) {
|
|
196
|
+
throw this.s.rt.error("flash.errors::IllegalOperationError", 3732);
|
|
197
|
+
}
|
|
198
|
+
// A worker may end itself; the primordial stops its thread. Until it
|
|
199
|
+
// has, the shared memory refuses it anything more.
|
|
200
|
+
if (this.parent && id === this.id) {
|
|
201
|
+
avm2.syncOf(this.s.rt).stop(id);
|
|
202
|
+
this.parent.post({ type: "terminate" });
|
|
203
|
+
return true;
|
|
204
|
+
}
|
|
205
|
+
const background = this.backgrounds.get(id);
|
|
206
|
+
if (!background || background.state === "new" || background.state === "terminated") {
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
// One this background worker made: the primordial stops its thread,
|
|
210
|
+
// asked through its queue, which it takes even while it waits.
|
|
211
|
+
if (this.parent) {
|
|
212
|
+
this.request(packEnd(id, this.id));
|
|
213
|
+
}
|
|
214
|
+
this.end(background);
|
|
215
|
+
return true;
|
|
216
|
+
}
|
|
217
|
+
/** Put `bytes` in the primordial's queue of requests, and tell it. */
|
|
218
|
+
request(bytes) {
|
|
219
|
+
const sync = avm2.syncOf(this.s.rt);
|
|
220
|
+
this.inShared(() => sync.push(sync.requests, bytes));
|
|
221
|
+
this.parent?.post({ type: "requests" });
|
|
222
|
+
}
|
|
223
|
+
/** What `f` does in the shared memory, its errors a script's: MemoryError 1000 where it is full. */
|
|
224
|
+
inShared(f) {
|
|
225
|
+
try {
|
|
226
|
+
return f();
|
|
227
|
+
}
|
|
228
|
+
catch (e) {
|
|
229
|
+
throw avm2.syncError(this.s.rt, e);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
state(id) {
|
|
233
|
+
if (id === this.id || id === PRIMORDIAL) {
|
|
234
|
+
return "running";
|
|
235
|
+
}
|
|
236
|
+
// One this background worker made runs as soon as its own thread says so.
|
|
237
|
+
const background = this.backgrounds.get(id);
|
|
238
|
+
if (background?.state === "starting" && avm2.syncOf(this.s.rt).running(id)) {
|
|
239
|
+
return "running";
|
|
240
|
+
}
|
|
241
|
+
return STATES[background?.state ?? "terminated"];
|
|
242
|
+
}
|
|
243
|
+
/** WorkerDomain.listWorkers: the running workers, the primordial first, as Flash lists them. */
|
|
244
|
+
list() {
|
|
245
|
+
if (this.parent) {
|
|
246
|
+
return [this.objectOf(PRIMORDIAL), this.objectOf(this.id)];
|
|
247
|
+
}
|
|
248
|
+
const running = [...this.backgrounds.values()].filter((b) => b.state === "running");
|
|
249
|
+
return [this.objectOf(PRIMORDIAL), ...running.map((b) => this.objectOf(b.id))];
|
|
250
|
+
}
|
|
251
|
+
setShared(id, key, value) {
|
|
252
|
+
if (this.ended.has(id)) {
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
const own = this.propertiesOf(id);
|
|
256
|
+
if (value === undefined) {
|
|
257
|
+
own.delete(key);
|
|
258
|
+
}
|
|
259
|
+
else {
|
|
260
|
+
const wire = this.encode(value);
|
|
261
|
+
// A ByteArray read back by the worker that set it is itself, as in Flash.
|
|
262
|
+
own.set(key, { wire, local: wire.kind === "bytes" ? value : undefined });
|
|
263
|
+
}
|
|
264
|
+
// Where memory is shared, in the table every worker reads at once.
|
|
265
|
+
const sync = avm2.syncOf(this.s.rt);
|
|
266
|
+
if (sync.shared) {
|
|
267
|
+
const p = own.get(key);
|
|
268
|
+
if (p) {
|
|
269
|
+
p.token = sync.nextToken();
|
|
270
|
+
}
|
|
271
|
+
this.inShared(() => sync.updateTable((bytes) => {
|
|
272
|
+
const entries = unpackTable(bytes).filter((e) => e.worker !== id || e.key !== key);
|
|
273
|
+
if (p?.token !== undefined) {
|
|
274
|
+
entries.push({ worker: id, key, token: p.token, value: pack(p.wire) });
|
|
275
|
+
}
|
|
276
|
+
return packTable(entries);
|
|
277
|
+
}));
|
|
278
|
+
}
|
|
279
|
+
const message = {
|
|
280
|
+
type: "shared",
|
|
281
|
+
worker: id,
|
|
282
|
+
key,
|
|
283
|
+
value: value === undefined ? null : own.get(key).wire,
|
|
284
|
+
};
|
|
285
|
+
if (this.parent) {
|
|
286
|
+
this.parent.post(message);
|
|
287
|
+
}
|
|
288
|
+
else {
|
|
289
|
+
this.share(message, PRIMORDIAL);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
/** A shared property set, posted on by the primordial: the primordial's to every worker but `from`. */
|
|
293
|
+
share(message, from) {
|
|
294
|
+
for (const background of this.backgrounds.values()) {
|
|
295
|
+
const to = background.id;
|
|
296
|
+
const ofCreator = this.backgrounds.get(message.worker)?.creator === to;
|
|
297
|
+
if (to !== from && (message.worker === PRIMORDIAL || message.worker === to || ofCreator)) {
|
|
298
|
+
// One not started gets it with the rest when it starts.
|
|
299
|
+
if (background.state !== "new") {
|
|
300
|
+
this.post(background, message);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
getShared(id, key) {
|
|
306
|
+
const p = this.shared.get(id)?.get(key);
|
|
307
|
+
if (avm2.syncOf(this.s.rt).shared) {
|
|
308
|
+
// What any worker set last, at once; this VM's own value where it set it.
|
|
309
|
+
const entry = this.tableEntries().get(tableKey(id, key));
|
|
310
|
+
if (!entry) {
|
|
311
|
+
return undefined;
|
|
312
|
+
}
|
|
313
|
+
if (p?.token !== entry.token) {
|
|
314
|
+
return this.decode(this.unpacked(unpack(entry.value)));
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
if (!p) {
|
|
318
|
+
return undefined;
|
|
319
|
+
}
|
|
320
|
+
return p.local !== undefined ? p.local : this.decode(p.wire);
|
|
321
|
+
}
|
|
322
|
+
/** The shared table's entries, read again where another worker has changed it. */
|
|
323
|
+
tableEntries() {
|
|
324
|
+
const sync = avm2.syncOf(this.s.rt);
|
|
325
|
+
if (this.table?.version !== sync.tableVersion()) {
|
|
326
|
+
const { version, bytes } = sync.readTable();
|
|
327
|
+
const entries = new Map();
|
|
328
|
+
for (const e of unpackTable(bytes)) {
|
|
329
|
+
entries.set(tableKey(e.worker, e.key), e);
|
|
330
|
+
}
|
|
331
|
+
this.table = { version, entries };
|
|
332
|
+
}
|
|
333
|
+
return this.table.entries;
|
|
334
|
+
}
|
|
335
|
+
/** Worker.createMessageChannel: a channel from `sender` to `receiver`. */
|
|
336
|
+
createChannel(sender, receiver) {
|
|
337
|
+
// Ids made by a background worker are its own, apart from the primordial's.
|
|
338
|
+
const id = this.id * 0x100000 + this.nextChannel++;
|
|
339
|
+
const sync = avm2.syncOf(this.s.rt);
|
|
340
|
+
const queue = sync.shared ? this.inShared(() => sync.newQueue()) : 0;
|
|
341
|
+
return this.channelObject({ id, sender, receiver, queue });
|
|
342
|
+
}
|
|
343
|
+
send(o, value) {
|
|
344
|
+
const rt = this.s.rt;
|
|
345
|
+
const channel = this.channelOf(o);
|
|
346
|
+
if (channel.ref.sender !== this.id) {
|
|
347
|
+
throw rt.error("ArgumentError", 3736);
|
|
348
|
+
}
|
|
349
|
+
if (channel.state !== "open") {
|
|
350
|
+
throw rt.error("flash.errors::IOError", 3738);
|
|
351
|
+
}
|
|
352
|
+
const wire = this.encode(value);
|
|
353
|
+
if (channel.ref.queue !== 0) {
|
|
354
|
+
// Queued at once where both ends see it; the notice brings the
|
|
355
|
+
// receiver its channelMessage, and a shareable ByteArray's memory.
|
|
356
|
+
const sync = avm2.syncOf(this.s.rt);
|
|
357
|
+
this.inShared(() => sync.push(channel.ref.queue, pack(wire)));
|
|
358
|
+
const notice = wire.kind === "shared" ? wire : null;
|
|
359
|
+
this.route({ type: "message", channel: channel.ref, value: notice }, this.id);
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
this.route({ type: "message", channel: channel.ref, value: wire }, this.id);
|
|
363
|
+
}
|
|
364
|
+
receive(o, block) {
|
|
365
|
+
const rt = this.s.rt;
|
|
366
|
+
const channel = this.channelOf(o);
|
|
367
|
+
if (channel.ref.receiver !== this.id) {
|
|
368
|
+
throw rt.error("ArgumentError", 3737);
|
|
369
|
+
}
|
|
370
|
+
if (channel.ref.queue !== 0) {
|
|
371
|
+
return this.receiveShared(channel, block);
|
|
372
|
+
}
|
|
373
|
+
const wire = channel.queue.shift();
|
|
374
|
+
if (wire === undefined) {
|
|
375
|
+
if (channel.state === "closed") {
|
|
376
|
+
throw rt.error("flash.errors::IOError", 3738);
|
|
377
|
+
}
|
|
378
|
+
if (block) {
|
|
379
|
+
throw rt.unsupported("MessageChannel.receive(true) with no message queued");
|
|
380
|
+
}
|
|
381
|
+
return undefined;
|
|
382
|
+
}
|
|
383
|
+
// The last of a closing channel's closes it, with no event here: Flash
|
|
384
|
+
// dispatches one at a close, which tells the state as the event comes.
|
|
385
|
+
if (channel.state === "closing" && channel.queue.length === 0) {
|
|
386
|
+
channel.state = "closed";
|
|
387
|
+
this.drained(channel);
|
|
388
|
+
}
|
|
389
|
+
return this.decode(wire);
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* The first message of a channel whose queue is in shared memory,
|
|
393
|
+
* waiting for one with `block`: in a worker with Atomics.wait, on the
|
|
394
|
+
* primordial of a page spinning, up to Flash's script timeout.
|
|
395
|
+
*/
|
|
396
|
+
receiveShared(channel, block) {
|
|
397
|
+
const rt = this.s.rt;
|
|
398
|
+
const sync = avm2.syncOf(rt);
|
|
399
|
+
const q = channel.ref.queue;
|
|
400
|
+
let bytes = sync.shift(q);
|
|
401
|
+
if (bytes === null && block && channel.state === "open") {
|
|
402
|
+
try {
|
|
403
|
+
sync.waitFor(q);
|
|
404
|
+
}
|
|
405
|
+
catch (e) {
|
|
406
|
+
throw avm2.syncError(rt, e);
|
|
407
|
+
}
|
|
408
|
+
bytes = sync.shift(q);
|
|
409
|
+
}
|
|
410
|
+
if (bytes === null) {
|
|
411
|
+
if (channel.state === "closed" || (block && sync.closed(q))) {
|
|
412
|
+
throw rt.error("flash.errors::IOError", 3738);
|
|
413
|
+
}
|
|
414
|
+
return undefined;
|
|
415
|
+
}
|
|
416
|
+
if (channel.state === "closing" && sync.queued(q) === 0) {
|
|
417
|
+
channel.state = "closed";
|
|
418
|
+
this.drained(channel);
|
|
419
|
+
}
|
|
420
|
+
return this.decode(this.unpacked(unpack(bytes)));
|
|
421
|
+
}
|
|
422
|
+
/** A value from a shared queue, a shareable ByteArray's memory found by its id. */
|
|
423
|
+
unpacked(value) {
|
|
424
|
+
if (value.kind !== "shared") {
|
|
425
|
+
return value;
|
|
426
|
+
}
|
|
427
|
+
const memory = this.memories.get(value.id);
|
|
428
|
+
if (!memory) {
|
|
429
|
+
// Its memory comes in a message, which a worker that has not been
|
|
430
|
+
// back in its event loop since another shared it has not taken.
|
|
431
|
+
throw this.s.rt.unsupported("reading a shareable ByteArray another worker shared before its memory reached this one");
|
|
432
|
+
}
|
|
433
|
+
return { kind: "shared", memory };
|
|
434
|
+
}
|
|
435
|
+
messageAvailable(o) {
|
|
436
|
+
const channel = this.channelOf(o);
|
|
437
|
+
if (channel.ref.queue !== 0) {
|
|
438
|
+
return avm2.syncOf(this.s.rt).queued(channel.ref.queue) > 0;
|
|
439
|
+
}
|
|
440
|
+
return channel.ref.receiver === this.id ? channel.queue.length > 0 : channel.undelivered > 0;
|
|
441
|
+
}
|
|
442
|
+
channelState(o) {
|
|
443
|
+
return this.channelOf(o).state;
|
|
444
|
+
}
|
|
445
|
+
/** MessageChannel.close: closing while the receiver has messages queued, then closed. */
|
|
446
|
+
close(o) {
|
|
447
|
+
const channel = this.channelOf(o);
|
|
448
|
+
if (channel.state !== "open") {
|
|
449
|
+
return;
|
|
450
|
+
}
|
|
451
|
+
if (channel.ref.queue !== 0) {
|
|
452
|
+
// Wakes a receiver blocked on it.
|
|
453
|
+
avm2.syncOf(this.s.rt).close(channel.ref.queue);
|
|
454
|
+
}
|
|
455
|
+
this.route({ type: "close", channel: channel.ref, drained: false }, this.id);
|
|
456
|
+
this.closed(channel);
|
|
457
|
+
}
|
|
458
|
+
/** Stop every background worker's thread, as the player goes. */
|
|
459
|
+
stopAll() {
|
|
460
|
+
// A terminated background worker leaves the workers it made to the
|
|
461
|
+
// primordial, which runs them; the shared memory refuses it anything.
|
|
462
|
+
if (this.parent && avm2.syncOf(this.s.rt).terminated) {
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
465
|
+
for (const background of this.backgrounds.values()) {
|
|
466
|
+
if (background.state !== "new" && background.state !== "terminated") {
|
|
467
|
+
this.end(background);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
this.host?.release?.();
|
|
471
|
+
}
|
|
472
|
+
/** A message from the primordial, in a background worker's VM. */
|
|
473
|
+
fromParent(message) {
|
|
474
|
+
switch (message.type) {
|
|
475
|
+
case "shared":
|
|
476
|
+
this.applyShared(message);
|
|
477
|
+
break;
|
|
478
|
+
case "message":
|
|
479
|
+
case "close":
|
|
480
|
+
this.arrive(message);
|
|
481
|
+
break;
|
|
482
|
+
case "state": {
|
|
483
|
+
const child = this.backgrounds.get(message.worker);
|
|
484
|
+
if (child && message.state === "running" && child.state === "starting") {
|
|
485
|
+
child.state = "running";
|
|
486
|
+
this.stateChanged(child.id);
|
|
487
|
+
}
|
|
488
|
+
else if (child && message.state === "terminated") {
|
|
489
|
+
this.end(child);
|
|
490
|
+
}
|
|
491
|
+
break;
|
|
492
|
+
}
|
|
493
|
+
case "init":
|
|
494
|
+
break;
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
fromBackground(background, message) {
|
|
498
|
+
if (background.state === "terminated") {
|
|
499
|
+
return;
|
|
500
|
+
}
|
|
501
|
+
switch (message.type) {
|
|
502
|
+
case "running":
|
|
503
|
+
background.state = "running";
|
|
504
|
+
this.stateChanged(background.id);
|
|
505
|
+
this.toCreator(background, "running");
|
|
506
|
+
break;
|
|
507
|
+
case "requests":
|
|
508
|
+
this.serviceRequests();
|
|
509
|
+
break;
|
|
510
|
+
case "idle":
|
|
511
|
+
for (const w of background.waits.filter((w) => w.upTo <= message.received)) {
|
|
512
|
+
w.done();
|
|
513
|
+
}
|
|
514
|
+
background.waits = background.waits.filter((w) => w.upTo > message.received);
|
|
515
|
+
for (const channel of this.channels.values()) {
|
|
516
|
+
if (channel.ref.receiver === background.id) {
|
|
517
|
+
channel.undelivered = 0;
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
break;
|
|
521
|
+
case "trace":
|
|
522
|
+
this.s.rt.print(message.line);
|
|
523
|
+
break;
|
|
524
|
+
case "uncaught":
|
|
525
|
+
this.s.reportUncaught(new Error(`a background worker: ${message.text}`));
|
|
526
|
+
break;
|
|
527
|
+
case "terminate":
|
|
528
|
+
this.end(background);
|
|
529
|
+
break;
|
|
530
|
+
case "shared":
|
|
531
|
+
this.applyShared(message);
|
|
532
|
+
this.share(message, background.id);
|
|
533
|
+
break;
|
|
534
|
+
case "message":
|
|
535
|
+
case "close":
|
|
536
|
+
this.route(message, background.id);
|
|
537
|
+
break;
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
/**
|
|
541
|
+
* A message on its way to the channel's receiver, or a close to both its
|
|
542
|
+
* ends but the one it came from. A background worker's go through the
|
|
543
|
+
* primordial, which routes them on.
|
|
544
|
+
*/
|
|
545
|
+
route(message, from) {
|
|
546
|
+
const ref = message.channel;
|
|
547
|
+
// The primordial's own copy of a channel between two others follows its state.
|
|
548
|
+
if (!this.parent &&
|
|
549
|
+
message.type === "close" &&
|
|
550
|
+
ref.sender !== this.id &&
|
|
551
|
+
ref.receiver !== this.id) {
|
|
552
|
+
const channel = this.channels.get(ref.id);
|
|
553
|
+
const state = message.drained ? "closed" : "closing";
|
|
554
|
+
if (channel && channel.state !== state && channel.state !== "closed") {
|
|
555
|
+
channel.state = state;
|
|
556
|
+
this.stateEvent(channel);
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
const ends = message.type === "close" ? [ref.sender, ref.receiver] : [ref.receiver];
|
|
560
|
+
let parentPosted = false;
|
|
561
|
+
for (const to of new Set(ends)) {
|
|
562
|
+
if (to === from && message.type === "close") {
|
|
563
|
+
continue;
|
|
564
|
+
}
|
|
565
|
+
if (to === this.id) {
|
|
566
|
+
this.arrive(message);
|
|
567
|
+
}
|
|
568
|
+
else if (this.parent) {
|
|
569
|
+
if (!parentPosted) {
|
|
570
|
+
this.parent.post(message);
|
|
571
|
+
parentPosted = true;
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
else {
|
|
575
|
+
const background = this.backgrounds.get(to);
|
|
576
|
+
if (background) {
|
|
577
|
+
if (message.type === "message" && ref.queue === 0) {
|
|
578
|
+
this.channel(ref).undelivered++;
|
|
579
|
+
}
|
|
580
|
+
this.post(background, message);
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
/** A message or a close at this end of a channel, its event dispatched in the next frame. */
|
|
586
|
+
arrive(message) {
|
|
587
|
+
const channel = this.channel(message.channel);
|
|
588
|
+
if (message.type === "close") {
|
|
589
|
+
if (message.drained) {
|
|
590
|
+
if (channel.state !== "closed") {
|
|
591
|
+
channel.state = "closed";
|
|
592
|
+
this.stateEvent(channel);
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
else if (channel.state === "open") {
|
|
596
|
+
this.closed(channel);
|
|
597
|
+
}
|
|
598
|
+
return;
|
|
599
|
+
}
|
|
600
|
+
if (message.value?.kind === "shared") {
|
|
601
|
+
this.memories.set(message.value.memory.id, message.value.memory);
|
|
602
|
+
}
|
|
603
|
+
if (message.channel.queue === 0 && message.value) {
|
|
604
|
+
channel.queue.push(message.value);
|
|
605
|
+
}
|
|
606
|
+
this.s.loads.deferHostEvent(() => this.dispatch(channel, "channelMessage"));
|
|
607
|
+
}
|
|
608
|
+
/**
|
|
609
|
+
* This end closed, by itself or by the other: closing until the
|
|
610
|
+
* receiver's queue is empty, which only the receiver sees, so a sender on
|
|
611
|
+
* another worker is closing until the receiver tells it (drained).
|
|
612
|
+
*/
|
|
613
|
+
closed(channel) {
|
|
614
|
+
const receiving = channel.ref.receiver === this.id;
|
|
615
|
+
channel.state = receiving && this.queued(channel) === 0 ? "closed" : "closing";
|
|
616
|
+
this.stateEvent(channel);
|
|
617
|
+
if (receiving) {
|
|
618
|
+
this.drained(channel);
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
/** At the receiver, a channel just closed: the sender on another worker is told. */
|
|
622
|
+
drained(channel) {
|
|
623
|
+
if (channel.state === "closed" && channel.ref.sender !== this.id) {
|
|
624
|
+
this.route({ type: "close", channel: channel.ref, drained: true }, this.id);
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
/** How many messages wait at the receiver. */
|
|
628
|
+
queued(channel) {
|
|
629
|
+
return channel.ref.queue !== 0
|
|
630
|
+
? avm2.syncOf(this.s.rt).queued(channel.ref.queue)
|
|
631
|
+
: channel.queue.length;
|
|
632
|
+
}
|
|
633
|
+
stateEvent(channel) {
|
|
634
|
+
this.s.loads.deferHostEvent(() => this.dispatch(channel, "channelState"));
|
|
635
|
+
}
|
|
636
|
+
dispatch(channel, type) {
|
|
637
|
+
if (channel.object) {
|
|
638
|
+
dispatchEvent(this.s, channel.object, this.s.event(type));
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
/** workerState for worker `id` in the next frame; `last`, its object is let go after it. */
|
|
642
|
+
stateChanged(id, last = false) {
|
|
643
|
+
this.s.loads.deferHostEvent(() => {
|
|
644
|
+
const o = this.objects.get(id);
|
|
645
|
+
if (o) {
|
|
646
|
+
dispatchEvent(this.s, o, this.s.event("workerState"));
|
|
647
|
+
}
|
|
648
|
+
// A script that still holds a terminated worker's object reads its state by its id.
|
|
649
|
+
if (last) {
|
|
650
|
+
this.objects.delete(id);
|
|
651
|
+
}
|
|
652
|
+
});
|
|
653
|
+
}
|
|
654
|
+
/**
|
|
655
|
+
* Make the queue of requests background workers start their workers
|
|
656
|
+
* through, once the primordial starts one, where memory is shared; it
|
|
657
|
+
* takes them whenever it waits as well as when it is told of one.
|
|
658
|
+
*/
|
|
659
|
+
takeRequests() {
|
|
660
|
+
const sync = avm2.syncOf(this.s.rt);
|
|
661
|
+
if (!sync.shared || sync.requests !== 0) {
|
|
662
|
+
return;
|
|
663
|
+
}
|
|
664
|
+
sync.requests = sync.newQueue();
|
|
665
|
+
sync.poll = () => {
|
|
666
|
+
if (sync.queued(sync.requests) > 0) {
|
|
667
|
+
this.serviceRequests();
|
|
668
|
+
}
|
|
669
|
+
};
|
|
670
|
+
}
|
|
671
|
+
/** Start each worker a background worker has asked for. */
|
|
672
|
+
serviceRequests() {
|
|
673
|
+
const sync = avm2.syncOf(this.s.rt);
|
|
674
|
+
// Starting one may wait for the shared heap, which polls again.
|
|
675
|
+
if (this.servicing || sync.requests === 0) {
|
|
676
|
+
return;
|
|
677
|
+
}
|
|
678
|
+
this.servicing = true;
|
|
679
|
+
try {
|
|
680
|
+
for (let bytes = sync.shift(sync.requests); bytes; bytes = sync.shift(sync.requests)) {
|
|
681
|
+
const request = unpackRequest(bytes);
|
|
682
|
+
if (request.type === "end") {
|
|
683
|
+
const child = this.backgrounds.get(request.id);
|
|
684
|
+
if (child?.creator === request.creator) {
|
|
685
|
+
this.end(child);
|
|
686
|
+
}
|
|
687
|
+
continue;
|
|
688
|
+
}
|
|
689
|
+
const { job } = request;
|
|
690
|
+
const creator = this.backgrounds.get(job.creator);
|
|
691
|
+
if (!creator) {
|
|
692
|
+
// Its maker has ended.
|
|
693
|
+
continue;
|
|
694
|
+
}
|
|
695
|
+
for (const p of job.shared) {
|
|
696
|
+
try {
|
|
697
|
+
const value = this.unpacked(p.value);
|
|
698
|
+
this.applyShared({ type: "shared", worker: p.worker, key: p.key, value });
|
|
699
|
+
}
|
|
700
|
+
catch (error) {
|
|
701
|
+
this.s.reportUncaught(error);
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
this.createFor(creator, job.id, job.swf);
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
finally {
|
|
708
|
+
this.servicing = false;
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
/** Start worker `id`, which background worker `creator` made to run `swf`. */
|
|
712
|
+
createFor(creator, id, swf) {
|
|
713
|
+
avm2.syncOf(this.s.rt).addThread(id);
|
|
714
|
+
const child = {
|
|
715
|
+
id,
|
|
716
|
+
creator: creator.id,
|
|
717
|
+
swf,
|
|
718
|
+
state: "new",
|
|
719
|
+
thread: null,
|
|
720
|
+
pending: [],
|
|
721
|
+
sent: 0,
|
|
722
|
+
waits: [],
|
|
723
|
+
};
|
|
724
|
+
this.backgrounds.set(id, child);
|
|
725
|
+
try {
|
|
726
|
+
this.start(id);
|
|
727
|
+
}
|
|
728
|
+
catch (error) {
|
|
729
|
+
this.s.reportUncaught(error);
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
/** Tell the background worker that made `background` its state. */
|
|
733
|
+
toCreator(background, state) {
|
|
734
|
+
const creator = background.creator === null ? null : this.backgrounds.get(background.creator);
|
|
735
|
+
if (creator && !this.parent) {
|
|
736
|
+
this.post(creator, { type: "state", worker: background.id, state });
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
/** Stop its thread, and let go of what it held: its SWF, its shared properties, its channels. */
|
|
740
|
+
end(background) {
|
|
741
|
+
const id = background.id;
|
|
742
|
+
if (background.state === "terminated") {
|
|
743
|
+
return;
|
|
744
|
+
}
|
|
745
|
+
this.toCreator(background, "terminated");
|
|
746
|
+
background.state = "terminated";
|
|
747
|
+
const thread = background.thread;
|
|
748
|
+
background.thread = null;
|
|
749
|
+
background.pending.length = 0;
|
|
750
|
+
background.swf = new Uint8Array(0);
|
|
751
|
+
for (const w of background.waits.splice(0)) {
|
|
752
|
+
w.done();
|
|
753
|
+
}
|
|
754
|
+
this.backgrounds.delete(id);
|
|
755
|
+
this.ended.add(id);
|
|
756
|
+
const sync = avm2.syncOf(this.s.rt);
|
|
757
|
+
if (sync.shared && !this.parent) {
|
|
758
|
+
sync.updateTable((bytes) => packTable(unpackTable(bytes).filter((e) => e.worker !== id)));
|
|
759
|
+
}
|
|
760
|
+
// No notify picks it, and while its thread runs on the shared memory
|
|
761
|
+
// refuses it anything more; the Mutexes it holds are let go once its
|
|
762
|
+
// thread has stopped. Only the primordial runs the thread.
|
|
763
|
+
sync.stop(id);
|
|
764
|
+
if (!this.parent) {
|
|
765
|
+
if (thread) {
|
|
766
|
+
stopThread(sync, id, thread);
|
|
767
|
+
}
|
|
768
|
+
else {
|
|
769
|
+
sync.end(id);
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
this.shared.delete(id);
|
|
773
|
+
// A channel's AS3 objects keep theirs; nothing more is routed to it.
|
|
774
|
+
for (const [key, channel] of this.channels) {
|
|
775
|
+
if (channel.ref.sender === id || channel.ref.receiver === id) {
|
|
776
|
+
channel.undelivered = 0;
|
|
777
|
+
if (channel.ref.queue !== 0 && !sync.terminated) {
|
|
778
|
+
// What it had not taken, or would have, goes with it.
|
|
779
|
+
sync.close(channel.ref.queue);
|
|
780
|
+
while (sync.shift(channel.ref.queue) !== null) {
|
|
781
|
+
// Each entry freed.
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
this.channels.delete(key);
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
this.stateChanged(id, true);
|
|
788
|
+
}
|
|
789
|
+
post(background, message) {
|
|
790
|
+
if (background.state === "terminated") {
|
|
791
|
+
return;
|
|
792
|
+
}
|
|
793
|
+
if (!background.thread) {
|
|
794
|
+
background.pending.push(message);
|
|
795
|
+
return;
|
|
796
|
+
}
|
|
797
|
+
background.thread.post(message);
|
|
798
|
+
background.sent++;
|
|
799
|
+
this.wait(background, background.sent);
|
|
800
|
+
}
|
|
801
|
+
/**
|
|
802
|
+
* Have settled() wait until the thread has run its first `upTo` messages,
|
|
803
|
+
* or is blocked in a lock or a wait, which only another worker ends: it
|
|
804
|
+
* runs no frame meanwhile to say it has run them.
|
|
805
|
+
*/
|
|
806
|
+
wait(background, upTo) {
|
|
807
|
+
const sync = avm2.syncOf(this.s.rt);
|
|
808
|
+
this.s.loads.trackRequest(new Promise((resolve) => {
|
|
809
|
+
let timer = null;
|
|
810
|
+
const done = () => {
|
|
811
|
+
if (timer !== null) {
|
|
812
|
+
clearInterval(timer);
|
|
813
|
+
}
|
|
814
|
+
resolve();
|
|
815
|
+
};
|
|
816
|
+
if (sync.shared) {
|
|
817
|
+
timer = setInterval(() => {
|
|
818
|
+
if (sync.blocked(background.id)) {
|
|
819
|
+
done();
|
|
820
|
+
}
|
|
821
|
+
}, 5);
|
|
822
|
+
}
|
|
823
|
+
background.waits.push({ upTo, done });
|
|
824
|
+
}));
|
|
825
|
+
}
|
|
826
|
+
applyShared(message) {
|
|
827
|
+
if (message.value?.kind === "shared") {
|
|
828
|
+
this.memories.set(message.value.memory.id, message.value.memory);
|
|
829
|
+
}
|
|
830
|
+
const own = this.propertiesOf(message.worker);
|
|
831
|
+
if (message.value === null) {
|
|
832
|
+
own.delete(message.key);
|
|
833
|
+
}
|
|
834
|
+
else {
|
|
835
|
+
own.set(message.key, { wire: message.value, local: undefined });
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
propertiesOf(id) {
|
|
839
|
+
let own = this.shared.get(id);
|
|
840
|
+
if (!own) {
|
|
841
|
+
own = new Map();
|
|
842
|
+
this.shared.set(id, own);
|
|
843
|
+
}
|
|
844
|
+
return own;
|
|
845
|
+
}
|
|
846
|
+
channel(ref) {
|
|
847
|
+
let channel = this.channels.get(ref.id);
|
|
848
|
+
if (!channel) {
|
|
849
|
+
channel = { ref, state: "open", queue: [], undelivered: 0, object: null };
|
|
850
|
+
this.channels.set(ref.id, channel);
|
|
851
|
+
}
|
|
852
|
+
return channel;
|
|
853
|
+
}
|
|
854
|
+
channelObject(ref) {
|
|
855
|
+
const channel = this.channel(ref);
|
|
856
|
+
if (!channel.object) {
|
|
857
|
+
const rt = this.s.rt;
|
|
858
|
+
const o = rt.constructClass(rt.classNamed("flash.system::MessageChannel"), []);
|
|
859
|
+
o.$channel = channel;
|
|
860
|
+
channel.object = o;
|
|
861
|
+
}
|
|
862
|
+
return channel.object;
|
|
863
|
+
}
|
|
864
|
+
channelOf(o) {
|
|
865
|
+
return o.$channel;
|
|
866
|
+
}
|
|
867
|
+
/** A value as it crosses to another worker: only the top value is looked at, as in avmplus. */
|
|
868
|
+
encode(value) {
|
|
869
|
+
const rt = this.s.rt;
|
|
870
|
+
if (value === null || typeof value !== "object") {
|
|
871
|
+
return { kind: "value", value: value };
|
|
872
|
+
}
|
|
873
|
+
if (value.$channel) {
|
|
874
|
+
return { kind: "channel", channel: value.$channel.ref };
|
|
875
|
+
}
|
|
876
|
+
if (rt.isInstance(value, rt.classNamed("flash.utils::ByteArray"))) {
|
|
877
|
+
const bytes = avm2.bytesOf(rt, value);
|
|
878
|
+
// Its memory, shared from now on; on a page that is not cross-origin
|
|
879
|
+
// isolated, the error that says so rather than a copy nobody writes.
|
|
880
|
+
if (bytes.shareable) {
|
|
881
|
+
const memory = bytes.share();
|
|
882
|
+
this.memories.set(memory.id, memory);
|
|
883
|
+
return { kind: "shared", memory };
|
|
884
|
+
}
|
|
885
|
+
return { kind: "bytes", bytes: bytes.buffer.slice(0, bytes.length) };
|
|
886
|
+
}
|
|
887
|
+
// By reference, as an address in the memory every worker has; on a page
|
|
888
|
+
// that is not cross-origin isolated, the error that says it needs it.
|
|
889
|
+
const ref = avm2.syncRef(value);
|
|
890
|
+
if (ref) {
|
|
891
|
+
if (!avm2.syncOf(rt).shared) {
|
|
892
|
+
throw avm2.notIsolated(ref.kind === "mutex" ? "a Mutex" : "a Condition");
|
|
893
|
+
}
|
|
894
|
+
return { kind: "sync", ref };
|
|
895
|
+
}
|
|
896
|
+
const holder = rt.construct(rt.classNamed("flash.utils::ByteArray"));
|
|
897
|
+
const bytes = avm2.bytesOf(rt, holder);
|
|
898
|
+
new avm2.Amf3Writer(rt, bytes).value(value);
|
|
899
|
+
return { kind: "amf", bytes: bytes.buffer.slice(0, bytes.length) };
|
|
900
|
+
}
|
|
901
|
+
decode(wire) {
|
|
902
|
+
const rt = this.s.rt;
|
|
903
|
+
switch (wire.kind) {
|
|
904
|
+
case "value":
|
|
905
|
+
return wire.value;
|
|
906
|
+
case "channel":
|
|
907
|
+
return this.channelObject(wire.channel);
|
|
908
|
+
case "sync":
|
|
909
|
+
return avm2.syncObject(rt, wire.ref);
|
|
910
|
+
case "shared":
|
|
911
|
+
this.memories.set(wire.memory.id, wire.memory);
|
|
912
|
+
return avm2.sharedByteArray(rt, wire.memory);
|
|
913
|
+
case "bytes":
|
|
914
|
+
case "amf": {
|
|
915
|
+
const holder = rt.construct(rt.classNamed("flash.utils::ByteArray"));
|
|
916
|
+
const bytes = avm2.bytesOf(rt, holder);
|
|
917
|
+
bytes.write(wire.bytes);
|
|
918
|
+
bytes.position = 0;
|
|
919
|
+
return wire.kind === "bytes" ? holder : new avm2.Amf3Reader(rt, bytes).value();
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
}
|