module

WebExtension

According to architecture of WebKit2GTK, JavaScript code runs in a separeted process called Render Process. That's why extending JavaScript can not be done in the same process which manages the WebView. Instead WebKit2GTK proposes a new way to extend JavaScript with native code called WebExtension. A WebExtension is a shared library which will be loaded at runtime by Render Process. This module provides some simple macros to reduce redundant works in making a webExtension. The following code shows an simple example which provides a JS function. It reads given file on filesystem.

require "alizarin"
include WebExtension
initialize_extension do
  # code inside this block will be executed when this Web Extension is loaded by Render Process
  func = function params do
    if params.size != 1
      JSCFunction.raise "#{params.size} parameter(s) provided, expect 1"
      undefined
    else
      path = params.first.to_s
      File.read(path) rescue nil # Return content of file at *path*, otherwise return JS's null
    end
  end
  JSCContext.set_value("read_file", func)
end

Builds shared library:

$ crystal build --single-module --link-flags="-shared -fpic" -o <output-path> <source-file>

NOTE: The shared library should be placed in the directory provided with WebView#extension_dir=

In main process (which manages an instance of WebView), opens WebInspector's console and types:

read_file("/a-file-located-some-where")

See more:

  1. JSCContext
  2. JSCFunction
  3. JSCPrimative
  4. JSCObject
  5. JSObjectUtils

Class methods

eval(js : String)

Evaluates js and gets the result back.

Source
uuid

Gets UUID hex string of the WebView which loads this extension

Source

Macros

function(arg_name)

This macro initializes an anonymous JavaScript function.

func = function p do
  puts typeof(p) # => Array(JSCFunction|JSCObject|JSCPrimative)
  # Developers can return anything as long as it has method to_jsc() : JSC::JSValue
  if p.size != 0
    JSCPrimative.new true
  else
    false
  else
  # return type is (JSCPrimative|Bool), it's ok because both JSCPrimative and Bool have method to_jsc()
end
Source
initialize_extension

Entry point of a Web Extension shared library

Source
new(constructor, *args)

JavaScript's new operator, returns JSCPrimative | JSCFunction | JSCObject

include WebExtension
promise = JSCContext.get_value("Promise")
new Promise, function p {
  resolve = p.first.as(JSCFunction)
  spawn do
    1000.times{ sleep 0.1 }
    resolve.call true
  end
}
Source
register_class(type)

Exposes a Crystal's Class so it can be used in JavaScript

Example:

  • webextension.cr:
class File
  def initialize(p : [] of (JSCFunction | JSCObject | JSCPrimative))
    super(p.first.to_s)
  end

  @[JSCInstanceMethod]
  def content(p)
    self.seek(0)
    self.gets_to_end
  end
end
JSCContext.set_value "File", WebExtension.register_class(File)
  • index.js
var content = new File("./LICENSE").content();

See more at JSCInstanceMethod.

Source
undefined

JavaScript undefined

Source

Nested types