Changeset 186966 in webkit for trunk/Source/JavaScriptCore/API


Ignore:
Timestamp:
Jul 17, 2015, 3:40:40 PM (10 years ago)
Author:
Yusuke Suzuki
Message:

Integrate automatic microtask draining into JSC framework and re-enable Promise
https://bugs.webkit.org/show_bug.cgi?id=146828

Reviewed by Sam Weinig.

Source/JavaScriptCore:

Add automatic microtask draining system into JSC framework.
When the depth of VM lock becomes 0, before this, we drain the queued microtasks.
Enqueuing behavior can be injected by the JSGlobalObject's method table.
It is utilized in WebCore to post the microtask to WebCore's event loop.

In the case of JSC interactive shell, VM depth is always greater than 0.
So we manually drains the queued microtasks after evaluating the written line.

Since now JSC framework has the microtask queue, we can drain the queued microtasks.
So re-enable the Promise in the JSC framework context.

  • API/JSContextRef.cpp:

(javaScriptRuntimeFlags): Deleted.

  • API/tests/testapi.c:

(main):

  • API/tests/testapi.mm:

(testObjectiveCAPIMain):

  • jsc.cpp:

(runInteractive):

  • runtime/JSGlobalObject.cpp:

(JSC::JSGlobalObject::queueMicrotask):

  • runtime/JSLock.cpp:

(JSC::JSLock::willReleaseLock):

  • runtime/VM.cpp:

(JSC::VM::queueMicrotask):
(JSC::VM::drainMicrotasks):
(JSC::QueuedTask::run):

  • runtime/VM.h:

(JSC::QueuedTask::QueuedTask):

LayoutTests:

Add Promise tests mainly focusing on microtasks.
They can be executed in JSC shell. So they are locate in js/ directory (not js/dom).

  • js/promise-nested-microtasks-expected.txt: Added.
  • js/promise-nested-microtasks.html: Added.
  • js/promise-resolve-in-non-dom-expected.txt: Added.
  • js/promise-resolve-in-non-dom.html: Added.
  • js/script-tests/promise-nested-microtasks.js: Added.

(Promise.resolve.then):

  • js/script-tests/promise-resolve-non-dom.js: Added.

(value.then):

  • resources/standalone-post.js:
Location:
trunk/Source/JavaScriptCore/API
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/API/JSContextRef.cpp

    r185346 r186966  
    6060using namespace JSC;
    6161
    62 static RuntimeFlags javaScriptRuntimeFlags(const JSGlobalObject* globalObject)
    63 {
    64     RuntimeFlags runtimeFlags = JSGlobalObject::javaScriptRuntimeFlags(globalObject);
    65     runtimeFlags.setPromiseDisabled(true);
    66     return runtimeFlags;
    67 }
    68 
    69 const GlobalObjectMethodTable JSC::javaScriptCoreAPIGlobalObjectMethodTable = { &JSGlobalObject::allowsAccessFrom, &JSGlobalObject::supportsProfiling, &JSGlobalObject::supportsRichSourceInfo, &JSGlobalObject::shouldInterruptScript, &javaScriptRuntimeFlags, nullptr, &JSGlobalObject::shouldInterruptScriptBeforeTimeout };
     62const GlobalObjectMethodTable JSC::javaScriptCoreAPIGlobalObjectMethodTable = { &JSGlobalObject::allowsAccessFrom, &JSGlobalObject::supportsProfiling, &JSGlobalObject::supportsRichSourceInfo, &JSGlobalObject::shouldInterruptScript, &JSGlobalObject::javaScriptRuntimeFlags, nullptr, &JSGlobalObject::shouldInterruptScriptBeforeTimeout };
    7063
    7164// From the API's perspective, a context group remains alive iff
  • trunk/Source/JavaScriptCore/API/tests/testapi.c

    r183754 r186966  
    18551855        {
    18561856            JSStringRef promiseProperty = JSStringCreateWithUTF8CString("Promise");
    1857             ASSERT(!JSObjectHasProperty(context, globalObject, promiseProperty));
     1857            ASSERT(JSObjectHasProperty(context, globalObject, promiseProperty));
    18581858            JSStringRelease(promiseProperty);
    18591859        }
    18601860        {
    18611861            JSStringRef script = JSStringCreateWithUTF8CString("typeof Promise");
    1862             JSStringRef undefined = JSStringCreateWithUTF8CString("undefined");
     1862            JSStringRef function = JSStringCreateWithUTF8CString("function");
    18631863            JSValueRef value = JSEvaluateScript(context, script, NULL, NULL, 1, NULL);
    18641864            ASSERT(JSValueIsString(context, value));
    18651865            JSStringRef valueAsString = JSValueToStringCopy(context, value, NULL);
    1866             ASSERT(JSStringIsEqual(valueAsString, undefined));
     1866            ASSERT(JSStringIsEqual(valueAsString, function));
    18671867            JSStringRelease(valueAsString);
    1868             JSStringRelease(undefined);
     1868            JSStringRelease(function);
    18691869            JSStringRelease(script);
    18701870        }
    1871         printf("PASS: Promise is not exposed under JSContext API.\n");
     1871        printf("PASS: Promise is exposed under JSContext API.\n");
     1872    }
     1873
     1874    // Check microtasks.
     1875    {
     1876        JSGlobalContextRef context = JSGlobalContextCreateInGroup(NULL, NULL);
     1877        {
     1878            JSObjectRef globalObject = JSContextGetGlobalObject(context);
     1879            JSValueRef exception;
     1880            JSStringRef code = JSStringCreateWithUTF8CString("result = 0; Promise.resolve(42).then(function (value) { result = value; });");
     1881            JSStringRef file = JSStringCreateWithUTF8CString("");
     1882            assertTrue(JSEvaluateScript(context, code, globalObject, file, 1, &exception), "An exception should not be thrown");
     1883            JSStringRelease(code);
     1884            JSStringRelease(file);
     1885
     1886            JSStringRef resultProperty = JSStringCreateWithUTF8CString("result");
     1887            ASSERT(JSObjectHasProperty(context, globalObject, resultProperty));
     1888
     1889            JSValueRef resultValue = JSObjectGetProperty(context, globalObject, resultProperty, &exception);
     1890            assertEqualsAsNumber(resultValue, 42);
     1891            JSStringRelease(resultProperty);
     1892        }
     1893        JSGlobalContextRelease(context);
    18721894    }
    18731895
  • trunk/Source/JavaScriptCore/API/tests/testapi.mm

    r185122 r186966  
    541541    @autoreleasepool {
    542542        JSContext *context = [[JSContext alloc] init];
    543         checkResult(@"Promise is not exposed", [context[@"Promise"] isUndefined]);
     543        checkResult(@"Promise is exposed", ![context[@"Promise"] isUndefined]);
    544544        JSValue *result = [context evaluateScript:@"typeof Promise"];
    545         checkResult(@"typeof Promise is 'undefined'", result.isString && [result isEqualToObject:@"undefined"]);
     545        checkResult(@"typeof Promise is 'function'", result.isString && [result isEqualToObject:@"function"]);
     546    }
     547
     548    @autoreleasepool {
     549        JSVirtualMachine* vm = [[JSVirtualMachine alloc] init];
     550        JSContext* context = [[JSContext alloc] initWithVirtualMachine:vm];
     551        [context evaluateScript:@"result = 0; Promise.resolve(42).then(function (value) { result = value; });"];
     552        checkResult(@"Microtask is drained", [context[@"result"]  isEqualToObject:@42]);
    546553    }
    547554
Note: See TracChangeset for help on using the changeset viewer.