Support [NoInterfaceObject] in web-sys

This commit enables `[NoInterfaceObject]` annotated interfaces in
`web-sys`. The `NoInterfaceObject` attribute means that there's not
actually a JS class for the object, but all of its properties and such
can still be accessed structually and invoked. This should help provide
more bindings for some more common types on the web!

Note that this builds on recent features to ensure that `dyn_into` and
friends always fail for `NoInterfaceObject` objects because they don't
actually have a class.

Closes #893
Closes #1257
Closes #1315
This commit is contained in:
Alex Crichton 2019-04-12 11:08:05 -07:00
parent c4776becbb
commit 01a52233d3
7 changed files with 121 additions and 17 deletions

View File

@ -56,6 +56,7 @@ Algorithm = []
AlignSetting = []
AnalyserNode = []
AnalyserOptions = []
AngleInstancedArrays = []
Animation = []
AnimationEffect = []
AnimationEvent = []
@ -63,6 +64,7 @@ AnimationEventInit = []
AnimationPlayState = []
AnimationPlaybackEvent = []
AnimationPlaybackEventInit = []
AnimationPropertyDetails = []
AnimationPropertyValueDetails = []
AnimationTimeline = []
AssignedNodesOptions = []
@ -159,6 +161,7 @@ ChromeFilePropertyBag = []
ChromeWorker = []
Client = []
ClientQueryOptions = []
ClientRectsAndTexts = []
ClientType = []
Clients = []
ClipboardEvent = []
@ -195,6 +198,7 @@ ContextAttributes2d = []
ConvertCoordinateOptions = []
ConvolverNode = []
ConvolverOptions = []
Coordinates = []
Credential = []
CredentialCreationOptions = []
CredentialRequestOptions = []
@ -240,6 +244,7 @@ DecoderDoctorNotificationType = []
DedicatedWorkerGlobalScope = []
DelayNode = []
DelayOptions = []
DeviceAcceleration = []
DeviceAccelerationInit = []
DeviceLightEvent = []
DeviceLightEventInit = []
@ -249,6 +254,7 @@ DeviceOrientationEvent = []
DeviceOrientationEventInit = []
DeviceProximityEvent = []
DeviceProximityEventInit = []
DeviceRotationRate = []
DeviceRotationRateInit = []
DhKeyDeriveParams = []
DirectionSetting = []
@ -311,11 +317,22 @@ EventModifierInit = []
EventSource = []
EventSourceInit = []
EventTarget = []
Exception = []
ExtBlendMinmax = []
ExtColorBufferFloat = []
ExtColorBufferHalfFloat = []
ExtDisjointTimerQuery = []
ExtFragDepth = []
ExtSRgb = []
ExtShaderTextureLod = []
ExtTextureFilterAnisotropic = []
ExtendableEvent = []
ExtendableEventInit = []
ExtendableMessageEvent = []
ExtendableMessageEventInit = []
External = []
FakePluginMimeEntry = []
FakePluginTagInit = []
FetchEvent = []
FetchEventInit = []
FetchObserver = []
@ -345,6 +362,7 @@ FontFace = []
FontFaceDescriptors = []
FontFaceLoadStatus = []
FontFaceSet = []
FontFaceSetIterator = []
FontFaceSetIteratorResult = []
FontFaceSetLoadEvent = []
FontFaceSetLoadEventInit = []
@ -368,8 +386,10 @@ GamepadHapticActuatorType = []
GamepadMappingType = []
GamepadPose = []
GamepadServiceTest = []
Geolocation = []
GetNotificationOptions = []
GetRootNodeOptions = []
GetUserMediaRequest = []
GridDeclaration = []
GridTrackState = []
GroupedHistoryEventInit = []
@ -416,6 +436,7 @@ HtmlHeadElement = []
HtmlHeadingElement = []
HtmlHrElement = []
HtmlHtmlElement = []
HtmlHyperlinkElementUtils = []
HtmlIFrameElement = []
HtmlImageElement = []
HtmlInputElement = []
@ -491,10 +512,12 @@ IdbVersionChangeEventInit = []
IdleDeadline = []
IdleRequestOptions = []
IirFilterNode = []
IirFilterOptions = []
ImageBitmap = []
ImageBitmapFormat = []
ImageBitmapRenderingContext = []
ImageCapture = []
ImageCaptureError = []
ImageCaptureErrorEvent = []
ImageCaptureErrorEventInit = []
ImageData = []
@ -505,12 +528,14 @@ IntersectionObserver = []
IntersectionObserverEntry = []
IntersectionObserverEntryInit = []
IntersectionObserverInit = []
IntlUtils = []
IterableKeyAndValueResult = []
IterableKeyOrValueResult = []
IterationCompositeOperation = []
JsonWebKey = []
KeyAlgorithm = []
KeyEvent = []
KeyIdsInitData = []
KeyboardEvent = []
KeyboardEventInit = []
KeyframeEffect = []
@ -519,6 +544,7 @@ L10nElement = []
L10nValue = []
LifecycleCallbacks = []
LineAlignSetting = []
ListBoxObject = []
LocalMediaStream = []
LocaleInfo = []
Location = []
@ -569,6 +595,7 @@ MediaStreamAudioDestinationNode = []
MediaStreamAudioSourceNode = []
MediaStreamAudioSourceOptions = []
MediaStreamConstraints = []
MediaStreamError = []
MediaStreamEvent = []
MediaStreamEventInit = []
MediaStreamTrack = []
@ -602,6 +629,7 @@ MimeTypeArray = []
MouseEvent = []
MouseEventInit = []
MouseScrollEvent = []
MozDebug = []
MutationEvent = []
MutationObserver = []
MutationObserverInit = []
@ -612,6 +640,7 @@ NativeOsFileReadOptions = []
NativeOsFileWriteAtomicOptions = []
NavigationType = []
Navigator = []
NavigatorAutomationInformation = []
NetworkCommandOptions = []
NetworkInformation = []
NetworkResultOptions = []
@ -627,6 +656,13 @@ NotificationEventInit = []
NotificationOptions = []
NotificationPermission = []
ObserverCallback = []
OesElementIndexUint = []
OesStandardDerivatives = []
OesTextureFloat = []
OesTextureFloatLinear = []
OesTextureHalfFloat = []
OesTextureHalfFloatLinear = []
OesVertexArrayObject = []
OfflineAudioCompletionEvent = []
OfflineAudioCompletionEventInit = []
OfflineAudioContext = []
@ -672,6 +708,7 @@ PerformanceNavigation = []
PerformanceNavigationTiming = []
PerformanceObserver = []
PerformanceObserverEntryList = []
PerformanceObserverInit = []
PerformanceResourceTiming = []
PerformanceServerTiming = []
PerformanceTiming = []
@ -693,7 +730,9 @@ PopStateEvent = []
PopStateEventInit = []
PopupBlockedEvent = []
PopupBlockedEventInit = []
Position = []
PositionAlignSetting = []
PositionError = []
PositionOptions = []
Presentation = []
PresentationAvailability = []
@ -716,9 +755,11 @@ ProfileTimelineStackFrame = []
ProfileTimelineWorkerOperationType = []
ProgressEvent = []
ProgressEventInit = []
PromiseNativeHandler = []
PromiseRejectionEvent = []
PromiseRejectionEventInit = []
PublicKeyCredential = []
PublicKeyCredentialCreationOptions = []
PublicKeyCredentialDescriptor = []
PublicKeyCredentialEntity = []
PublicKeyCredentialParameters = []
@ -792,6 +833,7 @@ RtcIdentityAssertionResult = []
RtcIdentityProvider = []
RtcIdentityProviderDetails = []
RtcIdentityProviderOptions = []
RtcIdentityProviderRegistrar = []
RtcIdentityValidationResult = []
RtcInboundRtpStreamStats = []
RtcLifecycleEvent = []
@ -844,6 +886,7 @@ ScreenOrientation = []
ScriptProcessorNode = []
ScrollAreaEvent = []
ScrollBehavior = []
ScrollBoxObject = []
ScrollIntoViewOptions = []
ScrollLogicalPosition = []
ScrollOptions = []
@ -952,7 +995,27 @@ SvgMetadataElement = []
SvgNumber = []
SvgNumberList = []
SvgPathElement = []
SvgPathSeg = []
SvgPathSegArcAbs = []
SvgPathSegArcRel = []
SvgPathSegClosePath = []
SvgPathSegCurvetoCubicAbs = []
SvgPathSegCurvetoCubicRel = []
SvgPathSegCurvetoCubicSmoothAbs = []
SvgPathSegCurvetoCubicSmoothRel = []
SvgPathSegCurvetoQuadraticAbs = []
SvgPathSegCurvetoQuadraticRel = []
SvgPathSegCurvetoQuadraticSmoothAbs = []
SvgPathSegCurvetoQuadraticSmoothRel = []
SvgPathSegLinetoAbs = []
SvgPathSegLinetoHorizontalAbs = []
SvgPathSegLinetoHorizontalRel = []
SvgPathSegLinetoRel = []
SvgPathSegLinetoVerticalAbs = []
SvgPathSegLinetoVerticalRel = []
SvgPathSegList = []
SvgPathSegMovetoAbs = []
SvgPathSegMovetoRel = []
SvgPatternElement = []
SvgPoint = []
SvgPointList = []
@ -1044,7 +1107,9 @@ TrackEventInit = []
TransitionEvent = []
TransitionEventInit = []
Transport = []
TreeBoxObject = []
TreeCellInfo = []
TreeView = []
TreeWalker = []
U2f = []
U2fClientData = []
@ -1183,6 +1248,19 @@ WebKitCssMatrix = []
WebSocket = []
WebSocketDict = []
WebSocketElement = []
WebglColorBufferFloat = []
WebglCompressedTextureAstc = []
WebglCompressedTextureAtc = []
WebglCompressedTextureEtc = []
WebglCompressedTextureEtc1 = []
WebglCompressedTexturePvrtc = []
WebglCompressedTextureS3tc = []
WebglCompressedTextureS3tcSrgb = []
WebglDebugRendererInfo = []
WebglDebugShaders = []
WebglDepthTexture = []
WebglDrawBuffers = []
WebglLoseContext = []
WebrtcGlobalStatisticsReport = []
WheelEvent = []
WheelEventInit = []

