Skip to content

A fifth composite pull request #81

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Nov 12, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion opal/browser/blob.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,19 @@ def text(&block)
end

# {Buffer} view into the blob
#
# If block is given it will be called with a parameter once we receive
# the buffer. Otherwise return a {Promise} which will resolve once we
# receive it.
def buffer
Buffer.new(`#@native.arrayBuffer()`)
promise = nil
unless block_given?
promise = Promise.new
block = proc { |i| promise.resolve(i) }
end
resblock = proc { |i| block.call(Buffer.new(i)) }
`#@native.arrayBuffer().then(#{resblock.to_n})`
promise
end

# Create a new blob by slicing this blob
Expand Down
79 changes: 79 additions & 0 deletions opal/browser/crypto.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
module Browser

# Implements (parts of) the web crypto interface
#
# https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API
class Crypto
include NativeCachedWrapper

class Digest
def initialize(buf)
@buffer = Buffer.new(buf)
end

attr_reader :buffer

# Convert a digest to a hexadecimal string
def to_hex
buffer.to_a.map { |i| "%02x" % i }.join
end

# Convert a digest to a binary string
def to_s
buffer.to_a.map { |i| "%c" % i }.join
end

# Convert a digest to a Base64-encoded string
#
# You will need to `require "base64"`
def to_b64
Base64.strict_encode64(to_s)
end

# Convert a digest to a urlsafe Base64-encoded string
#
# You will need to `require "base64"`
def to_u64(padding: false)
Base64.urlsafe_encode64(to_s, padding: padding)
end
end

# Compute a cryptographic digest of data (a Buffer). If block is given,
# it will call a block, otherwise it will return a Promise that will
# return once a digest is computed.
#
# Allowed values for algo: SHA-1, SHA-256 (default), SHA-368, SHA-512.
#
# The block/promise will be given an argument of type {Digest} which can
# be used to format a digest.
#
# Example:
# ```
# Browser::Blob.new(['test']).buffer.then { |b|
# $window.crypto.digest(b)
# }.then { |d|
# puts d.to_hex
# }
# ```
def digest data, algo = 'SHA-256', &block
promise = nil
unless block_given?
promise = Promise.new
block = proc { |i| promise.resolve(i) }
end
resblock = proc { |i| block.call(Digest.new(i)) }

`#@native.subtle.digest(algo, #{Native.convert(data)}).then(#{resblock.to_n})`
promise
end
end

class Window
# @!attribute [r] crypto
# @return [Crypto] the crypto interface of this window
def crypto
@crypto ||= Crypto.new(`#@native.crypto`)
end
end

end
18 changes: 17 additions & 1 deletion opal/browser/dom/node.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,17 @@ def ==(other)
`#@native === #{Native.convert(other)}`
end

# Initialize a new node after `#dup` or `#clone`.
#
# This method is not to be called directly. Use `Node#dup` or
# `Node#clone`.
#
# This method creates a deep detached clone of a DOM subtree to be used
# in the same document. The new node will have all events detached.
def initialize_copy(old)
set_native_reference `#{old.to_n}.cloneNode(true)`
end

# Append a child to the node.
#
# When passing a {String} a text node will be created.
Expand Down Expand Up @@ -253,12 +264,17 @@ def comment?
node_type == COMMENT_NODE
end

# @!attribute [r] document
# @!attribute [rw] document
# @return [Document?] the document the node is attached to
def document
DOM(`#@native.ownerDocument`) if defined?(`#@native.ownerDocument`)
end

# Detach a node and transfer it to another document.
def document=(new_document)
`#{Native.try_convert(new_document, new_document)}.adoptNode(#@native)`
end

# Return true if the node is a document.
def document?
node_type == DOCUMENT_NODE
Expand Down
8 changes: 8 additions & 0 deletions opal/browser/utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ def self.included(klass)
def restricted?
!!@restricted
end

# Change a native reference and make sure the change is reflected on JS
# side as well. This method is used by Node#initialize_copy. Please don't
# use this method outside of the cloning semantic.
def set_native_reference(native)
`#{native}.$$opal_native_cached = #{self}`
@native = native
end
end

module NativeCachedWrapperClassMethods
Expand Down
48 changes: 48 additions & 0 deletions spec/dom/node_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,54 @@
end
end

describe "#clone" do
html '<div class="waht"><ul><li>1</li></ul></div>'

it 'should clone a DOM node with an object' do
obj = $document['.waht']
new_obj = obj.clone

expect(obj).not_to eq(new_obj) # Equality is defined as equality of DOM nodes
expect(obj.at_css('li')).not_to eq(new_obj.at_css('li'))
end

it 'should dup a DOM node with an object' do
obj = $document['.waht']
new_obj = obj.dup

expect(obj).not_to eq(new_obj) # Equality is defined as equality of DOM nodes
expect(obj.at_css('li')).not_to eq(new_obj.at_css('li'))
end

it 'should produce an object which adheres to DOM semantics' do
obj = $document['.waht'].clone
xobj = obj.clone
5.times do
obj << xobj.clone
end
expect(obj.css('li').count).to eq(6)
end

it 'should integrate well with NativeCachedWrapper' do
obj = $document['.waht'].clone
native = obj.to_n
expect(DOM(native).hash).to eq(obj.hash)
end
end

describe "#document=" do
html '<iframe id="diframe" src="about:blank"></iframe><div id="ddiv">hah</div>'

it 'should detach a DOM node and attach it to a new document' do
obj = $document['ddiv']
ifr = $document['diframe']

obj.document = ifr.content_document
expect($document['ddiv']).to eq(nil)
expect(obj.document).to eq(ifr.content_document)
end
end

describe "#document?" do
it "should be true for document" do
expect($document.document?).to be_truthy
Expand Down