Skip to content

toLeopard: Avoid overwriting any browser globals, perhaps #138

@towerofnix

Description

@towerofnix

From @PullJosh: #137 (comment)

Question: Do we want to blacklist browser-provided identifiers like Array, Audio, Error, File, Map, Set, Temporal, etc., which are not used in generated Leopard code but could cause conflicts or confusion when the user starts adding their own hand-written JS code?

There are a lot of them. And keeping up-to-date might be challenging.

We're really interested in this point. It's true that with the new PR, we avoid overwriting globals which in-scope generated Leopard code depends on, fixing certain project runtime bugs when the fates align poorly (#133).

But that's not the only reason to avoid overwriting globals. Like PullJosh wrote, users who are learning JavaScript will start to use lots of browser-provided globals. (And likely pretty quickly! BTW, Object is missing from your list ✨) It would be nice if generated code never overshadowed at least the popular ones.

It would be pretty snazzy if the Leopard editor gracefully helped you rename sprites, but in the meanwhile (and certainly if you're working in your own text editor) it can be awkward to change a generates sprite named Array over to, well, some other name, when you want to start using array utilities... in the sprite... that is named Array. (You know, after you've introduced code in other sprites that already uses Array, so now the string "Array" means two totally different things in your overall project code.)


Some implementation thoughts:

  • Yes, maintaining the list ourselves would be awkward. Temporal is a nice new global (good point) and more are getting added all the time. There's obviously a limit to what Leopard should handle, and we wouldn't be totally amiss to just select the most popular ones, or the ones that are part of the ECMAScript standard itself (rather than DOM, etc), or so on. However...
  • Another alternative is to just use the globals package. This is an abundantly popular package (75M+ weekly downloads, recommended by eslint, etc) and literally automatically up-to-date.
  • We should probably choose a better name than just tacking on a 2. class Array2 extends Sprite is silly. How about class ArraySprite extends Sprite? Or something else?
Here are all the first-letter-capitalized names in globals.browser.

AbortController AbortSignal AbsoluteOrientationSensor AbstractRange Accelerometer AnalyserNode Animation AnimationEffect AnimationEvent AnimationPlaybackEvent AnimationTimeline Attr Audio AudioBuffer AudioBufferSourceNode AudioContext AudioData AudioDecoder AudioDestinationNode AudioEncoder AudioListener AudioNode AudioParam AudioParamMap AudioProcessingEvent AudioScheduledSourceNode AudioSinkInfo AudioWorklet AudioWorkletGlobalScope AudioWorkletNode AudioWorkletProcessor AuthenticatorAssertionResponse AuthenticatorAttestationResponse AuthenticatorResponse BackgroundFetchManager BackgroundFetchRecord BackgroundFetchRegistration BarProp BaseAudioContext BatteryManager BeforeUnloadEvent BiquadFilterNode Blob BlobEvent Bluetooth BluetoothCharacteristicProperties BluetoothDevice BluetoothRemoteGATTCharacteristic BluetoothRemoteGATTDescriptor BluetoothRemoteGATTServer BluetoothRemoteGATTService BluetoothUUID BroadcastChannel BrowserCaptureMediaStreamTrack ByteLengthQueuingStrategy Cache CacheStorage CanvasCaptureMediaStream CanvasCaptureMediaStreamTrack CanvasGradient CanvasPattern CanvasRenderingContext2D CaptureController CaretPosition CDATASection ChannelMergerNode ChannelSplitterNode CharacterBoundsUpdateEvent CharacterData Clipboard ClipboardEvent ClipboardItem CloseEvent Comment CompositionEvent CompressionStream ConstantSourceNode ContentVisibilityAutoStateChangeEvent ConvolverNode CookieChangeEvent CookieDeprecationLabel CookieStore CookieStoreManager CountQueuingStrategy Credential CredentialsContainer CropTarget Crypto CryptoKey CSS CSSAnimation CSSConditionRule CSSContainerRule CSSCounterStyleRule CSSFontFaceRule CSSFontFeatureValuesRule CSSFontPaletteValuesRule CSSGroupingRule CSSImageValue CSSImportRule CSSKeyframeRule CSSKeyframesRule CSSKeywordValue CSSLayerBlockRule CSSLayerStatementRule CSSMathClamp CSSMathInvert CSSMathMax CSSMathMin CSSMathNegate CSSMathProduct CSSMathSum CSSMathValue CSSMatrixComponent CSSMediaRule CSSNamespaceRule CSSNumericArray CSSNumericValue CSSPageRule CSSPerspective CSSPositionTryDescriptors CSSPositionTryRule CSSPositionValue CSSPropertyRule CSSRotate CSSRule CSSRuleList CSSScale CSSScopeRule CSSSkew CSSSkewX CSSSkewY CSSStartingStyleRule CSSStyleDeclaration CSSStyleRule CSSStyleSheet CSSStyleValue CSSSupportsRule CSSTransformComponent CSSTransformValue CSSTransition CSSTranslate CSSUnitValue CSSUnparsedValue CSSVariableReferenceValue CustomElementRegistry CustomEvent CustomStateSet DataTransfer DataTransferItem DataTransferItemList DecompressionStream DelayNode DelegatedInkTrailPresenter DeviceMotionEvent DeviceMotionEventAcceleration DeviceMotionEventRotationRate DeviceOrientationEvent Document DocumentFragment DocumentPictureInPicture DocumentPictureInPictureEvent DocumentTimeline DocumentType DOMError DOMException DOMImplementation DOMMatrix DOMMatrixReadOnly DOMParser DOMPoint DOMPointReadOnly DOMQuad DOMRect DOMRectList DOMRectReadOnly DOMStringList DOMStringMap DOMTokenList DragEvent DynamicsCompressorNode EditContext Element ElementInternals EncodedAudioChunk EncodedVideoChunk ErrorEvent Event EventCounts EventSource EventTarget External EyeDropper FeaturePolicy FederatedCredential Fence FencedFrameConfig FetchLaterResult File FileList FileReader FileSystem FileSystemDirectoryEntry FileSystemDirectoryHandle FileSystemDirectoryReader FileSystemEntry FileSystemFileEntry FileSystemFileHandle FileSystemHandle FileSystemWritableFileStream FocusEvent FontData FontFace FontFaceSet FontFaceSetLoadEvent FormData FormDataEvent FragmentDirective GainNode Gamepad GamepadAxisMoveEvent GamepadButton GamepadButtonEvent GamepadEvent GamepadHapticActuator GamepadPose Geolocation GeolocationCoordinates GeolocationPosition GeolocationPositionError GPU GPUAdapter GPUAdapterInfo GPUBindGroup GPUBindGroupLayout GPUBuffer GPUBufferUsage GPUCanvasContext GPUColorWrite GPUCommandBuffer GPUCommandEncoder GPUCompilationInfo GPUCompilationMessage GPUComputePassEncoder GPUComputePipeline GPUDevice GPUDeviceLostInfo GPUError GPUExternalTexture GPUInternalError GPUMapMode GPUOutOfMemoryError GPUPipelineError GPUPipelineLayout GPUQuerySet GPUQueue GPURenderBundle GPURenderBundleEncoder GPURenderPassEncoder GPURenderPipeline GPUSampler GPUShaderModule GPUShaderStage GPUSupportedFeatures GPUSupportedLimits GPUTexture GPUTextureUsage GPUTextureView GPUUncapturedErrorEvent GPUValidationError GravitySensor Gyroscope HashChangeEvent Headers HID HIDConnectionEvent HIDDevice HIDInputReportEvent Highlight HighlightRegistry History HTMLAllCollection HTMLAnchorElement HTMLAreaElement HTMLAudioElement HTMLBaseElement HTMLBodyElement HTMLBRElement HTMLButtonElement HTMLCanvasElement HTMLCollection HTMLDataElement HTMLDataListElement HTMLDetailsElement HTMLDialogElement HTMLDirectoryElement HTMLDivElement HTMLDListElement HTMLDocument HTMLElement HTMLEmbedElement HTMLFencedFrameElement HTMLFieldSetElement HTMLFontElement HTMLFormControlsCollection HTMLFormElement HTMLFrameElement HTMLFrameSetElement HTMLHeadElement HTMLHeadingElement HTMLHRElement HTMLHtmlElement HTMLIFrameElement HTMLImageElement HTMLInputElement HTMLLabelElement HTMLLegendElement HTMLLIElement HTMLLinkElement HTMLMapElement HTMLMarqueeElement HTMLMediaElement HTMLMenuElement HTMLMetaElement HTMLMeterElement HTMLModElement HTMLObjectElement HTMLOListElement HTMLOptGroupElement HTMLOptionElement HTMLOptionsCollection HTMLOutputElement HTMLParagraphElement HTMLParamElement HTMLPictureElement HTMLPreElement HTMLProgressElement HTMLQuoteElement HTMLScriptElement HTMLSelectElement HTMLSlotElement HTMLSourceElement HTMLSpanElement HTMLStyleElement HTMLTableCaptionElement HTMLTableCellElement HTMLTableColElement HTMLTableElement HTMLTableRowElement HTMLTableSectionElement HTMLTemplateElement HTMLTextAreaElement HTMLTimeElement HTMLTitleElement HTMLTrackElement HTMLUListElement HTMLUnknownElement HTMLVideoElement IDBCursor IDBCursorWithValue IDBDatabase IDBFactory IDBIndex IDBKeyRange IDBObjectStore IDBOpenDBRequest IDBRequest IDBTransaction IDBVersionChangeEvent IdentityCredential IdentityCredentialError IdentityProvider IdleDeadline IdleDetector IIRFilterNode Image ImageBitmap ImageBitmapRenderingContext ImageCapture ImageData ImageDecoder ImageTrack ImageTrackList Ink InputDeviceCapabilities InputDeviceInfo InputEvent IntersectionObserver IntersectionObserverEntry Iterator Keyboard KeyboardEvent KeyboardLayoutMap KeyframeEffect LargestContentfulPaint LaunchParams LaunchQueue LayoutShift LayoutShiftAttribution LinearAccelerationSensor Location Lock LockManager MathMLElement MediaCapabilities MediaCapabilitiesInfo MediaDeviceInfo MediaDevices MediaElementAudioSourceNode MediaEncryptedEvent MediaError MediaKeyError MediaKeyMessageEvent MediaKeys MediaKeySession MediaKeyStatusMap MediaKeySystemAccess MediaList MediaMetadata MediaQueryList MediaQueryListEvent MediaRecorder MediaRecorderErrorEvent MediaSession MediaSource MediaSourceHandle MediaStream MediaStreamAudioDestinationNode MediaStreamAudioSourceNode MediaStreamEvent MediaStreamTrack MediaStreamTrackAudioSourceNode MediaStreamTrackAudioStats MediaStreamTrackEvent MediaStreamTrackGenerator MediaStreamTrackProcessor MediaStreamTrackVideoStats MessageChannel MessageEvent MessagePort MIDIAccess MIDIConnectionEvent MIDIInput MIDIInputMap MIDIMessageEvent MIDIOutput MIDIOutputMap MIDIPort MimeType MimeTypeArray ModelGenericSession ModelManager MouseEvent MutationEvent MutationObserver MutationRecord NamedNodeMap NavigateEvent Navigation NavigationActivation NavigationCurrentEntryChangeEvent NavigationDestination NavigationHistoryEntry NavigationPreloadManager NavigationTransition Navigator NavigatorLogin NavigatorManagedData NavigatorUAData NetworkInformation Node NodeFilter NodeIterator NodeList Notification NotifyPaintEvent NotRestoredReasonDetails NotRestoredReasons OfflineAudioCompletionEvent OfflineAudioContext OffscreenCanvas OffscreenCanvasRenderingContext2D Option OrientationSensor OscillatorNode OTPCredential OverconstrainedError PageRevealEvent PageSwapEvent PageTransitionEvent PannerNode PasswordCredential Path2D PaymentAddress PaymentManager PaymentMethodChangeEvent PaymentRequest PaymentRequestUpdateEvent PaymentResponse Performance PerformanceElementTiming PerformanceEntry PerformanceEventTiming PerformanceLongAnimationFrameTiming PerformanceLongTaskTiming PerformanceMark PerformanceMeasure PerformanceNavigation PerformanceNavigationTiming PerformanceObserver PerformanceObserverEntryList PerformancePaintTiming PerformanceResourceTiming PerformanceScriptTiming PerformanceServerTiming PerformanceTiming PeriodicSyncManager PeriodicWave Permissions PermissionStatus PERSISTENT PictureInPictureEvent PictureInPictureWindow Plugin PluginArray PointerEvent PopStateEvent Presentation PresentationAvailability PresentationConnection PresentationConnectionAvailableEvent PresentationConnectionCloseEvent PresentationConnectionList PresentationReceiver PresentationRequest PressureObserver PressureRecord ProcessingInstruction Profiler ProgressEvent PromiseRejectionEvent ProtectedAudience PublicKeyCredential PushManager PushSubscription PushSubscriptionOptions RadioNodeList Range ReadableByteStreamController ReadableStream ReadableStreamBYOBReader ReadableStreamBYOBRequest ReadableStreamDefaultController ReadableStreamDefaultReader RelativeOrientationSensor RemotePlayback ReportingObserver Request ResizeObserver ResizeObserverEntry ResizeObserverSize Response RTCCertificate RTCDataChannel RTCDataChannelEvent RTCDtlsTransport RTCDTMFSender RTCDTMFToneChangeEvent RTCEncodedAudioFrame RTCEncodedVideoFrame RTCError RTCErrorEvent RTCIceCandidate RTCIceTransport RTCPeerConnection RTCPeerConnectionIceErrorEvent RTCPeerConnectionIceEvent RTCRtpReceiver RTCRtpScriptTransform RTCRtpSender RTCRtpTransceiver RTCSctpTransport RTCSessionDescription RTCStatsReport RTCTrackEvent Scheduler Scheduling Screen ScreenDetailed ScreenDetails ScreenOrientation ScriptProcessorNode ScrollTimeline SecurityPolicyViolationEvent Selection Sensor SensorErrorEvent Serial SerialPort ServiceWorker ServiceWorkerContainer ServiceWorkerRegistration ShadowRoot SharedStorage SharedStorageWorklet SharedWorker SourceBuffer SourceBufferList SpeechSynthesis SpeechSynthesisErrorEvent SpeechSynthesisEvent SpeechSynthesisUtterance SpeechSynthesisVoice StaticRange StereoPannerNode Storage StorageBucket StorageBucketManager StorageEvent StorageManager StylePropertyMap StylePropertyMapReadOnly StyleSheet StyleSheetList SubmitEvent SubtleCrypto SVGAElement SVGAngle SVGAnimatedAngle SVGAnimatedBoolean SVGAnimatedEnumeration SVGAnimatedInteger SVGAnimatedLength SVGAnimatedLengthList SVGAnimatedNumber SVGAnimatedNumberList SVGAnimatedPreserveAspectRatio SVGAnimatedRect SVGAnimatedString SVGAnimatedTransformList SVGAnimateElement SVGAnimateMotionElement SVGAnimateTransformElement SVGAnimationElement SVGCircleElement SVGClipPathElement SVGComponentTransferFunctionElement SVGDefsElement SVGDescElement SVGElement SVGEllipseElement SVGFEBlendElement SVGFEColorMatrixElement SVGFEComponentTransferElement SVGFECompositeElement SVGFEConvolveMatrixElement SVGFEDiffuseLightingElement SVGFEDisplacementMapElement SVGFEDistantLightElement SVGFEDropShadowElement SVGFEFloodElement SVGFEFuncAElement SVGFEFuncBElement SVGFEFuncGElement SVGFEFuncRElement SVGFEGaussianBlurElement SVGFEImageElement SVGFEMergeElement SVGFEMergeNodeElement SVGFEMorphologyElement SVGFEOffsetElement SVGFEPointLightElement SVGFESpecularLightingElement SVGFESpotLightElement SVGFETileElement SVGFETurbulenceElement SVGFilterElement SVGForeignObjectElement SVGGElement SVGGeometryElement SVGGradientElement SVGGraphicsElement SVGImageElement SVGLength SVGLengthList SVGLinearGradientElement SVGLineElement SVGMarkerElement SVGMaskElement SVGMatrix SVGMetadataElement SVGMPathElement SVGNumber SVGNumberList SVGPathElement SVGPatternElement SVGPoint SVGPointList SVGPolygonElement SVGPolylineElement SVGPreserveAspectRatio SVGRadialGradientElement SVGRect SVGRectElement SVGScriptElement SVGSetElement SVGStopElement SVGStringList SVGStyleElement SVGSVGElement SVGSwitchElement SVGSymbolElement SVGTextContentElement SVGTextElement SVGTextPathElement SVGTextPositioningElement SVGTitleElement SVGTransform SVGTransformList SVGTSpanElement SVGUnitTypes SVGUseElement SVGViewElement SyncManager TaskAttributionTiming TaskController TaskPriorityChangeEvent TaskSignal TEMPORARY Text TextDecoder TextDecoderStream TextEncoder TextEncoderStream TextEvent TextFormat TextFormatUpdateEvent TextMetrics TextTrack TextTrackCue TextTrackCueList TextTrackList TextUpdateEvent TimeEvent TimeRanges ToggleEvent Touch TouchEvent TouchList TrackEvent TransformStream TransformStreamDefaultController TransitionEvent TreeWalker TrustedHTML TrustedScript TrustedScriptURL TrustedTypePolicy TrustedTypePolicyFactory UIEvent URL URLPattern URLSearchParams USB USBAlternateInterface USBConfiguration USBConnectionEvent USBDevice USBEndpoint USBInterface USBInTransferResult USBIsochronousInTransferPacket USBIsochronousInTransferResult USBIsochronousOutTransferPacket USBIsochronousOutTransferResult USBOutTransferResult UserActivation ValidityState VideoColorSpace VideoDecoder VideoEncoder VideoFrame VideoPlaybackQuality ViewTimeline ViewTransition ViewTransitionTypeSet VirtualKeyboard VirtualKeyboardGeometryChangeEvent VisibilityStateEntry VisualViewport VTTCue VTTRegion WakeLock WakeLockSentinel WaveShaperNode WebAssembly WebGL2RenderingContext WebGLActiveInfo WebGLBuffer WebGLContextEvent WebGLFramebuffer WebGLProgram WebGLQuery WebGLRenderbuffer WebGLRenderingContext WebGLSampler WebGLShader WebGLShaderPrecisionFormat WebGLSync WebGLTexture WebGLTransformFeedback WebGLUniformLocation WebGLVertexArrayObject WebSocket WebSocketError WebSocketStream WebTransport WebTransportBidirectionalStream WebTransportDatagramDuplexStream WebTransportError WebTransportReceiveStream WebTransportSendStream WGSLLanguageFeatures WheelEvent Window WindowControlsOverlay WindowControlsOverlayGeometryChangeEvent Worker Worklet WorkletGlobalScope WritableStream WritableStreamDefaultController WritableStreamDefaultWriter XMLDocument XMLHttpRequest XMLHttpRequestEventTarget XMLHttpRequestUpload XMLSerializer XPathEvaluator XPathExpression XPathResult XRAnchor XRAnchorSet XRBoundedReferenceSpace XRCamera XRCPUDepthInformation XRDepthInformation XRDOMOverlayState XRFrame XRHitTestResult XRHitTestSource XRInputSource XRInputSourceArray XRInputSourceEvent XRInputSourcesChangeEvent XRLayer XRLightEstimate XRLightProbe XRPose XRRay XRReferenceSpace XRReferenceSpaceEvent XRRenderState XRRigidTransform XRSession XRSessionEvent XRSpace XRSystem XRTransientInputHitTestResult XRTransientInputHitTestSource XRView XRViewerPose XRViewport XRWebGLBinding XRWebGLDepthInformation XRWebGLLayer XSLTProcessor

And here are just the ones under globals.builtin. (Please note that this is not a subset of globals.browser, i.e. we need to combine them if we want to use both.)

AggregateError Array ArrayBuffer Atomics BigInt BigInt64Array BigUint64Array Boolean DataView Date Error EvalError FinalizationRegistry Float32Array Float64Array Function Infinity Int16Array Int32Array Int8Array Intl JSON Map Math NaN Number Object Promise Proxy RangeError ReferenceError Reflect RegExp Set SharedArrayBuffer String Symbol SyntaxError TypeError Uint16Array Uint32Array Uint8Array Uint8ClampedArray URIError WeakMap WeakRef WeakSet

(Note that the list above includes recent additions like AggregateError.)

So we have a few practical options:

  1. Just hard-code our own list, altogether, but more expansive than currently. Admit that it's not intended to be comprehensive. May be a subset of globals.builtin or a subset of the union [globals.builtin, globals.browser].
  2. Hard-code our own subset of globals.builtin and combine that with globals.browser in its entirety.
  3. Use globals.builtin in its entirety, don't bother with globals.browser.
  4. Use the union of globals.builtin and globals.browser in its entirety.

I'm leaning towards the "don't hard-code anything" options, but could go either way on including globals.browser. There are a lot of names in that list, and most of them are extremely domain-specific. There's a decent chance that users themselves might code new Sprite subclasses with those names, and never run into a problem for it! But do feel free to convince us that globals.browser should totally be part of the reserved sprite name list, if you think that's right. Or share some totally different direction, we're always interested! 🥳

Metadata

Metadata

Assignees

No one assigned

    Labels

    fmt: LeopardPertains to Leopard format (JavaScript)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions