1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

webview.hostObjects が async で失敗するのをなんとかする ver.2

Last updated at Posted at 2022-01-15

message を汚染せず匿名関数でやりくりするタイプ

JavaScript
addEventListener('ExeLoaded',e=>{

	var url = `https://script.google.com/macros/s/SampleDeployId/exec`;
	var text = `SampleText: Fixed newly exposed boat not showing up in the boat yard menu 
	Changed contraptions to drop resources and inventory objects (crates) to drop resources even 
	when killed with fire. Previously anything killed by fire would drop nothing.`

	chrome.webview.hostObjects.exe.PostError(url,text).then(r=>{
		console.log(r)// null、async失敗
	})
	_exe.post(url,text).then(r=>{
	 	console.log(r)// async成功
	})
})

var _exe = new class {
	constructor(){
		addEventListener('HostObjectAdded',e=>{
			this.Promise.data = {}
			this.Promise.id = 0
			e.value.methods.forEach(s=>this.addMethod(e.value.name,...s.split(',')))
			dispatchEvent(new Event('ExeLoaded'))
		})
	}
	addMethod(h,m,attr){
		var s = m[0].toLowerCase() + m.slice(1);
		if(this[s]) return
		if(attr=='async'){
			this[s] = (...a)=>new this.Promise.Script(h,m,...a)
		}else{
			this[s] = (...a)=>new this.Promise.Json(h,m,...a)
		}
	}
}
_exe.Promise = class{
	constructor(){this.hook = ()=>{}}
	then(resolve){
		this.hook = resolve
		return this
	}
}
_exe.Promise.Script = class extends _exe.Promise{
	constructor(h,s,...a){super()
		var id = ++_exe.Promise.id
		_exe.Promise.data[id] = this
		chrome.webview.hostObjects[h][s](`
			(function(v,i){
				v[i].hook(/*value*/)
				delete v[i]
			})(_exe.Promise.data,${id})
		`,...a)
	}
}
_exe.Promise.Json = class extends _exe.Promise{
	constructor(h,s,...a){super()
		chrome.webview.hostObjects[h][s](...a).then(r=>{
			try{this.hook(JSON.parse(r))}
			catch(e){this.hook(r)}
		})
	}
}
HostObject.cs
public class HostObject {
	protected CoreWebView2 core = null!;
	public HostObject(WebView2 view) {
		view.NavigationCompleted+=(s,e) => {
			core = view.CoreWebView2;
			core.AddHostObjectToScript("exe",this);
			IIFE(@$"
				var e = new Event('HostObjectAdded')
				e.value = {{
					name:'exe',
					methods:{JsonSerializer.Serialize(GetMethods())},
				}}
				dispatchEvent(e)
			");
		};
	}
	
	//nullが返る
	public async Task<string> PostError(string url,string data) {
		var content = new StringContent(data,Encoding.UTF8);
		using(var client = new HttpClient()) {
			var response = await client.PostAsync(url,content);
			var s = await response.Content.ReadAsStringAsync();
			return s;
		}
	}
	//手動でResolve 
	public async void Post(string script,string url,string data) {
		var content = new StringContent(data, Encoding.UTF8);
		using (var client = new HttpClient()){
		    var response = await client.PostAsync(url, content);
			var s = await response.Content.ReadAsStringAsync();
			Resolve(script,s);
		}
	}

	protected async void Resolve(string script,object v) {
		var s = script.Replace("/*value*/",JsonSerializer.Serialize(v));
		var r = await core.ExecuteScriptAsync(s);
	}
	protected async void IIFE(string script) {//即時実行関数
		var r = await core.ExecuteScriptAsync($"(function(){{{script}}})()");
	}
	public string[] GetMethods(){
		var objectMethods = typeof(Object).GetMethods();
		var methods = new List<string>();
		Type async = typeof(AsyncStateMachineAttribute);
		foreach(MethodInfo m in GetType().GetMethods()) {
			if(!Array.Exists(objectMethods,v => { return v.Name==m.Name; })){
				if(m.GetCustomAttribute(async)==null) {
					methods.Add(m.Name);
				} else {
					methods.Add($"{m.Name},async");
				}
			}
		}
		return methods.ToArray();
	}
}
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?