View File

@ -12,3 +12,4 @@ pub mod global;
pub mod namespace;
pub mod simple;
pub mod throws;
pub mod no_interface;

View File

@ -0,0 +1,8 @@
global.GetNoInterfaceObject = class {
static get() {
return {
number: 3,
foo: () => {},
}
}
};

View File

@ -0,0 +1,11 @@
use js_sys::Object;
use wasm_bindgen_test::*;
include!(concat!(env!("OUT_DIR"), "/no_interface.rs"));
#[wasm_bindgen_test]
fn smoke() {
let obj = GetNoInterfaceObject::get();
assert_eq!(obj.number(), 3.0);
obj.foo();
}

View File

@ -0,0 +1,9 @@
[NoInterfaceObject]
interface NoInterfaceObject {
readonly attribute double number;
void foo();
};
interface GetNoInterfaceObject {
static NoInterfaceObject get();
};

View File

@ -45,6 +45,7 @@ pub(crate) struct FirstPassRecord<'src> {
pub(crate) struct InterfaceData<'src> {
/// Whether only partial interfaces were encountered
pub(crate) partial: bool,
pub(crate) has_interface: bool,
pub(crate) deprecated: Option<String>,
pub(crate) attributes: Vec<&'src AttributeInterfaceMember<'src>>,
pub(crate) consts: Vec<&'src ConstMember<'src>>,
@ -303,22 +304,14 @@ impl<'src> FirstPass<'src, ()> for weedle::InterfaceDefinition<'src> {
return Ok(());
}
if util::is_no_interface_object(&self.attributes) {
log::info!(
"Skipping because of `NoInterfaceObject` attribute: {:?}",
self.identifier.0
);
return Ok(());
}
{
let interface_data = record.interfaces.entry(self.identifier.0).or_default();
interface_data.partial = false;
interface_data.superclass = self.inheritance.map(|s| s.identifier.0);
interface_data.definition_attributes = self.attributes.as_ref();
interface_data.deprecated =
util::get_rust_deprecated(&self.attributes).map(|s| s.to_string());
}
let interface_data = record.interfaces.entry(self.identifier.0).or_default();
interface_data.partial = false;
interface_data.superclass = self.inheritance.map(|s| s.identifier.0);
interface_data.definition_attributes = self.attributes.as_ref();
interface_data.deprecated =
util::get_rust_deprecated(&self.attributes).map(|s| s.to_string());
interface_data.has_interface =
!util::is_no_interface_object(&self.attributes);
if let Some(attrs) = &self.attributes {
for attr in attrs.body.list.iter() {
process_interface_attribute(record, self.identifier.0, attr);

View File

@ -514,7 +514,11 @@ impl<'src> FirstPassRecord<'src> {
attrs,
doc_comment: None,
instanceof_shim: format!("__widl_instanceof_{}", name),
is_type_of: None,
is_type_of: if data.has_interface {
None
} else {
Some(syn::parse_quote!{ |_| false })
},
extends: Vec::new(),
vendor_prefixes: Vec::new(),
};