WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
Patch
bug-165724-20161227173458.patch (text/plain), 42.84 KB, created by
Yusuke Suzuki
on 2016-12-27 00:36:11 PST
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Yusuke Suzuki
Created:
2016-12-27 00:36:11 PST
Size:
42.84 KB
patch
obsolete
>Subversion Revision: 210152 >diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog >index f7af06f0cd3ec86e51429f515ed0a231e6342485..a681581541ce0c8dc7fa4e36e742bcb857a5c1f2 100644 >--- a/Source/JavaScriptCore/ChangeLog >+++ b/Source/JavaScriptCore/ChangeLog >@@ -1,3 +1,97 @@ >+2016-12-27 Yusuke Suzuki <utatane.tea@gmail.com> >+ >+ [JSC] Prototype dynamic-import >+ https://bugs.webkit.org/show_bug.cgi?id=165724 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ In this patch, we implement stage3 dynamic-import proposal[1]. >+ This patch adds a new special operator `import`. And by using it, we can import >+ the module dynamically from modules and scripts. Before this feature, the module >+ is always imported statically and before executing the modules, importing the modules >+ needs to be done. And especially, the module can only be imported from the module. >+ So the classic script cannot import and use the modules. This dynamic-import relaxes >+ the above restrictions. >+ >+ The typical dynamic-import form is the following. >+ >+ import("...").then(function (namespace) { ... }); >+ >+ You can pass any AssignmentExpression for the import operator. So you can determine >+ the importing modules dynamically. >+ >+ import(value).then(function (namespace) { ... }); >+ >+ And previously the module import declaration is only allowed in the top level statements. >+ But this import operator is just an expression. So you can use it in the function. >+ And you can use it conditionally. >+ >+ async function go(cond) >+ { >+ if (cond) >+ return import("..."); >+ return undefined; >+ } >+ await go(true); >+ >+ Currently, this patch just implements this feature only for the JSC shell. >+ JSC module loader requires a new hook, `importModule`. And the JSC shell implements >+ this hook. So, for now, this dynamic-import is not available in the browser side. >+ If you write this `import` call, it always returns the rejected promise. >+ >+ import is implemented like a special operator similar to `super`. >+ This is because import is context-sensitive. If you call the `import`, the module >+ key resolution is done based on the caller's running context. >+ >+ For example, if you are running the script which filename is "./ok/hello.js", the module >+ key for the call`import("./resource/syntax.js")` becomes `"./ok/resource/syntax.js"`. >+ But if you write the completely same import form in the script "./error/hello.js", the >+ key becomes "./error/resource/syntax.js". So exposing this feature as the `import` >+ function is misleading: this function becomes caller's context-sensitive. That's why >+ dynamic-import is specified as a special operator. >+ >+ To resolve the module key, we need the caller's context information like the filename of >+ the caller. This is provided by the SourceOrigin implemented in r210149. >+ In the JSC shell implementation, this SourceOrigin holds the filename of the caller. So >+ based on this implementation, the module loader resolve the module key. >+ In the near future, we will extend this SourceOrigin to hold more information needed for >+ the browser-side import implementation. >+ >+ [1]: https://tc39.github.io/proposal-dynamic-import/ >+ >+ * builtins/ModuleLoaderPrototype.js: >+ (importModule): >+ * bytecompiler/BytecodeGenerator.cpp: >+ (JSC::BytecodeGenerator::emitGetTemplateObject): >+ (JSC::BytecodeGenerator::emitGetGlobalPrivate): >+ * bytecompiler/BytecodeGenerator.h: >+ * bytecompiler/NodesCodegen.cpp: >+ (JSC::ImportNode::emitBytecode): >+ * jsc.cpp: >+ (GlobalObject::moduleLoaderImportModule): >+ * parser/ASTBuilder.h: >+ (JSC::ASTBuilder::createImportExpr): >+ * parser/NodeConstructors.h: >+ (JSC::ImportNode::ImportNode): >+ * parser/Nodes.h: >+ (JSC::ExpressionNode::isImportNode): >+ * parser/Parser.cpp: >+ (JSC::Parser<LexerType>::parseMemberExpression): >+ * parser/SyntaxChecker.h: >+ (JSC::SyntaxChecker::createImportExpr): >+ * runtime/JSGlobalObject.cpp: >+ (JSC::JSGlobalObject::init): >+ * runtime/JSGlobalObject.h: >+ * runtime/JSGlobalObjectFunctions.cpp: >+ (JSC::globalFuncImportModule): >+ * runtime/JSGlobalObjectFunctions.h: >+ * runtime/JSModuleLoader.cpp: >+ (JSC::JSModuleLoader::importModule): >+ (JSC::JSModuleLoader::getModuleNamespaceObject): >+ * runtime/JSModuleLoader.h: >+ * runtime/ModuleLoaderPrototype.cpp: >+ (JSC::moduleLoaderPrototypeGetModuleNamespaceObject): >+ > 2016-12-26 Yusuke Suzuki <utatane.tea@gmail.com> > > Use variadic templates in JSC Parser to clean up >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index b98d7258f9e334ed8cba18f79eb813e1701373a3..fea9170ece7cc142230eb8c2e7dd7aa524a96ddf 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,16 @@ >+2016-12-27 Yusuke Suzuki <utatane.tea@gmail.com> >+ >+ [JSC] Prototype dynamic-import >+ https://bugs.webkit.org/show_bug.cgi?id=165724 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ We do not set a handler for import for now. >+ So dynamic import feature is only enabled in the JSC shell right now. >+ >+ * bindings/js/JSDOMWindowBase.cpp: >+ * bindings/js/JSWorkerGlobalScopeBase.cpp: >+ > 2016-12-26 Zalan Bujtas <zalan@apple.com> > > ASSERTION FAILED: !rect.isEmpty() in WebCore::GraphicsContext::drawRect >diff --git a/Source/JavaScriptCore/builtins/ModuleLoaderPrototype.js b/Source/JavaScriptCore/builtins/ModuleLoaderPrototype.js >index 01c2b211e774407dcaff2d17ff33c4a45f47a24f..600285b5898f6262e61a13438060c138af1db68d 100644 >--- a/Source/JavaScriptCore/builtins/ModuleLoaderPrototype.js >+++ b/Source/JavaScriptCore/builtins/ModuleLoaderPrototype.js >@@ -470,3 +470,19 @@ function linkAndEvaluateModule(key, initiator) > this.link(entry, initiator); > return this.moduleEvaluation(entry.module, initiator); > } >+ >+function importModule(moduleName, referrer, initiator) >+{ >+ "use strict"; >+ >+ // Loader.resolve hook point. >+ // resolve: moduleName => Promise(moduleKey) >+ // Take the name and resolve it to the unique identifier for the resource location. >+ // For example, take the "jquery" and return the URL for the resource. >+ return this.resolve(moduleName, referrer, initiator).then((key) => { >+ return this.requestInstantiateAll(key, initiator); >+ }).then((entry) => { >+ this.linkAndEvaluateModule(entry.key, initiator); >+ return this.getModuleNamespaceObject(entry.module); >+ }); >+} >diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp >index 423e574dbfb4c4ea44405a129a06990f607d4ec1..30a8b6d59fbb3c288ed7ed92dad0bf1cce51df0e 100644 >--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp >+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp >@@ -4261,22 +4261,24 @@ RegisterID* BytecodeGenerator::emitGetTemplateObject(RegisterID* dst, TaggedTemp > cookedStrings.append(templateString->value()->cooked().impl()); > } > >- RefPtr<RegisterID> getTemplateObject = nullptr; >- Variable var = variable(propertyNames().builtinNames().getTemplateObjectPrivateName()); >- if (RegisterID* local = var.local()) >- getTemplateObject = emitMove(newTemporary(), local); >- else { >- getTemplateObject = newTemporary(); >- RefPtr<RegisterID> scope = newTemporary(); >- moveToDestinationIfNeeded(scope.get(), emitResolveScope(scope.get(), var)); >- emitGetFromScope(getTemplateObject.get(), scope.get(), var, ThrowIfNotFound); >- } >- >+ RefPtr<RegisterID> getTemplateObject = emitGetGlobalPrivate(newTemporary(), propertyNames().builtinNames().getTemplateObjectPrivateName()); > CallArguments arguments(*this, nullptr); > emitLoad(arguments.thisRegister(), JSValue(addTemplateRegistryKeyConstant(m_vm->templateRegistryKeyTable().createKey(rawStrings, cookedStrings)))); > return emitCall(dst, getTemplateObject.get(), NoExpectedFunction, arguments, taggedTemplate->divot(), taggedTemplate->divotStart(), taggedTemplate->divotEnd(), DebuggableCall::No); > } > >+RegisterID* BytecodeGenerator::emitGetGlobalPrivate(RegisterID* dst, const Identifier& property) >+{ >+ dst = tempDestination(dst); >+ Variable var = variable(property); >+ if (RegisterID* local = var.local()) >+ return emitMove(dst, local); >+ >+ RefPtr<RegisterID> scope = newTemporary(); >+ moveToDestinationIfNeeded(scope.get(), emitResolveScope(scope.get(), var)); >+ return emitGetFromScope(dst, scope.get(), var, ThrowIfNotFound); >+} >+ > RegisterID* BytecodeGenerator::emitGetEnumerableLength(RegisterID* dst, RegisterID* base) > { > emitOpcode(op_get_enumerable_length); >diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h >index 0aaec9d4701d0955918f3455f46a1c9a2fd45111..5f547ae720f1eaab56f8e61ec7c5c678139bc9ac 100644 >--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h >+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h >@@ -678,6 +678,7 @@ namespace JSC { > void emitEnumeration(ThrowableExpressionData* enumerationNode, ExpressionNode* subjectNode, const std::function<void(BytecodeGenerator&, RegisterID*)>& callBack, ForOfNode* = nullptr, RegisterID* forLoopSymbolTable = nullptr); > > RegisterID* emitGetTemplateObject(RegisterID* dst, TaggedTemplateNode*); >+ RegisterID* emitGetGlobalPrivate(RegisterID* dst, const Identifier& property); > > enum class ReturnFrom { Normal, Finally }; > RegisterID* emitReturn(RegisterID* src, ReturnFrom = ReturnFrom::Normal); >diff --git a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp >index 7becf753b588f27cc66ce283a44daf71202c98f8..5744d5801138c06459cefbed14804eb8fb1c41a6 100644 >--- a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp >+++ b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp >@@ -190,6 +190,17 @@ RegisterID* SuperNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds > return generator.moveToDestinationIfNeeded(generator.finalDestination(dst), result); > } > >+// ------------------------------ ImportNode ------------------------------------- >+ >+RegisterID* ImportNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) >+{ >+ RefPtr<RegisterID> importModule = generator.emitGetGlobalPrivate(generator.newTemporary(), generator.propertyNames().builtinNames().importModulePrivateName()); >+ CallArguments arguments(generator, nullptr, 1); >+ generator.emitLoad(arguments.thisRegister(), jsUndefined()); >+ generator.emitNode(arguments.argumentRegister(0), m_expr); >+ return generator.emitCall(generator.finalDestination(dst, importModule.get()), importModule.get(), NoExpectedFunction, arguments, divot(), divotStart(), divotEnd(), DebuggableCall::No); >+} >+ > // ------------------------------ NewTargetNode ---------------------------------- > > RegisterID* NewTargetNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) >diff --git a/Source/JavaScriptCore/jsc.cpp b/Source/JavaScriptCore/jsc.cpp >index 65765f47f91740ff34df8a4d7b6aef3402f9010b..cd9b06c9e425956f0f96012e86e1e97b8e1f7802 100644 >--- a/Source/JavaScriptCore/jsc.cpp >+++ b/Source/JavaScriptCore/jsc.cpp >@@ -25,6 +25,7 @@ > #include "ArrayBuffer.h" > #include "ArrayPrototype.h" > #include "BuiltinExecutableCreator.h" >+#include "BuiltinNames.h" > #include "ButterflyInlines.h" > #include "CodeBlock.h" > #include "Completion.h" >@@ -48,6 +49,7 @@ > #include "JSInternalPromise.h" > #include "JSInternalPromiseDeferred.h" > #include "JSLock.h" >+#include "JSModuleLoader.h" > #include "JSNativeStdFunction.h" > #include "JSONObject.h" > #include "JSProxy.h" >@@ -1277,6 +1279,7 @@ class GlobalObject : public JSGlobalObject { > putDirect(vm, identifier, JSFunction::create(vm, this, arguments, identifier.string(), function, NoIntrinsic, function)); > } > >+ static JSInternalPromise* moduleLoaderImportModule(JSGlobalObject*, ExecState*, JSModuleLoader*, JSString*, const SourceOrigin&); > static JSInternalPromise* moduleLoaderResolve(JSGlobalObject*, ExecState*, JSModuleLoader*, JSValue, JSValue, JSValue); > static JSInternalPromise* moduleLoaderFetch(JSGlobalObject*, ExecState*, JSModuleLoader*, JSValue, JSValue); > }; >@@ -1288,6 +1291,7 @@ const GlobalObjectMethodTable GlobalObject::s_globalObjectMethodTable = { > &javaScriptRuntimeFlags, > nullptr, > &shouldInterruptScriptBeforeTimeout, >+ &moduleLoaderImportModule, > &moduleLoaderResolve, > &moduleLoaderFetch, > nullptr, >@@ -1420,6 +1424,21 @@ static String resolvePath(const DirectoryName& directoryName, const ModuleName& > return builder.toString(); > } > >+JSInternalPromise* GlobalObject::moduleLoaderImportModule(JSGlobalObject*, ExecState* exec, JSModuleLoader* moduleLoader, JSString* moduleName, const SourceOrigin& sourceOrigin) >+{ >+ auto* function = jsCast<JSObject*>(moduleLoader->get(exec, exec->propertyNames().builtinNames().importModulePublicName())); >+ CallData callData; >+ CallType callType = JSC::getCallData(function, callData); >+ ASSERT(callType != CallType::None); >+ >+ MarkedArgumentBuffer arguments; >+ arguments.append(moduleName); >+ arguments.append(jsString(exec, sourceOrigin.string())); >+ arguments.append(jsUndefined()); >+ >+ return jsCast<JSInternalPromise*>(call(exec, function, callType, callData, moduleLoader, arguments)); >+} >+ > JSInternalPromise* GlobalObject::moduleLoaderResolve(JSGlobalObject* globalObject, ExecState* exec, JSModuleLoader*, JSValue keyValue, JSValue referrerValue, JSValue) > { > VM& vm = globalObject->vm(); >diff --git a/Source/JavaScriptCore/parser/ASTBuilder.h b/Source/JavaScriptCore/parser/ASTBuilder.h >index 57ec412054b2df91e52f5d70cf26417489713bde..4e74b5bbf4740d89be3a072e534b62228a721ab0 100644 >--- a/Source/JavaScriptCore/parser/ASTBuilder.h >+++ b/Source/JavaScriptCore/parser/ASTBuilder.h >@@ -178,6 +178,12 @@ class ASTBuilder { > { > return new (m_parserArena) SuperNode(location); > } >+ ExpressionNode* createImportExpr(const JSTokenLocation& location, ExpressionNode* expr, const JSTextPosition& start, const JSTextPosition& divot, const JSTextPosition& end) >+ { >+ auto* node = new (m_parserArena) ImportNode(location, expr); >+ setExceptionLocation(node, start, divot, end); >+ return node; >+ } > ExpressionNode* createNewTargetExpr(const JSTokenLocation location) > { > usesNewTarget(); >diff --git a/Source/JavaScriptCore/parser/NodeConstructors.h b/Source/JavaScriptCore/parser/NodeConstructors.h >index e27e20945233691ac26af3e0ae60f2f325296485..7d2e2e93694d87d49ae4c002ddc1dfc3bcc36449 100644 >--- a/Source/JavaScriptCore/parser/NodeConstructors.h >+++ b/Source/JavaScriptCore/parser/NodeConstructors.h >@@ -167,6 +167,12 @@ namespace JSC { > { > } > >+ inline ImportNode::ImportNode(const JSTokenLocation& location, ExpressionNode* expr) >+ : ExpressionNode(location) >+ , m_expr(expr) >+ { >+ } >+ > inline NewTargetNode::NewTargetNode(const JSTokenLocation& location) > : ExpressionNode(location) > { >diff --git a/Source/JavaScriptCore/parser/Nodes.h b/Source/JavaScriptCore/parser/Nodes.h >index 24110aa1600d99e93ee3fdc55a725e33a6517250..7324cd424b55bdf5c29ef74f73967920b6e433e6 100644 >--- a/Source/JavaScriptCore/parser/Nodes.h >+++ b/Source/JavaScriptCore/parser/Nodes.h >@@ -186,6 +186,7 @@ namespace JSC { > virtual bool isBoolean() const { return false; } > virtual bool isSpreadExpression() const { return false; } > virtual bool isSuperNode() const { return false; } >+ virtual bool isImportNode() const { return false; } > virtual bool isNewTarget() const { return false; } > virtual bool isBytecodeIntrinsicNode() const { return false; } > >@@ -570,6 +571,17 @@ namespace JSC { > RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; > }; > >+ class ImportNode : public ExpressionNode, public ThrowableExpressionData { >+ public: >+ ImportNode(const JSTokenLocation&, ExpressionNode*); >+ >+ private: >+ bool isImportNode() const override { return true; } >+ RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; >+ >+ ExpressionNode* m_expr; >+ }; >+ > class NewTargetNode final : public ExpressionNode { > public: > NewTargetNode(const JSTokenLocation&); >diff --git a/Source/JavaScriptCore/parser/Parser.cpp b/Source/JavaScriptCore/parser/Parser.cpp >index 65ec38aa60ebe8f20bd816b4f37f5de8f4939ddf..3b74c3bce86cfabb79ef6d0e2e3ec5bffac211b0 100644 >--- a/Source/JavaScriptCore/parser/Parser.cpp >+++ b/Source/JavaScriptCore/parser/Parser.cpp >@@ -4343,7 +4343,8 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseMemberExpres > } > > bool baseIsSuper = match(SUPER); >- semanticFailIfTrue(baseIsSuper && newCount, "Cannot use new with super"); >+ bool baseIsImport = match(IMPORT); >+ semanticFailIfTrue((baseIsSuper || baseIsImport) && newCount, "Cannot use new with ", getToken()); > > bool baseIsNewTarget = false; > if (newCount && match(DOT)) { >@@ -4383,6 +4384,13 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseMemberExpres > semanticFailIfTrue(functionSuperBinding == SuperBinding::NotNeeded, "super is not valid in this context"); > } > } >+ } else if (baseIsImport) { >+ JSTextPosition expressionEnd = lastTokenEndPosition(); >+ next(); >+ handleProductionOrFail2(OPENPAREN, "(", "start", "'import' call"); >+ TreeExpression expr = parseAssignmentExpression(context); >+ handleProductionOrFail2(CLOSEPAREN, ")", "end", "'import' call"); >+ return context.createImportExpr(location, expr, expressionStart, expressionEnd, lastTokenEndPosition()); > } else if (!baseIsNewTarget) { > const bool isAsync = match(ASYNC); > >diff --git a/Source/JavaScriptCore/parser/SyntaxChecker.h b/Source/JavaScriptCore/parser/SyntaxChecker.h >index f32854a8b97bd6c0f4743e6b681e209295c35e87..52d947a65b2e5b47c81ff0a44c64396bef202488 100644 >--- a/Source/JavaScriptCore/parser/SyntaxChecker.h >+++ b/Source/JavaScriptCore/parser/SyntaxChecker.h >@@ -71,7 +71,7 @@ class SyntaxChecker { > enum { NoneExpr = 0, > ResolveEvalExpr, ResolveExpr, IntegerExpr, DoubleExpr, StringExpr, > ThisExpr, NullExpr, BoolExpr, RegExpExpr, ObjectLiteralExpr, >- FunctionExpr, ClassExpr, SuperExpr, BracketExpr, DotExpr, CallExpr, >+ FunctionExpr, ClassExpr, SuperExpr, ImportExpr, BracketExpr, DotExpr, CallExpr, > NewExpr, PreExpr, PostExpr, UnaryExpr, BinaryExpr, > ConditionalExpr, AssignmentExpr, TypeofExpr, NewTargetExpr, > DeleteExpr, ArrayLiteralExpr, BindingDestructuring, RestParameter, >@@ -156,6 +156,7 @@ class SyntaxChecker { > ExpressionType createLogicalNot(const JSTokenLocation&, ExpressionType) { return UnaryExpr; } > ExpressionType createUnaryPlus(const JSTokenLocation&, ExpressionType) { return UnaryExpr; } > ExpressionType createVoid(const JSTokenLocation&, ExpressionType) { return UnaryExpr; } >+ ExpressionType createImportExpr(const JSTokenLocation&, ExpressionType, int, int, int) { return ImportExpr; } > ExpressionType createThisExpr(const JSTokenLocation&) { return ThisExpr; } > ExpressionType createSuperExpr(const JSTokenLocation&) { return SuperExpr; } > ExpressionType createNewTargetExpr(const JSTokenLocation&) { return NewTargetExpr; } >diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp >index a70ecf4e50307600d4d50fa4fb9bea3e98bab0aa..242e055bc45f7ba0071498e3f6c63eb28a70ae1b 100644 >--- a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp >+++ b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp >@@ -256,6 +256,7 @@ const GlobalObjectMethodTable JSGlobalObject::s_globalObjectMethodTable = { > nullptr, > nullptr, > nullptr, >+ nullptr, > nullptr > }; > >@@ -732,6 +733,7 @@ putDirectWithoutTransition(vm, vm.propertyNames-> jsName, lowerName ## Construct > JSFunction* privateFuncTrunc = JSFunction::create(vm, this, 0, String(), mathProtoFuncTrunc, TruncIntrinsic); > > JSFunction* privateFuncGetTemplateObject = JSFunction::create(vm, this, 0, String(), getTemplateObject); >+ JSFunction* privateFuncImportModule = JSFunction::create(vm, this, 0, String(), globalFuncImportModule); > JSFunction* privateFuncTypedArrayLength = JSFunction::create(vm, this, 0, String(), typedArrayViewPrivateFuncLength); > JSFunction* privateFuncTypedArrayGetOriginalConstructor = JSFunction::create(vm, this, 0, String(), typedArrayViewPrivateFuncGetOriginalConstructor); > JSFunction* privateFuncTypedArraySort = JSFunction::create(vm, this, 0, String(), typedArrayViewPrivateFuncSort); >@@ -785,6 +787,7 @@ putDirectWithoutTransition(vm, vm.propertyNames-> jsName, lowerName ## Construct > GlobalPropertyInfo(vm.propertyNames->undefinedKeyword, jsUndefined(), DontEnum | DontDelete | ReadOnly), > GlobalPropertyInfo(vm.propertyNames->builtinNames().ownEnumerablePropertyKeysPrivateName(), JSFunction::create(vm, this, 0, String(), ownEnumerablePropertyKeys), DontEnum | DontDelete | ReadOnly), > GlobalPropertyInfo(vm.propertyNames->builtinNames().getTemplateObjectPrivateName(), privateFuncGetTemplateObject, DontEnum | DontDelete | ReadOnly), >+ GlobalPropertyInfo(vm.propertyNames->builtinNames().importModulePrivateName(), privateFuncImportModule, DontEnum | DontDelete | ReadOnly), > GlobalPropertyInfo(vm.propertyNames->builtinNames().enqueueJobPrivateName(), JSFunction::create(vm, this, 0, String(), enqueueJob), DontEnum | DontDelete | ReadOnly), > GlobalPropertyInfo(vm.propertyNames->builtinNames().ErrorPrivateName(), m_errorConstructor.get(), DontEnum | DontDelete | ReadOnly), > GlobalPropertyInfo(vm.propertyNames->builtinNames().RangeErrorPrivateName(), m_rangeErrorConstructor.get(), DontEnum | DontDelete | ReadOnly), >diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.h b/Source/JavaScriptCore/runtime/JSGlobalObject.h >index b423c49bd4fcf1b4cb58c83e1bdc66a81be7e37d..76aeb3030bafb0bf4f27f7d4eaa1043b19f5654b 100644 >--- a/Source/JavaScriptCore/runtime/JSGlobalObject.h >+++ b/Source/JavaScriptCore/runtime/JSGlobalObject.h >@@ -184,6 +184,9 @@ struct GlobalObjectMethodTable { > typedef bool (*ShouldInterruptScriptBeforeTimeoutPtr)(const JSGlobalObject*); > ShouldInterruptScriptBeforeTimeoutPtr shouldInterruptScriptBeforeTimeout; > >+ typedef JSInternalPromise* (*ModuleLoaderImportModulePtr)(JSGlobalObject*, ExecState*, JSModuleLoader*, JSString*, const SourceOrigin&); >+ ModuleLoaderImportModulePtr moduleLoaderImportModule; >+ > typedef JSInternalPromise* (*ModuleLoaderResolvePtr)(JSGlobalObject*, ExecState*, JSModuleLoader*, JSValue, JSValue, JSValue); > ModuleLoaderResolvePtr moduleLoaderResolve; > >diff --git a/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp b/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp >index 110f5243f084be1e84c19d5e468aed4712586c64..ef7a3fe63cf054be8ad73441179ff6bd091910a3 100644 >--- a/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp >+++ b/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp >@@ -27,10 +27,14 @@ > > #include "CallFrame.h" > #include "EvalExecutable.h" >+#include "Exception.h" > #include "IndirectEvalExecutable.h" > #include "Interpreter.h" > #include "JSFunction.h" > #include "JSGlobalObject.h" >+#include "JSInternalPromise.h" >+#include "JSModuleLoader.h" >+#include "JSPromiseDeferred.h" > #include "JSString.h" > #include "JSStringBuilder.h" > #include "Lexer.h" >@@ -925,4 +929,38 @@ EncodedJSValue JSC_HOST_CALL globalFuncBuiltinLog(ExecState* exec) > return JSValue::encode(jsUndefined()); > } > >+EncodedJSValue JSC_HOST_CALL globalFuncImportModule(ExecState* exec) >+{ >+ VM& vm = exec->vm(); >+ auto catchScope = DECLARE_CATCH_SCOPE(vm); >+ >+ auto* globalObject = exec->lexicalGlobalObject(); >+ >+ auto* promise = JSPromiseDeferred::create(exec, globalObject); >+ RETURN_IF_EXCEPTION(catchScope, encodedJSValue()); >+ >+ auto sourceOrigin = exec->callerSourceOrigin(); >+ if (sourceOrigin.isNull()) { >+ promise->reject(exec, createError(exec, ASCIILiteral("Could not resolve the module specifier."))); >+ return JSValue::encode(promise->promise()); >+ } >+ >+ auto* specifier = exec->argument(0).toString(exec); >+ if (Exception* exception = catchScope.exception()) { >+ catchScope.clearException(); >+ promise->reject(exec, exception); >+ return JSValue::encode(promise->promise()); >+ } >+ >+ auto* internalPromise = globalObject->moduleLoader()->importModule(exec, specifier, sourceOrigin); >+ if (Exception* exception = catchScope.exception()) { >+ catchScope.clearException(); >+ promise->reject(exec, exception); >+ return JSValue::encode(promise->promise()); >+ } >+ promise->resolve(exec, internalPromise); >+ >+ return JSValue::encode(promise->promise()); >+} >+ > } // namespace JSC >diff --git a/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.h b/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.h >index dcdba38a5b9ddf1e30412c75e3270a992a96d89b..cd42704f258637e592bb3fb67254da0102c00b59 100644 >--- a/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.h >+++ b/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.h >@@ -50,6 +50,7 @@ EncodedJSValue JSC_HOST_CALL globalFuncThrowTypeErrorArgumentsCalleeAndCaller(Ex > EncodedJSValue JSC_HOST_CALL globalFuncProtoGetter(ExecState*); > EncodedJSValue JSC_HOST_CALL globalFuncProtoSetter(ExecState*); > EncodedJSValue JSC_HOST_CALL globalFuncBuiltinLog(ExecState*); >+EncodedJSValue JSC_HOST_CALL globalFuncImportModule(ExecState*); > > static const double mantissaOverflowLowerBound = 9007199254740992.0; > double parseIntOverflow(const LChar*, unsigned length, int radix); >diff --git a/Source/JavaScriptCore/runtime/JSModuleLoader.cpp b/Source/JavaScriptCore/runtime/JSModuleLoader.cpp >index bfd8f4951d008654eb5ae9025509aeb9b27487d4..a2ffb82974cdbaeebce2c9c941a228978b5888ef 100644 >--- a/Source/JavaScriptCore/runtime/JSModuleLoader.cpp >+++ b/Source/JavaScriptCore/runtime/JSModuleLoader.cpp >@@ -134,6 +134,30 @@ JSValue JSModuleLoader::linkAndEvaluateModule(ExecState* exec, JSValue moduleKey > return call(exec, function, callType, callData, this, arguments); > } > >+JSInternalPromise* JSModuleLoader::importModule(ExecState* exec, JSString* moduleName, const SourceOrigin& referrer) >+{ >+ if (Options::dumpModuleLoadingState()) >+ dataLog("Loader [import] ", printableModuleKey(exec, moduleName), "\n"); >+ >+ JSGlobalObject* globalObject = exec->lexicalGlobalObject(); >+ VM& vm = globalObject->vm(); >+ auto scope = DECLARE_CATCH_SCOPE(vm); >+ >+ if (globalObject->globalObjectMethodTable()->moduleLoaderImportModule) >+ return globalObject->globalObjectMethodTable()->moduleLoaderImportModule(globalObject, exec, this, moduleName, referrer); >+ >+ JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::create(exec, globalObject); >+ auto moduleNameString = moduleName->value(exec); >+ if (UNLIKELY(scope.exception())) { >+ JSValue exception = scope.exception()->value(); >+ scope.clearException(); >+ deferred->reject(exec, exception); >+ return deferred->promise(); >+ } >+ deferred->reject(exec, createError(exec, makeString("Could not import the module '", moduleNameString, "'."))); >+ return deferred->promise(); >+} >+ > JSInternalPromise* JSModuleLoader::resolve(ExecState* exec, JSValue name, JSValue referrer, JSValue initiator) > { > if (Options::dumpModuleLoadingState()) >@@ -197,4 +221,19 @@ JSValue JSModuleLoader::evaluate(ExecState* exec, JSValue key, JSValue moduleRec > return moduleRecord->evaluate(exec); > } > >+JSModuleNamespaceObject* JSModuleLoader::getModuleNamespaceObject(ExecState* exec, JSValue moduleRecordValue) >+{ >+ VM& vm = exec->vm(); >+ auto scope = DECLARE_THROW_SCOPE(vm); >+ >+ auto* moduleRecord = jsDynamicCast<AbstractModuleRecord*>(moduleRecordValue); >+ if (!moduleRecord) { >+ throwTypeError(exec, scope); >+ return nullptr; >+ } >+ >+ scope.release(); >+ return moduleRecord->getModuleNamespace(exec); >+} >+ > } // namespace JSC >diff --git a/Source/JavaScriptCore/runtime/JSModuleLoader.h b/Source/JavaScriptCore/runtime/JSModuleLoader.h >index d3bb3bcb606f609fedea2f29ee29dd33a94fef86..73ecce67da99d22ab1f54acace1acfd3d36c3258 100644 >--- a/Source/JavaScriptCore/runtime/JSModuleLoader.h >+++ b/Source/JavaScriptCore/runtime/JSModuleLoader.h >@@ -31,6 +31,7 @@ > namespace JSC { > > class JSInternalPromise; >+class JSModuleNamespaceObject; > > class JSModuleLoader : public JSNonFinalObject { > private: >@@ -67,6 +68,7 @@ class JSModuleLoader : public JSNonFinalObject { > JSValue linkAndEvaluateModule(ExecState*, JSValue moduleKey, JSValue initiator); > > // Platform dependent hooked APIs. >+ JSInternalPromise* importModule(ExecState*, JSString* moduleName, const SourceOrigin& referrer); > JSInternalPromise* resolve(ExecState*, JSValue name, JSValue referrer, JSValue initiator); > JSInternalPromise* fetch(ExecState*, JSValue key, JSValue initiator); > JSInternalPromise* instantiate(ExecState*, JSValue key, JSValue source, JSValue initiator); >@@ -74,6 +76,9 @@ class JSModuleLoader : public JSNonFinalObject { > // Additional platform dependent hooked APIs. > JSValue evaluate(ExecState*, JSValue key, JSValue moduleRecord, JSValue initiator); > >+ // Utility functions. >+ JSModuleNamespaceObject* getModuleNamespaceObject(ExecState*, JSValue moduleRecord); >+ > protected: > void finishCreation(ExecState*, VM&, JSGlobalObject*); > }; >diff --git a/Source/JavaScriptCore/runtime/ModuleLoaderPrototype.cpp b/Source/JavaScriptCore/runtime/ModuleLoaderPrototype.cpp >index ee07a9b961ea31b8cc441f1e7f163921239932fc..3871e8c64ade3c823f2a7bb1f51019d16d8cd6a5 100644 >--- a/Source/JavaScriptCore/runtime/ModuleLoaderPrototype.cpp >+++ b/Source/JavaScriptCore/runtime/ModuleLoaderPrototype.cpp >@@ -37,6 +37,7 @@ > #include "JSMap.h" > #include "JSModuleEnvironment.h" > #include "JSModuleLoader.h" >+#include "JSModuleNamespaceObject.h" > #include "JSModuleRecord.h" > #include "ModuleAnalyzer.h" > #include "Nodes.h" >@@ -52,6 +53,7 @@ static EncodedJSValue JSC_HOST_CALL moduleLoaderPrototypeModuleDeclarationInstan > static EncodedJSValue JSC_HOST_CALL moduleLoaderPrototypeResolve(ExecState*); > static EncodedJSValue JSC_HOST_CALL moduleLoaderPrototypeFetch(ExecState*); > static EncodedJSValue JSC_HOST_CALL moduleLoaderPrototypeInstantiate(ExecState*); >+static EncodedJSValue JSC_HOST_CALL moduleLoaderPrototypeGetModuleNamespaceObject(ExecState*); > > } > >@@ -85,6 +87,8 @@ const ClassInfo ModuleLoaderPrototype::s_info = { "ModuleLoader", &Base::s_info, > loadAndEvaluateModule JSBuiltin DontEnum|Function 3 > loadModule JSBuiltin DontEnum|Function 3 > linkAndEvaluateModule JSBuiltin DontEnum|Function 2 >+ importModule JSBuiltin DontEnum|Function 3 >+ getModuleNamespaceObject moduleLoaderPrototypeGetModuleNamespaceObject DontEnum|Function 1 > parseModule moduleLoaderPrototypeParseModule DontEnum|Function 2 > requestedModules moduleLoaderPrototypeRequestedModules DontEnum|Function 1 > resolve moduleLoaderPrototypeResolve DontEnum|Function 2 >@@ -211,6 +215,19 @@ EncodedJSValue JSC_HOST_CALL moduleLoaderPrototypeInstantiate(ExecState* exec) > return JSValue::encode(loader->instantiate(exec, exec->argument(0), exec->argument(1), exec->argument(2))); > } > >+EncodedJSValue JSC_HOST_CALL moduleLoaderPrototypeGetModuleNamespaceObject(ExecState* exec) >+{ >+ VM& vm = exec->vm(); >+ auto scope = DECLARE_THROW_SCOPE(vm); >+ >+ JSModuleLoader* loader = jsDynamicCast<JSModuleLoader*>(exec->thisValue()); >+ if (!loader) >+ return JSValue::encode(jsUndefined()); >+ auto* moduleNamespaceObject = loader->getModuleNamespaceObject(exec, exec->argument(0)); >+ RETURN_IF_EXCEPTION(scope, encodedJSValue()); >+ return JSValue::encode(moduleNamespaceObject); >+} >+ > // ------------------- Additional Hook Functions --------------------------- > > EncodedJSValue JSC_HOST_CALL moduleLoaderPrototypeEvaluate(ExecState* exec) >diff --git a/Source/WebCore/bindings/js/JSDOMWindowBase.cpp b/Source/WebCore/bindings/js/JSDOMWindowBase.cpp >index fa8c52d4a1aad5b7f60de2857752735252e84224..397e5942b98fa5abd78f9abcbbecf42aed062fa9 100644 >--- a/Source/WebCore/bindings/js/JSDOMWindowBase.cpp >+++ b/Source/WebCore/bindings/js/JSDOMWindowBase.cpp >@@ -64,6 +64,7 @@ const GlobalObjectMethodTable JSDOMWindowBase::s_globalObjectMethodTable = { > &javaScriptRuntimeFlags, > &queueTaskToEventLoop, > &shouldInterruptScriptBeforeTimeout, >+ nullptr, > &moduleLoaderResolve, > &moduleLoaderFetch, > nullptr, >diff --git a/Source/WebCore/bindings/js/JSWorkerGlobalScopeBase.cpp b/Source/WebCore/bindings/js/JSWorkerGlobalScopeBase.cpp >index 62f76c8dad3b1f6ac6fed43fe90bef0f9a605af0..1a5f7a0f31b519fd06889a11b2ac1bc83afa3d85 100644 >--- a/Source/WebCore/bindings/js/JSWorkerGlobalScopeBase.cpp >+++ b/Source/WebCore/bindings/js/JSWorkerGlobalScopeBase.cpp >@@ -57,6 +57,7 @@ const GlobalObjectMethodTable JSWorkerGlobalScopeBase::s_globalObjectMethodTable > nullptr, > nullptr, > nullptr, >+ nullptr, > &defaultLanguage > }; > >diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog >index 5df7de30451706f7410b7262dc54a12c72bec9dd..880a01fd68dd464f789a9cabf707e3d0c566fe94 100644 >--- a/LayoutTests/ChangeLog >+++ b/LayoutTests/ChangeLog >@@ -1,3 +1,12 @@ >+2016-12-27 Yusuke Suzuki <utatane.tea@gmail.com> >+ >+ [JSC] Prototype dynamic-import >+ https://bugs.webkit.org/show_bug.cgi?id=165724 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * sputnik/Conformance/07_Lexical_Conventions/7.5_Tokens/7.5.3_Future_Reserved_Words/S7.5.3_A1.16-expected.txt: >+ > 2016-12-26 Zalan Bujtas <zalan@apple.com> > > ASSERTION FAILED: !rect.isEmpty() in WebCore::GraphicsContext::drawRect >diff --git a/LayoutTests/sputnik/Conformance/07_Lexical_Conventions/7.5_Tokens/7.5.3_Future_Reserved_Words/S7.5.3_A1.16-expected.txt b/LayoutTests/sputnik/Conformance/07_Lexical_Conventions/7.5_Tokens/7.5.3_Future_Reserved_Words/S7.5.3_A1.16-expected.txt >index 8a0563789b17ed6faafff2d36cef78f7f536a4b7..11bbdc9b9bf3461424a5c1eccddafd97d5f5a612 100644 >--- a/LayoutTests/sputnik/Conformance/07_Lexical_Conventions/7.5_Tokens/7.5.3_Future_Reserved_Words/S7.5.3_A1.16-expected.txt >+++ b/LayoutTests/sputnik/Conformance/07_Lexical_Conventions/7.5_Tokens/7.5.3_Future_Reserved_Words/S7.5.3_A1.16-expected.txt >@@ -1,4 +1,4 @@ >-CONSOLE MESSAGE: line 76: SyntaxError: Unexpected keyword 'import' >+CONSOLE MESSAGE: line 76: SyntaxError: Unexpected token '='. Expected '(' to start an 'import' call. > S7.5.3_A1.16 > > PASS Expected parsing failure >diff --git a/JSTests/ChangeLog b/JSTests/ChangeLog >index 1f9d672bb928b15e845a4341c3fd08f457fad584..33876f86fb80ee2989f77af265dbb0de83fa8d81 100644 >--- a/JSTests/ChangeLog >+++ b/JSTests/ChangeLog >@@ -1,3 +1,29 @@ >+2016-12-27 Yusuke Suzuki <utatane.tea@gmail.com> >+ >+ [JSC] Prototype dynamic-import >+ https://bugs.webkit.org/show_bug.cgi?id=165724 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * stress/import-basic.js: Added. >+ (async): >+ (catch): >+ * stress/import-from-eval.js: Added. >+ (async): >+ (catch): >+ * stress/import-syntax.js: Added. >+ (testSyntaxError): >+ * stress/import-tests/cocoa.js: Added. >+ (export.Cocoa): >+ (export.hello): >+ * stress/import-tests/multiple.js: Added. >+ (export.result): >+ * stress/import-tests/multiple2.js: Added. >+ (export.ok): >+ * stress/import-tests/should.js: Added. >+ (export.shouldBe): >+ (export.shouldThrow): >+ > 2016-12-25 Yusuke Suzuki <utatane.tea@gmail.com> > > Propagate the source origin as much as possible >diff --git a/JSTests/stress/import-basic.js b/JSTests/stress/import-basic.js >new file mode 100644 >index 0000000000000000000000000000000000000000..c5d967cb8891c194638fdf2e3c490bf3bde60f8d >--- /dev/null >+++ b/JSTests/stress/import-basic.js >@@ -0,0 +1,53 @@ >+(async function () { >+ const { shouldBe } = await import('./import-tests/should.js'); >+ { >+ let a = await import('./import-tests/cocoa.js'); >+ let b = await import('./import-tests/cocoa.js'); >+ shouldBe(a, b); >+ shouldBe(a.hello(), 42); >+ } >+ >+ { >+ let a = await import('./import-tests/multiple.js'); >+ let a2 = await a.result(); >+ shouldBe(a !== a2, true); >+ shouldBe(a2.ok(), 42); >+ let a3 = await a.result(); >+ shouldBe(a2, a3); >+ } >+ >+ { >+ let error = null; >+ try { >+ let a = await import({ toString() { throw new Error('out'); } }); >+ } catch (e) { >+ error = e; >+ } >+ shouldBe(error !== null, true); >+ shouldBe(String(error), `Error: out`); >+ } >+ >+ { >+ async function load(cond) { >+ if (cond) >+ return import('./import-tests/cocoa.js'); >+ return undefined; >+ } >+ >+ let v = await load(false); >+ shouldBe(v, undefined); >+ let v2 = await load(true); >+ let v3 = await import('./import-tests/cocoa.js'); >+ shouldBe(v2, v2); >+ } >+ >+ { >+ let value = './import-tests/cocoa.js'; >+ let v = await import(value); >+ let v2 = await import('./import-tests/cocoa.js'); >+ shouldBe(v, v2); >+ } >+}()).catch((error) => { >+ print(String(error)); >+ abort(); >+}); >diff --git a/JSTests/stress/import-from-eval.js b/JSTests/stress/import-from-eval.js >new file mode 100644 >index 0000000000000000000000000000000000000000..b8e0792a05d34a7937e5bd9fccf5d71435c2d2f4 >--- /dev/null >+++ b/JSTests/stress/import-from-eval.js >@@ -0,0 +1,36 @@ >+(async function () { >+ const { shouldBe, shouldThrow } = await import("./import-tests/should.js"); >+ >+ { >+ let cocoa = await eval(`import("./import-tests/cocoa.js")`); >+ shouldBe(cocoa.hello(), 42); >+ } >+ >+ { >+ let cocoa = await (0, eval)(`import("./import-tests/cocoa.js")`); >+ shouldBe(cocoa.hello(), 42); >+ } >+ >+ { >+ let cocoa = await eval(`eval('import("./import-tests/cocoa.js")')`); >+ shouldBe(cocoa.hello(), 42); >+ } >+ >+ { >+ let cocoa = await ((new Function(`return eval('import("./import-tests/cocoa.js")')`))()); >+ shouldBe(cocoa.hello(), 42); >+ } >+ >+ { >+ let cocoa = await eval(`(new Function('return import("./import-tests/cocoa.js")'))()`); >+ shouldBe(cocoa.hello(), 42); >+ } >+ >+ { >+ let cocoa = await [`import("./import-tests/cocoa.js")`].map(eval)[0]; >+ shouldBe(cocoa.hello(), 42); >+ } >+}()).catch((error) => { >+ print(String(error)); >+ abort(); >+}); >diff --git a/JSTests/stress/import-syntax.js b/JSTests/stress/import-syntax.js >new file mode 100644 >index 0000000000000000000000000000000000000000..064016c85a19f66a9b96a4bdfffe915dade2b657 >--- /dev/null >+++ b/JSTests/stress/import-syntax.js >@@ -0,0 +1,32 @@ >+function testSyntaxError(script, message) { >+ var error = null; >+ try { >+ eval(script); >+ } catch (e) { >+ error = e; >+ } >+ if (!error) >+ throw new Error("Expected syntax error not thrown"); >+ >+ if (String(error) !== message) >+ throw new Error(`Bad error: ${String(error)}`); >+} >+ >+testSyntaxError(`import)`, `SyntaxError: Unexpected token ')'. Expected '(' to start an 'import' call.`); >+testSyntaxError(`new import(`, `SyntaxError: Cannot use new with import.`); >+testSyntaxError(`import.hello()`, `SyntaxError: Unexpected token '.'. Expected '(' to start an 'import' call.`); >+testSyntaxError(`import[`, `SyntaxError: Unexpected token '['. Expected '(' to start an 'import' call.`); >+testSyntaxError(`import<`, `SyntaxError: Unexpected token '<'. Expected '(' to start an 'import' call.`); >+ >+testSyntaxError(`import()`, `SyntaxError: Unexpected token ')'`); >+testSyntaxError(`import("Hello";`, `SyntaxError: Unexpected token ';'. Expected ')' to end an 'import' call.`); >+testSyntaxError(`import("Hello"];`, `SyntaxError: Unexpected token ']'. Expected ')' to end an 'import' call.`); >+testSyntaxError(`import("Hello",;`, `SyntaxError: Unexpected token ','. Expected ')' to end an 'import' call.`); >+testSyntaxError(`import("Hello", "Hello2";`, `SyntaxError: Unexpected token ','. Expected ')' to end an 'import' call.`); >+ >+testSyntaxError(`import = 42`, `SyntaxError: Unexpected token '='. Expected '(' to start an 'import' call.`); >+testSyntaxError(`[import] = 42`, `SyntaxError: Unexpected token ']'. Expected '(' to start an 'import' call.`); >+testSyntaxError(`{import} = 42`, `SyntaxError: Unexpected token '}'. Expected '(' to start an 'import' call.`); >+testSyntaxError(`let import = 42`, `SyntaxError: Unexpected keyword 'import'`); >+testSyntaxError(`var import = 42`, `SyntaxError: Cannot use the keyword 'import' as a variable name.`); >+testSyntaxError(`const import = 42`, `SyntaxError: Cannot use the keyword 'import' as a lexical variable name.`); >diff --git a/JSTests/stress/import-tests/cocoa.js b/JSTests/stress/import-tests/cocoa.js >new file mode 100644 >index 0000000000000000000000000000000000000000..910b02c68c8a96066013d139daefed710627828b >--- /dev/null >+++ b/JSTests/stress/import-tests/cocoa.js >@@ -0,0 +1,7 @@ >+export class Cocoa { >+} >+ >+export function hello() >+{ >+ return 42; >+} >diff --git a/JSTests/stress/import-tests/multiple.js b/JSTests/stress/import-tests/multiple.js >new file mode 100644 >index 0000000000000000000000000000000000000000..41805c4032706e65d3fbb1e188261eb20dbd53d3 >--- /dev/null >+++ b/JSTests/stress/import-tests/multiple.js >@@ -0,0 +1,4 @@ >+export function result() >+{ >+ return import('./multiple2.js'); >+} >diff --git a/JSTests/stress/import-tests/multiple2.js b/JSTests/stress/import-tests/multiple2.js >new file mode 100644 >index 0000000000000000000000000000000000000000..ba6f85ab4a2aa80c61fa3913d1db30347625035a >--- /dev/null >+++ b/JSTests/stress/import-tests/multiple2.js >@@ -0,0 +1,4 @@ >+export function ok() >+{ >+ return 42; >+} >diff --git a/JSTests/stress/import-tests/should.js b/JSTests/stress/import-tests/should.js >new file mode 100644 >index 0000000000000000000000000000000000000000..a006f84ebdfa01eac165d2fa2ed151ca7a64bad4 >--- /dev/null >+++ b/JSTests/stress/import-tests/should.js >@@ -0,0 +1,19 @@ >+export function shouldBe(actual, expected) { >+ if (actual !== expected) >+ throw new Error(`bad value: ${String(actual)}`); >+} >+ >+export function shouldThrow(func, errorMessage) { >+ var errorThrown = false; >+ var error = null; >+ try { >+ func(); >+ } catch (e) { >+ errorThrown = true; >+ error = e; >+ } >+ if (!errorThrown) >+ throw new Error('not thrown'); >+ if (String(error) !== errorMessage) >+ throw new Error(`bad error: ${String(error)}`); >+}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 165724
:
297763
|
297764
|
297765
|
297766
|
297767
|
297768
|
297771
|
297780
|
297782
|
297783
|
298382