mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-16 08:27:05 +00:00
dawn_node: Implement the [SameObject] IDL attribute
This is done by moving the set up of these attributes to the place where
the wrapper objects are created, by doing:
jsObject.DefineProperty("foo", impl->getOnceFoo());
Three alternatives that weren't chosen are:
- Caching a weak reference to the member's Napi::Value on the wrapper
struct, and recreate it only as needed. This is good because it
doesn't risk using the value after it is GCed, but it can result in
multiple calls to the getters, which could be unexpected (for example
for GPUDevice.lost in a follow-up CL).
- Caching a persistent reference to the member's Napi::Value on the
wrapper struct. This calls the getter once and doesn't risk using the
value after it is GCed. However if Javascript does something like
`myGPUDevice.limits.device = myGPUDevice`, a cycle is created that
the GC doesn't have visibility into, and that can't be collected.
(the origin of the edge of the reference graph that persistent
references make is unknown to the GC).
- Caching the member on a hidden variable of the JS object. I didn't
find a way to do this. The closest would have been to do
jsObject[Symbol(...)] = cachedValue but even symbols can be retrieved
with Object.getOwnPropertySymbols.
Bug: dawn:1123
Fixed: dawn:1144
Change-Id: I1bc82dd9d10be95bf2bdca73bdfb843bc556d2df
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/85361
Reviewed-by: Ben Clayton <bclayton@google.com>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
committed by
Dawn LUCI CQ
parent
76517cfc32
commit
ecc3fe6f0f
@@ -135,7 +135,6 @@ namespace wgpu::binding {
|
||||
}
|
||||
|
||||
interop::Interface<interop::GPUQueue> GPUDevice::getQueue(Napi::Env env) {
|
||||
// TODO(crbug.com/dawn/1144): Should probably return the same Queue JS object.
|
||||
return interop::GPUQueue::Create<GPUQueue>(env, device_.GetQueue(), async_);
|
||||
}
|
||||
|
||||
|
||||
@@ -149,9 +149,11 @@ Wrappers* Wrappers::instance = nullptr;
|
||||
InstanceMethod("{{$m.Name}}", &W{{$.Name}}::{{$m.Name}}),
|
||||
{{- end}}
|
||||
{{- range $a := AttributesOf $}}
|
||||
{{- if not (HasAnnotation $a "SameObject")}}
|
||||
InstanceAccessor("{{$a.Name}}", &W{{$.Name}}::get{{Title $a.Name}},
|
||||
{{- if $a.Readonly}} nullptr{{else}} &W{{$.Name}}::set{{Title $a.Name}}{{end -}}
|
||||
),
|
||||
{{- end}}
|
||||
{{- end}}
|
||||
{{- range $c := ConstantsOf $}}
|
||||
StaticValue("{{$c.Name}}", ToJS(env, {{$.Name}}::{{$c.Name}}), napi_default_jsproperty),
|
||||
@@ -219,6 +221,7 @@ Wrappers* Wrappers::instance = nullptr;
|
||||
{{- end}}
|
||||
|
||||
{{- range $a := AttributesOf $}}
|
||||
{{- if not (HasAnnotation $a "SameObject")}}
|
||||
Napi::Value get{{Title $a.Name}}(const Napi::CallbackInfo& info) {
|
||||
return ToJS(info.Env(), impl->get{{Title $a.Name}}(info.Env()));
|
||||
}
|
||||
@@ -233,7 +236,8 @@ Wrappers* Wrappers::instance = nullptr;
|
||||
Napi::Error::New(info.Env(), res.error).ThrowAsJavaScriptException();
|
||||
}
|
||||
}
|
||||
{{- end }}
|
||||
{{- end}}
|
||||
{{- end}}
|
||||
{{- end}}
|
||||
};
|
||||
{{end}}
|
||||
@@ -331,6 +335,16 @@ Interface<{{$.Name}}> {{$.Name}}::Bind(Napi::Env env, std::unique_ptr<{{$.Name}}
|
||||
auto object = wrappers->{{$.Name}}_ctor.New({});
|
||||
auto* wrapper = Wrappers::W{{$.Name}}::Unwrap(object);
|
||||
wrapper->impl = std::move(impl);
|
||||
|
||||
{{- /*Add the [SameObject] members as read-only property on the JS object.*/ -}}
|
||||
{{- range $a := AttributesOf $}}
|
||||
{{- if HasAnnotation $a "SameObject"}}
|
||||
object.DefineProperty(Napi::PropertyDescriptor::Value(
|
||||
"{{$a.Name}}", ToJS(env, wrapper->impl->get{{Title $a.Name}}(env))
|
||||
));
|
||||
{{- end}}
|
||||
{{- end}}
|
||||
|
||||
return Interface<{{$.Name}}>(object);
|
||||
}
|
||||
|
||||
|
||||
@@ -108,6 +108,7 @@ func run() error {
|
||||
"ConstantsOf": constantsOf,
|
||||
"EnumEntryName": enumEntryName,
|
||||
"Eval": g.eval,
|
||||
"HasAnnotation": hasAnnotation,
|
||||
"Include": g.include,
|
||||
"IsBasicLiteral": is(ast.BasicLiteral{}),
|
||||
"IsConstructor": isConstructor,
|
||||
@@ -493,6 +494,22 @@ func enumEntryName(s string) string {
|
||||
return "k" + strings.ReplaceAll(pascalCase(strings.Trim(s, `"`)), "-", "")
|
||||
}
|
||||
|
||||
func findAnnotation(list []*ast.Annotation, name string) *ast.Annotation {
|
||||
for _, annotation := range list {
|
||||
if annotation.Name == name {
|
||||
return annotation
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func hasAnnotation(obj interface{}, name string) bool {
|
||||
if member, ok := obj.(*ast.Member); ok {
|
||||
return findAnnotation(member.Annotations, name) != nil
|
||||
}
|
||||
panic("Unhandled AST node type in hasAnnotation")
|
||||
}
|
||||
|
||||
// Method describes a WebIDL interface method
|
||||
type Method struct {
|
||||
// Name of the method
|
||||
|
||||
Reference in New Issue
Block a user