Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: opal/opal
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 9b67f083adc3
Choose a base ref
...
head repository: opal/opal
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: b15ea9fc7c50
Choose a head ref
  • 7 commits
  • 3 files changed
  • 1 contributor

Commits on Dec 25, 2013

  1. Unverified

    This user has not yet uploaded their public signing key.
    Copy the full SHA
    e6ad1df View commit details
  2. Copy the full SHA
    68898af View commit details
  3. Add some more specs for Promise

    meh committed Dec 25, 2013
    Copy the full SHA
    69d2944 View commit details
  4. Copy the full SHA
    2c51885 View commit details
  5. Copy the full SHA
    8cc8e2a View commit details
  6. Add Promise::When#reduce

    meh committed Dec 25, 2013
    Copy the full SHA
    7f06587 View commit details
  7. Copy the full SHA
    b15ea9f View commit details
Showing with 113 additions and 29 deletions.
  1. +16 −0 spec/opal/stdlib/promise/then_spec.rb
  2. +15 −0 spec/opal/stdlib/promise/when_spec.rb
  3. +82 −29 stdlib/promise.rb
16 changes: 16 additions & 0 deletions spec/opal/stdlib/promise/then_spec.rb
Original file line number Diff line number Diff line change
@@ -35,4 +35,20 @@

x.should == 23
end

it 'sends raised exceptions as rejections' do
x = nil

Promise.value(2).then { raise "hue" }.rescue { |v| x = v }

x.should be_kind_of(RuntimeError)
end

it 'sends raised exceptions inside rescue blocks as next errors' do
x = nil

Promise.value(2).then { raise "hue" }.rescue { raise "omg" }.rescue { |v| x = v }

x.should be_kind_of(RuntimeError)
end
end
15 changes: 15 additions & 0 deletions spec/opal/stdlib/promise/when_spec.rb
Original file line number Diff line number Diff line change
@@ -16,4 +16,19 @@

x.should == 3
end

it 'can be built lazily' do
a = Promise.new
b = Promise.value(3)

x = 42

Promise.when(a).and(b).then {|c, d|
x = c + d
}

a.resolve(2)

x.should == 5
end
end
111 changes: 82 additions & 29 deletions stdlib/promise.rb
Original file line number Diff line number Diff line change
@@ -17,10 +17,11 @@ def initialize(success = nil, failure = nil)
@success = success
@failure = failure

@realized = nil
@value = nil
@error = nil
@delayed = nil
@realized = nil
@exception = false
@value = nil
@error = nil
@delayed = nil

@prev = nil
@next = nil
@@ -30,16 +31,20 @@ def act?
@success != nil
end

def exception?
@exception
end

def realized?
@realized != nil
end

def resolved?
@realized == :value
@realized == :resolve
end

def rejected?
@realized == :error
@realized == :reject
end

def ^(promise)
@@ -58,7 +63,9 @@ def <<(promise)
def >>(promise)
@next = promise

if resolved?
if exception?
promise.reject(@delayed)
elsif resolved?
promise.resolve(@delayed || value)
elsif rejected? && (!@failure || Promise === (@delayed || @error))
promise.reject(@delayed || error)
@@ -78,20 +85,28 @@ def resolve(value)
return value ^ self
end

@realized = :value
@realized = :resolve
@value = value

if @success
value = @success.call(value)
begin
if @success
value = @success.call(value)
end

resolve!(value)
rescue Exception => e
exception!(e)
end

self
end

def resolve!(value)
if @next
@next.resolve(value)
else
@delayed = value
end

self
end

def reject(value)
@@ -105,30 +120,40 @@ def reject(value)
return value ^ self
end

@realized = :error
@realized = :reject
@error = value

if @failure
value = @failure.call(value)
begin
if @failure
value = @failure.call(value)

if Promise === value
if @next
@next.reject(value)
else
@delayed = value
if Promise === value
reject!(value)
end
end
else
if @next
@next.reject(value)
else
@delayed = value
reject!(value)
end
rescue Exception => e
exception!(e)
end

self
end

def reject!(value)
if @next
@next.reject(value)
else
@delayed = value
end
end

def exception!(error)
@exception = true

reject!(error)
end

def then(&block)
self ^ Promise.new(block)
end
@@ -202,7 +227,37 @@ def initialize(promises = [])
}
end

def each(&block)
raise ArgumentError, 'no block given' unless block

self.then {|values|
values.each(&block)
}
end

def collect(&block)
raise ArgumentError, 'no block given' unless block

self.then {|values|
Promise.when values.map(&block)
}
end

def inject(*args, &block)
self.then {|values|
values.reduce(*args, &block)
}
end

alias map collect

alias reduce inject

def wait(promise)
unless Promise === promise
promise = Promise.value(promise)
end

@wait << promise

promise.always {
@@ -212,6 +267,8 @@ def wait(promise)
self
end

alias and wait

def >>(*)
super.tap {
try
@@ -227,9 +284,5 @@ def try
end
end
end

def and(&block)
wait Promise.new(block)
end
end
end